1. 基于GC9A01驱动的1.28寸IPS圆屏SPI移植与驱动开发实战
本文详细介绍了基于GC9A01驱动芯片的1.28寸IPS圆形屏幕的SPI驱动移植与开发全流程。从硬件引脚连接到软件代码修改,逐步解析了在嵌入式平台(如STM32)上点亮屏幕、绘制图形及显示文字的关键步骤,并提供了常见问题调试方法,帮助开发者快速实现屏幕驱动。
基于GC9A01驱动的1.28寸IPS圆屏SPI移植与驱动开发实战
最近在做一个智能手表项目,需要用到一块小巧的圆形屏幕,最终选定了这款1.28寸的IPS圆屏,驱动芯片是GC9A01,接口是SPI。网上资料虽然不少,但很多都语焉不详,移植起来总遇到各种问题。今天我就把自己从零开始,把这块屏幕成功点亮并显示图形的完整过程分享出来,希望能帮你少走弯路。
这篇文章适合有一定嵌入式开发基础的朋友,比如会用过STM32、立创开发板或者其他ARM Cortex-M系列MCU的开发者。我会从硬件接线开始,一步步带你完成驱动移植、代码适配,最后实现图形和文字的显示。整个过程都是基于我实际项目的经验,代码可以直接拿来用。
1. 准备工作:了解屏幕与获取资料
1.1 屏幕规格与资料下载
咱们先来看看这块屏幕的基本情况。这是一块1.28英寸的圆形IPS液晶屏,分辨率是240x240,显示效果非常细腻。驱动芯片是GC9A01,通过SPI接口与主控通信,工作电压是3.3V。
注意:所有开发工作都离不开厂家提供的资料。请务必先下载资料包,里面包含了最重要的参考例程和芯片手册。
资料获取方式:
- 采购链接:可以在电商平台搜索“1.28寸IPS圆屏 GC9A01”找到。
- 资料下载:通过网盘获取,提取码为
8888。
资料包里最关键的是一个完整的工程例程,这是我们移植的基础。拿到资料后,先找到 LCD 这个文件夹,里面包含了驱动芯片GC9A01的所有底层驱动代码。
1.2 引脚定义与连接
这块屏幕通过一个8Pin的FPC排线与主板连接。我们需要搞清楚每个引脚是干什么的,才能正确连接到我们的开发板上。
屏幕的引脚定义如下表所示:
| 屏幕引脚 | 功能说明 | 必须连接吗? |
|---|---|---|
| GND | 电源地 | 必须 |
| VCC | 电源正极 (3.3V) | 必须 |
| SCL | SPI时钟线 (SCK) | 必须 |
| SDA | SPI数据线 (MOSI,主出从入) | 必须 |
| RES | 复位引脚,低电平有效 | 建议连接 |
| DC | 数据/命令选择引脚 | 必须 |
| CS | SPI片选引脚 | 必须 |
| BLK | 背光控制引脚 | 可选 |
这里有几个关键点需要解释一下:
- SPI主从关系:屏幕是SPI从设备,我们的MCU是主设备。所以SCL对应MCU的SCK,SDA对应MCU的MOSI。
- RES引脚:如果不方便用GPIO控制,可以将其连接到MCU的复位引脚。这样MCU复位时,屏幕也跟着复位,算是一个省IO的窍门。
- BLK引脚:背光控制。如果项目不需要调节背光亮度,可以直接接3.3V常亮,或者悬空(有些模块内部已上拉)。
在我的项目中,我使用的是立创开发板,具体的连接关系如下,你可以根据自己板子的GPIO资源进行调整:
| 屏幕引脚 | 我的开发板连接 |
|---|---|
| GND | GND |
| VCC | 3V3 |
| SCL | P302 (作为SPI的SCK) |
| SDA | P207 (作为SPI的MOSI) |
| RES | P403 (普通GPIO) |
| DC | P407 (普通GPIO) |
| CS | P408 (普通GPIO) |
| BLK | P409 (普通GPIO,用于PWM调光) |
2. 驱动代码移植详解
硬件接好后,接下来就是软件部分的重头戏了。移植的核心工作就是修改厂家提供的驱动代码,让它能在你的开发板和编译环境下跑起来。
2.1 工程文件准备
首先,把资料包里的 LCD 文件夹整个复制到你自己的工程目录下。通常我会放在 Drivers 或 User 文件夹里,保持工程结构清晰。
然后,在你的IDE(比如Keil、IAR或者立创的RASC)中,将 LCD 文件夹下的 .c 和 .h 文件添加到工程。主要涉及以下四个文件:
lcd_init.c/h:屏幕初始化、底层SPI通信、基本命令写入函数。lcd.c/h:上层应用函数,如画点、画线、显示字符图片等。
添加完成后,记得在需要调用LCD功能的主文件里(比如 main.c 或 app.c)包含头文件 #include "lcd.h"。
2.2 关键代码修改与解析
直接复制代码肯定会编译不过,因为引脚定义、延时函数、SPI接口都不同。我们需要有针对性地修改。
第一步:修改引脚定义 (lcd_init.h)
这是最需要修改的地方。找到文件中关于引脚宏定义的部分,根据你实际的硬件连接进行修改。
//-----------------LCD端口定义----------------
// 根据你的连接修改以下四个宏定义
#define LCD_RES_PIN BSP_IO_PORT_04_PIN_03 // RES -> P403
#define LCD_DC_PIN BSP_IO_PORT_04_PIN_07 // DC -> P407
#define LCD_CS_PIN BSP_IO_PORT_04_PIN_08 // CS -> P408
#define LCD_BLK_PIN BSP_IO_PORT_04_PIN_09 // BLK -> P409
/* LCD信号控制宏定义 */
// 这些宏定义了如何控制上述引脚的高低电平
// 通常使用你的HAL库或SDK提供的GPIO写函数
#define LCD_RES_Clr() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_RES_PIN, 0) // RES拉低
#define LCD_RES_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_RES_PIN, 1) // RES拉高
// ... DC, CS, BLK 同理
第二步:修改SPI通信函数 (lcd_init.c)
厂家例程可能使用软件模拟SPI(GPIO翻转)或硬件SPI。我推荐使用硬件SPI,速度更快,不占用CPU。你需要将 LCD_Writ_Bus(u8 dat) 这个函数替换成你自己平台的SPI发送函数。
这是我的实现,基于立创开发板的FSP库:
void LCD_Writ_Bus(u8 dat)
{
LCD_CS_Clr(); // 拉低片选,开始通信
/* 使用硬件SPI发送一个字节数据 */
fsp_err_t err = R_SPI_WriteRead(&g_spi0_ctrl,
&dat, // 要发送的数据指针
NULL, // 接收缓冲区(我们只发不收,设为NULL)
1, // 发送数据长度(1字节)
SPI_BIT_WIDTH_8_BITS); // 数据位宽8位
if (err != FSP_SUCCESS)
{
printf("SPI发送错误\r\n");
return;
}
/* 等待SPI发送完成(这里用了中断标志位,也可用查询方式) */
while (false == g_transfer_complete);
g_transfer_complete = false; // 清除标志位
LCD_CS_Set(); // 拉高片选,结束本次通信
}
提示:
g_spi0_ctrl和g_transfer_complete需要你在别处定义和初始化。g_transfer_complete是一个在SPI发送完成中断回调函数里置位的标志位。
第三步:修改延时函数 (lcd_init.h)
驱动初始化需要用到毫秒和微秒级的延时。你需要将下面的宏定义指向你工程里已有的延时函数。
#ifndef delay_ms
#define delay_ms(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MILLISECONDS)
#endif
#ifndef delay_us
#define delay_us(x) R_BSP_SoftwareDelay(x, BSP_DELAY_UNITS_MICROSECONDS)
#endif
第四步:理解核心函数
修改完硬件相关的部分,我们来看看几个最核心的函数,理解它们才能用好驱动。
-
LCD_WR_REG(u8 dat)和LCD_WR_DATA(u16 dat):LCD_WR_REG用于向GC9A01芯片写入命令(比如设置显示方向、开显示等)。在写命令前,需要把DC引脚拉低。LCD_WR_DATA用于向芯片写入数据(比如要显示的颜色值)。在写数据前,需要把DC引脚拉高。- 这两个函数是所有高级功能(画图、写字)的基础。
-
LCD_Address_Set(u16 x1, u16 y1, u16 x2, u16 y2):- 这是最关键的函数之一。它用于设置接下来要写入数据的屏幕区域(窗口)。
- 例如,
LCD_Address_Set(10, 20, 50, 100)就设定了一个从(10,20)到(50,100)的矩形区域。之后调用LCD_WR_DATA写入的颜色数据,就会依次填充这个区域。 - 画点、填充矩形、显示图片等操作前,都必须先调用这个函数设置好范围。
-
LCD_Init(void):- 初始化函数。里面是一长串按照GC9A01数据手册编写的寄存器配置序列。除非你非常了解这颗驱动芯片,否则不要随意修改里面的数值。 这些“魔法数字”负责初始化屏幕的伽马、电压、扫描方向等参数。
2.3 屏幕方向设置
在 lcd_init.h 文件中,有一个重要的宏定义,用于设置屏幕是横屏还是竖屏显示:
#define USE_HORIZONTAL 0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
这个设置会影响 LCD_Init() 函数中对扫描方向的配置。如果你发现显示的内容方向不对,修改这个值(0,1,2,3)试试看。
3. 应用层函数使用与显示测试
底层驱动调通后,我们就可以使用 lcd.c 中提供的高级函数来显示内容了。这些函数都是基于前面讲的核心函数构建的。
3.1 基本图形绘制
lcd.c 提供了丰富的绘图函数,我们挑几个最常用的来看看:
- 清屏或填充颜色:
LCD_Fill(0, 0, LCD_W, LCD_H, WHITE)可以将整个屏幕填充为白色。 - 画点:
LCD_DrawPoint(100, 100, RED)在坐标(100,100)处画一个红点。 - 画线:
LCD_DrawLine(10, 10, 100, 50, BLUE)从(10,10)到(100,50)画一条蓝线。 - 画矩形:
LCD_DrawRectangle(30, 30, 80, 80, GREEN)画一个绿色矩形框。 - 画圆:
Draw_Circle(120, 120, 40, YELLOW)以(120,120)为圆心,画一个半径为40的黄色圆。
3.2 显示文字与数字
显示文字稍微复杂一点,因为需要字库。例程中通常包含英文字符的点阵数组(在 lcdfont.h 中)。显示汉字则需要额外的汉字字库,并调用对应的函数。
- 显示英文字符串:
LCD_ShowString(10, 50, "Hello World!", RED, WHITE, 16, 0)在(10,50)位置以16号字体、红字白底显示字符串。 - 显示整数:
LCD_ShowIntNum(100, 80, 12345, 5, BLUE, BLACK, 24)显示5位整数12345。 - 显示汉字:
LCD_ShowChinese(30, 40, "中景园电子", RED, WHITE, 32, 0)显示汉字。注意:这里的汉字字符串“中景园电子”需要提前用取模软件生成点阵数组,并放入字库中。例程中的tfont16,tfont24等就是字库数组。
3.3 编写测试程序
最后,我们在主函数里写一个简单的测试程序,把上面功能都试一遍。下面是一个参考例程,它会显示一些文字和一个递增的数字,并贴上一张小图片。
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h" // 假设这里存放了图片数组
void main_app(void)
{
u8 i, j;
float t = 0;
LCD_Init(); // 初始化屏幕
LCD_Fill(0, 0, LCD_W, LCD_H, WHITE); // 清屏为白色
while(1)
{
// 显示汉字
LCD_ShowChinese(30, 40, "中景园电子", RED, WHITE, 32, 0);
// 显示英文字符串
LCD_ShowString(32, 80, "LCD_Diameter:", RED, WHITE, 16, 0);
// 显示屏幕宽度(整数)
LCD_ShowIntNum(134, 80, LCD_W, 3, RED, WHITE, 16);
// 显示递增的数字(浮点数)
LCD_ShowString(32, 100, "Increaseing Num:", RED, WHITE, 16, 0);
LCD_ShowFloatNum1(160, 100, t, 4, RED, WHITE, 16);
t += 0.11;
// 显示一张40x40的小图片,平铺显示
for(j = 0; j < 3 ; j++)
{
for(i = 0; i < 6; i++)
{
LCD_ShowPicture(40*i, 120+j*40, 40, 40, gImage_1);
}
}
// 可以加个延时,控制刷新速度
delay_ms(200);
}
}
将代码编译下载到开发板,如果一切顺利,你就能看到屏幕上显示出文字和图案了。那个浮点数会不断累加,形成动态效果。
4. 常见问题与调试心得
-
屏幕白屏或花屏:
- 首先检查电源和地线,确保电压是稳定的3.3V。
- 检查SPI时钟极性(CPOL)和相位(CPHA)。GC9A01通常工作在模式0(CPOL=0, CPHA=0)或模式3(CPOL=1, CPHA=1)。我的例程使用的是模式0。如果不对,屏幕无法正确解析数据。
- 检查复位时序。在初始化最开始,确保给了足够长的复位低电平脉冲(通常几十毫秒)。
-
显示方向或颜色不对:
- 检查
USE_HORIZONTAL的设定。 - 检查颜色格式。GC9A01通常使用RGB565格式(16位色),即一个像素点用2个字节表示。确保你发送的颜色数据格式正确。
- 检查
-
SPI通信失败:
- 用逻辑分析仪或示波器抓一下SCK、MOSI、CS、DC这几个引脚的波形,是最直接的调试方法。看是否有数据发出,时序是否符合要求。
- 确认SPI的时钟频率是否合适。刚开始调试时,可以先把频率设低一点(比如1MHz),稳定后再提高。
-
显示内容错位:
- 重点检查
LCD_Address_Set函数。确保你设置的坐标区域没有超出屏幕范围(0-239)。 - 画点函数
LCD_DrawPoint内部调用了LCD_Address_Set(x,y,x,y),如果你自己设置区域后忘记改回来,会影响后续操作。
- 重点检查
这块GC9A01的屏幕性价比很高,圆形设计也很适合做穿戴设备。驱动移植的关键在于耐心,一步步对照引脚、修改底层通信函数、理解初始化序列。一旦底层打通,上面的图形界面开发就是顺水推舟了。希望这篇实战记录能帮你快速点亮手中的小圆屏。
更多推荐
所有评论(0)