记录AT32开发中遇到的问题;
硬件部分:
硬件部分我是参考官方开发板来做的;
经过测试,硬件部分没有任何问题;
| 原理图 | ![]() |
|---|---|
| PCB仿真图 | ![]() |
| 实物图 | ![]() |
| 显示效果 | ![]() |
有几个值得关注的地方,我将在下面列出:
使用编码器开关作为输入设备;
使用CH340E芯片作为串口转USB;
通过TYPE-C接口的正反插实现不同的功能(连接CH340E芯片和AT32的USB引脚):
屏幕接口采用的是FPC0.5mm接口,方便安装;
硬件部分的测试很快就结束了,主要就是测试各个外设是否能正常使用;
经测试,主控芯片、屏幕、spiflash、USB接口、CH340E、编码器开关、RTC时钟均能正常使用;
软件开发:
参考资料:
主控芯片使用的是雅特力的AT32F403ACGU7,其特性如下所示:
![]() |
|---|
参考资料网站:https://www.arterytek.com/cn/product/AT32F403A.jsp
![]() |
|---|
下载固件库源码,经解压后,可以在目录:
1 | .\AT32F403A_407_Firmware_Library_V2.1.2\project\at_start_f403a\examples |
找到各个外设的例子:
1 | $ ls |
首先当然是串口打印和点灯,这样能测试时钟配置是否正常,以及判断芯片好坏与否;
具体开发:
关键代码如下:
点灯:
1 | void at32_led_init(void) |
串口:
1 | void uart_print_init(uint32_t baudrate) |
串口重定向:
1 |
|
然后在main函数中分别初始化后即可:
1 | at32_led_init(); |
通过USB线将板子连接在电脑上,即可通过串口助手收到板子发送的信息,并且板子上的LED开始闪烁;
LCD屏幕:
然后便是测试LCD屏幕,LCD的接口使用的是SPI串行通信接口,使用AT32的硬件SPI接口,初始方案使用的是中景园的例子,成功点亮,后续为了提高帧率,优化了下,并且使用DMA传输,刷屏速度大大加快;
下表是引脚配置:
| LCD引脚 | AT32引脚 |
|---|---|
| RST | PA8 |
| DC | PB10 |
| CS | PB12 |
| BLK | PA3 |
| MOSI | PB15(SPI2) |
| CLK | PB13(SPI2) |
下边是屏幕驱动的关键代码:
1 | /* |
编码器开关:
接下来是测试编码器开关,编码器型号为:SIQ-02FVS3,
![]() |
![]() |
|---|---|
根据上述原理图可以发现这其实跟光电编码器很相似;
因而我使用外部中断来检测编码器的转动方向和转动角度以及按键状态:
1 | static uint8_t flag_exit = 0; |
cnt_encode中存放旋转次数(24°为1单位),至于按键的按动状态检测则放在了1ms的定时器中;
经测试,该检测算法可以很好的消除拨码开关转动时的抖动,最后得到的结果是比较准确的;
中间件移植:
外设都测试完毕,接下来就是各种中间件的移植:LVGL移植、FATFS移植、USB Device等;
LVGL-8.3移植:
文件夹创建:
下载以后打开文件可以看见下面四个文件:
![]() |
|---|
第一步:
在stm32工程下面创建一个文件夹,名称为lvgl;
将上图中的四个文件加入到lvgl文件夹中;
把lv_conf_template.h文件重命名为lv_conf.h;
![]() |
|---|
第二步:
在lvgl/examples/porting文件夹中把三个.h文件开头的#if 0改为#if 1;
打开你原本的stm32工程(就是那个正常驱动屏幕的工程),使能c99;
![]() |
|---|
第三步:
在左侧栏中添加两个文件夹
![]() |
|---|
添加两个port文件,位于lvgl/examples/porting,因为没有用到文件系统,故没有添加fs:
![]() |
|---|
添加lvgl源文件,将lvgl/src目录下的core draw font hal misc widgets文件夹下的所有文件全部添加进lvgl组
注:文件夹中还有子文件夹要一层一层打开并加入;
![]() |
|---|
将lvgl/src/extra/目录下的文件添加进lvgl组。具体为:
layouts目录下所有子目录文件;
themes目录下所有子目录文件;
widgets目录下所有子目录文件;
lv_extra.c;
![]() |
|---|
加入路径,将lvgl ,src,porting文件夹添加到源路径下。
![]() |
|---|
修改配置文件:
修改lv_port_disp_template.h:
![]() |
|---|
修改lv_port_disp_template.c:
将开头的#if 0改成#if 1
修改lv_conf.h:
![]() |
|---|
这两句是修改你屏幕大小的,直接粘贴在那里就可以了。
1 |
修改显示的必要文件:
在lv_port_disp_template.c中包含着显示的重要文件,这里我们只需要修改两处:
第一处:
把框选的地方注释掉,
![]() |
|---|
去除warning;
此时编译应该没有error,但是有warning这个warning无伤大雅可以直接屏蔽;
![]() |
|---|
--diag_suppress=188,546,68,111
当完成这一步的时候就已经说明你已经把显示的移植了99%了,可以编译看一下是否有报错;
第二处:
这是刷新函数,用于图形填充的,这里介绍两种方法,第一种是不断画点,只需要把红色部分写成你原来工程中的画点的函数就可以了,如果你的画点函数传入的形参中颜色的定义并不是指针的方式的话,一定要写成图中color_p->full的形式,不然会报错的。
不要把
#include“lcd.h”遗忘
![]() |
|---|
第二种方法是通过区域填充来实现的如果你是使用中景园的代码,你直接调用他的区域填充函数基本上会花屏,所以需要对他的函数进行一下改良。
可在你本来工程下面的lcd.c中添加一段代码:
1 | void lvgl_LCD_Color_Fill(u16 sx, u16 sy, u16 ex, u16 ey, lv_color_t *color) |
也许他会报错说找不到lv_color_t这是以为我们没有在文件开头添加#include "lvgl.h"添加以后还需要在lcd.h文件中进行声明,不出意外还会报错,需要你在文件开头加入#include "lvgl.h",我们就可以把第一种的描点换成画图:
![]() |
|---|
显示测试:
在main.c中`#include "lvgl.h" #include "lv_port_disp_template.h" 随后在屏幕初始化后面加上代码:
1 | lv_init(); |
还需要一个在嘀嗒定时器里加一个跳动的“心脏”进行刷新;
lv_tick_inc(1);//在中断里面进行刷新;如果这个对你而言比较难实现你也可以把这个放到主函数的循环里面;
并在主函数中创建一个测试函数:
1 | void lv_ex_label(void) |
将测试函数写在lv_port_disp_init();的后面
1 | LCD_Init(); |
在主函数中写:
1 | lv_task_handler(); |
lv_port_disp.c示例代码:
1 |
|
这里的数据传输部分的代码直接使用的是DMA传输,在该分辨率下,lvgl的benchmark加权平均帧率甚至能达到200FPS;





















