最近在做LVGL的移植,用到的屏幕驱动时GC9A01的,记录一下学习历程,防止日后遗忘。
这款屏幕我使用的是SPI协议,参考了部分稚辉菌大佬这个项目的程序:
【自制】我做了个能动的迷你电脑配件!【软核】_哔哩哔哩_bilibili
目录
SPI的通信部分是:CS和CLK拉低后即可通信,拉高结束通信
使用C实现SPI通信(标准库写法):
void LCD_Writ_Bus(u8 dat)
{
u8 i;
LCD_CS_Clr();//拉低
for(i=0;i<8;i++)
{
LCD_SCLK_Clr();//拉低
if(dat&0x80)
{
LCD_MOSI_Set();
}
else
{
LCD_MOSI_Clr();
}
LCD_SCLK_Set();//拉高
dat<<=1;
}
LCD_CS_Set();//拉高
}
作为一个LCD最重要的就是画点函数了,长这样:
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
// void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
//{
// LCD_WR_REG(0x2a);//列地址设置
// LCD_WR_DATA(x1);
// LCD_WR_DATA(x2);
// LCD_WR_REG(0x2b);//行地址设置
// LCD_WR_DATA(y1);
// LCD_WR_DATA(y2);
// LCD_WR_REG(0x2c);//储存器写
//}
LCD_Address_Set(x,y,x,y);//设置光标位置
LCD_WR_DATA(color);
}
翻下数据手册 这是命令的作用(这个发送的是16位命令,上边介绍的是8位的):
HALL库
现在我们可以画点了,通过调用这个函数*(HALL库):
下图是调用2A命令,设置列地址的起始位置和结束位置,发一个16位的data就是设置起始地址,发两个16位的data就是设置起始和结束地址
void SetDataOrCommand(bool _isData)
{
if (_isData)
{
LCD_DC_GPIO_Port->BSRR = LCD_DC_Pin;
} else {
LCD_DC_GPIO_Port->BSRR = (uint32_t) LCD_DC_Pin << 16U;
}
}
void WriteCommand(uint8_t _cmd)
{
SetDataOrCommand(false);
HAL_SPI_Transmit(spi, &_cmd, 1, 100);
}
void Setpoint(uint16_t _startX, uint16_t _startY,uint16_t color)
{
ChipSelect(true);
uint8_t data[4];
WriteCommand(0x2A); // COL_ADDR_SET
data[0] = (_startX >> 8) & 0xFF;
data[1] = _startX & 0xFF;
WriteData(data, sizeof(data), false);
WriteCommand(0x2B); // ROW_ADDR_SET
data[0] = (_startY >> 8) & 0xFF;
data[1] = _startY & 0xFF;
WriteData(data, sizeof(data), false);
WriteCommand(0x2C); // ROW_ADDR_SET
data[0] = (color >> 8) & 0xFF;
data[1] = color & 0xFF;
WriteData(data, sizeof(data), false);
ChipSelect(false);
}
//这里传入的是一组数据,使用指针来接收数据
void Setwindow(uint16_t _startX, uint16_t _endX, uint16_t _startY, uint16_t _endY,uint16_t *color)
{
ChipSelect(true);
uint16_t height, width;
uint16_t i, j;
width = _endX - _startX + 1; /* 得到填充的宽度 */
height = _endY - _startY + 1; /* 高度 */
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
//将像素的值通过坐标写入
Setpoint(_startX+j,_startY+i,color[i * width + j]);
}
}
ChipSelect(false);
}
如果画一个区域就是这样的,依次进行设置,最后写内存的部分,本质上就是给像素点写颜色,因为这个芯片本质上就是一个巨大的RAM,一共320x18x240 bits,RGB的模式也分几种,上述代码主要是LVGL进行缓存更新时候调用的画区域的函数,本质上是对GRAM的内存进行更新
如有描述不对的地方,欢迎评论区指证!