The LCD is already place on board. The MCP23017 interfaces to the ATMega644P using only two TWI wires. But it need to place and wire on a breadboard module with the keypad.
I use a remembrance 4x4 keypad module that's ready to connect to GPA.
- "main.c"
- /*
- * 10-i2c_mcp23017_keypad.c
- *
- * Created: 2/5/2026 9:05:21 AM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const char MCP23017_W=0x40;
- const char MCP23017_R=0x41;
- //IOCON.BANK=0
- enum BANK0{
- IODIRA=0,IODIRB,IPOLA,IPOLB,GPINTENA,GPINTENB,DEFVALA,
- DEFVALB,INTCONA,INTCONB,IOCON1,IOCON2,GPPUA,GPPUB,
- INTFA,INTFB,INTCAPA,INTCAPB,GPIOA,GPIOB,OLATA,OLATB
- };
- void mcp23017_write(char address,char data){
- twi_start();
- /*Select the write address*/
- twi_write(MCP23017_W);
- /*Select a register address*/
- twi_write(address);
- /*Send configuration data*/
- twi_write(data);
- twi_stop();
- }
- unsigned char mcp23017_read(char address){
- /*Select a specific address*/
- twi_start();
- twi_write(MCP23017_W);
- twi_write(address);
- twi_stop();
- /*Read data from the given address*/
- twi_start();
- twi_write(MCP23017_R);
- unsigned char i2cData=twi_read(1);
- twi_stop();
- return i2cData;
- }
- const char key_16[4][4]={'1','2','3','A',
- '4','5','6','B',
- '7','8','9','C',
- '*','0','#','D'};
- char keyScan(void){
- char data=0,temp,key;
- for(char i=0;i<4;i++){
- data=0xFF;
- data&=~(1<<i);
- mcp23017_write(OLATA,data);
- _delay_ms(5);
- data=mcp23017_read(GPIOA);
- data&=0xF0;
- if((data&0x10)==0) {temp=key_16[i][0]; break;}
- else if((data&0x20)==0){temp=key_16[i][1]; break;}
- else if((data&0x40)==0){temp=key_16[i][2]; break;}
- else if((data&0x80)==0){temp=key_16[i][3]; break;}
- else temp=0;
- _delay_ms(10);
- }
- return temp;
- }
- int main(void)
- {
- /* Replace with your application code */
- lcd_init();
- twi_init();
- lcd_text("ATMEGA644P TWI");
- lcd_xy(1,2);
- lcd_text("MCP23017 KeyPad");
- _delay_ms(5000);
- lcd_clear();
- //Key Pad Init
- mcp23017_write(IODIRA,0xF0);
- mcp23017_write(GPPUA,0xF0);
- char temp,charCount=0,newLine=0,line=1;
- while (1)
- {
- temp=keyScan();
- if(temp!=0){
- lcd_data(temp);
- charCount++;
- _delay_ms(500);
- }
- if(charCount>16){
- newLine=1;
- charCount=0;
- line+=1;
- }
- if(newLine){
- newLine=0;
- if(line==2) lcd_xy(1,2);
- else{
- lcd_xy(1,1);
- lcd_command(0x01);
- _delay_ms(5);
- line=1;
- }
- }
- }
- }
We need to add the "twi.c" to project before the twi function can be called.
- "twi.c"
- /*
- * twi.c
- *
- * Created: 2/4/2026 10:22:02 AM
- * Author: Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- void twi_init(void){
- TWSR|=0x00; //Prescaler Selection Bit
- TWBR=0x0F; //Baud Rate Generator
- TWCR=(1<<TWEN); //Enable The TWI Module
- PORTC|=(1<<0);
- PORTC|=(1<<1);
- }
- void twi_start(void){
- TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- void twi_write(unsigned char data){
- TWDR=data;
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- unsigned char twi_read(char ACK){
- if(ACK==0)
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
- else
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- return TWDR;
- }
- void twi_stop(){
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
- _delay_us(10);
- }
- Schematic
| Proteus Circuit and Simulation |
| Keypad Scanning |
- ATMega644P AVR Board Experiment
| AVR Prototype Board Experiment |
| AVR Prototype Board Experiment |
This PCB was offered by PCBWay (pcbway.com).
I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.
![]() |
| 10 PCBs for only 5USD |
For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.
![]() |
| PCBWay Instant Quote |
There's on port left GPB. So I added one more keypad port.
| Two Keypad Ports |
Source Code:
- /*
- * 10-i2c_mcp23017_keypad_2.c
- *
- * Created: 2/5/2026 3:14:18 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const char MCP23017_W=0x40;
- const char MCP23017_R=0x41;
- //IOCON.BANK=0
- enum BANK0{
- IODIRA=0,IODIRB,IPOLA,IPOLB,GPINTENA,GPINTENB,DEFVALA,
- DEFVALB,INTCONA,INTCONB,IOCON1,IOCON2,GPPUA,GPPUB,
- INTFA,INTFB,INTCAPA,INTCAPB,GPIOA,GPIOB,OLATA,OLATB
- };
- void mcp23017_write(char address,char data){
- twi_start();
- /*Select the write address*/
- twi_write(MCP23017_W);
- /*Select a register address*/
- twi_write(address);
- /*Send configuration data*/
- twi_write(data);
- twi_stop();
- }
- unsigned char mcp23017_read(char address){
- /*Select a specific address*/
- twi_start();
- twi_write(MCP23017_W);
- twi_write(address);
- twi_stop();
- /*Read data from the given address*/
- twi_start();
- twi_write(MCP23017_R);
- unsigned char i2cData=twi_read(1);
- twi_stop();
- return i2cData;
- }
- //KeyPad at GPA
- const char key_1[4][4]={'1','2','3','A',
- '4','5','6','B',
- '7','8','9','C',
- '*','0','#','D'};
- //KeyPad at GPB
- const char key_2[4][4]={'E','F','G','H',
- 'I','J','K','L',
- 'M','N','O','P',
- 'Q','R','S','T'};
- //KeyPad at GPA
- char keyScan_1(void){
- char data=0,temp,key;
- for(char i=0;i<4;i++){
- data=0xFF;
- data&=~(1<<i);
- mcp23017_write(OLATA,data);
- _delay_ms(5);
- data=mcp23017_read(GPIOA);
- data&=0xF0;
- if((data&0x10)==0) {temp=key_1[i][0]; break;}
- else if((data&0x20)==0){temp=key_1[i][1]; break;}
- else if((data&0x40)==0){temp=key_1[i][2]; break;}
- else if((data&0x80)==0){temp=key_1[i][3]; break;}
- else temp=0;
- _delay_ms(10);
- }
- return temp;
- }
- //KeyPad at GPB
- char keyScan_2(void){
- char data=0,temp,key;
- for(char i=0;i<4;i++){
- data=0xFF;
- data&=~(1<<i);
- mcp23017_write(OLATB,data);
- _delay_ms(5);
- data=mcp23017_read(GPIOB);
- data&=0xF0;
- if((data&0x10)==0) {temp=key_2[i][0]; break;}
- else if((data&0x20)==0){temp=key_2[i][1]; break;}
- else if((data&0x40)==0){temp=key_2[i][2]; break;}
- else if((data&0x80)==0){temp=key_2[i][3]; break;}
- else temp=0;
- _delay_ms(10);
- }
- return temp;
- }
- int main(void)
- {
- /* Replace with your application code */
- lcd_init();
- twi_init();
- lcd_text("ATMEGA644P TWI");
- lcd_xy(1,2);
- lcd_text("MCP23017 KeyPad");
- _delay_ms(5000);
- lcd_clear();
- //Key Pad Init
- mcp23017_write(IODIRA,0xF0);
- mcp23017_write(GPPUA,0xF0);
- mcp23017_write(IODIRB,0xF0);
- mcp23017_write(GPPUB,0xF0);
- char keyPad_1,keyPad_2,charCount=0,newLine=0,line=1;
- while (1)
- {
- keyPad_1=keyScan_1();
- if(keyPad_1!=0){
- lcd_data(keyPad_1);
- charCount++;
- _delay_ms(500);
- }
- keyPad_2=keyScan_2();
- if(keyPad_2!=0){
- lcd_data(keyPad_2);
- charCount++;
- _delay_ms(500);
- }
- if(charCount>16){
- newLine=1;
- charCount=0;
- line+=1;
- }
- if(newLine){
- newLine=0;
- if(line==2) lcd_xy(1,2);
- else{
- lcd_xy(1,1);
- lcd_command(0x01);
- _delay_ms(5);
- line=1;
- }
- }
- }
- }
Schematic:
| Schematic |
AVR Prototype Board:
| AVR Prototype Board |
| AVR Prototype Board Experiment |


No comments:
Post a Comment