五、OLED屏显示温湿度和实时时间信息
1、添加u8g2软件包
2、编写oled_display显示线程
(1)在application分组下创建一个用户文件oled_display.cpp文件,存放本项目中的OLED显示代码。
代码如下:
#include <rthw.h> #include <rtthread.h> #include <rtdevice.h> #include <U8g2lib.h> #include <stdio.h> #include <board.h> #include "drv_common.h" #include <drv_soft_i2c.h> extern "C" { #include <sht3x.h> } extern "C" { sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr); rt_err_t sht3x_read_singleshot(sht3x_device_t dev); } #define OLED_I2C_PIN_SCL 24 // #define OLED_I2C_PIN_SDA 25 // static U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,\ /* clock=*/ OLED_I2C_PIN_SCL,\ /* data=*/ OLED_I2C_PIN_SDA,\ /* reset=*/ U8X8_PIN_NONE); #define SUN 0 #define SUN_CLOUD 1 #define CLOUD 2 #define RAIN 3 #define THUNDER 4 static void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol) { // fonts used: // u8g2_font_open_iconic_embedded_6x_t // u8g2_font_open_iconic_weather_6x_t // encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic switch(symbol) { case SUN: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 69); break; case SUN_CLOUD: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 65); break; case CLOUD: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 64); break; case RAIN: u8g2.setFont(u8g2_font_open_iconic_weather_6x_t); u8g2.drawGlyph(x, y, 67); break; case THUNDER: u8g2.setFont(u8g2_font_open_iconic_embedded_6x_t); u8g2.drawGlyph(x, y, 67); break; } } static void drawWeather(uint8_t symbol, int degree) { drawWeatherSymbol(0, 63, symbol); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(55, 63); u8g2.print(degree); u8g2.print("C"); } static void drawHumidity(uint8_t symbol, int humidity) { drawWeatherSymbol(0, 63, symbol); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(55, 63); u8g2.print(humidity); u8g2.print("%"); } #ifdef __cplusplus extern "C" { #endif void oled_display() { u8g2.begin(); u8g2.clearBuffer(); u8g2.setFont(u8g2_font_logisoso32_tf); u8g2.setCursor(48+3, 42); u8g2.print("Hi~"); // requires enableUTF8Print() u8g2.setFont(u8g2_font_6x13_tr); // choose a suitable font u8g2.drawStr(30, 60, "By Mculover666"); // write something to the internal memory u8g2.sendBuffer(); sht3x_device_t sht3x_device; sht3x_device = sht3x_init("i2c3", 0x44); rt_thread_mdelay(2000); int status = 0; char mstr[3]; char hstr[3]; time_t now; struct tm *p; int min = 0, hour = 0; int temperature = 0,humidity = 0; while(1) { switch(status) { case 0: now = time(RT_NULL); p=gmtime((const time_t*) &now); hour = p->tm_hour; min = p->tm_min; sprintf(mstr, "%02d", min); sprintf(hstr, "%02d", hour); u8g2.firstPage(); do { u8g2.setFont(u8g2_font_logisoso42_tn); u8g2.drawStr(0,63,hstr); u8g2.drawStr(50,63,":"); u8g2.drawStr(67,63,mstr); } while ( u8g2.nextPage() ); rt_thread_mdelay(5000); status = 1; break; case 1: if(RT_EOK == sht3x_read_singleshot(sht3x_device)) { temperature = (int)sht3x_device->temperature; } else { temperature = 0; } u8g2.clearBuffer(); drawWeather(SUN, temperature); u8g2.sendBuffer(); rt_thread_mdelay(5000); status = 2; break; case 2: if(RT_EOK == sht3x_read_singleshot(sht3x_device)) { humidity = (int)sht3x_device->humidity; } else { humidity = 0; } u8g2.clearBuffer(); drawHumidity(RAIN, humidity); u8g2.sendBuffer(); rt_thread_mdelay(5000); status = 0; break; } } } MSH_CMD_EXPORT(oled_display, oled start); #ifdef __cplusplus } #endif
(2)在 applications 文件夹下创建oled_display.h
/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-09 ASUS the first version */ #ifndef APPLICATIONS_OLED_DISPLAY_H_ #define APPLICATIONS_OLED_DISPLAY_H_ #ifdef __cplusplus extern "C" { #endif void oled_display(void); #ifdef __cplusplus } #endif #endif /* APPLICATIONS_OLED_DISPLAY_H_ */
(3)最终的主函数
/* * Copyright (c) 2006-2020, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-09-02 RT-Thread first version */ #include <rtthread.h> #include <rtdevice.h> #include "drv_common.h" extern void wlan_autoconnect_init(void); int main(void) { rt_uint32_t count = 1; rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); wlan_autoconnect_init(); rt_wlan_config_autoreconnect(RT_TRUE); oled_display(); return RT_EOK; } #include "stm32h7xx.h" static int vtor_config(void) { /* Vector Table Relocation in Internal QSPI_FLASH */ SCB->VTOR = QSPI_BASE; return 0; } INIT_BOARD_EXPORT(vtor_config);
(4)参考board.h关于i2c的引脚配置,同款开发板的作者可参照,当然此处的i2c1也可以直接在oled_display.cpp中直接定义,因为前面在RT-Thread Setting中就已经配置好了,可以直接定义,此处只作为一个重定义。
/*-------------------------- I2C CONFIG BEGIN --------------------------*/ #ifdef BSP_USING_I2C1 #define BSP_I2C1_SCL_PIN 24 // p2 10 PB8 #define BSP_I2C1_SDA_PIN 25 // p2 7 PB9 #endif #ifdef BSP_USING_I2C3 #define BSP_I2C3_SCL_PIN 119 //p1 29 PH7 #define BSP_I2C3_SDA_PIN 120 //p1 28 PH8 #endif /*-------------------------- UART CONFIG END --------------------------*/
六、实验展示
七、问题总结
注意:由于我们是在C主程序下调用c++代码,但是RT-Thread对于C++不太友好,需要我们将CPP程序封装成C。同样的在cpp程序中调用C也需要封装
//如何在封装CPP代码为C:需要我们在.h和.cpp代码中分别对被调用的C++代码都进行封装,具体可参照上文中oled_display.cpp代码 #ifdef __cplusplus extern "C" { #endif // cpp函数 #ifdef __cplusplus } #endif
在使用开发板的过程中,一定需要频繁的去翻阅数据手册和引脚图,有时候开发工具也会莫名的出故障,一般可以尝试下重新构建思路和原理,重启以及寻求大佬帮助。