news 2026/5/7 13:19:35

STM32F4驱动ST7735S小屏幕:从SPI配置到图片显示,一个完整项目带你玩转TFTLCD

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F4驱动ST7735S小屏幕:从SPI配置到图片显示,一个完整项目带你玩转TFTLCD

STM32F4驱动ST7735S小屏幕:从SPI配置到图片显示实战指南

手里这块1.44寸的ST7735S屏幕已经吃灰三个月了?跟着我做这个温湿度监测项目,保证让你的开发板和小屏幕都活起来。不需要死记硬背那些SPI参数,咱们直接动手做出能显示动态数据的实用界面。

1. 硬件连接与SPI配置

先来看看硬件接线。ST7735S通常有7个关键引脚需要连接:

屏幕引脚STM32F4对应引脚备注
VCC3.3V注意电压匹配
GNDGND共地是关键
SCLPB3 (SPI1_SCK)时钟信号线
SDAPB5 (SPI1_MOSI)主设备输出从设备输入
RESPA1自定义复位引脚
DCPA2数据/命令选择
CSPA3片选信号

硬件SPI初始化代码要特别注意时钟相位和极性的配置:

void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; SPI_InitTypeDef SPI_InitStruct; // 启用GPIOB和SPI1时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // 配置PB3(SCK), PB5(MOSI)为复用功能 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStruct); // 引脚复用映射 GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1); // SPI参数配置 SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; // 单线发送模式 SPI_InitStruct.SPI_Mode = SPI_Mode_Master; SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL = SPI_CPOL_High; // 关键配置 SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge; // 关键配置 SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 21MHz/4=5.25MHz SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStruct); SPI_Cmd(SPI1, ENABLE); }

提示:ST7735S的SPI时序要求CPOL=1, CPHA=1,这个配置不对屏幕会完全没有反应。如果遇到白屏问题,首先检查这两项参数。

2. 屏幕初始化与基础绘图

ST7735S的初始化需要发送一系列命令和参数。这里有个技巧:把厂商提供的初始化代码封装成数组,直接批量发送:

const uint8_t init_cmds[] = { // 命令 参数长度 参数 0x11, 0, // 睡眠退出 0x36, 1, 0x08, // 内存访问控制 0x3A, 1, 0x05, // 颜色格式设置 RGB565 0xB1, 2, 0x01, 0x2C, // 帧率控制 0xB2, 2, 0x01, 0x2C, // 帧率控制 0xB3, 2, 0x01, 0x2C, 0x01, 0x2C, // 帧率控制 0xB4, 1, 0x07, // 显示反转控制 0xC0, 2, 0xA2, 0x02, // 电源控制1 0xC1, 1, 0x05, // 电源控制2 0xC2, 2, 0x0A, 0x00, // 电源控制3 0xC3, 2, 0x8A, 0x2A, // 电源控制4 0xC4, 2, 0x8A, 0xEE, // 电源控制5 0xC5, 1, 0x0E, // VCOM控制 0x20, 0, // 关闭反显 0x29, 0 // 开启显示 }; void ST7735_Init(void) { uint8_t *p = (uint8_t *)init_cmds; for(int i=0; i<sizeof(init_cmds);) { uint8_t cmd = p[i++]; uint8_t len = p[i++]; ST7735_WriteCommand(cmd); while(len--) { ST7735_WriteData(p[i++]); } if(cmd == 0x11 || cmd == 0x29) { delay_ms(120); // 重要命令需要延时 } } }

实现基础绘图函数时,注意设置正确的窗口地址:

void ST7735_SetWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { ST7735_WriteCommand(0x2A); // 列地址设置 ST7735_WriteData(0); ST7735_WriteData(x0); ST7735_WriteData(0); ST7735_WriteData(x1); ST7735_WriteCommand(0x2B); // 行地址设置 ST7735_WriteData(0); ST7735_WriteData(y0); ST7735_WriteData(0); ST7735_WriteData(y1); ST7735_WriteCommand(0x2C); // 开始写入GRAM } void ST7735_DrawPixel(uint8_t x, uint8_t y, uint16_t color) { if(x >= 128 || y >= 160) return; ST7735_SetWindow(x, y, x, y); ST7735_WriteData(color >> 8); ST7735_WriteData(color & 0xFF); }

3. 图片显示与字库实现

显示图片前需要将图片转换为RGB565格式的数组。推荐使用Img2Lcd工具,设置如下:

  1. 输出格式选择"C语言数组"
  2. 扫描模式选择"水平扫描"
  3. 颜色位数选择"16位真彩色"
  4. 勾选"高位在前"选项

生成的数组可以直接用DMA传输:

// 图片数据示例 const uint16_t gImage_test[128*160] = { 0xFFFF, 0xFFFF, 0xFFFF, // ... }; void ST7735_ShowImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *img) { ST7735_SetWindow(x, y, x+width-1, y+height-1); ST7735_WriteData_DMA((uint8_t *)img, width*height*2); }

字库实现需要先制作字模。使用PCtoLCD2002软件生成8x16 ASCII字库:

  1. 选择"字符模式"
  2. 设置字体为宋体,大小8x16
  3. 取模方式设置为"逐行式","高位在前"
  4. 生成所有可见ASCII字符(0x20-0x7E)
// 8x16 ASCII字模示例 const uint8_t font8x16[95][16] = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 空格 {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // ! // ...其他字符 }; void ST7735_DrawChar(uint8_t x, uint8_t y, char c, uint16_t color, uint16_t bgcolor) { if(c < 0x20 || c > 0x7E) return; const uint8_t *p = font8x16[c - 0x20]; for(uint8_t i=0; i<16; i++) { uint8_t line = p[i]; for(uint8_t j=0; j<8; j++) { if(line & (0x80 >> j)) { ST7735_DrawPixel(x+j, y+i, color); } else if(bgcolor != TRANSPARENT) { ST7735_DrawPixel(x+j, y+i, bgcolor); } } } }

4. 温湿度监测界面实现

结合DHT11传感器,我们可以实现一个完整的温湿度监测界面。首先设计界面布局:

typedef struct { uint16_t temp; uint16_t humidity; uint8_t update_flag; } EnvData; void UI_DrawFrame(void) { // 绘制边框 ST7735_DrawRect(0, 0, 127, 159, RGB(0,255,0)); // 绘制标题 ST7735_DrawString(10, 5, "Env Monitor", RGB(255,255,255), RGB(0,0,0)); // 温度区域 ST7735_FillRect(10, 30, 108, 50, RGB(50,50,50)); ST7735_DrawString(15, 35, "Temperature:", RGB(255,255,0), RGB(50,50,50)); // 湿度区域 ST7735_FillRect(10, 90, 108, 50, RGB(50,50,50)); ST7735_DrawString(15, 95, "Humidity:", RGB(0,255,255), RGB(50,50,50)); } void UI_UpdateData(EnvData *data) { if(data->update_flag) { char buf[16]; // 更新温度 sprintf(buf, "%2d C",>int main(void) { SystemInit(); ST7735_Init(); DHT11_Init(); UI_DrawFrame(); EnvData env = {0}; uint32_t last_update = 0; while(1) { if(HAL_GetTick() - last_update > 2000) { // 每2秒更新一次 if(DHT11_ReadData(&env.temp, &env.humidity) == SUCCESS) { env.update_flag = 1; UI_UpdateData(&env); } last_update = HAL_GetTick(); } } }

注意:实际项目中建议使用双缓冲机制,先在内存中绘制完整帧再一次性刷新到屏幕,可以避免闪烁现象。对于STM32F4,可以利用其充足的RAM开辟一个128x160x2=40KB的显存缓冲区。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 13:16:29

GuardClaw:为AI助手构建本地隐私执行层的实战指南

1. 项目概述&#xff1a;为你的AI助手装上隐私“利爪” 如果你和我一样&#xff0c;每天都在用各种AI助手处理工作&#xff0c;从写代码、分析数据到整理会议纪要&#xff0c;那你肯定也思考过同一个问题&#xff1a;我发给云端AI的那些信息&#xff0c;真的安全吗&#xff1f;…

作者头像 李华
网站建设 2026/5/7 13:13:29

老漏洞新谈:CVE-2010-0738的HEAD请求绕过与JBoss JMX Console的权限之殇

CVE-2010-0738&#xff1a;HEAD请求的艺术与JMX Console的防御盲区 十年前那个春寒料峭的三月&#xff0c;当安全研究员在JBoss JMX控制台前反复切换HTTP请求方法时&#xff0c;一个看似平常的HEAD请求意外触发了系统响应。这个后来被编号为CVE-2010-0738的漏洞&#xff0c;不…

作者头像 李华
网站建设 2026/5/7 13:12:31

STM32H7实战:用CubeMX+FreeRTOS打造一个能插拔的SD卡虚拟U盘(附源码)

STM32H7动态资源管理实战&#xff1a;基于FreeRTOS的SD卡/U盘双模热切换架构设计 在嵌入式系统开发中&#xff0c;外设资源的动态管理一直是提升系统灵活性的关键挑战。想象一下这样的场景&#xff1a;你的工业数据采集设备正在通过SD卡持续记录传感器数据&#xff0c;当工程师…

作者头像 李华
网站建设 2026/5/7 13:11:34

量子误差缓解与非厄米动力学模拟技术解析

1. 量子误差缓解与非厄米动力学模拟概述量子计算作为下一代计算范式&#xff0c;其核心优势在于利用量子叠加和纠缠等特性解决经典计算机难以处理的复杂问题。然而&#xff0c;量子系统极易受到环境噪声的影响&#xff0c;导致计算误差积累。量子误差缓解(Quantum Error Mitiga…

作者头像 李华