在STM32上使用U8g2图形库驱动GP1287 VFD屏(LL库)
izilzty 发布于 阅读:6309
本文将以STM32F103C8T6和GP1287VFD屏为例,从CubeMX创建工程开始进行说明。以前有写过一些用法,在这里,但是当时更多的是写的怎么自己修改库来支持这个屏幕,关于怎么创建工程写的比较少。最近刚好在测试这个屏幕,所以就用它来演示。
最后附有创建好的测试工程,如有需要请自行下载。文章所有步骤都有操作验证一遍,但是不排除遗漏的可能,如果按照文章建立工程无法点亮屏幕,但使用后面所附的示例工程可以点亮的话请留言说明,我会再次检查。
1、准备工作
-
从GitHub上下载U8g2的源码:https://github.com/olikraus/u8g2,解压后备用。这里只用到clib文件夹内的文件,其他文件可以删除
-
确保使用的Keil uVision支持AC6编译器,这样可以省下手动去除U8g2库内不使用代码的工作。
2、使用CubeMX创建工程
-
根据你的开发板晶振频率配置好时钟树,这里HCLK频率设置为72MHz,频率可以随意设置,最终保证你的SPI时钟率适合屏幕即可。
-
在右侧芯片视图上右键分配3个
GPIO_Output
引脚,分别命名为SPI1_CS
、SPI1_RESET
、SPI1_HVEN
,并在左侧GPIO
选项卡内按照表格配置引脚。参数(SPI1_CS、SPI1_RESET) 值 GPIO output level High Maximum output speed High 参数(SPI1_HVEN) 值 GPIO output level Low Maximum output speed Low -
在左侧选项卡内将
SPI1
设置为Transmit Only Master
,并按表格配置分频和数据格式,未出现的值保持默认即可。参数 值 First Bit MSB First Prescaler 16 (4.5MBits/s) CPOL High CPHA 2 Edge -
在左侧
SYS
选项卡内开启Serial Wire DEBUG
启用调试。 -
在上方
Project Manager
选项卡的Project
页面内输入工程名称、选择IDE为MDK-ARM
。 -
在上方
Project Manager
选项卡的Advanced Setting
内点击所有HAL
字符,并在下拉框内修改为LL
以使用LL库。 -
点击右上方
GENERATE CODE
生成代码。
3、将U8g2源码加入工程
-
将U8g2的
clib
文件夹复制到工程的根文件夹(和MDK-ARM文件夹平级),并改名为U8g2
。 -
用Keil打开刚才生成的工程。
-
点击魔术棒图标或按快捷
Alt+F7
打开工程配置页面。 -
在
Target
选项卡内将编译器修改为version 6
。 -
在
C/C++(AC6)
选项卡内将U8g2文件夹添加到Include目路径中,可以只用相对路径,在这里为..\U8g2
。 -
确定并关闭工程配置页面。
-
在左侧工程文件树内右键选择
Add Group
添加一个组,重命名为U8g2
。 -
双击这个组,将U8g2文件夹内所有C文件添加进去。
4、添加自定义IO和延时回调,供U8g2调用
-
展开Application/User/Core,打开main.c
-
在开头用户代码区域加入U8g2头文件:
/* USER CODE BEGIN Includes */ #include "u8g2.h" /* USER CODE END Includes */
-
定义一个全局U8g2变量,里面会存放显示数据。
/* USER CODE BEGIN PV */ u8g2_t u8g2; /* USER CODE END PV */
-
在main函数前的自定义代码区域增加IO和延时回调函数:
/* USER CODE BEGIN 0 */ uint8_t u8x8_byte_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_BYTE_INIT: LL_SPI_Enable(SPI1); break; case U8X8_MSG_BYTE_SEND: for (uint8_t i = 0; i < arg_int; i++) { LL_SPI_TransmitData8(SPI1, *(uint8_t *)arg_ptr); while (LL_SPI_IsActiveFlag_TXE(SPI1) == RESET) { __NOP(); } arg_ptr = (uint8_t *)arg_ptr + 1; } break; case U8X8_MSG_BYTE_START_TRANSFER: LL_GPIO_ResetOutputPin(SPI1_CS_GPIO_Port, SPI1_CS_Pin); break; case U8X8_MSG_BYTE_END_TRANSFER: while (LL_SPI_IsActiveFlag_BSY(SPI1) == SET) { __NOP(); } LL_GPIO_SetOutputPin(SPI1_CS_GPIO_Port, SPI1_CS_Pin); break; default: return 0; } return 1; } uint8_t u8x8_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr) { switch (msg) { case U8X8_MSG_DELAY_MILLI: if (arg_int > 1) { arg_int = -1; } LL_mDelay(arg_int); break; case U8X8_MSG_GPIO_RESET: if (arg_int) LL_GPIO_SetOutputPin(SPI1_RESET_GPIO_Port, SPI1_RESET_Pin); else LL_GPIO_ResetOutputPin(SPI1_RESET_GPIO_Port, SPI1_RESET_Pin); break; default: return 0; } return 1; } /* USER CODE END 0 */
-
关于回调函数的详细信息可以参考官方移植说明:https://github.com/olikraus/u8g2/wiki/Porting-to-new-MCU-platform
5、添加初始化代码,并测试编译
-
在while函数前的自定义代码区域增加U8g2初始化代码:
/* USER CODE BEGIN 2 */ u8g2_Setup_gp1287ai_256x50_f(&u8g2, U8G2_R0, u8x8_byte_hw_spi, u8x8_gpio_and_delay); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); u8g2_SendBuffer(&u8g2); LL_GPIO_SetOutputPin(SPI1_HVEN_GPIO_Port, SPI1_HVEN_Pin); LL_mDelay(1200); /* USER CODE END 2 */
-
保存并编译,0错误0警告通过编译即为正常。
6、在屏幕上显示“HelloWorld”
-
在while函数内的自定义代码区域增加绘制代码:
u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); u8g2_DrawStr(&u8g2, 0, 10, "Hello World!"); u8g2_SendBuffer(&u8g2); LL_mDelay(1000); /* USER CODE END WHILE */
-
保存并编译下载,屏幕上应显示HelloWorld文字。
-
另外需要注意,生成的工程默认设置为下载完成后需要按一下复位按钮程序才会开始运行。