TA的每日心情  | 奋斗 2025-7-11 08:33 | 
|---|
 
  签到天数: 2 天 连续签到: 1 天 [LV.1]初来乍到 
举人 
 
 
	- 积分
 - 511
 
 
 
 
 | 
 
 
?零知开源是一个真正属于国人自己的开源软硬件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧! 
 
 
 
(1)项目概述 
  本教程将重点讲解如何在STM32F407VET6零知增强板上实现ST7789显示屏的中文显示功能,结合BMP581传感器数据展示。项目使用I2C通信读取传感器数据,通过SPI接口在TFT屏幕上显示中文界面。  
 (2)项目亮点 
    >使用U8g2库实现高质量中文渲染 
    >混合使用Adafruit_GFX和U8g2实现高效显示 
    >实时显示温度、压力和高度数据 
    >针对STM32F4系列优化内存使用 
  
 
 
 
一、硬件系统设计1.1 硬件组成 
组件  | 型号  | 接口  | 功能  |  主控板  | STM32F407VET6零知增强板  | -  | 核心控制器  |  气压传感器  | BMP581  | I2C  | 温度/气压数据采集  |  TFT显示屏  | ST7789  | SPI  | 数据可视化显示  |  接口扩展  | 零知扩展板  | -  | 提供标准接口  |  
  
 
 
1.2 接线方案零知增强板(STM32F407VET6)  | BMP581(I2C)  | ST7789(SPI)  | 引脚功能说明  |  3.3V  | VCC  | VCC  | 电源  |  GND  | GND  | GND  | 接地  |  21/SCL  | SCL  | /  | 时钟线  |  20/SDA  | SDA  | /  | 数据线  |  53  | /  | CS  | 片选  |  2  | /  | DC  | 数据/命令选择  |  51  | /  | SDA  | 主出从入  |  52  | /  | SCL  | 时钟  |  4  | /  | RES  | 复位  |  
  
1.3 连接硬件图 
 
 
1.4 接线实物图 
二、软件架构设计2.1 库依赖关系- SparkFun_BMP581库:提供传感器初始化接口、封装数据读取函数、处理I2C通信协议
 - Adafruit_ST7789+GFX库:实现屏幕底层驱动、提供图形绘制API、优化显示性能
 - U8g2_for_Adafruit_GFX:添加中文字符支持、扩展文本渲染能力
 
 
 
2.2 初始化流程
- // sketch_jun30d.ino
 
 - #include <Wire.h>
 
 - #include "SparkFun_BMP581_Arduino_Library.h"
 
 - #include <Adafruit_GFX.h>
 
 - #include <Adafruit_ST7789.h>
 
 - #include <SPI.h>
 
 - #include <U8g2_for_Adafruit_GFX.h>  // 添加U8g2库支持中文字体
 
  
- // Screen pin configuration
 
 - #define TFT_CS 53
 
 - #define TFT_RST 4
 
 - #define TFT_DC 2
 
 - #define TFT_MOSI 51
 
 - #define TFT_SCLK 52
 
  
- // Using hardware SPI
 
 - Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
 
 - U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;  // 创建U8g2对象
 
  
- // Create a new sensor object
 
 - BMP581 pressureSensor;
 
  
- // I2C address selection
 
 - uint8_t i2cAddress = BMP581_I2C_ADDRESS_DEFAULT;  // 0x47
 
  
- // Display configuration
 
 - #define SCREEN_WIDTH 240
 
 - #define SCREEN_HEIGHT 320
 
 - #define ST77xx_PURPLE 0x862F
 
 - #define VALUE_SIZE 3
 
 - #define LABEL_SIZE 1
 
  
- // Color definitions
 
 - #define BACKGROUND ST77XX_BLACK
 
 - #define TEXT_COLOR ST77XX_WHITE
 
 - #define TEMP_COLOR ST77xx_PURPLE
 
 - #define PRESS_COLOR ST77XX_CYAN
 
 - #define ALT_COLOR ST77XX_GREEN
 
 - #define BOX_COLOR ST77XX_ORANGE
 
  
- // 精简版中文字体定义
 
 - #define CN_FONT u8g2_font_unifont_t_chinese3  // 使用精简中文字体
 
  
- void setup() {
 
 -   Serial.begin(115200);
 
 -   Serial.println("BMP581 Enhanced Text Display Example");
 
  
-   // Initialize I2C library
 
 -   Wire.begin();
 
  
-   // Initialize screen
 
 -   tft.init(SCREEN_WIDTH, SCREEN_HEIGHT);
 
 -   tft.setRotation(3);
 
 -   tft.fillScreen(BACKGROUND);
 
 -   tft.setTextColor(TEXT_COLOR);
 
  
-   // 初始化U8g2对象,设置中文显示
 
 -   u8g2_for_adafruit_gfx.begin(tft);                      // 将U8g2与Adafruit_GFX关联
 
 -   u8g2_for_adafruit_gfx.setFontMode(1);                  // 透明模式
 
 -   u8g2_for_adafruit_gfx.setFontDirection(0);             // 从左到右
 
 -   u8g2_for_adafruit_gfx.setForegroundColor(TEXT_COLOR);  // 设置前景色
 
 -   u8g2_for_adafruit_gfx.setFont(CN_FONT);                // 使用精简中文字体
 
  
-   // Check sensor connection
 
 -   while (pressureSensor.beginI2C(i2cAddress) != BMP5_OK) {
 
 -     Serial.println("Error: BMP581 not connected, check wiring and I2C address!");
 
  
-     // 显示错误信息
 
 -     u8g2_for_adafruit_gfx.setCursor(10, 30);
 
 -     u8g2_for_adafruit_gfx.print("传感器未找到!");
 
 -     u8g2_for_adafruit_gfx.setCursor(10, 60);
 
 -     u8g2_for_adafruit_gfx.print("请排查接线!");
 
  
-     delay(1000);
 
 -     tft.fillScreen(BACKGROUND);
 
 -   }
 
  
-   Serial.println("BMP581 connected!");
 
 -   drawStaticElements();
 
 - }
 
  复制代码 
2.3 数据读取机制
- void loop() {
 
 -   // Get measurements from the sensor
 
 -   bmp5_sensor_data data = { 0, 0 };
 
 -   int8_t err = pressureSensor.getSensorData(&data);
 
  
-   if (err == BMP5_OK) {
 
 -     // Convert pressure from Pa to hPa (1 hPa = 100 Pa)
 
 -     float pressure_hPa = data.pressure / 100.0;
 
  
-     // Calculate altitude using simplified formula
 
 -     float altitude = (1013.25 - pressure_hPa) / 16.5 * 100;
 
  
-     // Update text display
 
 -     updateTextDisplay(data.temperature, pressure_hPa, altitude);
 
  
-     Serial.print("空气温度 (C): ");
 
 -     Serial.print(data.temperature);
 
 -     Serial.print("\t大气压强 (hPa): ");
 
 -     Serial.print(pressure_hPa);
 
 -     Serial.print("\t海拔高度 (m): ");
 
 -     Serial.println(altitude);
 
 -   } else {
 
 -     Serial.print("Error getting data from sensor! Error code: ");
 
 -     Serial.println(err);
 
 -   }
 
  
-   delay(1000);  // Update every second
 
 - }
 
 
  复制代码 
2.4 中文文本渲染
- void drawStaticElements() {
 
 -   tft.fillScreen(BACKGROUND);
 
  
-   // 使用U8g2绘制中文标题
 
 -   u8g2_for_adafruit_gfx.setForegroundColor(ST77XX_YELLOW);
 
 -   u8g2_for_adafruit_gfx.setCursor(SCREEN_WIDTH / 2 + 95, 20);  // 居中位置
 
 -   u8g2_for_adafruit_gfx.print("BMP581传感器");                 // 中文标题
 
  
-   // 绘制温度框和标签
 
 -   drawDataBox(30, 10, "热量", "(C)", TEMP_COLOR);
 
  
-   // 绘制压力框和标签
 
 -   drawDataBox(30, 90, "大气压强", "(hPa)", PRESS_COLOR);
 
  
-   // 绘制高度框和标签
 
 -   drawDataBox(30, 170, "距离海平面高度", "(m)", ALT_COLOR);
 
 - }
 
  
- void drawDataBox(int x, int y, const char* label, const char* unit, uint16_t color) {
 
 -   // Draw box
 
 -   tft.drawRoundRect(x, y, SCREEN_WIDTH - 60, 60, 10, BOX_COLOR);
 
  
-   // 使用U8g2绘制中文标签
 
 -   u8g2_for_adafruit_gfx.setForegroundColor(color);
 
 -   u8g2_for_adafruit_gfx.setCursor(x + 15, y + 20);  // 调整位置
 
 -   u8g2_for_adafruit_gfx.print(label);
 
  
-   // Draw unit (smaller text)
 
 -   tft.setTextSize(LABEL_SIZE - 1);
 
 -   tft.setCursor(x + SCREEN_WIDTH - 60 - 40, y + 10);
 
 -   tft.print(unit);
 
 - }
 
 
  复制代码 
2.5 动态数据更新
- void updateTextDisplay(float temp, float pressure, float altitude) {
 
 -   // Update temperature
 
 -   updateDataValue(30, 10, temp, 1, TEMP_COLOR);
 
  
-   // Update pressure
 
 -   updateDataValue(30, 90, pressure, 1, PRESS_COLOR);
 
  
-   // Update altitude
 
 -   updateDataValue(30, 170, altitude, 1, ALT_COLOR);
 
 - }
 
  
- void updateDataValue(int x, int y, float value, int decimals, uint16_t color) {
 
 -   // Clear previous value
 
 -   tft.fillRect(x + 10, y + 30, SCREEN_WIDTH - 80, 25, BACKGROUND);
 
  
-   // Draw new value
 
 -   tft.setTextSize(VALUE_SIZE);
 
 -   tft.setTextColor(color);
 
 -   tft.setCursor(x + 15, y + 30);
 
 -   tft.print(value, decimals);
 
 - }
 
 
  复制代码 
三、功能展示 3.1 显示效果标题:蓝色中文"BMP581传感器"右对齐显示 
数据框: 
    蓝色圆角矩形边框、中文标签(灰色/红色/紫色)、单位符号(小字号英文) 
数据值: 
    大字号显示(字号3)、每秒更新一次、刷新时无闪烁(局部刷新优化)  
3.2 系统工作流程 
 
 
3.3 视频演示效果 
https://live.csdn.net/v/484270
将通过传感器获取到的气压值与下面的app海拔仪气压值进行对比 
3.4 串口监视器数据串口监视器将同时每秒输出一次数据:
 
3.5 性能指标| 项目  | 指标  | 说明  |  | 采样频率  | 1Hz  | 每秒更新一次数据  |  | 温度精度  | ±0.5℃  | 符合BMP581规格  |  | 压强精度  | ±0.5hPa  | 符合BMP581规格  |  | 显示延迟  | <100ms  | 从采集到显示时间  |  | 功耗  | 15mA @3.3V  | 不含背光功耗  |   
四、海拔计算与精度说明 代码中使用简化的海拔计算公式: 
 float altitude = (1013.25 - pressure_hPa) / 12 * 100; 
 
计算原理 
   1013.25 hPa:标准海平面气压 
   气压梯度:每下降12 hPa,海拔升高约100米   
 精度考虑 ,实际测量中可能存在10-50米的误差,主要因素包括:
- 当地气象条件变化
 - 温度对气压的影响
 - 传感器本身的测量误差
 - 公式本身的近似性
 
  
五、常见问题解答Q1:为什么中文显示为方框或乱码?A:原因及解决方案
1.字体未正确设置:
 - // 确保正确定义中文字体
 
 - #define CN_FONT u8g2_font_unifont_t_chinese3
 
 - u8g2_for_adafruit_gfx.setFont(CN_FONT);
 
  复制代码
2.库版本问题: 
 - # 推荐安装的库版本
 
 - Adafruit ST7735 and ST7789 Library v1.9.3
 
 - U8g2_for_Adafruit_GFX v1.7.0 
 
  复制代码 
Q2:编译时出现内存不足错误怎么办?A:优化策略 
如果仍不足,可更换更小字体: 
// 替代字体(约30KB) 
#define CN_FONT u8g2_font_wqy12_t_gb2312  
  
Q3:如何添加更多中文内容?A:扩展方法
1.在drawStaticElements()中添加新元素 
2.确保使用的字符在字体库中存在:
 - // 添加新标签
 
 - drawDataBox(30, 250, "湿度", "%", HUMIDITY_COLOR);
 
  复制代码3.如需生僻字,需自定义字体子集(本教程未包含)
 注意:u8g2_font_unifont_t_chinese3包含GB2312一级字库(3755个常用汉字),满足大多数应用需求。 
 
  
Q4:传感器初始化失败怎么办?A:排查步骤 
1.检查I2C接线:SDA/SCL是否反接 
2.确认I2C地址:使用I2C扫描工具检测 
- void scanI2C() {
 
 -   for(uint8_t addr=1; addr<127; addr++) {
 
 -     Wire.beginTransmission(addr);
 
 -     if(Wire.endTransmission() == 0) {
 
 -       Serial.print("Found device at 0x");
 
 -       Serial.println(addr, HEX);
 
 -     }
 
 -   }
 
 - }
 
  复制代码 3.检查电源:确保3.3V供电稳定 
 
六、结论- 本教程详细讲解了在STM32F407VET6零知增强板上实现ST7789显示屏中文显示的技术方案。通过使用U8g2_for_Adafruit_GFX库,我们能够:
 
  复制代码
 - 高效渲染中文字符
 - 保持与Adafruit_GFX的兼容性
 - 实现中英文混合显示
 - 在有限的硬件资源下优化性能
 
 
  
 
 
通过本教程,开发者可以快速构建稳定可靠的环境监测系统,点击了解更多零知开发教程: 
 https://www.lingzhilab.com/freesources.html 
 
  
  
 |   
 
  
  
  
 
 
 |