STM32F103驱动ST7567 LCD屏:手把手教你移植U8g2库(SPI接口,附完整工程)

发布时间:2026/5/20 2:04:36

STM32F103驱动ST7567 LCD屏:手把手教你移植U8g2库(SPI接口,附完整工程) STM32F103驱动ST7567 LCD屏从零开始移植U8g2库实战指南当你第一次拿到一块ST7567驱动的LCD屏时可能会被各种引脚定义和初始化代码搞得晕头转向。本文将带你从硬件连接到软件移植一步步完成U8g2库在STM32F103上的适配过程。不同于简单的代码复制粘贴我们会深入理解每个移植环节背后的原理确保你不仅能成功点亮屏幕还能掌握二次开发的能力。1. 硬件准备与环境搭建1.1 认识你的LCD模块常见的ST7567驱动LCD屏如JLX12864通常具有以下特性128x64像素分辨率单色显示支持SPI和8位并行接口工作电压3.3V-5V典型引脚定义引脚名称功能描述连接STM32引脚建议VCC电源正极(3.3V/5V)3.3VGND电源地GNDSCL时钟信号PA5(SPI1_SCK)SDA数据信号PA7(SPI1_MOSI)CS片选信号任意GPIORES复位信号任意GPIOA0数据/命令选择任意GPIOLED背光正极通过电阻接VCC1.2 开发环境准备推荐使用以下工具组合IDE选择Keil MDK适合传统开发STM32CubeIDE集成HAL库新手友好必备软件STM32CubeMX用于引脚配置ST-Link Utility烧录调试硬件连接检查清单确认LCD供电电压与开发板匹配检查所有信号线连接正确确保背光电路有适当限流电阻// 示例STM32CubeMX生成的SPI初始化代码HAL库 void MX_SPI1_Init(void) { hspi1.Instance SPI1; hspi1.Init.Mode SPI_MODE_MASTER; hspi1.Init.Direction SPI_DIRECTION_2LINES; hspi1.Init.DataSize SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity SPI_POLARITY_LOW; hspi1.Init.CLKPhase SPI_PHASE_1EDGE; hspi1.Init.NSS SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler SPI_BAUDRATEPRESCALER_8; hspi1.Init.FirstBit SPI_FIRSTBIT_MSB; hspi1.Init.TIMode SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial 10; if (HAL_SPI_Init(hspi1) ! HAL_OK) { Error_Handler(); } }2. U8g2库精简与适配2.1 获取与精简U8g2源码从GitHub克隆最新U8g2库git clone https://github.com/olikraus/u8g2.git必须保留的文件csrc/u8g2.h- 核心头文件csrc/u8x8.h- 底层驱动接口csrc/u8g2_d_setup.c- 显示控制器设置csrc/u8g2_d_memory.c- 内存管理csrc/u8g2_buffer.c- 显示缓冲csrc/u8x8_byte.c- 字节传输实现csrc/u8x8_gpio.c- GPIO抽象层提示ST7567驱动文件位于csrc/u8g2_d_st7567.c这是必须包含的核心驱动文件。2.2 关键文件修改指南u8g2_d_setup.c修改要点仅保留ST7567相关的初始化函数注释掉其他不用的显示控制器代码// 修改后的u8g2_d_setup.c示例 void u8g2_Setup_st7567_jlx12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb) { uint8_t tile_buf_height; uint8_t *buf; u8g2_SetupDisplay(u8g2, u8x8_d_st7567_jlx12864, u8x8_cad_001, byte_cb, gpio_and_delay_cb); buf u8g2_m_16_8_f(tile_buf_height); u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); }u8g2_d_memory.c优化仅保留实际使用的内存分配函数删除其他控制器专用的内存管理代码// 精简后的内存管理函数 uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt) { static uint8_t buf[1024]; // 128x64/8 1024字节 *page_cnt 8; return buf; }3. 硬件抽象层实现3.1 GPIO初始化配置根据你的实际硬件连接修改以下宏定义// 硬件引脚定义根据实际连接修改 #define LCD_CS_PORT GPIOA #define LCD_CS_PIN GPIO_PIN_4 #define LCD_DC_PORT GPIOA #define LCD_DC_PIN GPIO_PIN_3 #define LCD_RESET_PORT GPIOA #define LCD_RESET_PIN GPIO_PIN_2 // GPIO初始化函数 void LCD_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; // 使能GPIO时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); // CS引脚配置 GPIO_InitStruct.Pin LCD_CS_PIN; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull GPIO_NOPULL; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(LCD_CS_PORT, GPIO_InitStruct); // DC引脚配置 GPIO_InitStruct.Pin LCD_DC_PIN; HAL_GPIO_Init(LCD_DC_PORT, GPIO_InitStruct); // RESET引脚配置 GPIO_InitStruct.Pin LCD_RESET_PIN; HAL_GPIO_Init(LCD_RESET_PORT, GPIO_InitStruct); // 初始状态设置 HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(LCD_RESET_PORT, LCD_RESET_PIN, GPIO_PIN_SET); }3.2 关键回调函数实现gpio_and_delay_cb是U8g2与硬件交互的核心接口需要实现以下功能uint8_t u8g2_gpio_and_delay_stm32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: // 硬件初始化 LCD_GPIO_Init(); MX_SPI1_Init(); break; case U8X8_MSG_DELAY_MILLI: // 毫秒级延时 HAL_Delay(arg_int); break; case U8X8_MSG_GPIO_CS: // 片选信号控制 HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, (GPIO_PinState)arg_int); break; case U8X8_MSG_GPIO_DC: // 数据/命令选择 HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, (GPIO_PinState)arg_int); break; case U8X8_MSG_GPIO_RESET: // 复位控制 HAL_GPIO_WritePin(LCD_RESET_PORT, LCD_RESET_PIN, (GPIO_PinState)arg_int); break; default: return 0; } return 1; }4. 显示测试与性能优化4.1 初始化序列与基础测试完成移植后使用以下代码测试LCDu8g2_t u8g2; // 初始化U8g2库 u8g2_Setup_st7567_jlx12864_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8g2_gpio_and_delay_stm32); u8g2_InitDisplay(u8g2); // 初始化显示 u8g2_SetPowerSave(u8g2, 0); // 关闭省电模式 u8g2_SetContrast(u8g2, 130); // 设置对比度(0-255) // 绘制测试图形 u8g2_ClearBuffer(u8g2); u8g2_SetFont(u8g2, u8g2_font_ncenB14_tr); u8g2_DrawStr(u8g2, 10, 30, Hello ST7567); u8g2_DrawBox(u8g2, 5, 35, 118, 20); u8g2_SendBuffer(u8g2);4.2 SPI通信优化技巧硬件SPI加速修改u8x8_byte_4wire_sw_spi为硬件SPI实现提升SPI时钟频率最高支持10MHz// 硬件SPI传输实现示例 uint8_t u8x8_byte_stm32_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_BYTE_SEND: HAL_SPI_Transmit(hspi1, (uint8_t *)arg_ptr, arg_int, HAL_MAX_DELAY); break; case U8X8_MSG_BYTE_INIT: break; case U8X8_MSG_BYTE_SET_DC: HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, (GPIO_PinState)arg_int); break; case U8X8_MSG_BYTE_START_TRANSFER: HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET); break; case U8X8_MSG_BYTE_END_TRANSFER: HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET); break; } return 1; }双缓冲技术使用u8g2_Setup_st7567_jlx12864_1和u8g2_Setup_st7567_jlx12864_2初始化交替刷新减少闪烁4.3 常见问题排查屏幕无显示检查背光是否点亮测量RESET信号是否正常确认SPI信号是否有波形显示乱码检查SPI时钟极性设置确认字节传输顺序MSB/LSB验证对比度设置是否合适刷新缓慢切换到硬件SPI模式提高SPI时钟频率减少全屏刷新次数

相关新闻