由于瑞萨RL78/G15开发板上没有配置相应的显示器件,故特意为它配置了一款I2C接口的LCD1602显示模块,从而使其可以大大地增强信息输出的表现力。
该显示模块是以PCF8574为核心处理芯片,是由它把I2C信号转化为并行信号来驱动LCD1602显示的。
PCF8574 采用CMOS电路设计。它通过两条双向总线(I 2 C)以使大多数 MCU 实现远程I/O 口扩展。该器件包含一个 8 位准双向口和一个 I 2C 总线接口。PCF8574 电流消耗很低,且口输出锁存具有大电流驱动能力,可直接驱动 LED。
在该显示模块中,LCD1602实际上是采用4位数据的方式来驱动,而非常规的8位数据驱动方式。
改显示模块与开发板的连接关系为:
LCD1602(I2C)
SCL---D6--15
SDA---D7--16
在GPIO口模拟I2C的情况下,其输出高低电平的语句定义为:
  1. #define SCL_high  digitalWrite(15, HIGH)
  2. #define SCL_low   digitalWrite(15, LOW)
  3. #define SDA_high  digitalWrite(16, HIGH)
  4. #define SDA_low   digitalWrite(16, LOW)
模拟I2C开始与结束的函数为:
  1. void start()
  2. {
  3.         SDA_high;
  4.         SCL_high;
  5.         SDA_low;
  6. }

  7. void stop()
  8. {
  9.         SDA_low;
  10.         SCL_high;
  11.         SDA_high;
  12. }
模拟I2C方式字节数据的函数为:
  1. void write_byte(uint8_t date)
  2. {
  3.         uint8_t i,temp,m;
  4.         temp=date;
  5.         for(i=0;i<8;i++)
  6.         {
  7.           SCL_low;
  8.           m=temp;
  9.           m=m&0x80;
  10.           if(m==0x80)
  11.           {
  12.                 SDA_high;
  13.           }
  14.           else  SDA_low;
  15.           temp=temp<<1;
  16.           SCL_high;
  17.         }
  18.         SCL_low;
  19.         SDA_high;
  20. }
进行应答处理判别的函数为:
  1. void look()
  2. {
  3.       uint8_t i,sda;
  4.       pinMode(16, INPUT);
  5.       i=0;
  6.       sda=digitalRead(16);
  7.       while((sda==1)&&(i<250)) i++;
  8.       pinMode(16, OUTPUT);
  9. }

  10. void respons()
  11. {
  12.      uint8_t i;
  13.      SCL_high;
  14.      look();
  15.      SCL_low;
  16. }
向指定地址发送数据的函数为:
  1. void write_add(uint8_t date1)
  2. {
  3.      start();
  4.      if(M_8574==0)
  5.         write_byte(0x4e);
  6.      else if(M_8574==1)
  7.         write_byte(0x7e);
  8.      else if(M_8574==2)
  9.         write_byte(0x27);
  10.      else if(M_8574==3)
  11.         write_byte(0x3f);
  12.      respons();
  13.      write_byte(date1);
  14.      respons();
  15.      stop();
  16. }
发送指令的函数为:
  1. void write_com(uint8_t com)
  2. {
  3.         uint8_t com1,com2;
  4.         com1=com|0x0f;
  5.         write_add(com1 &0xfc);
  6.         write_add(com1 &0xf8);
  7.         com2=com<<4;
  8.         com2=com2|0x0f;
  9.         write_add(com2&0xfc);
  10.         write_add(com2&0xf8);
  11. }
发送数据的函数为:
  1. void write_date(uint8_t date)
  2. {
  3.         uint8_t date1,date2;
  4.         date1 =date|0x0f;
  5.         write_add(date1 &0xfd);
  6.         write_add(date1 &0xf9);
  7.         date2=date<<4;
  8.         date2=date2|0x0f;
  9.         write_add(date2&0xfd);
  10.         write_add(date2&0xf9);
  11. }

对LCD1602进行初始化的函数为:
  1. void init_lcd()
  2. {
  3.         SDA_high;
  4.         SCL_high;
  5.         write_add(0x08);
  6.         write_com(0x0f);
  7.         write_com(0x28);
  8.         write_add(0x0c);
  9.         write_add(0x08);
  10.         write_com(0x28);
  11.         write_com(0x01);
  12.         write_com(0x0c);
  13.         write_com(0x06);
  14. }
用于显示处理的函数为:
  1. void display()
  2. {
  3.         uint8_t i;
  4.         write_com(0x80);
  5.         for(i=0;i<16;i++)
  6.         {
  7.                 write_date(t0[i]);
  8.         }
  9.         write_com(0x80+0x40);
  10.         for(i=0;i<16;i++)
  11.         {
  12.                 write_date(t1[i]);
  13.           }

  14.         if(M_8574==0)
  15.         {
  16.                 write_date('4');
  17.                 write_date('E');
  18.         }
  19.         else if(M_8574==1)
  20.         {
  21.                 write_date('7');
  22.                 write_date('E');
  23.         }
  24.         else if(M_8574==2)
  25.         {
  26.                 write_date('2');
  27.                 write_date('7');
  28.         }
  29.         else if(M_8574==3)
  30.         {
  31.                 write_date('3');
  32.                 write_date('F');
  33.         }
  34. }
进行显示测试的主程序为:
  1. void setup() {
  2.    pinMode(15, OUTPUT);
  3.    pinMode(16, OUTPUT);
  4.    init_lcd();
  5. }

  6. void loop() {
  7.      display();
  8.      delay(50);
  9.      init_lcd();
  10.      M_8574++;
  11.      if(M_8574>=4)
  12.      {
  13.           M_8574=0;
  14.      }
  15. }
经程序的下载测试,其显示效果如下图所示,说明功能正常,这样就有效地提高了显示输出的表现力。
此外,由于是采用GPIO口模拟I2C的处理方式,故它也十分有利于移植到其它的开发板来实现驱动显示。
image.png
显示效果图