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

技术参数

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

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


修改调试

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

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

1
2
3
4
void LCD_CmdWrite(uint8_t addr);
void LCD_DataWrite(uint8_t value);
uint8_t LCD_StatusRead(void);
uint8_t LCD_DataRead(void);

分别是写指令写数据读指令以及读数据

上面4个时序写好之后,就可以封装两个函数来读和写寄存器了。

1
2
void writeREG(uint8_t addr, uint8_t value);
uint8_t readREG(uint8_t addr);

只要搞清楚关键的几个函数,剩下的上层代码是可以复用的。底层驱动只要参照datasheet,严格按照时序来编写即可。

要注意的一点是,因为TM4C123G没有一个port是放出所有8个GPIO用于外接的,所以需要两个port合并起来一起用。下面贴代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}
1
2
3
4
static void writeREG(uint8_t addr, uint8_t value){
LCD_CmdWrite(addr);
LCD_DataWrite(value);
}
1
2
3
4
5
static uint8_t readREG(uint8_t addr){
uint8_t value;
LCD_CmdWrite(addr);
return LCD_DataRead();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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);
}

0%