✔零知开源是一个真正属于国人自己的开源软硬件平台,在开发效率上超越了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 视频演示效果
STM32F4结合BMP581气压传感器实现ST7789显示
将通过传感器获取到的气压值与下面的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://pan.baidu.com/s/1EPrOlbQ2wHjGa691qyf71Q?pwd=2kj7
大气压强传感器:BMP581数据手册
主控芯片:STM32F4参考手册
通过本教程,开发者可以快速构建稳定可靠的环境监测系统,点击了解更多零知开发教程: