BUG分享|SPI接口屏幕无法点亮(SPI无法判断发送完成)
引言
在驱动ST7735、ST7789之类的屏幕时,明明SPI能够发送数据,可是就是点不亮,下面分享一个遇到的这种问题。
问题起因是想以最快速度驱动屏幕,由于这块屏幕只需要SPI-MOSI,所以SPI配置直接配置单线发送模式。
单片机:STM32F411CEU6
库函数:标准库
补充:SPI使用SPI1 单线发送模式
现象
SPI可以正常发送数据,屏幕却始终不亮。
屏幕PWR(背光)始终开启,屏幕CS(spi片选)始终使能。
检查屏幕的RST(复位),波形正常。
上逻辑分析仪。
由于我的逻辑分析仪最大采样为100Mhz,这里将SPI进行256分频,频率:(50/256)Mhz
图中通道2为屏幕的DC引脚,DC拉低代表数据为命令,DC拉高表示数据为参数。这段应用等效代码如下:
void vST7789V3_WR_CMD(u8 cmd){
/* 拉低DC脚 */
LCD_DC_ON();
/* SPI1发送数据 */
SPI_I2S_SendData(SPI1, Byte);
/* 等待发送区空 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
/* 拉高DC脚 */
LCD_DC_OFF();
}
分析
波形不是我们想要的,SPI还没发送完1字节,DC引脚就拉高了,显然循环等待的东西并不能判断SPI是否完成。
查询标准库电子书
其中关于标志的解读,SPI_I2S_FLAG_TXE
标志是发送区空标志,SPI_I2S_FLAG_RXNE
标志是接收区不空标志。
那问题找到了,代码中仅仅判断了发送区为空就把DC拉高了,而此时SPI并没有发送完。即,SPI_I2S_FLAG_TXE
标志不能判断SPI发送完成。
如何判断SPI发送完成呢?列出的标志里没有这一项。参考标准库中的例程,写法如下:
文件:spi_flash.c
/**
* @brief Sends a Half Word through the SPI interface and return the Half Word
* received from the SPI bus.
* @param HalfWord: Half Word to send.
* @retval The value of the received Half Word.
*/
uint16_t sFLASH_SendHalfWord(uint16_t HalfWord)
{
/*!< Loop while DR register in not empty */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
/*!< Send Half Word through the sFLASH peripheral */
SPI_I2S_SendData(sFLASH_SPI, HalfWord);
/*!< Wait to receive a Half Word */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/*!< Return the Half Word read from the SPI bus */
return SPI_I2S_ReceiveData(sFLASH_SPI);
}
这里是先等待发送区为空,然后发送数据,最后等待接收区为非空,接收区为空即表示发送也同时完成了,可以将该位作为发送完成标志位。
由于使用了接收标志,所以spi必须设置为全双工模式,在单线发送模式下,SPI_I2S_FLAG_RXNE
标志一直不会置位,就无法判断发送完成。
解决方案
u8 SPI1_ReadWriteByte(u8 Byte){ //通过SPI2口发送1个数据,同时接收1个数据 如果失败返回0
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空
SPI_I2S_SendData(SPI1, Byte); //通过外设 SPIx 发送一个byte 数据
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完
return SPI_I2S_ReceiveData(SPI1); //返回通过 SPIx 最近接收的数据
}
SPI配置全双工模式,如果不想使用MISO端口,在GPIO配置时,不配MISO即可,不能使用单线发送模式。
对于数据量小,使用频繁的SPI发送,使用这种直接发送的方式。对于数据量大,使用相对不频繁,速度要求较快的地方,使用DMA方式发送。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现