[其他ST产品] 硬件SPI+LCD增强屏幕刷新率

[复制链接]
3365|17
 楼主| wangtaohui 发表于 2023-6-28 20:08 | 显示全部楼层 |阅读模式
前言
        近日在研究如何提高LCD的刷新率,修改程序发现LCD屏幕用的是模拟通信,所以刷新特别慢,在设置硬件SPI,并使用通过HAL库HAL_SPI_Transmit()函数发送数据后刷新率并没有提升,为此疑惑了很久。

        对此研究了整整一两天,网上找到可能的答案并在此记录一下,网上说可能是“HAL库的HAL_SPI_Transmit()函数其实并没有这么快,建议改一下寄存器的方法试一试”,也许是HAL库并不完善,之后我尝试该方法,发现刷新率瞬间提高了。

        设备芯片用的是STM32F103C8T6,目的仅仅是通过SPI发送数据给LCD屏幕,而手册规定STM32的SPI时钟最快是18MHz。对于STM32F103的SPI1接口时钟,由72M的PCLK2分频得到,所以分配系数大于等于4(72M/4 = 18M)。对于STM32F103的SPI2/3接口时钟,由36M的PCLK1分频得到,所以分配系数等于2时候达到最高速率,可以更快,但可能不稳定。

        由于实验只是LCD刷屏或者实时显示大字体文字刷新速率提高,没有CS片选信号,只需要两条线SCK和SDA。代码基于HAL库开发,只是在SPI配置上直接用寄存器写,小知识在正点原子的库函数和HAL库中写寄存器操作都是通用的,因为无论是标准库还是库函数都是实现对寄存器操作的封装。


 楼主| wangtaohui 发表于 2023-6-28 20:08 | 显示全部楼层
SPI协议概括
  SPI协议简单介绍一下。SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线。
 楼主| wangtaohui 发表于 2023-6-28 20:11 | 显示全部楼层
SPI相关代码
        spi.h

        SDA连接PB15 SCK连接PB13(端口选择要根据自己的原理图修改,寻找支持SPI的引脚)
  1. #ifndef __SPI_H
  2. #define __SPI_H

  3. #include "sys.h"

  4. /* SPI接口定义 */
  5. #define SPI_INTERFACE                SPI2
  6. #define SPI_PRESCALER                SPI_BAUDRATEPRESCALER_2
  7. #define SPI_CLK_ENABLE()             do{ __HAL_RCC_SPI2_CLK_ENABLE(); }while(0)

  8. /* 引脚定义 */
  9. #define SPI_SCK_GPIO_PORT            GPIOB
  10. #define SPI_SCK_GPIO_PIN             GPIO_PIN_13
  11. #define SPI_SCK_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)


  12. #define SPI_SDA_GPIO_PORT            GPIOB
  13. #define SPI_SDA_GPIO_PIN             GPIO_PIN_15
  14. #define SPI_SDA_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)



  15. /* 操作函数 */
  16. void SPI2_Init(void);         
  17. void SPI2_SetSpeed(u8 SpeedSet);
  18. u8  SPI2_WriteData(u8 *TxData, u16 size);  

  19. #endif


 楼主| wangtaohui 发表于 2023-6-28 20:11 | 显示全部楼层
spi.c

该文件在SPI的GPIO设置初始化中运用了HAL库,其他设置用寄存器,特别是函数编写部分。

  1. #include "spi.h"


  2. /**
  3. * [url=home.php?mod=space&uid=247401]@brief[/url]       SPI接口初始化
  4. * @param       无
  5. * @retval      无
  6. */
  7. void SPI2_Init(void)
  8. {
  9.        
  10.     GPIO_InitTypeDef SPI2_Init_Struct;
  11.    
  12.     /* 使能时钟 */
  13.     SPI_CLK_ENABLE();
  14.     SPI_SCK_GPIO_CLK_ENABLE();
  15.     SPI_SDA_GPIO_CLK_ENABLE();
  16.    
  17.     /* 初始化SCK引脚 */
  18.     SPI2_Init_Struct.Pin    = SPI_SCK_GPIO_PIN;
  19.     SPI2_Init_Struct.Mode   = GPIO_MODE_AF_PP;
  20.     SPI2_Init_Struct.Pull   = GPIO_PULLUP;
  21.     SPI2_Init_Struct.Speed  = GPIO_SPEED_FREQ_HIGH;
  22.     HAL_GPIO_Init(SPI_SCK_GPIO_PORT, &SPI2_Init_Struct);
  23.    
  24.     /* 初始化SDA引脚 */
  25.     SPI2_Init_Struct.Pin    = SPI_SDA_GPIO_PIN;
  26.     SPI2_Init_Struct.Mode   = GPIO_MODE_AF_PP;
  27.     SPI2_Init_Struct.Pull   = GPIO_PULLUP;
  28.     SPI2_Init_Struct.Speed  = GPIO_SPEED_FREQ_HIGH;
  29.     HAL_GPIO_Init(SPI_SDA_GPIO_PORT, &SPI2_Init_Struct);
  30.           

  31.     RCC->APB1RSTR|=1<<14;        //复位SPI2
  32.         RCC->APB1RSTR&=~(1<<14);//停止复位SPI2
  33.                
  34.         SPI2->CR1|=0<<10;//全双工模式       
  35.         SPI2->CR1|=1<<9; //软件nss管理
  36.         SPI2->CR1|=1<<8;  

  37.         SPI2->CR1|=1<<2; //SPI主机
  38.         SPI2->CR1|=0<<11;//8bit数据格式       
  39.         SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
  40.         SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1  
  41.         SPI2->CR1|=7<<3; //Fsck=Fcpu/256
  42.         SPI2->CR1|=0<<7; //MSBfirst   
  43.         SPI2->CR1|=1<<6; //SPI设备使能
  44.     SPI2->I2SCFGR&=~(1<<11);//选择SPI模式
  45.         SPI2_ReadWriteByte(0xff);//启动传输(主要作用:维持MOSI为高)               

  46. }

  47. void SPI2_SetSpeed(u8 SpeedSet)
  48. {
  49.         SpeedSet&=0X07;                        //限制范围
  50.         SPI2->CR1&=0XFFC7;
  51.         SPI2->CR1|=SpeedSet<<3;        //设置SPI2速度  
  52.         SPI2->CR1|=1<<6;                 //SPI设备使能          
  53. }



  54. u8  SPI2_WriteData(u8 *TxData, u16 size)
  55. {
  56.        
  57.         u16 i=0;
  58.        
  59.         for(i=0;i<size;i++)
  60.         {
  61.                 SPI2->DR=TxData[i];
  62.                 while((SPI2->SR&1<<1)==0);                //等待发送区空
  63.         }
  64.        
  65.         return 1;
  66. }
 楼主| wangtaohui 发表于 2023-6-28 20:12 | 显示全部楼层
接下来就是LCD部分代码,其实只要更改两个函数即可,因为其他写文字刷屏的函数都是基于这两个函数写数据的。

  1. //写寄存器函数(命令)
  2. void LCD_WR_REG(u8 cmd)
  3. {   
  4.     LCD_RS=0;//RS=0的时候写命令   
  5.         SPI2_WriteData(&cmd,sizeof(cmd));
  6. }


  7. //写LCD数据
  8. void LCD_WR_DATA(u8 data)
  9. {          
  10.     LCD_RS=1;//RS=1的时候写数据      
  11.     SPI2_WriteData(&data,siezof(data));
  12. }
 楼主| wangtaohui 发表于 2023-6-28 20:12 | 显示全部楼层
这些函数都是基于正点原子的历程修改的,硬件SPI加上后LCD刷屏速率应该会加快很多,其实可以更快就是加上DMA取数据。
星辰大海不退缩 发表于 2023-6-29 12:47 | 显示全部楼层
楼主这些有相关的数据对比嘛,或是实际提升的对比还是感官上有明显对比?
Undshing 发表于 2023-7-1 23:40 | 显示全部楼层
刷新率可以提高多少啊?
Clyde011 发表于 2023-12-30 07:24 | 显示全部楼层

它们之间的间距应至少为0.5mm。
公羊子丹 发表于 2023-12-30 08:17 | 显示全部楼层

会占用PCB的空间,成本也会更高。
万图 发表于 2023-12-30 09:20 | 显示全部楼层

对于信号回路的峰值电压防护电路不应动作,通常在信号回路中,防护电路的动作电压是信号回路的峰值电压的1.3~1.6倍。
Uriah 发表于 2023-12-30 10:23 | 显示全部楼层

它们通常用于分线板或小模块。
帛灿灿 发表于 2023-12-30 12:19 | 显示全部楼层

开关管T交替工作于通/断两种状态,当开关管关断时,脉冲变压器处于“空载”状态,其中储存的磁能将被积累到下一个周期
Bblythe 发表于 2023-12-30 13:22 | 显示全部楼层

在印刷电路板制造中
周半梅 发表于 2023-12-30 15:18 | 显示全部楼层

选择测试方法和测试参数是检测过程中的重要步骤
Pulitzer 发表于 2023-12-30 16:21 | 显示全部楼层

它产生的噪声是对地噪声
童雨竹 发表于 2023-12-30 18:17 | 显示全部楼层

对于环氧树脂而言,一般把导热系数为0.5W/M·K的导热性能已经被定义为高导热
Wordsworth 发表于 2023-12-30 19:20 | 显示全部楼层

抑制各种高速信号产生的电磁波向外发射
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

529

帖子

0

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