基于RA8875芯片的液晶屏驱动程序

1 minute read

Published:

技术参数

* 分辨率:800×480px
* 接口方式:16位8080并列式MCU接口
* LCD控制芯片:RA8875
* 电容触控芯片:GT910
* 工作电压:3.3V(背光单独5V供电)
* 工作电流:500mA

我这里只用到了显示功能,因此只涉及LCD控制芯片的驱动程序编写。


修改调试

我在网上能找到RA8875的例程是基于STM32编写的,直接使用了FSMC的接口。但是由于我用的单片机是M4C123G,只有基本的GPIO控制功能,因此需要自己编写底层驱动。至于上层的图形库是可以复用的。

参照FSMC接口的写法,以及RA8875datasheet,发现最重要的有几个基本函数:

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);
}