- /* @attention
- *
- * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
- * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
- * TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY
- * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
- * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
- * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
- **************************************************************************************************/
- #include "lcd.h"
- #include "spi.h"
- #include <stdio.h>
- #
- //管理LCD重要参数
- //默认为竖屏
- _lcd_dev lcddev;
- extern DMA_HandleTypeDef hdma_spi1_tx;
- //画笔颜色,背景颜色
- uint16_t POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;
- uint16_t DeviceCode;
- uint8_t LCD_SPI_WriteByte(uint8_t TxData) {
- uint8_t RxData = 0X00;
- if(HAL_SPI_TransmitReceive(LCD_SPI_Handle, &TxData, &RxData, 1, 100) != HAL_OK)
- {
- RxData = 0XFF;
- }
- return RxData;
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_WR_REG(uint8_t data)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write an 8-bit command to the LCD screen
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :data:Command value to be written
- * @retvalue :None
- ******************************************************************************/
- void LCD_WR_REG(uint8_t data)
- {
- LCD_CS_CLR;
- LCD_RS_CLR;
- LCD_SPI_WriteByte(data);
- LCD_CS_SET;
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_WR_DATA(uint8_t data)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write an 8-bit data to the LCD screen
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :data:data value to be written
- * @retvalue :None
- ******************************************************************************/
- void LCD_WR_DATA(uint8_t data)
- {
- LCD_CS_CLR;
- LCD_RS_SET;
- LCD_SPI_WriteByte(data);
- LCD_CS_SET;
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write data into registers
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :LCD_Reg:Register address
- LCD_RegValue:Data to be written
- * @retvalue :None
- ******************************************************************************/
- void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
- {
- LCD_WR_REG(LCD_Reg);
- LCD_WR_DATA(LCD_RegValue);
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_WriteRAM_Prepare(void)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write GRAM
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :None
- * @retvalue :None
- ******************************************************************************/
- void LCD_WriteRAM_Prepare(void)
- {
- LCD_WR_REG(lcddev.wramcmd);
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void Lcd_WriteData_16Bit(uint16_t Data)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write an 16-bit command to the LCD screen
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :Data:Data to be written
- * @retvalue :None
- ******************************************************************************/
- void Lcd_WriteData_16Bit(uint16_t Data)
- {
- LCD_CS_CLR;
- LCD_RS_SET;
- LCD_SPI_WriteByte(Data>>8);
- LCD_SPI_WriteByte(Data);
- LCD_CS_SET;
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_DrawPoint(uint16_t x,uint16_t y)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Write a pixel data at a specified location
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :x:the x coordinate of the pixel
- y:the y coordinate of the pixel
- * @retvalue :None
- ******************************************************************************/
- void LCD_DrawPoint(uint16_t x,uint16_t y)
- {
- LCD_SetCursor(x,y);//设置光标位置
- Lcd_WriteData_16Bit(POINT_COLOR);
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_Clear(uint16_t Color)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Full screen filled LCD screen
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :color:Filled color
- * @retvalue :None
- ******************************************************************************/
- void LCD_Clear(uint16_t Color)
- {
- unsigned int i,m;
- LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);
- LCD_CS_CLR;
- LCD_RS_SET;
- for(i=0;i<lcddev.height;i++)
- {
- for(m=0;m<lcddev.width;m++)
- {
- Lcd_WriteData_16Bit(Color);
- }
- }
- LCD_CS_SET;
- }
- /*****************************************************************************
- * [url=home.php?mod=space&uid=139335]@name[/url] :void LCD_RESET(void)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Reset LCD screen
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :None
- * @retvalue :None
- ******************************************************************************/
- void LCD_RESET(void)
- {
- LCD_RST_CLR;
- HAL_Delay(100);
- LCD_RST_SET;
- HAL_Delay(50);
- }
- /*****************************************************************************
- * @name :void LCD_RESET(void)
- * @date :2018-08-09
- * @function :Initialization LCD screen
- * @parameters :None
- * @retvalue :None
- ******************************************************************************/
- void LCD_Init(void)
- {
- LCD_RESET(); //LCD 复位
- //*************3.2inch ILI9341初始化**********//
- LCD_WR_REG(0xCF);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0xD9); //C1
- LCD_WR_DATA(0X30);
- LCD_WR_REG(0xED);
- LCD_WR_DATA(0x64);
- LCD_WR_DATA(0x03);
- LCD_WR_DATA(0X12);
- LCD_WR_DATA(0X81);
- LCD_WR_REG(0xE8);
- LCD_WR_DATA(0x85);
- LCD_WR_DATA(0x10);
- LCD_WR_DATA(0x7A);
- LCD_WR_REG(0xCB);
- LCD_WR_DATA(0x39);
- LCD_WR_DATA(0x2C);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x34);
- LCD_WR_DATA(0x02);
- LCD_WR_REG(0xF7);
- LCD_WR_DATA(0x20);
- LCD_WR_REG(0xEA);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x00);
- LCD_WR_REG(0xC0); //Power control
- LCD_WR_DATA(0x1B); //VRH[5:0]
- LCD_WR_REG(0xC1); //P0
- LCD_WR_DATA(0x12); //SAP[2:0];BT[3:0] //0x01
- LCD_WR_REG(0xC5); //VCM control
- LCD_WR_DATA(0x26); //3F
- LCD_WR_DATA(0x26); //3C
- LCD_WR_REG(0xC7); //VCM control2
- LCD_WR_DATA(0XB0);
- LCD_WR_REG(0x36); // Memory Access Control
- LCD_WR_DATA(0x08);
- LCD_WR_REG(0x3A);
- LCD_WR_DATA(0x55);
- LCD_WR_REG(0xB1);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x1A);
- LCD_WR_REG(0xB6); // Display Function Control
- LCD_WR_DATA(0x0A);
- LCD_WR_DATA(0xA2);
- LCD_WR_REG(0xF2); // 3Gamma Function Disable
- LCD_WR_DATA(0x00);
- LCD_WR_REG(0x26); //Gamma curve selected
- LCD_WR_DATA(0x01);
- LCD_WR_REG(0xE0); //Set Gamma
- LCD_WR_DATA(0x1F);
- LCD_WR_DATA(0x24);
- LCD_WR_DATA(0x24);
- LCD_WR_DATA(0x0D);
- LCD_WR_DATA(0x12);
- LCD_WR_DATA(0x09);
- LCD_WR_DATA(0x52);
- LCD_WR_DATA(0xB7);
- LCD_WR_DATA(0x3F);
- LCD_WR_DATA(0x0C);
- LCD_WR_DATA(0x15);
- LCD_WR_DATA(0x06);
- LCD_WR_DATA(0x0E);
- LCD_WR_DATA(0x08);
- LCD_WR_DATA(0x00);
- LCD_WR_REG(0XE1); //Set Gamma
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x1B);
- LCD_WR_DATA(0x1B);
- LCD_WR_DATA(0x02);
- LCD_WR_DATA(0x0E);
- LCD_WR_DATA(0x06);
- LCD_WR_DATA(0x2E);
- LCD_WR_DATA(0x48);
- LCD_WR_DATA(0x3F);
- LCD_WR_DATA(0x03);
- LCD_WR_DATA(0x0A);
- LCD_WR_DATA(0x09);
- LCD_WR_DATA(0x31);
- LCD_WR_DATA(0x37);
- LCD_WR_DATA(0x1F);
- LCD_WR_REG(0x2B);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x01);
- LCD_WR_DATA(0x3f);
- LCD_WR_REG(0x2A);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0x00);
- LCD_WR_DATA(0xef);
- LCD_WR_REG(0x11); //Exit Sleep
- HAL_Delay(120);
- LCD_WR_REG(0x29); //display on
- LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
- LCD_BL_ON;//点亮背光
- LCD_Clear(GREEN);//清全屏白色
- }
-
- /*****************************************************************************
- * @name :void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd)
- * @date :2018-08-09
- * @function :Setting LCD display window
- * @parameters :xStar:the bebinning x coordinate of the LCD display window
- yStar:the bebinning y coordinate of the LCD display window
- xEnd:the endning x coordinate of the LCD display window
- yEnd:the endning y coordinate of the LCD display window
- * @retvalue :None
- ******************************************************************************/
- void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd)
- {
- LCD_WR_REG(lcddev.setxcmd);
- LCD_WR_DATA(xStar>>8);
- LCD_WR_DATA(0x00FF&xStar);
- LCD_WR_DATA(xEnd>>8);
- LCD_WR_DATA(0x00FF&xEnd);
- LCD_WR_REG(lcddev.setycmd);
- LCD_WR_DATA(yStar>>8);
- LCD_WR_DATA(0x00FF&yStar);
- LCD_WR_DATA(yEnd>>8);
- LCD_WR_DATA(0x00FF&yEnd);
- LCD_WriteRAM_Prepare(); //开始写入GRAM
- }
- /*****************************************************************************
- * @name :void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
- * @date :2018-08-09
- * @function :Set coordinate value
- * @parameters :Xpos:the x coordinate of the pixel
- Ypos:the y coordinate of the pixel
- * @retvalue :None
- ******************************************************************************/
- void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
- {
- LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);
- }
- /*****************************************************************************
- * @name :void LCD_direction(uint8_t direction)
- * @date :2018-08-09
- * @function :Setting the display direction of LCD screen
- * @parameters :direction:0-0 degree
- 1-90 degree
- 2-180 degree
- 3-270 degree
- * @retvalue :None
- ******************************************************************************/
- void LCD_direction(uint8_t direction)
- {
- lcddev.setxcmd=0x2A;
- lcddev.setycmd=0x2B;
- lcddev.wramcmd=0x2C;
- switch(direction){
- case 0:
- lcddev.width=LCD_W;
- lcddev.height=LCD_H;
- LCD_WriteReg(0x36,(1<<3)|(0<<6)|(0<<7));//BGR==1,MY==0,MX==0,MV==0
- break;
- case 1:
- lcddev.width=LCD_H;
- lcddev.height=LCD_W;
- LCD_WriteReg(0x36,(1<<3)|(0<<7)|(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
- break;
- case 2:
- lcddev.width=LCD_W;
- lcddev.height=LCD_H;
- LCD_WriteReg(0x36,(1<<3)|(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0
- break;
- case 3:
- lcddev.width=LCD_H;
- lcddev.height=LCD_W;
- LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
- break;
- default:break;
- }
- }
- void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma) {
- // if (hdma == hdma_spi1_tx) {
- LCD_CS_SET;
- LCD_RS_SET;
- // }
- }
四、如何优化SPI的传输速率
一般情况下,直接提升SPI传输速率的方法是,提高SPI的工作频率。在数据手册中,也没有看到最大工作频率;那么就只能看MCU支持多大的工作频率;
除了以上方法,还有以下几种方法:
——SPI传输使用DMA方式;
——提高IDE的优化等级;
——使用RAM存储LCD显示数据。
下面就实测以上几种方法的刷新率;
1、先来看看正常配置后的刷新率;2s一张图;如下视频
2、设置编译器优化等级;刷新率快了一点;1s一张图;如下
等级优化设置:
3、设置SPI为DMA传输;也是2s一张图;1s一张图,如下视频
- LCD_CS_CLR;
- HAL_SPI_Transmit_DMA(LCD_SPI_Handle, &TxData, 1);
- while((HAL_SPI_GetState(&hspi1)) != HAL_SPI_STATE_READY);
- LCD_CS_SET;
4、设置SPI为DMA传输,并且优化等级为fast;没有什么变化;2s一张图,如下视频
5、把SPI的数据缓存放在RAM中;使用DMA传输;刷新率大幅提高;见如下视频;
具体操作如下:
- /* 在STM32L4R5ZITX_RAM.ld 中声明一个段,这个段在RAM中;*/
- /*add user section*/
- .lcdbuffer :
- {
- . = ALIGN(4);
- . = ALIGN(4);
- } >RAM
-
- /* 最后在头文件中设置LCD显示数据数组在声明的段中*/
- __attribute__((section(".lcdbuffer"))) unsigned short LCD_BUFFER[320][240] ;
编译后可以看到LCD_BUFFER运行地址是在RAM中;
此前DMA是传输一个字节,传输大量数据就会重复进行传输过程。
而直接使用RAM中的缓存,则可以把数据通过DMA把半屏数据传输到LCD的DDRAM中。