[蓝牙芯片] 沁恒CH585开发板的2种TFT显示屏驱动方式及比较

[复制链接]
 楼主| jinglixixi 发表于 2025-7-5 19:11 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2025-7-7 08:39 编辑

#申请原创#

@21小跑堂

CH585是沁恒出品的一款集成了 BLE 无线通讯和高速 USB 及 NFC 的 RISC-V MCU 微控制器。并在片上集成了 2Mbps 低功耗蓝牙 BLE 通讯模块、USB 全速控制器及收发器、USB 高速控制器及收发器(480Mbps)、NFC 近场通信无线接口、段式 LCD 驱动模块、LED 点阵屏接口、2 个 SPI、4 个串口、14 路 ADC、触摸按键检测模块等丰富的外设资源。
其内核框架如图1所示,与以前产品不同的是减少了RTC的介绍。
51377fb0a619e5f06bb1878504d2fbfd
图1 内核框架

开发板的外观如图2和图3所示,可见它采用的是单面器件布局。
snap1.jpg
图2 开发板正面

snap.jpg
图3 开发板背面

为了便于显示,就为其配置了一个SPI接口的2.2’ TFT显示屏,其分辨率为240*320像素点。
在显示驱动方面,有2种驱动可供选择,一种是采用模拟的方式,另一种则是以硬件的方式。
对于模拟的方式,其好处就是易于实现,不受硬件在引脚方面的制约;而对于硬件方式,其好处就是处理速度快,可以充分发挥SPI接口的作用。此外,相对其他的开发板,似乎在CH585上也更易于实现,通过后面的对比会加深大家对这种想法的认识。

1. 模拟方式
要以模拟的方式来实现TFT显示屏的驱动,先要定义引脚的连接关系并对所用引脚加以配置。
这里为显示屏所建立的连接关系为:
CS  -----PA0
RST  ----PA1
DC   ----PA2
MOSI-----PA3
SCK  -----PA5
其引脚配置的函数为:
  1. void TFT_CONFIG()
  2. {
  3. GPIOA_ModeCfg( GPIO_Pin_4, GPIO_ModeOut_PP_5mA );
  4. GPIOA_ModeCfg( GPIO_Pin_0, GPIO_ModeOut_PP_5mA );
  5. GPIOA_ModeCfg( GPIO_Pin_1, GPIO_ModeOut_PP_5mA );
  6. GPIOA_ModeCfg( GPIO_Pin_2, GPIO_ModeOut_PP_5mA );
  7. GPIOA_ModeCfg( GPIO_Pin_3, GPIO_ModeOut_PP_5mA );
  8. GPIOA_ModeCfg( GPIO_Pin_5 , GPIO_ModeOut_PP_5mA );
  9. }

实现引脚输出高低电平的语句定义为:
#define LCD_CS_High()   GPIOA_SetBits(GPIO_Pin_0)
#define LCD_CS_Low()    GPIOA_ResetBits(GPIO_Pin_0)
#define LCD_REST_High() GPIOA_SetBits(GPIO_Pin_1)
#define LCD_REST_Low()  GPIOA_ResetBits(GPIO_Pin_1)
#define LCD_DC_High()   GPIOA_SetBits(GPIO_Pin_2)
#define LCD_DC_Low()    GPIOA_ResetBits(GPIO_Pin_2)
#define LCD_SDI_High()  GPIOA_SetBits(GPIO_Pin_3)
#define LCD_SDI_Low()   GPIOA_ResetBits(GPIO_Pin_3)
#define LCD_SCK_High()  GPIOA_SetBits(GPIO_Pin_5)
#define LCD_SCK_Low()   GPIOA_ResetBits(GPIO_Pin_5)

在模拟方式下,最为关键的是模拟SPI方式进行字节数据的方式,其函数内容为:
  1. void LCD_Writ_Bus(unsigned char com)
  2. {
  3. unsigned char uci;
  4. for(uci=0;uci<8;uci++)
  5. {
  6. if(com & 0x80)
  7. {
  8. LCD_SDI_High();
  9. }
  10. else
  11. {
  12. LCD_SDI_Low();
  13. }
  14. com = com << 1;
  15. DelayUs(1);
  16. LCD_SCK_Low();
  17. LCD_SCK_High();
  18. }
  19. }

其他一些支持显示驱动的辅助函数有:
单字节数据发送函数LCD_WR_DATA8(char da)
双字节数据发送函数LCD_WR_DATA(int da)
寄存器发送函数LCD_WR_REG(char da)
向寄存器发送双字节数据函数LCD_WR_REG_DATA(int reg,int da)

对显示屏的初始化函数为:
  1. void TFT_Init(void)
  2. {   
  3.     LCD_REST_Low();
  4.     DelayMs(20);
  5.     LCD_REST_High();
  6.     DelayMs(20);
  7.     LCD_CS_Low();  

  8.     LCD_WR_REG(0xCB);   
  9.     LCD_WR_DATA8(0x39);
  10.     LCD_WR_DATA8(0x2C);
  11.     LCD_WR_DATA8(0x00);
  12.     LCD_WR_DATA8(0x34);
  13.     LCD_WR_DATA8(0x02);

  14.     LCD_WR_REG(0xCF);  
  15.     LCD_WR_DATA8(0x00);
  16.     LCD_WR_DATA8(0XC1);
  17.     LCD_WR_DATA8(0X30);

  18.     LCD_WR_REG(0xE8);  
  19.     LCD_WR_DATA8(0x85);
  20.     LCD_WR_DATA8(0x00);
  21.     LCD_WR_DATA8(0x78);

  22.     LCD_WR_REG(0xEA);  
  23.     LCD_WR_DATA8(0x00);
  24.     LCD_WR_DATA8(0x00);

  25.     LCD_WR_REG(0xED);  
  26.     LCD_WR_DATA8(0x64);
  27.     LCD_WR_DATA8(0x03);
  28.     LCD_WR_DATA8(0X12);
  29.     LCD_WR_DATA8(0X81);

  30.     LCD_WR_REG(0xF7);  
  31.     LCD_WR_DATA8(0x20);
  32.   
  33.     LCD_WR_REG(0xC0);  
  34.     LCD_WR_DATA8(0x23);

  35.     LCD_WR_REG(0xC1);
  36.     LCD_WR_DATA8(0x10);

  37.     LCD_WR_REG(0xC5);
  38.     LCD_WR_DATA8(0x3e);
  39.     LCD_WR_DATA8(0x28);

  40.     LCD_WR_REG(0xC7);
  41.     LCD_WR_DATA8(0x86);

  42.     LCD_WR_REG(0x36);
  43.     LCD_WR_DATA8(0xE8);
  44.   
  45.     LCD_WR_REG(0x3A);   
  46.     LCD_WR_DATA8(0x55);

  47.     LCD_WR_REG(0xB1);   
  48.     LCD_WR_DATA8(0x00);  
  49.     LCD_WR_DATA8(0x18);

  50.     LCD_WR_REG(0xB6);
  51.     LCD_WR_DATA8(0x08);
  52.     LCD_WR_DATA8(0x82);
  53.     LCD_WR_DATA8(0x27);  

  54.     LCD_WR_REG(0xF2);
  55.     LCD_WR_DATA8(0x00);

  56.     LCD_WR_REG(0x26);
  57.     LCD_WR_DATA8(0x01);

  58.     LCD_WR_REG(0xE0);
  59.     LCD_WR_DATA8(0x0F);
  60.     LCD_WR_DATA8(0x31);
  61.     LCD_WR_DATA8(0x2B);
  62.     LCD_WR_DATA8(0x0C);
  63.     LCD_WR_DATA8(0x0E);
  64.     LCD_WR_DATA8(0x08);
  65.     LCD_WR_DATA8(0x4E);
  66.     LCD_WR_DATA8(0xF1);
  67.     LCD_WR_DATA8(0x37);
  68.     LCD_WR_DATA8(0x07);
  69.     LCD_WR_DATA8(0x10);
  70.     LCD_WR_DATA8(0x03);
  71.     LCD_WR_DATA8(0x0E);
  72.     LCD_WR_DATA8(0x09);
  73.     LCD_WR_DATA8(0x00);

  74.     LCD_WR_REG(0XE1);
  75.     LCD_WR_DATA8(0x00);
  76.     LCD_WR_DATA8(0x0E);
  77.     LCD_WR_DATA8(0x14);
  78.     LCD_WR_DATA8(0x03);
  79.     LCD_WR_DATA8(0x11);
  80.     LCD_WR_DATA8(0x07);
  81.     LCD_WR_DATA8(0x31);
  82.     LCD_WR_DATA8(0xC1);
  83.     LCD_WR_DATA8(0x48);
  84.     LCD_WR_DATA8(0x08);
  85.     LCD_WR_DATA8(0x0F);
  86.     LCD_WR_DATA8(0x0C);
  87.     LCD_WR_DATA8(0x31);
  88.     LCD_WR_DATA8(0x36);
  89.     LCD_WR_DATA8(0x0F);

  90.     LCD_WR_REG(0x11);
  91.     DelayMs(120);
  92.                
  93.     LCD_WR_REG(0x29);
  94.     LCD_WR_REG(0x2c);
  95. }

实现色彩清屏处理的函数为:
  1. void LCD_Clear(unsigned int Color)
  2. {
  3.     char VH,VL;
  4.     unsigned int i,j;
  5.     VH=Color>>8;
  6.     VL=Color;
  7.     Address_set(0,0,LCD_H-1,LCD_W-1);
  8.     for(i=0;i<LCD_H;i++)
  9.     {
  10.         for (j=0;j<LCD_W;j++)
  11.         {
  12.             LCD_WR_DATA8(VH);
  13.             LCD_WR_DATA8(VL);
  14.         }
  15.     }
  16. }

有了以上函数的支持,进行驱动测试的主程序为:
  1. int main()
  2. {
  3.     uint8_t i;
  4.     HSECFG_Capacitance(HSECap_18p);
  5.     SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
  6.     TFT_CONFIG();
  7.     DelayMs(1);
  8.     TFT_Init();
  9.     LCD_Clear(RED);
  10.     while(1);
  11. }

经编译和选择,其测试效果如图4所示,说明驱动有效。
bcec80ec9f19efe5247c7facaaa10568
图4 驱动测试

2. 硬件方式
有了前面模拟驱动的基础,下面再将其改为硬件方式的驱动。
SPI 是一种全双工串行接口,总线上连接有一个主机和若干从机,同一时刻,仅有一对主从在通讯。通常 SPI 接口由 4 个引脚组成:SPI 片选引脚 SCS、SPI 时钟引脚 SCK、SPI 串行数据引脚 MISO(主机输入/从机输出引脚)和 SPI 串行数据引脚 MOSI(主机输出/从机输入引脚)。
CH585 芯片提供 2 个 SPI 接口(SPI0 和 SPI1)其特性如下:
SPI0 支持主机模式(Master)和从机模式(Slave),SPI1 只支持主机模式(Master)
兼容串行外设接口(SPI)规范
支持模式 0 和模式 3 数据传输方式
8 位数据传输方式,数据位序可选:字节低位在前或者高位在前
时钟频率最高可达系统主频 Fsys 的一半
8 字节 FIFO
SPI0 从机模式支持首字节为命令模式或数据流模式
SPI0 支持 DMA,数据传输效率更高
SPI 支持模式 0 和模式 3 两种传输格式,通过设置 R8_SPIx_CTRL_MOD 的 RB_SPI_MST_SCK_MOD 进
行选择。总是在 SCK 上升沿采样串行数据输入,在下降沿输出串行数据。

SPI 的工作时序如图5所示:
sx.jpg
5 工作时序


替代模拟方式所选取的是SPI0,其所用的引脚如图6所示。
cd9d7c61307b6d2d2e03e20e8b84e1d8
图6 所用接口

因此TFT显示屏新的引脚连接关系为:
CS  -----PA12
SCK -----PA13
MOSI-----PA14
RST  ----PA1
DC   ----PA2

也就是说在硬件驱动方式下,只需所用2个辅助引脚进行配合,其他则是通过SPI接口来完成。
辅助引脚的配置函数为:
  1. void TFT_CONFIG()
  2. {
  3.     GPIOA_ModeCfg( GPIO_Pin_4, GPIO_ModeOut_PP_5mA );
  4.     GPIOA_ModeCfg( GPIO_Pin_1, GPIO_ModeOut_PP_5mA );
  5.     GPIOA_ModeCfg( GPIO_Pin_2, GPIO_ModeOut_PP_5mA );
  6. }

配置SPI0的语句为:
GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
SPI0_MasterDefInit();

在此基础上,新的SPI模式下方式字节数据的函数变为:
  1. void LCD_Writ_Bus(unsigned char com)
  2. {
  3.     GPIOA_ResetBits(GPIO_Pin_12);
  4.     SPI0_MasterSendByte(com);
  5. }

这样就完成了模拟方式向硬件方式的转换,看上去是不是非常简单!
这里引用到2个函数,其内容为:
  1. void SPI0_MasterDefInit(void)
  2. {
  3. R8_SPI0_CLOCK_DIV = 4; // 主频时钟4分频
  4. R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR;
  5. R8_SPI0_CTRL_MOD = RB_SPI_MOSI_OE | RB_SPI_SCK_OE;
  6. R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF;
  7. R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; // 不启动DMA方式
  8. }

  9. void SPI0_MasterSendByte(uint8_t d)
  10. {
  11.     R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
  12.     R16_SPI0_TOTAL_CNT = 1;         // 设置要发送的数据长度
  13.     R8_SPI0_FIFO = d;
  14.     while(!(R8_SPI0_INT_FLAG & RB_SPI_FREE));
  15. }

在确保硬件驱动有效的情况下,通过添加字符及字符串显示函数,实现显示测试的主程序为:
  1. int main()
  2. {
  3.     uint8_t i;
  4.     HSECFG_Capacitance(HSECap_18p);
  5.     SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
  6.     TFT_CONFIG();
  7.     GPIOA_SetBits(GPIO_Pin_12);
  8.     GPIOA_ModeCfg(GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
  9.     SPI0_MasterDefInit();
  10.     DelayMs(1);
  11.     TFT_Init();
  12.     LCD_Clear(RED);
  13.     BACK_COLOR=RED;
  14.     POINT_COLOR=WHITE;
  15.     LCD_ShowChar(10,10,'V',0);
  16.     LCD_ShowString(10,30,"CH585");
  17.     while(1);
  18. }

经编译和下载,其测试效果如图7所示,说明硬件驱动是成功的,且明显地加快了显示的速度。
3f423969ad11b70f5c521cd5846e76b0
图7 测试效果

通过对模拟和硬件2种驱动方式的对比,可以发现模拟方式向硬件方式的转换是十分方便的,此外也发现CH585在SPI的使用方面也有了新的变化,且更加易于使用啦!










您需要登录后才可以回帖 登录 | 注册

本版积分规则

517

主题

2932

帖子

39

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