[产品应用] 基于CW32L052的I2C型LCD1602屏显示驱动

[复制链接]
 楼主| jinglixixi 发表于 2023-9-1 10:46 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2023-9-1 10:49 编辑

#申请原创#  @21小跑堂
CW32L052R8T6 StartKit 评估板是一款基于Cortex-M0+内核的开发板,配有64KB FLASH和8KB RAM,其主频可达48MHz。此外,它还配有FLASH 芯片CW25Q64A、EEPROM芯片CW24C02AD、蜂鸣器电路及红外收发电路等外设资源。
尽管它在显示方面它配有 4x16段码 LCD 显示屏,但在使用时还是存在诸多的不便,为此便为其配置了一款I2C型的LCD1602显示模块,这样就可大大地增强信息输出的表现了。
1.jpg
1  显示效果

2.jpg
2  显示模块

该显示模块是以PCF8574为核心处理芯片,由它将I2C信号转化为并行信号来驱动LCD1602的显示,其电路连接如图3和图4所示。

3.jpg

图3  PCF8574

4.jpg
图4  LCD1602

PCF8574 采用CMOS电路设计。它通过两条双向总线(I 2 C)可使大多数 MCU 实现远程 I/O 口扩展。该器件包含一个 8 位准双向口和一个 I 2 C 总线接口。PCF8574 电流消耗很低,且口输出锁存具有大电流驱动能力,可直接驱动 LED。
由图4可知,LCD1602实际是采用4位的驱动方式,而非常规的8位驱动方式。
显示模块与开发板的连接关系为:
SDA ---PA15
CLK ---PC10

对所用引脚的配置函数为:
  1. void LCD_Configuration(void)
  2. {  
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     GPIO_InitStructure.Pins = LED1_GPIO_PIN;
  5.     GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  6.     GPIO_InitStructure.IT = GPIO_IT_NONE;
  7.     GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
  8.     GPIO_InitStructure.Pins = LED2_GPIO_PIN;
  9.     GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  10.     GPIO_InitStructure.IT = GPIO_IT_NONE;
  11.     GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
  12. }

在GPIO口模拟I2C的情况下,其输出高低电平的语句定义为:
defineSDA_high    PA15_SETHIGH()
defineSDA_low    PA15_SETLOW()
defineSCL_high    PC10_SETHIGH()
define SCL_low    PC10_SETLOW()

模拟I2C开始与结束的函数为:
  1. void start()
  2. {
  3.         SDA_high;
  4.         delay();
  5.         SCL_high;
  6.         delay();
  7.         SDA_low;
  8.         delay();
  9. }

  10. void stop()
  11. {
  12.         SDA_low;
  13.         delay();
  14.         SCL_high;
  15.         delay();
  16.         SDA_high;
  17.         delay();
  18. }

所需的延时函数为:
  1. void delay()
  2. {
  3.     uint32_t i;
  4.     for(i=0;i<200;i++);
  5. }

模拟I2C方式字节数据的函数为:
  1. void write_byte(uchar date)
  2. {
  3.         uchar i,temp,m;
  4.         temp=date;
  5.         for(i=0;i<8;i++)
  6.         {
  7.            SCL_low;
  8.            delay();
  9.            m=temp;
  10.           m=m&0x80;
  11.           if(m==0x80)
  12.           {
  13.                 SDA_high;
  14.           }
  15.           else  SDA_low;
  16.           temp=temp<<1;
  17.           delay();
  18.           SCL_high;
  19.           delay();
  20.         }
  21.         SCL_low;
  22.         delay();
  23.         SDA_high;
  24.         delay();
  25. }

进行应答处理判别的函数为:
  1. void respons()
  2. {
  3.         uchar i;
  4.         SCL_high;
  5.         delay();
  6.         look();
  7.         SCL_low;
  8.         delay();
  9. }

  10. void look()
  11. {
  12.     uchar i,sda;
  13.     GPIO_InitTypeDef GPIO_InitStructure;
  14.     GPIO_InitStructure.Pins = GPIO_PIN_15;
  15.     GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
  16.     GPIO_InitStructure.IT = GPIO_IT_NONE;
  17.     GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
  18.     i=0;
  19.     sda=PA15_GETVALUE();
  20.     while((sda==1)&&(i<250)) i++;
  21.     GPIO_InitStructure.Pins = GPIO_PIN_15;
  22.     GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;;
  23.     GPIO_InitStructure.IT = GPIO_IT_NONE;
  24.     GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
  25. }

向指定地址发送数据的函数为:
  1. void write_add(uchar 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(uchar com)
  2. {
  3.         uchar com1,com2;
  4.         com1=com|0x0f;
  5.         write_add(com1 &0xfc);
  6.         delay1(2);
  7.         write_add(com1 &0xf8);
  8.         com2=com<<4;
  9.         com2=com2|0x0f;
  10.         write_add(com2&0xfc);
  11.         delay1(2);
  12.         write_add(com2&0xf8);
  13. }

发送数据的函数为:
  1. void write_date(uchar date)
  2. {
  3.         uchar date1,date2;
  4.         date1 =date|0x0f;
  5.         write_add(date1 &0xfd);
  6.         delay1(2);
  7.         write_add(date1 &0xf9);
  8.         date2=date<<4;
  9.         date2=date2|0x0f;
  10.         write_add(date2&0xfd);
  11.         delay1(2);
  12.         write_add(date2&0xf9);
  13. }

对LCD1602进行初始化的函数为:
  1. void init_lcd()
  2. {
  3.         SDA_high;
  4.         delay();
  5.         SCL_high;
  6.         delay();
  7.         write_add(0x08);
  8.         write_com(0x0f);
  9.         write_com(0x28);
  10.         write_add(0x0c);
  11.         write_add(0x08);
  12.         write_com(0x28);
  13.         write_com(0x01);
  14.         write_com(0x0c);
  15.         write_com(0x06);
  16. }

用于显示处理的函数为:
  1. void display()
  2. {
  3.         write_com(0x80);
  4.         for(i=0;i<16;i++)
  5.         {
  6.                 write_date(t0[i]);
  7.                 delay1(10);
  8.         }
  9.         write_com(0x80+0x40);
  10.         for(i=0;i<14;i++)
  11.         {
  12.                 write_date(t1[i]);
  13.                 delay1(10);
  14.         }
  15.         write_com(0x80+0x40+14);
  16.         if(M_8574==0)
  17.         {
  18.                 write_date('4');
  19.                 write_date('E');
  20.         }
  21.         else if(M_8574==1)
  22.         {
  23.                 write_date('7');
  24.                 write_date('E');
  25.         }
  26.         else if(M_8574==2)
  27.         {
  28.                 write_date('2');
  29.                 write_date('7');
  30.         }
  31.         else if(M_8574==3)
  32.         {
  33.                 write_date('3');
  34.                 write_date('F');
  35.         }
  36. }

进行显示测试的主程序为:
  1. int32_t main(void)
  2. {
  3.     RCC_Configuration();
  4.         InitTick( 24000000 );
  5.         LCD_Configuration();
  6.         delay1(10);
  7.         init_lcd();
  8.         while(1)
  9.         {
  10.                 display();
  11.                 delay1(100);
  12.                 init_lcd();
  13.                 M_8574++;
  14.                 if(M_8574>=4)
  15.                 {
  16.                         M_8574=0;
  17.                 }
  18.         }
  19. }

经程序的下载测试,其显示效果如图5所示,说明功能正常,这样就有效地提高了显示输出的表现力。
此外,由于是采用GPIO口模拟I2C的处理方式,故它也十分有利于移植到其它的开发板来实现驱动显示。
5.jpg
5 显示效果

评论

hi 大佬 ,很高兴看到您的原创帖子,但咱们论坛申请袁垂昂的文章字数需要达到800哦,目前还差点,你补充完整后可以再次@21小跑堂  发表于 2023-9-6 15:49
 楼主| jinglixixi 发表于 2023-9-7 09:15 | 显示全部楼层
好的知道了,谢谢!
小小蚂蚁举千斤 发表于 2023-9-10 20:17 | 显示全部楼层
这个应用确实挺好的,IIC的LCD显示
szt1993 发表于 2023-9-10 20:50 | 显示全部楼层
I2C通讯进行中转确实很简单
 楼主| jinglixixi 发表于 2023-9-11 00:04 | 显示全部楼层
感谢大家的支持!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

518

主题

2934

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部