一、简介
正如简介所述,本章节内容针对屏显示出现色差问题。前段时间使用FRDM-MCXN947成功驱动了一块1.77寸的TFT屏,颜色正常。双十二在淘宝上购得一块1.44寸同方案的TFT屏,除了尺寸分辨率不同,接线接口都一致,使用FRDM-MCXN947相同的工程去点这块1.44屏,显示的颜色出现异常了,红色变蓝色,画图显示如下图。商家提示需要参考给出的工程示例,重新编写驱动代码,因此采用Nano板验证该问题。
二、开发板资源
该开发板是基于STM32F103RBT6的,板载ST-Link,下载调试都很方便,板卡可在正点原子旗舰店购买。
三、代码移植
这里只是为验证屏的色差问题,因此咱们借助商家提供的参考驱动代码,移植到板块SDK中的SPI工程示例中。工程采用基于寄存器版本的,废话少说,咱们直接上部分主干代码吧。
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "key.h"
#include "spi.h"
#include "usmart.h"
#include "w25qxx.h"
#include "main.h"
#include "lcd.h"
//要写入到W25Q16的字符串数组
const u8 TEXT_Buffer[]={"NANOSTM32 SPI TEST"};
#define SIZE sizeof(TEXT_Buffer)
extern u16 POINT_COLOR;
void TEST_STAND() //测试画面
{
DispFrame(); //显示框线画面
StopDelay(Delay_Time); //画面延时
DispGrayHor16(); //显示16阶灰度画面
StopDelay(Delay_Time); //画面延时
StopDelay(Delay_Time); //画面延时
DispBand(); //显示彩条画面
StopDelay(Delay_Time); //画面延时
DispColor(RED); //显示红色画面
StopDelay(Delay_Time); //画面延时
DispColor(GREEN); //显示绿色画面
StopDelay(Delay_Time); //画面延时
DispColor(BLUE); //显示蓝色画面
StopDelay(Delay_Time); //画面延时
DispColor(WHITE); //显示白色画面
StopDelay(Delay_Time); //画面延时
DispColor(BLACK); //显示黑色画面
StopDelay(Delay_Time); //画面延时
}
int main(void)
{
u8 key;
u16 i=0;
u8 datatemp[SIZE];
u32 FLASH_SIZE;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,115200);//串口初始化
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //按键初始化
W25QXX_Init(); //SPI FLASH 初始化
LCD_Init();
usmart_dev.init(72); //初始化USMART
printf("NANO STM32\r\n");
printf("SPI TEST\r\n");
while(W25QXX_ReadID()!=W25Q16)//检测W25Q16
{
printf("W25Q16 Check Failed!\r\n");
delay_ms(500);
printf("Please Check!\r\n");
delay_ms(500);
LED0=!LED0;//DS0闪烁
}
printf("W25Q16 Ready!\r\n");
printf("KEY_UP:Write KEY1:Read\r\n");
FLASH_SIZE=2*1024*1024; //FLASH 大小为2M字节
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES) //WK_UP 按下,写入W25Q16
{
LED2=0;
printf("\r\nStart Write W25Q16....\r\n");
W25QXX_Write((u8*)TEXT_Buffer,FLASH_SIZE-100,SIZE);
printf("W25Q16 Write Finished!\r\n");//提示传送完成
LED2=1;
}
if(key==KEY1_PRES) //KEY1 按下,读取字符串并显示
{
LED2=0;
printf("\r\nStart Read W25Q16....\r\n");
W25QXX_Read(datatemp,FLASH_SIZE-100,SIZE);
printf("The Data Readed Is: \r\n");//提示传送完成
printf("%s\r\n",datatemp);//显示读到的字符串
LED2=1;
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;//提示系统正在运行
i=0;
}
TEST_STAND();
POINT_COLOR = RED;
LCD_ShowString(0,32,100,16,16,"Hello World");
StopDelay(Delay_Time);
}
}
#ifndef __LCD_H2
#define __LCD_H2
#include "sys.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
//==================================================================
enum LCD_INTERFACE{MCU16,SPI4Line,MCU8,MCUH8,SPI3Line,SPI3Line2,SPI4Line_CS_D8};
typedef struct _LCD_CONFIG{
int col;
int row;
int col_pre;
int row_pre;
int delay_time;
u8 is_commdata16;
enum LCD_INTERFACE lcd_interface;
u32 pic_bytes;
}LCD_CONFIG;
//==================================================================
///*LCD-MCU端口定义*/
//==================================================================
#define LCD_RS_SET GPIOA->BSRR=1<<1 //DC PA1
#define LCD_WR_SET GPIOA->BSRR=1<<2 //SCL PA2
#define LCD_RD_SET GPIOA->BSRR=1<<3 //SDA PA3
#define LCD_RST_SET GPIOA->BSRR=1<<4 //RES PA4
#define LCD_RS_CLR GPIOA->BRR=1<<1 //DC PA1
#define LCD_WR_CLR GPIOA->BRR=1<<2 //SCL PA2
#define LCD_RD_CLR GPIOA->BRR=1<<3 //SDA PA3
#define LCD_RST_CLR GPIOA->BRR=1<<4 //RES PA4
//IO SPI
#define LCD_SPI_SCL_SET GPIOA->BSRR=1<<2 //SPI_SCL
#define LCD_SPI_SDA_SET GPIOA->BSRR=1<<3 //SPI_SDA
#define LCD_SPI_SDA2_SET GPIOB->BSRR=1<<2 //SPI_SDA2
#define LCD_SPI_SCL_CLR GPIOA->BRR=1<<2 //SPI_SCL
#define LCD_SPI_SDA_CLR GPIOA->BRR=1<<3 //SPI_SDA
#define LCD_SPI_SDA2_CLR GPIOB->BRR=1<<2 //SPI_SDA2
#define DATAOUT(x) GPIOA->ODR=x; //数据输出
#define DATAIN GPIOA->IDR; //数据输入
#define LCD_PD_SET GPIOA->BSRR=1<<5 //BLK PA5
#define LCD_PD_CLR GPIOA->BRR=1<<5 //BLK PA5
#define LCD_CS_SET CS_SET() //CS PA6
#define LCD_CS_CLR CS_CLR() //CS PA6
///*画笔颜色*/
//=======================================================
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
#define GRAY25 0xADB5
//GUI颜色
#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
//以上三色为PANEL的颜色
#define LIGHTGREEN 0X841F //浅绿色
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)
#define X_min 0x0043 //TP测试范围常量定义
#define X_max 0x07AE
#define Y_min 0x00A1
#define Y_max 0x0759
//==========================================
extern u16 BACK_COLOR, POINT_COLOR ;
void LCD_CONFIG_INIT(void);
void LCD_Init(void);
void LCD_IC_Init(void);
void LCD_WR_REG(u16 data);
void LCD_WR_DATA(u16 data);
void SendData(unsigned int color);
void DispColor(unsigned int color);
void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int Yend);
void LCD_GPIOInit(void);
void WriteOneDot(unsigned int color);
void WriteDispData(unsigned int color1,unsigned int color2);
void DispFrame(void);
void DispBand(void);
void DispGrayHor16(void);
void DispGrayHor32(void);
extern void TP_DrawLine(void);
void DrawGird(unsigned int color);
void PutPixel(unsigned int x,unsigned int y,unsigned int color);
void DispStr(unsigned char *str,unsigned int Xstart,unsigned int Ystart,unsigned int TextColor,unsigned int BackColor);
void DispInt(unsigned int i,unsigned int Xstart,unsigned int Ystart,unsigned int TextColor,unsigned int BackColor);
void StopDelay(unsigned int sdly);
void LCD_SetCursor(unsigned short Xpos, unsigned short Ypos);
void LCD_Fast_DrawPoint(unsigned short x,unsigned short y,unsigned short color);
void LCD_DispChars_24a(/*坐标X*/unsigned short Char_X,/*坐标Y*/unsigned short Char_Y,/*显示内容*/char hz[],/*显示颜色*/uint16_t Char_Color,/*显示样式*/u8 XY_Mod );
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p);
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);
void LCD_DrawPoint(u16 x,u16 y);
void LCD_ShowCharaa(uint16_t x,uint16_t y,uint16_t fc, uint16_t bc, uint8_t num,uint8_t size,uint8_t mode);
void LCD_ShowCharqq(uint16_t x,uint16_t y,uint16_t fc, uint16_t bc, uint8_t num,uint8_t size,uint8_t mode);
void Show_Str(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode);
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode);
void DispColor_9bit_window(unsigned char r,unsigned char g,unsigned char b);
void DispBand_9b(void);
void DispFrame_9b(void);
void DispGrayHor16_9b(void);
void DispChess(u8 div);
void TEST_STAND_9b(void);
#endif
#include <stdio.h>
#include <string.h>
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "w25qxx.h"
#include "lcd.h"
#include "interface.h"
#include "stm32f10x_gpio.h"
#include "main.h"
#include "stm32f10x_rcc.h"
//=========================================
// 函数: void LCD_GPIOInit(void)
// 描述: LCD 相关的GPIO设定
//=========================================
void LCD_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6);
}
//struct LCD_CONFIG lcdconfig;
LCD_CONFIG lcdconfig;
//=============================================================
// 函数: void LCD_CONFIG_INIT(void)
// 描述: LCD设置初始化
//=============================================================
void LCD_CONFIG_INIT(void)
{
lcdconfig.col=COL;
lcdconfig.row=ROW;
lcdconfig.col_pre=COL_Pre;
lcdconfig.row_pre=ROW_Pre;
#ifdef LCD_SPI4Line
lcdconfig.lcd_interface=SPI4Line;
#endif
#ifdef LCD_SPI3Line
lcdconfig.lcd_interface=SPI3Line;
#endif
lcdconfig.delay_time=Delay_Time;
#ifdef commdata16
lcdconfig.is_commdata16=1;
#else
lcdconfig.is_commdata16=0;
#endif
#ifdef TEST_STAND_H9B
lcdconfig.pic_bytes=(COL*ROW)*3;
#else
lcdconfig.pic_bytes=(COL*ROW)<<1;
#endif
}
void LCD_RESET(void)
{
LCD_RST_SET;
delay_ms(50);
LCD_RST_CLR;
delay_ms(200);
LCD_RST_SET;
delay_ms(200);
}
void LCD_Init(void)
{
LCD_GPIOInit();
LCD_CONFIG_INIT();
LCD_RESET();
LCD_IC_Init();
}
void WriteOneDot(unsigned int color)
{
LCD_CS_CLR;
LCD_RD_SET;
LCD_RS_SET;
SendData(color);
LCD_CS_SET;
}
void WriteDispData(unsigned int color1,unsigned int color2)
{
SendData(color1);
SendData(color2);
}
void DispColor(unsigned int color)
{
unsigned int i,j;
BlockWrite(COL_Pre,COL+COL_Pre-1,ROW_Pre,ROW+ROW_Pre-1);
LCD_CS_CLR;
LCD_RS_SET;
LCD_RD_SET;
for(i=0;i<ROW;i++)
{
for(j=0;j<COL;j++)
{
SendData(color);
}
}
LCD_CS_SET;
}
void DispBand(void)
{
int i,j,k;
unsigned int color[8]={0xf800,0xf800,0x07e0,0x07e0,0x001f,0x001f,0xffff,0xffff};//0x94B2
BlockWrite(COL_Pre,COL+COL_Pre-1,ROW_Pre,ROW+ROW_Pre-1);
LCD_CS_CLR;
LCD_RD_SET;
LCD_RS_SET;
for(i=0;i<8;i++)
{
for(j=0;j<ROW/8;j++)
{
for(k=0;k<COL;k++)
{
SendData(color[i]);
}
}
}
for(j=0;j<ROW%8;j++)
{
for(k=0;k<COL;k++)
{
SendData(color[7]);
}
}
LCD_CS_SET;
}
//==========================================
void DispFrame(void)
{
unsigned int i,j;
BlockWrite(COL_Pre,COL+COL_Pre-1,ROW_Pre,ROW+ROW_Pre-1);
LCD_CS_CLR;
LCD_RS_SET;
LCD_RD_SET;
SendData(0xf800);
for(i=0;i<COL-2;i++){SendData(0xFFFF);}
SendData(0x001f);
for(j=0;j<ROW-2;j++)
{
SendData(0xf800);
for(i=0;i<COL-2;i++){SendData(0x0000);}
SendData(0x001F);
}
SendData(0xf800);
for(i=0;i<COL-2;i++){SendData(0xFFFF);}
SendData(0x001F);
LCD_CS_SET;
}
void DispGrayHor16(void)
{
int i,j,k;
BlockWrite(COL_Pre,COL+COL_Pre-1,ROW_Pre,ROW+ROW_Pre-1);
LCD_CS_CLR;
LCD_RD_SET;
LCD_RS_SET;
for(i=0;i<ROW;i++)
{
for(j=0;j<COL%16;j++)
{
SendData(0);
}
for(j=0;j<16;j++)
{
for(k=0;k<COL/16;k++)
{
SendData(((((j*2)<<3)|((j*4)>>3))<<8)|(((j*4)<<5)|(j*2)));
}
}
}
LCD_CS_SET;
}
void LCD_IC_Init()
{
WriteComm(0x11); //Sleep out
Delay(120);
//---------------ST7735S Frame Rate---------------//
WriteComm(0xB1);
WriteData(0x05);
WriteData(0x3A);
WriteData(0x3A);
WriteComm(0xB2);
WriteData(0x05);
WriteData(0x3A);
WriteData(0x3A);
WriteComm(0xB3);
WriteData(0x05);
WriteData(0x3A);
WriteData(0x3A);
WriteData(0x05);
WriteData(0x3A);
WriteData(0x3A);
//-----------------End ST7735S Frame Rate------------------//
WriteComm(0xB4); //Dot inversion
WriteData(0x03);
//------------------ST7735S Power Sequence----------------//
WriteComm(0xC0);
WriteData(0x62);
WriteData(0x02);
WriteData(0x04);
WriteComm(0xC1);
WriteData(0xC0);
WriteComm(0xC2);
WriteData(0x0D);
WriteData(0x00);
WriteComm(0xC3);
WriteData(0x8D);
WriteData(0x6A);
WriteComm(0xC4);
WriteData(0x8D);
WriteData(0xEE);
//-----------------End ST7735S Power Sequence--------------------//
WriteComm(0xC5); //VCOM
WriteData(0x12);
//-----------------ST7735S Gamma Sequence-------------------------//
WriteComm(0xE0);
WriteData(0x03);
WriteData(0x1B);
WriteData(0x12);
WriteData(0x11);
WriteData(0x3F);
WriteData(0x3A);
WriteData(0x32);
WriteData(0x34);
WriteData(0x2F);
WriteData(0x2B);
WriteData(0x30);
WriteData(0x3A);
WriteData(0x00);
WriteData(0x01);
WriteData(0x02);
WriteData(0x05);
WriteComm(0xE1);
WriteData(0x03);
WriteData(0x1B);
WriteData(0x12);
WriteData(0x11);
WriteData(0x32);
WriteData(0x2F);
WriteData(0x2A);
WriteData(0x2F);
WriteData(0x2E);
WriteData(0x2C);
WriteData(0x35);
WriteData(0x3F);
WriteData(0x00);
WriteData(0x00);
WriteData(0x01);
WriteData(0x05);
//---------------End ST7735S Gamma Sequence-------------//
WriteComm(0xFC); //Enable Gate power save mode
WriteData(0x8C);
WriteComm(0x3A); //65k mode
WriteData(0x05);
WriteComm(0x36); //65k mode
WriteData(0xC8);
WriteComm(0x29); //Display on
}
void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int Yend)
{
WriteComm(0x2a);
WriteData((Xstart)>>8);
WriteData((Xstart));
WriteData((Xend)>>8);
WriteData(Xend);
WriteComm(0x2b);
WriteData((Ystart)>>8);
WriteData((Ystart));
WriteData((Yend)>>8);
WriteData(Yend);
WriteComm(0x2c);
}
四、下载验证
由于板载ST-Link调试接口,只需要一个MicroUSB数据线,即可完成下载。显示效果如下视频,颜色纯正,验证商家的屏没问题,128X128的分辨率显示非常流畅。