728x90

728x90

Sunday, February 11, 2024

PIC16F887 SPI MCP23S17 Character LCD and KeyPad XC8 Example

In previous example, I use the MCP23S17 to drive an HD44780 based 20x4 character LCD using the 4-bit data transfer mode. This chip has two GPIO ports. So it can interface to various types of digital I/O devices including a dot matrix display, a multiplexing 7-Segment display, a matrix keypad, etc.

PIC16F887 SPI MCP23S17 Character LCD and KeyPad XC8 Example
Simulating Program in Proteus

In this example, I use a 20x4 character LCD and a 4x4 matrix keypad. They are controlled by the MCP23S17 GPIO extender chip. This chip uses the SPI interface that controlled by a PIC16F887 micro-controller. 

PIC16F887 SPI MCP23S17 Character LCD and KeyPad XC8 Example
A 4x4 membrane matrix keypad is suitable for most of hobbyist electronics projects

I add a key pad scanning routine in the C main file. It's very simple, and light weight. The founded key is an ASCII character that directly show on the LCD, otherwise it return 0 value.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on February 11, 2024, 10:42 AM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "mcp23S17.h"
  11.  
  12. #define _XTAL_FREQ 8000000UL
  13.  
  14. /*MCP23S17 4x4 KeyPad Scan Function*/
  15. const uint8_t key_ascii[][4]={
  16. '7','8','9','/',
  17. '4','5','6','*',
  18. '1','2','3','-',
  19. 'x','0','=','+'
  20. };
  21. uint8_t get_key(void);
  22.  
  23. void main(void) {
  24. uint8_t key=0,char_count=0, new_line=0,line_num=1;
  25. OSCCONbits.IRCF=7;
  26. lcd_init();
  27. lcd_text("PIC16F887 MCP23S17");
  28. lcd_xy(1,2); lcd_text("Character LCD KeyPad");
  29. lcd_xy(1,3); lcd_text("Example Using MPLABX");
  30. lcd_xy(1,4); lcd_text("IDE And XC8 Compiler");
  31. __delay_ms(3000);
  32. lcd_clear();
  33. while(1){
  34. key=get_key();
  35. if(key!=0){
  36. lcd_data(key);
  37. __delay_ms(250);
  38. char_count+=1;
  39. }
  40. if(char_count>=20){char_count=0; new_line=1;}
  41. if(new_line){
  42. new_line=0;
  43. line_num+=1;
  44. switch(line_num){
  45. case 2: lcd_xy(1,2); break;
  46. case 3: lcd_xy(1,3); break;
  47. case 4: lcd_xy(1,4); break;
  48. case 5: lcd_clear(); line_num=1; break;
  49. }
  50. }
  51. }
  52. }
  53.  
  54. uint8_t get_key(void){
  55. uint8_t data,key_value=0;
  56. for(uint8_t i=0;i<4;i++){
  57. mcp23S17_send(OLATB,1<<i);
  58. __delay_ms(10);
  59. data=mcp23S17_receive(GPIOB);
  60. data=data>>4;
  61. if(data==0x01) {key_value=key_ascii[i][0]; break;}
  62. else if(data==0x02) {key_value=key_ascii[i][1]; break;}
  63. else if(data==0x04) {key_value=key_ascii[i][2]; break;}
  64. else if(data==0x08) {key_value=key_ascii[i][3]; break;}
  65. else key_value=0;
  66. }
  67. return key_value;
  68. }

I wrote a driver for the MCP23S17 that use the SPI driver within the project file.

The mcp23S17.h C header file:

  1. /*
  2.  * File: mcp23S17.h
  3.  * Author: Admin
  4.  *
  5.  * Created on February 9, 2024, 3:54 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "spi.h"
  10.  
  11. /*MCP23S17 Registers Definition*/
  12. #define IODIRA 0x00
  13. #define IODIRB 0x01
  14. #define IPOLA 0x02
  15. #define IPOLB 0x03
  16. #define GPINTENA 0x04
  17. #define GPINTENB 0x05
  18. #define DEFVALA 0x06
  19. #define DEFVALB 0x07
  20. #define INTCONA 0x08
  21. #define INTCONB 0x09
  22. #define IOCONA 0x0A
  23. #define IOCONB 0x0B
  24. #define GPPUA 0x0C
  25. #define GPPUB 0x0D
  26. #define INTFA 0x0E
  27. #define INTFB 0x0F
  28. #define INTCAPA 0x10
  29. #define INTCAPB 0x11
  30. #define GPIOA 0x12
  31. #define GPIOB 0x13
  32. #define OLATA 0x14
  33. #define OLATB 0x15
  34.  
  35. /*MCP23S17 Address*/
  36. #define WRITE_ADDR 0x40
  37. #define READ_ADDR 0x41
  38.  
  39. /*MCP23S17 Read and Write Functions*/
  40. void mcp23S17_send(uint8_t address, uint8_t data);
  41. uint8_t mcp23S17_receive(uint8_t address);
  42.  
  43. /*MCP23S17 Character LCD Functions*/
  44. #define RS 0
  45. #define EN 2
  46. void lcd_command(uint8_t command);
  47. void lcd_data(uint8_t myChar);
  48. void lcd_xy(uint8_t x, uint8_t y);
  49. void lcd_text(uint8_t *txt);
  50. void lcd_clear(void);
  51. void lcd_init(void);
  52.  
  53.  

The mcp23S17.c C source file:

  1.  
  2. #include "mcp23S17.h"
  3.  
  4. /*MCP23S17 Input Output Functions*/
  5. void mcp23S17_send(uint8_t address, uint8_t data){
  6. nCS=0;
  7. spi_send(WRITE_ADDR);
  8. spi_send(address);
  9. spi_send(data);
  10. nCS=1;
  11. }
  12.  
  13. uint8_t mcp23S17_receive(uint8_t address){
  14. uint8_t data;
  15. nCS=0;
  16. spi_send(READ_ADDR);
  17. spi_send(address);
  18. data=spi_receive();
  19. nCS=1;
  20. return data;
  21. }
  22.  
  23. /*MCP23S17 Character LCD Functions*/
  24. void delay(uint16_t count){
  25. while(count>0) count--;
  26. }
  27. void lcd_command(uint8_t command){
  28. uint8_t data;
  29. data=command&0xF0;
  30. mcp23S17_send(OLATA, data|(1<<EN));
  31. delay(50);
  32. mcp23S17_send(OLATA, data);
  33. delay(50);
  34.  
  35. data=command<<4;
  36. mcp23S17_send(OLATA, data|(1<<EN));
  37. delay(50);
  38. mcp23S17_send(OLATA, data);
  39. delay(50);
  40. }
  41.  
  42. void lcd_data(uint8_t myChar){
  43. uint8_t data;
  44. data=myChar&0xF0;
  45. mcp23S17_send(OLATA, data|(1<<RS)|(1<<EN));
  46. delay(50);
  47. mcp23S17_send(OLATA, data);
  48. delay(50);
  49.  
  50. data=myChar<<4;
  51. mcp23S17_send(OLATA, data|(1<<RS)|(1<<EN));
  52. delay(50);
  53. mcp23S17_send(OLATA, data|(1<<RS));
  54. delay(50);
  55. }
  56.  
  57. void lcd_xy(uint8_t x, uint8_t y){
  58. /*20x4 Character LCD*/
  59. uint8_t tbe[]={0x80,0xC0,0x94,0xD4};
  60. lcd_command(tbe[y-1]+x-1);
  61. }
  62.  
  63. void lcd_text(uint8_t *txt){
  64. while(*txt) lcd_data(*txt++);
  65. }
  66.  
  67. void lcd_init(void){
  68. spi_init();
  69. nCS=1;
  70. /*LCD PORT*/
  71. mcp23S17_send(IODIRA,0x00);
  72. mcp23S17_send(OLATA,0x00);
  73. /*KeyPad PORT*/
  74. mcp23S17_send(IODIRB,0xF0);
  75.  
  76. lcd_command(0x33);
  77. lcd_command(0x32);
  78. lcd_command(0x28);
  79. lcd_command(0x0F);
  80. lcd_command(0x01);
  81. delay(500);
  82. lcd_command(0x06);
  83. }
  84.  
  85. void lcd_clear(void){
  86. lcd_command(0x01);
  87. delay(500);
  88. }
  89.  
  90.  

PIC16F887 SPI MCP23S17 Character LCD and KeyPad XC8 Example
Simulating Program

Click here to download its source file.



No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90