Sunday, January 21, 2024

PIC16F887 MCP23017 I2C LCD Example using XC8

In previous post, I showed a simple keypad scanning and 7-Segment display example using the MCP23017 16-bit I/O expander chip. However we can use a single 8-bit port of this chip to control a HD44780 based character LCD in 4-bit data transfer mode.

PIC16F887 MCP23017 I2C LCD Example using XC8
Simulating Program in Proteus

In this example, I use GPIOA of the MCP23017 to control a 16x2 character LCD via its 4-bit data bus. However LCD command and data still in 8-bit. The 8-bit data is divided into two nibbles. The higher nibble is transferred and latched into the LCD first. Then the lower nibble is transferred and latched into the LCD to complete the command or data transmission.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 21, 2024, 8:18 PM
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <xc.h>
  10. #include "config.h"
  11. #include "mcp23017.h"
  12.  
  13. #define _XTAL_FREQ 8000000UL
  14.  
  15. const char RS=0,RW=1,EN=2;
  16. __bit BLK_ON=0;
  17.  
  18. void lcd_command(uint8_t temp){
  19. uint8_t command,led;
  20. command=temp&0xF0;
  21. if(BLK_ON==1) led=0x08;
  22. else led=0;
  23. mcp23017_write(OLATA,command|led|(1<<EN));
  24. __delay_us(10);
  25. mcp23017_write(OLATA,command|led);
  26. __delay_us(25);
  27.  
  28. command=temp<<4;
  29. mcp23017_write(OLATA,command|led|(1<<EN));
  30. __delay_us(10);
  31. mcp23017_write(OLATA,command|led);
  32. __delay_us(25);
  33. }
  34.  
  35. void lcd_data(uint8_t temp){
  36. uint8_t data,led;
  37. data=temp&0xF0;
  38. if(BLK_ON==1) led=0x08;
  39. else led=0;
  40. mcp23017_write(OLATA,data|led|(1<<EN)|(1<<RS));
  41. __delay_us(10);
  42. mcp23017_write(OLATA,data|led|(1<<RS));
  43. __delay_us(25);
  44.  
  45. data=temp<<4;
  46. mcp23017_write(OLATA,data|led|(1<<EN)|(1<<RS));
  47. __delay_us(10);
  48. mcp23017_write(OLATA,data|led|(1<<RS));
  49. __delay_us(25);
  50. }
  51.  
  52. void lcd_xy(uint8_t x, uint8_t y){
  53. uint8_t cursor[]={0x80,0xC0};
  54. lcd_command(cursor[y-1]+x-1);
  55. }
  56.  
  57. void lcd_text(uint8_t *text){
  58. while(*text) lcd_data(*text++);
  59. }
  60.  
  61. void lcd_clear(void){
  62. lcd_command(0x01);
  63. __delay_ms(5);
  64. }
  65.  
  66. void lcd_init(void){
  67. BLK_ON=1;
  68. mcp23017_init();
  69. lcd_command(0x33);
  70. __delay_us(10);
  71. lcd_command(0x32);
  72. __delay_us(10);
  73. lcd_command(0x28);
  74. __delay_us(10);
  75. lcd_command(0x0F);
  76. __delay_us(10);
  77. lcd_command(0x01);
  78. __delay_ms(5);
  79. lcd_command(0x06);
  80. __delay_us(10);
  81. }
  82.  
  83. void main(void) {
  84. __delay_ms(100);
  85. OSCCONbits.IRCF=7;
  86. lcd_init();
  87. __delay_us(100);
  88. lcd_text(" PIC16F887 I2C");
  89. lcd_xy(1,2);
  90. lcd_text("And MCP23017 LCD");
  91. __delay_ms(2500);
  92. lcd_clear();
  93. lcd_command(0x0C);
  94. lcd_text("Counter Variable");
  95. long counter=0;
  96. uint8_t msg[10];
  97. while(1){
  98. sprintf(msg,"%ld",counter);
  99. lcd_xy(1,2); lcd_text(msg);
  100. counter++;
  101. __delay_us(250);
  102. }
  103. return;
  104. }
  105.  

The I2C master microprocessor send a counter variable to the LCD for every 250 Milli seconds. Simulating program in Proteus has interrupt due to firmware issue. So we can try on a real circuit.

PIC16F887 MCP23017 I2C LCD Example using XC8
Simulating Program in Proteus

The micro-controller use its internal 8MHz RC oscillator. So I left the CLKOUT and CLKIN pins unconnected. These two pin could be used for general purpose I/O.

Click here to download this example.

No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)