基于RA8875芯片的液晶屏驱动程序
Published:
技术参数
* 分辨率:800×480px
* 接口方式:16位8080并列式MCU接口
* LCD控制芯片:RA8875
* 电容触控芯片:GT910
* 工作电压:3.3V(背光单独5V供电)
* 工作电流:500mA
我这里只用到了显示功能,因此只涉及LCD控制芯片的驱动程序编写。
修改调试
我在网上能找到RA8875
的例程是基于STM32
编写的,直接使用了FSMC
的接口。但是由于我用的单片机是M4C123G
,只有基本的GPIO
控制功能,因此需要自己编写底层驱动。至于上层的图形库是可以复用的。
参照FSMC
接口的写法,以及RA8875
的datasheet
,发现最重要的有几个基本函数:
void LCD_CmdWrite(uint8_t addr);
void LCD_DataWrite(uint8_t value);
uint8_t LCD_StatusRead(void);
uint8_t LCD_DataRead(void);
分别是写指令、写数据、读指令以及读数据。
上面4个时序写好之后,就可以封装两个函数来读和写寄存器了。
void writeREG(uint8_t addr, uint8_t value);
uint8_t readREG(uint8_t addr);
只要搞清楚关键的几个函数,剩下的上层代码是可以复用的。底层驱动只要参照datasheet
,严格按照时序来编写即可。
要注意的一点是,因为TM4C123G
没有一个port是放出所有8个GPIO
用于外接的,所以需要两个port合并起来一起用。下面贴代码。
static uint8_t LCD_StatusRead(void){
uint8_t value, value1, value2;
GPIOPinTypeGPIOInput(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1);
CS_L;
RD_L;
RS_H;
WR_H;
SysCtlDelay(SysCtlClockGet()/3000);
value1 = GPIOPinRead(GPIO_PORTA_BASE,(GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7));
value2 = GPIOPinRead(GPIO_PORTD_BASE,(GPIO_PIN_0 | GPIO_PIN_1));
value = value1 | value2;
CS_H;
WR_L;
return value;
}
static void LCD_CmdWrite(uint8_t addr){
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1);
GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE,GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
CS_L;
RD_H;
RS_H;
WR_L;
GPIOPinWrite(GPIO_PORTA_BASE,
(GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7),
addr);
GPIOPinWrite(GPIO_PORTD_BASE,
(GPIO_PIN_0 | GPIO_PIN_1 ),
addr);
SysCtlDelay(SysCtlClockGet()/15000);
WR_H;
CS_H;
}
static void LCD_DataWrite(uint8_t value){
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1);
CS_L;
RD_H;
RS_L;
WR_L;
GPIOPinWrite(GPIO_PORTA_BASE,
(GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7),
value);
GPIOPinWrite(GPIO_PORTD_BASE,
(GPIO_PIN_0 | GPIO_PIN_1 ),
value);
SysCtlDelay(SysCtlClockGet()/15000);
WR_H;
CS_H;
}
static uint8_t LCD_DataRead(void){
GPIOPinTypeGPIOInput(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE,GPIO_PIN_0 | GPIO_PIN_1);
uint8_t value, value1, value2;
CS_L;
RD_L;
RS_L;
WR_H;
SysCtlDelay(SysCtlClockGet()/3000);
value1 = GPIOPinRead(GPIO_PORTA_BASE,(GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7));
value2 = GPIOPinRead(GPIO_PORTD_BASE,(GPIO_PIN_0 | GPIO_PIN_1));
value = value1 | value2;
CS_H;
WR_L;
return value;
}
static void writeREG(uint8_t addr, uint8_t value){
LCD_CmdWrite(addr);
LCD_DataWrite(value);
}
static uint8_t readREG(uint8_t addr){
uint8_t value;
LCD_CmdWrite(addr);
return LCD_DataRead();
}
static void RA8875Init(void){
LCD_CmdWrite(0x88);
SysCtlDelay(SysCtlClockGet()/3000000);
LCD_DataWrite(0x08);
SysCtlDelay(SysCtlClockGet()/3000);
LCD_CmdWrite(0x89);
SysCtlDelay(SysCtlClockGet()/3000000);
LCD_DataWrite(0x02);
//Software_Reset();
SysCtlDelay(SysCtlClockGet()/3000);
writeREG(0x10, 0x00); //8bit, color 256
writeREG(0x04, 0x81);
SysCtlDelay(SysCtlClockGet()/3000);
writeREG(0x14, 0x63);
writeREG(0x15, 0x00);
writeREG(0x16, 0x03);
writeREG(0x17, 0x03);
writeREG(0x18, 0x0B);
writeREG(0x19, 0xDF);
writeREG(0x1A, 0x01);
writeREG(0x1B, 0x1F);
writeREG(0x1C, 0x00);
writeREG(0x1D, 0x16);
writeREG(0x1E, 0x00);
writeREG(0x1F, 0x01);
//setting active window X
writeREG(0x30, 0x00);
writeREG(0x31, 0x00);
writeREG(0x34, 0x1F);
writeREG(0x35, 0x03);
//setting active window Y
writeREG(0x32, 0x00);
writeREG(0x33, 0x00);
writeREG(0x36, 0xDF);
writeREG(0x37, 0x01);
}