完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
一、硬件环境:
1、主控STM32F103RC(无FSMC,I8080时序软件模拟) 2、TFTLCD,320480,ILI9488 3、SPI-FLASH,W25Q128(存放解码之后的JPEG图片数据) 4、图片320480,每张图片300.02K 二、测试结果: 1、刷屏(单色)耗时53ms 代码如下: #define ILI9488_START_Write_DATA() {ILI9488_RS_G();ILI9488_RD_G();ILI9488_WR_G();ILI9488_CS_D();} #define ILI9488_STOP_Write_DATA() {ILI9488_CS_G();} #define ILI9488_Write_DATA_FAST(x) {ILI9488_W_DATA(x); ILI9488_WR_D();ILI9488_WR_G();} /* *@brief LCD按指定颜色清屏(可以考虑是否优化,连续读写) *@param color指定颜色 *@retval 无 / void LCD_Clear(uint16_t color) { uint32_t index=0; uint32_t totalpoint=lcddev.width; totalpoint=lcddev.height; //得到总点数 ILI9488_SetCursor_AndEnd(0x0000,0x0000,319,479); //设置光标位置 ILI9488_Write_CMD(lcddev.wramcmd);//发送读GRAM指令 ILI9488_START_Write_DATA(); for(index=0;index ILI9488_STOP_Write_DATA(); } 尝试过将for循环展开一部分,减少for循环判断次数,可以降低到40ms左右,但是好像无实际意义; 2、刷图(耗时182ms) 代码如下: static void image_showex(uint16_t xsta,uint16_t ysta,uint16_t width,uint16_t height,uint8_t scan,uint32_t addr) { uint32_t len=0; if((scan&0x03)==0)//水平扫描 { ILI9488_Scan_Dir(L2R_U2D);//从左到右,从上到下 ILI9488_SetCursor_AndEnd(xsta,ysta,width-1+xsta,height-1+ysta); ILI9488_SetCursor(xsta,ysta);//设置光标位置 }else //垂直扫描 { ILI9488_Scan_Dir(U2D_L2R);//从上到下,从左到右 ILI9488_SetCursor_AndEnd(xsta,ysta,width-1+xsta,height-1+ysta); ILI9488_SetCursor(xsta,ysta);//设置光标位置 } len=width*height; //写入的数据长度 //开始数据搬运 SPI_NSS_D();//选中 EX_FLASH_SPI_ReadWriteByte(W25X_FastReadData); //发送读取命令 EX_FLASH_SPI_ReadWriteByte((uint8_t)((addr)>>16)); //发送24bit地址 EX_FLASH_SPI_ReadWriteByte((uint8_t)((addr)>>8)); EX_FLASH_SPI_ReadWriteByte((uint8_t)addr); while((SPI1->SR&1<<1)==0){}//等待发送区空 SPI1->DR=0xffff; //发送一个byte while((SPI1->SR&1<<0)==0){}//等待接收完一个byte uint16_t spi_rdata=SPI1->DR; SPI1->CR1&=~(1<<6);//关闭SPI SPI1->CR1|=(1<<11);//16bit SPI1->CR1|=(1<<6);//开启SPI ILI9488_Write_CMD(lcddev.wramcmd); //发送读GRAM指令 ILI9488_START_Write_DATA(); while(len!=0) { while((SPI1->SR&1<<1)==0){}//等待发送区空 SPI1->DR=0; //发送一个byte while((SPI1->SR&1<<0)==0){}//等待接收完一个byte ILI9488_Write_DATA_FAST(SPI1->DR);//颠倒高第八位,所有图片数据消耗时间大致8ms len–; } ILI9488_STOP_Write_DATA(); SPI_NSS_G(); //取消片选 SPI1->CR1&=~(1<<6);//关闭SPI SPI1->CR1&=~(1<<11);//8bit SPI1->CR1|=(1<<6);//开启SPI } (1)、CUBE在配置SPI的时候只能配置到18M,但是软件我实际配置到36M也暂时没有发现问题; (2)、读取图像数据的时候,我将SPI设置到16bit模式,将刷图时间从244ms降低到现在的180ms; 三、持续优化思路 1、最终代码会被移植到一颗资源更加紧张的MCU上去(自己公司的MCU),因此不考虑FSMC的使用; 2、I8080时序上的优化是否还有可能性; 3、SPI的读取速度上是否还有优化的可能; (1)、使用DMA读取一批数据然后刷到TFT,是否可以减小时间; (2)、在读取数据的时候如果使用软件模拟SPI的Dual模式(2个数据线进行数据读取)是否可以减小时间; 后续:20190530-1240 前面从flash读一个数据写入TFT的过程为: 等待发送缓存器为空—>写一个亚数据—>等待接受缓存器不为空—>获取到一个数据写入TFT(while整个过程); 改为:等待发送缓存器为空—>写一个亚数据—>进入while循环 等待接受缓存器不为空—>获取到一个数据—>写一个亚数据—>将上一个数据写入TFT—>等待发送缓存器为空(while整个过程); 这样做的好处在于,等待亚数据写入的过程中,就可以吧上一个数据写入TFT,这样等TFT写入完成之后,亚数据也就写入完成了, “等待发送缓存器为空”的过程基本上直接就略过了; 改完之后,写入一个图片的时间缩短到122ms; 后续:20190531-1042 在对汇编程序分析之后: 使用 #define ILI9488_Write_DATA_FAST(x) {GPIOB->ODR=x;GPIOC->BRR =0X0010;GPIOC->BSRR=0X0010;} 代替 #define ILI9488_Write_DATA_FAST(x) {ILI9488_W_DATA(x); ILI9488_WR_D();ILI9488_WR_G();} #define ILI9488_W_DATA(X) (GPIOB->ODR=X) #define ILI9488_WR_G() (GPIOC->BSRR|=1<<4)//set bit #define ILI9488_WR_D() (GPIOC->BRR|=1<<4)//clear bit 改完之后,写入一个图片的时间缩短到114ms; 后续:20190531-1538 使用DMA+双缓存模式读取SPI-FLASH数据 SPI1->CR1&=~(1<<6);//关闭SPI SPI1->CR1|=(1<<11);//16bit SPI1->CR2|=(1<<0);//启动接受缓存器DMA SPI1->CR2|=(1<<1);//启动接受缓存器DMA //SPI1->CR1|=(1<<10);//只读模式 uint16_t read_len=SPI_READ_MAX; uint8_t read_rotation=0; DMA1_Channel2->CCR&=~(1<<0);//关闭通道 DMA1_Channel2->CMAR=(uint32_t)(&spi_rdata[read_rotation][0]); DMA1->IFCR=0XF0; DMA1_Channel2->CNDTR=read_len; DMA1_Channel3->CCR&=~(1<<0);//关闭通道 DMA1_Channel3->CMAR=(uint32_t)(&spi_rdata[read_rotation][0]); DMA1->IFCR=0XF0; DMA1_Channel3->CNDTR=read_len; DMA1_Channel2->CCR|=(1<<0);//开启通道 DMA1_Channel3->CCR|=(1<<0);//开启通道 SPI1->CR1|=(1<<6);//开启SPI // ILI9488_Write_CMD(lcddev.wramcmd); //发送读GRAM指令 ILI9488_START_Write_DATA(); len-=SPI_READ_MAX; read_len=SPI_READ_MAX; while(1) { while(DMA1_Channel2->CNDTR!=0){}//等待DMA传输完成 read_rotation++; if(read_rotation>1)read_rotation=0; DMA1_Channel2->CCR&=~(1<<0);//关闭通道 DMA1_Channel2->CMAR=(uint32_t)(&spi_rdata[read_rotation][0]); DMA1->IFCR=0XF0; DMA1_Channel2->CNDTR=read_len; DMA1_Channel3->CCR&=~(1<<0);//关闭通道 DMA1_Channel3->CMAR=(uint32_t)(&spi_rdata[read_rotation][0]); DMA1->IFCR=0XF0; DMA1_Channel3->CNDTR=read_len; DMA1_Channel2->CCR|=(1<<0);//开启通道 DMA1_Channel3->CCR|=(1<<0);//开启通道,发送通道,在于产生SPI时钟,不然就需要进入只读模式,这样出现数据错位 for(int i=0;i { ILI9488_Write_DATA_FAST(spi_rdata[1-read_rotation]); } if(len==0)break; else { if(len read_len=len; len=0; } else { len-=SPI_READ_MAX; read_len=SPI_READ_MAX; } } } 刷图时间缩减到68ms;效果还是很明显的; 在测试过程中,刚开始只使用了DMA读取,这样SPI就需要进入只读模式,但是有一个问题,如果DMA传输的时间小于把数据发送到TFT的时间,就会出现错位; 解决办法,加入DMA发送,产生时钟,SPI依然工作全双工模式;问题得以解决,而且时间上也没有多余的消耗; |
|
|
|
只有小组成员才能发言,加入小组>>
2386 浏览 0 评论
8910 浏览 4 评论
36487 浏览 19 评论
4981 浏览 0 评论
24307 浏览 34 评论
1376浏览 2评论
1630浏览 1评论
2018浏览 1评论
1442浏览 0评论
388浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 13:50 , Processed in 1.316164 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号