打印
[Arduino资料]

零知开源——STM32F4结合BMP581气压传感器实现ST7789中文显示教程

[复制链接]
37|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
​✔零知开源是一个真正属于国人自己的开源软硬件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!
✔访问零知开源平台,获取更多实战项目和教程资源吧!
www.lingzhilab.com



(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://pan.baidu.com/s/1EPrOlbQ2wHjGa691qyf71Q?pwd=2kj7
大气压强传感器:BMP581数据手册
主控芯片:STM32F4参考手册

通过本教程,开发者可以快速构建稳定可靠的环境监测系统,点击了解更多零知开发教程:
https://www.lingzhilab.com/freesources.html

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

30

帖子

0

粉丝