728x90

728x90

Wednesday, February 18, 2026

ATMega644P SPI SN74HC595 and SN74HC165 4x8 Matrix KeyPad Driving

In previous post I use these two SPI chips, SN74HC595 and SN74HC165 to expand the inputs/outputs of an MCU. Here I use these two chip pair to make a matrix keypad. These two 8-bit I/O expansion chip can build up to a 8x8 matrix keypad that yield 64 different keys. But I make only a 4x8 matrix keypad since it's not important.

ATMega644P SPI SN74HC595 and SN74HC165 4x8 Matrix KeyPad Driving
Simulating Program

The 8-bit output port of the SN74HC595 is a column scanner while the lower nibble input port of the SN74HC165 is a row detector (active high). Whenever any key press found the program assign a specific key in its keypad array.

Source Code "main.c":

  1. /*
  2. * 12-spi_sn74hc165_sn74hc595n_keypad.c
  3. *
  4. * Created: 2/18/2026 2:03:34 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. #define DDR_SPI DDRB
  11. #define PRT_SPI PORTB

  12. #define DD_SH 3
  13. #define DD_SS 4
  14. #define DD_MOSI 5
  15. #define DD_MISO 6
  16. #define DD_SCK 7


  17. void SPI_MasterInit(void)
  18. {
  19. /* Set MOSI and SCK output, all others input */
  20. DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
  21. /* Enable SPI, Master, set clock rate fck/16 */
  22. SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
  23. }

  24. void SPI_MasterTransmit(char cData)
  25. {
  26. /* Start transmission */
  27. SPDR = cData;
  28. /* Wait for transmission complete */
  29. while(!(SPSR & (1<<SPIF)))
  30. ;
  31. }

  32. void SPI_SlaveInit(void)
  33. {
  34. /* Set MISO output, all others input */
  35. DDR_SPI = (1<<DD_MISO);
  36. /* Enable SPI */
  37. SPCR = (1<<SPE);
  38. }
  39. char SPI_SlaveReceive(void)
  40. {
  41. /* Wait for reception complete */
  42. while(!(SPSR & (1<<SPIF)))
  43. ;
  44. /* Return Data Register */
  45. return SPDR;
  46. }

  47. const char key_16[4][8]={'1','2','3','4','5','6','7','8',
  48. '9','0','A','B','C','D','E','F',
  49. 'G','H','I','J','K','L','M','N',
  50. 'O','P','Q','R','S','T','U','V'};

  51. char key_scan(void){
  52. char data=0,temp,key;
  53. for(char i=0;i<8;i++){
  54. SPI_MasterTransmit(1<<i);
  55. PRT_SPI&=~(1<<DD_SS);
  56. _delay_us(10);
  57. PRT_SPI|=(1<<DD_SS);
  58. _delay_ms(5);
  59. PRT_SPI&=~(1<<DD_SH);
  60. PRT_SPI|=(1<<DD_SH);
  61. SPI_MasterTransmit(0);
  62. data=SPI_SlaveReceive();
  63. if(data==0x01) {temp=key_16[0][i]; break;}
  64. else if(data==0x02) {temp=key_16[1][i]; break;}
  65. else if(data==0x04){temp=key_16[2][i]; break;}
  66. else if(data==0x08){temp=key_16[3][i]; break;}
  67. else temp=0;
  68. _delay_ms(10);
  69. }
  70. return temp;
  71. }

  72. int main(void)
  73. {
  74. /* Replace with your application code */
  75. SPI_MasterInit();
  76. lcd_init();
  77. DDR_SPI|=(1<<DD_SH);
  78. char data=0;
  79. char temp,charCount=0,newLine=0,line=1;
  80. lcd_text("ATMega644P SPI");
  81. lcd_xy(1,2);
  82. lcd_text("MATRIX KEYPAD");
  83. _delay_ms(5000);
  84. lcd_clear();
  85. while (1)
  86. {
  87. temp=key_scan();
  88. if(temp!=0){
  89. lcd_data(temp);
  90. charCount++;
  91. _delay_ms(500);
  92. }
  93. if(charCount>16){
  94. newLine=1;
  95. charCount=0;
  96. line+=1;
  97. }
  98. if(newLine){
  99. newLine=0;
  100. if(line==2) lcd_xy(1,2);
  101. else{
  102. lcd_xy(1,1);
  103. lcd_command(0x01);
  104. _delay_ms(5);
  105. line=1;
  106. }
  107. }
  108. _delay_ms(100);
  109. }
  110. }






The character LCD uses the parallel port of the ATMega644P. But we can control this LCD by adding one more SN74HC595 and one additional Slave Select (SS) pin. 

ATMega644P SPI SN74HC595 and SN74HC165 4x8 Matrix KeyPad Driving
Simulating Program

I separate these two chip using different Slave Select pins. The SN74HC165 doesn't need serial data input. It only need serial clock and Slave Select pins controlled by the MCU. However I think we can cascade this two chip using a shared SPI pins. If I have more time I will test it using this method.


 

For a full tutorial page of ATMega644P Programming Using C please visit this page. 

No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90