【STM32H7教程】如何使用QUADSPI+DMA驱动ST77916屏幕
【STM32H7教程】如何使用QSPI驱动ST77916屏幕
前言
最近要驱动一个qspi的tft手表屏幕,之前在cubemx上能完美驱动nand flash的qspi配置步骤却突然不好使了,感觉这里面有很多问题,特此记录一下。
问题
1.flash_size要手动配置
最近使用qspi被一个问题卡了几天。就是不设置qspi的flash_size的话,qspi发送地址就会出错,比如当flash_size为1时 地址只能为0(不管位宽多少)。可能是发送时要检查地址超出了flash_size没有,所以你的地址有多少位就要设置flash_size为多少,比如24位地址就设置24。设置如下图所示。
2.逻辑分析仪一定要接mcu地
在观察qspi波形时发现一次传输中间cs引脚短暂拉高了(非常短比一个bit周期短很多),以为是哪里配置有问题,刚开始觉得是sample shifting的配置有问题,结果不是。最后把逻辑分析仪地接上mcu了才解决,看来就算逻辑分析仪和mcu共享usb接口的地也要额外接上地,不然还是有毛刺。
3.无法发出的命令
如果一个命令无需发数据(len==0),就必须配置cmd_cfg.DataMode = QSPI_DATA_NONE来关闭数据通路,否则整个命令都无法发出。
4.超时问题
发送数据很长的时候,就卡在while (HAL_QSPI_GetState(&hqspi) != HAL_QSPI_STATE_READY);这里是判断上一个qspi数据发送完毕没有的,感觉可能是上一个发送的数据太长超时了,还有很多数据没发完。我代码是这样写的HAL_QSPI_Transmit(&hqspi, (void*)pbuf, 100);于是就改成了(HAL_QSPI_Transmit(&hqspi, (void*)pbuf, HAL_MAX_DELAY);)这样延时很长,卡住的问题马上就好了。
5.四线模式不能用于配置
刚开始我固定了在一个程序里面要么单线要么四线,结果四线双线始终启动不了屏幕,只有单线可以启动。我看到屏幕官方代码的配置代码是单线的,于是只把屏幕刷新做成四线的,LCD_init里面用的单线spi,结果马上就可以了。刚开始以为是线的问题,看来是屏幕的寄存器只能用单线。当然四线qspi的指令和地址还是单线传输的。下面是配置不同线数的代码,在发送cmd前设置。只要配置指令和数据线数就可以了,要使用不同的线数要用不同的指令(02h,A2h,32h)
if( QSbit==1)
cmd_cfg.Instruction = 0x02;// 单线写指令字节
else if(QSbit==2)
cmd_cfg.Instruction = 0xA2;// 双线写指令字节
else//QSbit==4
cmd_cfg.Instruction = 0x32;// 四线写指令字节
if(QSbit==1)
cmd_cfg.DataMode = QSPI_DATA_1_LINE;//如果有Address要发 datamode千万不能为QSPI_DATA_NONE
else if(QSbit==2)
cmd_cfg.DataMode = QSPI_DATA_2_LINES;//如果有Address要发 datamode千万不能为QSPI_DATA_NONE
else//QSbit==4
cmd_cfg.DataMode = QSPI_DATA_4_LINES;//如果有Address要发 datamode千万不能为QSPI_DATA_NONE
问题6.DMA发送不能超过65536字节
在使用HAL_QSPI_Transmit_DMA函数发送数据的时候和HAL_QSPI_Transmit不同,HAL_QSPI_Transmit几乎不限制发送数据量,而HAL_QSPI_Transmit_DMA必须限制在65536字节内。这个问题卡了一天才发现是输入的len大于65536了。问题代码修改后如下所示。
blockRowCnt=90;//90是高度360的因数,保证最后一次发送也完整。同时90*360*2最接近65536的数了
lcd_tx_len = blockRowCnt*360*2;
qspi_lcd_wr_cmd(0x2C, lcd_tx_buf, lcd_tx_len);
问题7
如果用cubemx配置的其他外设占用了qspi的引脚比如cs引脚可能导致 qspi配置复位,使得flash_size复位为一并且DMA配置消失,进而导致出现硬件错误。进入如下错误处理函数。
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
问题8.如果DMA从QSPI发不出去
那可能就是qspi global interrupt没勾选,如下图勾选就可以了
代码
发送和接收代码
要启动一个qspi传输首先要新建一个命令类型cmd_cfg,设置好参数后就用HAL_QSPI_Command发送命令出去,如果是写数据后续还要用HAL_QSPI_Transmit发送数据出去,如果是读数据还要用HAL_QSPI_Receive接收。无论发送还是接收数据长度都是cmd_cfg.NbData定义的。
void qspi_lcd_wr_cmd(uint8_t cmd, uint8_t *pbuf, uint32_t len)
{
QSPI_CommandTypeDef cmd_cfg = {0};
while (HAL_QSPI_GetState(&hqspi) != HAL_QSPI_STATE_READY);//确定上个传输完成
cmd_cfg.Instruction = 0x02;// 指令字节
cmd_cfg.InstructionMode = QSPI_INSTRUCTION_1_LINE;//指令用了几根线
cmd_cfg.Address = cmd<<8; // 0x00前缀 = 写寄存器 address不为0可能卡住
cmd_cfg.AddressSize = QSPI_ADDRESS_24_BITS;//地址位数
cmd_cfg.AddressMode = QSPI_ADDRESS_1_LINE;//地址用了几根线
cmd_cfg.DummyCycles = 0;//空闲位数
cmd_cfg.NbData = len;//后续数据长度
if(len!=0)
cmd_cfg.DataMode = QSPI_DATA_1_LINE;//如果有Address要发 datamode千万不能为QSPI_DATA_NONE
else
cmd_cfg.DataMode = QSPI_DATA_NONE;//如果NbData为0 datamode千万不能为QSPI_DATA_NONE 否则这次传输无法启动
cmd_cfg.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;//每次调用HAL_QSPI_Command都要发指令
HAL_QSPI_Command(&hqspi, &cmd_cfg, 100);//发送指令和地址
HAL_QSPI_Transmit(&hqspi, (void*)pbuf, 100);//发送数据 长度在cmd_cfg定义了
}
void qspi_lcd_rd_reg(uint8_t cmd, uint8_t *pbuf, uint32_t len)
{
QSPI_CommandTypeDef cmd_cfg = {0};
while (HAL_QSPI_GetState(&hqspi) != HAL_QSPI_STATE_READY);//确定上个传输完成
cmd_cfg.Instruction = 0x0b;// 指令字节
cmd_cfg.InstructionMode = QSPI_INSTRUCTION_1_LINE;//指令用了几根线
cmd_cfg.Address = cmd<<8; // 0x00前缀 = 写寄存器 address不为0可能卡住
cmd_cfg.AddressSize = QSPI_ADDRESS_24_BITS;//地址位数
cmd_cfg.AddressMode = QSPI_ADDRESS_1_LINE;//地址用了几根线
cmd_cfg.DummyCycles = 0;//空闲位数
cmd_cfg.NbData = len;//后续数据长度
if(len!=0)
cmd_cfg.DataMode = QSPI_DATA_1_LINE;//如果有Address要发 datamode千万不能为QSPI_DATA_NONE
else
cmd_cfg.DataMode = QSPI_DATA_NONE;//如果NbData为0 datamode千万不能为QSPI_DATA_NONE 否则这次传输无法启动
cmd_cfg.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;//每次调用HAL_QSPI_Command都要发指令
HAL_QSPI_Command(&hqspi, &cmd_cfg, 100);//发送指令和地址
HAL_QSPI_Receive(&hqspi, (void*)pbuf, 100);//发送数据 长度在cmd_cfg定义了
}
更多推荐

所有评论(0)