自己用到了一款St9987芯片的2.0显示屏,320*240分辨率,16位RGB,驱动分享
1.开时钟
2.管脚配置(推挽输出 数据管脚开漏)
3.延时
void delay(uint m) // 12MHz Xtal, close to ms value
{
uint j;
uint i;
for(i=0; i<m; i++)
for(j=0; j<109; j++)
_nop_();
}
4.写命令
void SdCmd(uchar Command)
{
RS = 0;
gpio_bit_reset(GPIOA,0x1FE0);
gpio_bit_set(GPIOA,Command<<5);
_CS = 0;
_WR = 0;
_WR = 1;
_CS = 1;
}
5.写数据
void SdData(uchar Ddata)
{
RS = 1;
gpio_bit_reset(GPIOA,0x1FE0);
gpio_bit_set(GPIOA,Ddata<<5);
_CS = 0;
_WR = 0;
_WR = 1;
_CS = 1;
}
6.初始化
void lcd_inital(void)
{
//GPIO_BOP(GPIOA) = (uint32_t)0x1FE0;
_RST=1;
_CS=1;
_WR=1;
_RD=1;
delay(20;
_CS=0;
_RST=0; delay(100); //硬件复位
_RST=1; delay(120);
SdCmd( 0x11); //Sleep out
delay(150); //Delay 120ms
SdCmd ( 0x36); //
SdData( 0x60); //横屏0xA0
//
SdCmd ( 0x3A); //RGB 16位像素
SdData( 0x03);
SdCmd ( 0xB2);//门廊设置
SdData( 0x05);
SdData( 0x05);
SdData( 0x00);
SdData( 0x33);
SdData( 0x33);
SdCmd ( 0xB7);//门控
SdData( 0x24);
SdCmd ( 0xBB);//vcom设置
SdData( 0x22);
SdCmd ( 0xC0);//LCM控制
SdData( 0x2C);
SdCmd ( 0xC2); //VDV 和 VRH 命令使能
SdData( 0x01);
SdCmd ( 0xC3);//VRH 设置,VAP(GVDD) & VAN(GVCL)
SdData( 0x13);
SdCmd ( 0xC4);//VDV设置
SdData( 0x20);//VDV=0V
SdCmd ( 0xC6);//普通模式下的帧率控制
SdData( 0x0F);//点反转 & 60Hz
SdCmd ( 0xD0);//电源控制
SdData( 0xA4);
SdData( 0xA1);//AVDD=6.8V; AVCL=-4.8V;VDDS=2.3V
SdCmd ( 0xD6);
SdData( 0xA1);
// SdCmd(0xe8);
// SdData(0x83);
SdCmd ( 0xE0);//正向电压伽马控制
SdData( 0xD0);
SdData( 0x05);
SdData( 0x0A);
SdData( 0x09);
SdData( 0x08);
SdData( 0x05);
SdData( 0x2E);
SdData( 0x44);
SdData( 0x45);
SdData( 0x0F);
SdData( 0x17);
SdData( 0x16);
SdData( 0x2B);
SdData( 0x33);
SdCmd ( 0xE1); //负向电压伽马控制
SdData( 0xD0);
SdData( 0x05);
SdData( 0x0A);
SdData( 0x09);
SdData( 0x08);
SdData( 0x05);
SdData( 0x2E);
SdData( 0x43);//
SdData( 0x45);
SdData( 0x0F);
SdData( 0x16);
SdData( 0x16);
SdData( 0x2B);
SdData( 0x33);
//SdCmd ( 0x21);//显示反转on
LCD_Clear(0xFFFFFFFFFFFFFFFF);
delay(2);
SdCmd( 0x29); //Display on
7.开关背光
void DisplayOn(void)
{
SdCmd(0x13);
delay(10);
SdCmd(0x29);
delay(10);
SdCmd(0x36);
SdData(0xC0);
}
void DisplayOff(void)
{
uint8_t data = 0;
SdCmd(0x13);/* Partial off (Normal): NORON */
delay(10);
SdCmd(0x28);/* Display off: DISPOFF */
delay(10);
SdCmd(0x36);/* Memory data access control: MADCTL */
SdData(0xC0);
}
8.设置选定操作窗口大小
void LCD_Address_Set(U16 x1,U16 y1,U16 x2,U16 y2)
{
SdCmd(0x2a);//列地址设置
SdData(x1>>8);
SdData(x1);
SdData(x2>>8);
SdData(x2);
SdCmd(0x2b);//行地址设置
SdData(y1>>8);
SdData(y1);
SdData(y2>>8);
SdData(y2);
SdCmd(0x2c);//储存器写
}
9.清屏
union _clear
{
uint64_t ColorALL;
uint8_t color[8];
};
union _clear clearScreen;
void LCD_Clear(uint64_t data)
{
U16 i,j;
LCD_Address_Set(0,0,319,239);
clearScreen.ColorALL=data;
for(i=0;i<240;i++)
{
for (j=20;j<320;j+=4)
{
SdData(clearScreen.color[0]);
SdData(clearScreen.color[1]);
SdData(clearScreen.color[2]);
SdData(clearScreen.color[3]);
SdData(clearScreen.color[4]);
SdData(clearScreen.color[5]);
SdData(clearScreen.color[6]);
SdData(clearScreen.color[7]);
}
}
}
清屏为什么我要用一个64位联合体呢?(老手不用看),是为了加快清屏速度,联合体数组直接把64位的数据拆分成8个8位的数据,地址都是指向同一个地址,避免了大量的for循环
仅个人学习!