EE-223 Assignment
Name: Syed Hassan Rizwan
Registration Number: 2023683
Section: C
Write a C-language code to implement a 4x4 keypad interface with PIC18 using the
interrupt-on-change feature of PORTB. Display the pressed button's character on an 8-
bit LCD.
#include <xc.h>
#include <stdint.h>
// Configuration Settings
#pragma config OSC = HS // High-Speed Oscillator
#pragma config WDT = OFF // Disable Watchdog Timer
#pragma config LVP = OFF // Disable Low-Voltage Programming
#define CRYSTAL_FREQ 20000000 // 20MHz Crystal Frequency
// LCD Interface Definitions
#define LCD_PORT PORTC
#define LCD_RS LATEbits.LATE0
#define LCD_RW LATEbits.LATE1
#define LCD_EN LATEbits.LATE2
// Keypad Matrix Layout
const char keypad_matrix[4][4] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
volatile char detected_key = 0;
// Function Declarations
void initialize_display(void);
void send_display_command(uint8_t instruction);
void write_display_data(uint8_t character);
void print_display_message(const char *text);
void clear_display(void);
char read_keypad_input(void);
void __interrupt() interrupt_handler(void);
void main(void) {
// Display Setup
TRISC = 0x00;
TRISE = 0x00;
initialize_display();
// Keypad Configuration
TRISB |= 0xF0; // RB4-RB7 as inputs
[Link] = 0; // Enable PORTB pull-ups
// Keypad Output Pins
TRISD &= 0xF0; // RD0-RD3 as outputs
// Interrupt Configuration
[Link] = 1; // Enable PORTB change interrupt
[Link] = 1; // Global interrupt enable
IOCB = 0xF0; // Interrupt on change for RB4-RB7
print_display_message("Press Key:");
while(1) {
if(detected_key) {
send_display_command(0xC0); // Move to second line
write_display_data(detected_key);
detected_key = 0;
}
}
}
void __interrupt() interrupt_handler(void) {
if([Link]) {
__delay_ms(20); // Key debounce delay
detected_key = read_keypad_input();
[Link] = 0; // Clear interrupt flag
}
}
// Keypad Scanning Function
char read_keypad_input(void) {
for(uint8_t column = 0; column < 4; column++) {
LATD = ~(1 << column); // Activate one column
__delay_us(5);
uint8_t row_status = PORTB & 0xF0;
for(uint8_t row = 0; row < 4; row++) {
if(!(row_status & (0x10 << row))) {
while(!(PORTB & (0x10 << row))); // Wait for key release
return keypad_matrix[row][column];
}
}
}
return 0;
}
// Display Control Functions
void initialize_display(void) {
__delay_ms(20);
send_display_command(0x38); // 8-bit interface, 2 lines
send_display_command(0x0C); // Display on, cursor off
send_display_command(0x06); // Auto-increment mode
send_display_command(0x01); // Clear display
__delay_ms(2);
}
void send_display_command(uint8_t instruction) {
LCD_RS = 0;
LCD_RW = 0;
LCD_PORT = instruction;
LCD_EN = 1;
__delay_us(1);
LCD_EN = 0;
__delay_ms(2);
}
void write_display_data(uint8_t character) {
LCD_RS = 1;
LCD_RW = 0;
LCD_PORT = character;
LCD_EN = 1;
__delay_us(1);
LCD_EN = 0;
__delay_ms(2);
}
void print_display_message(const char *text) {
while(*text) {
write_display_data(*text++);
}
}
void clear_display(void) {
send_display_command(0x01);
__delay_ms(2);
}