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.
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.
/* * File: main.c * Author: Admin * * Created on January 21, 2024, 8:18 PM */ #include <stdio.h> #include <xc.h> #include "config.h" #include "mcp23017.h" #define _XTAL_FREQ 8000000UL const char RS=0,RW=1,EN=2; __bit BLK_ON=0; void lcd_command(uint8_t temp){ uint8_t command,led; command=temp&0xF0; if(BLK_ON==1) led=0x08; else led=0; mcp23017_write(OLATA,command|led|(1<<EN)); __delay_us(10); mcp23017_write(OLATA,command|led); __delay_us(25); command=temp<<4; mcp23017_write(OLATA,command|led|(1<<EN)); __delay_us(10); mcp23017_write(OLATA,command|led); __delay_us(25); } void lcd_data(uint8_t temp){ uint8_t data,led; data=temp&0xF0; if(BLK_ON==1) led=0x08; else led=0; mcp23017_write(OLATA,data|led|(1<<EN)|(1<<RS)); __delay_us(10); mcp23017_write(OLATA,data|led|(1<<RS)); __delay_us(25); data=temp<<4; mcp23017_write(OLATA,data|led|(1<<EN)|(1<<RS)); __delay_us(10); mcp23017_write(OLATA,data|led|(1<<RS)); __delay_us(25); } void lcd_xy(uint8_t x, uint8_t y){ uint8_t cursor[]={0x80,0xC0}; lcd_command(cursor[y-1]+x-1); } void lcd_text(uint8_t *text){ while(*text) lcd_data(*text++); } void lcd_clear(void){ lcd_command(0x01); __delay_ms(5); } void lcd_init(void){ BLK_ON=1; mcp23017_init(); lcd_command(0x33); __delay_us(10); lcd_command(0x32); __delay_us(10); lcd_command(0x28); __delay_us(10); lcd_command(0x0F); __delay_us(10); lcd_command(0x01); __delay_ms(5); lcd_command(0x06); __delay_us(10); } void main(void) { __delay_ms(100); OSCCONbits.IRCF=7; lcd_init(); __delay_us(100); lcd_text(" PIC16F887 I2C"); lcd_xy(1,2); lcd_text("And MCP23017 LCD"); __delay_ms(2500); lcd_clear(); lcd_command(0x0C); lcd_text("Counter Variable"); long counter=0; uint8_t msg[10]; while(1){ sprintf(msg,"%ld",counter); lcd_xy(1,2); lcd_text(msg); counter++; __delay_us(250); } return; }
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.
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