#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
// Definiciones para el teclado
#define KEYPAD_PORT PORTB
#define KEYPAD_PIN PINB
#define KEYPAD_DDR DDRB
#define ROWS 4
#define COLS 4
// 7-segment display definitions (Common Cathode)
#define SEGMENT_PORT PORTD
#define SEGMENT_DDR DDRD
// Keypad debounce delay in milliseconds
#define DEBOUNCE_DELAY 20
// Function prototypes
void init_ports(void);
uint8_t read_keypad(void);
uint8_t get_key(void);
uint8_t convert_to_7segment(uint8_t key);
void display(uint8_t value);
// Keypad mapping
const uint8_t keymap[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
int main(void) {
init_ports();
while (1) {
uint8_t key = get_key();
if (key != 0xFF) {
uint8_t segment = convert_to_7segment(key);
display(segment);
}
}
}
void init_ports(void) {
// Set keypad rows as output (PB0-PB3)
KEYPAD_DDR |= 0x0F; // Lower nibble as output
// Set keypad columns as input with pull-up (PB4-PB7)
KEYPAD_DDR &= 0x0F; // Upper nibble as input
KEYPAD_PORT |= 0xF0; // Enable pull-ups on upper nibble
// Set 7-segment display as output (PD0-PD6)
SEGMENT_DDR = 0x7F;
}
uint8_t read_keypad(void) {
for (uint8_t row = 0; row < ROWS; row++) {
// Activate one row at a time
KEYPAD_PORT = (KEYPAD_PORT & 0xF0) | ~(1 << row);
// Read columns
uint8_t cols = (KEYPAD_PIN >> 4) & 0x0F;
// Check if any column is low (button pressed)
if (cols != 0x0F) {
// Find which column is low
for (uint8_t col = 0; col < COLS; col++) {
if (!(cols & (1 << col))) {
return keymap[row][col];
}
}
}
}
return 0xFF; // No key pressed
}
uint8_t get_key(void) {
uint8_t key = read_keypad();
if (key != 0xFF) {
_delay_ms(DEBOUNCE_DELAY); // Debounce delay
if (key == read_keypad()) { // Verify key is still pressed
// Wait for key release
while (read_keypad() != 0xFF);
return key;
}
}
return 0xFF; // No valid key press
}
uint8_t convert_to_7segment(uint8_t key) {
// Custom 7-segment encoding (Common Cathode)
// Format: gfedcba (LSB is 'a')
switch (key) {
case '0': return 0x3F;
case '1': return 0x06;
case '2': return 0x5B;
case '3': return 0x4F;
case '4': return 0x66;
case '5': return 0x6D;
case '6': return 0x7D;
case '7': return 0x07;
case '8': return 0x7F;
case '9': return 0x6F;
case 'A': return 0x77;
case 'B': return 0x7C;
case 'C': return 0x39;
case 'D': return 0x5E;
case '*': return 0x63; // Custom symbol for *
case '#': return 0x73; // Custom symbol for #
default: return 0x00; // Blank for unknown
}
}
void display(uint8_t value) {
SEGMENT_PORT = value;
}
1. Conexiones ATMega328P :
- Conecte VCC a 5 V y GND a tierra
2. Conexiones del teclado 4x4:
- Filas: Conectar a PB0-PB3 (pines 14-17)
- Columnas: Conectar a PB4-PB7 (pines 18-21)
- Agregue resistencias pull-up de 10 kΩ en cada línea de columna
3. Pantalla de 7 segmentos (cátodo común):
- Conecte los segmentos ag a PD0-PD6 (pines 2-8)
- Conecte el cátodo común a GND
- Agregue resistencias limitadoras de corriente de 220 Ω en serie con cada segmento