简介
在上文中 (https://forum.eepw.com.cn/thread/387178/1) 我主要介绍了如何构建ESP8266最小电路并且如何使用对应的HTTP库请求心知天气并且将数据进行解析和构建通过串口将数据发送出去。那么在本文中我将对STM32端的代码进行整理,使其STM32可以解析串口的数据并且将天气数据显示在SSD1306上。
本文将采用STM32F103C8T6单片机结合STM32CUBEMX来快速生成工程同时使用Keil来进行软件的开发。
正文
首先让我们来分析以下需求。由于上文中我们介绍的ESP8266的数据输出为串口输出, 因此我们至少需要保证STM32初始化与ESP8266连接的串口。 同时为了驱动I2S我们还需要使用CUBEMX来帮助我们初始化I2C。
工程初始化如下
上图红色框内的则为我们需要用到的端口信息。在实际的电路设计中我们需要将STM32的RX接ESP8266的TX,将TX接ESP8266的RX, 由于我们目前并没有从STM32采集数据的需求,实际上STM32的TX接和不接没有任何区别。 如果你的ESP8266是和STM32采用一个LDO进行供电的话。 即两个模块共地,那么不需要额外的GND连接,如果两个模块是分别供电的话, 那么最好两个模块要除了TXD,RXD还要连接好GND。用来避免信号传输干扰增加传输稳定性。
这里SSD1306的驱动文件并不是我自己手写的,我是从GITHUB上找到的代码,经过验证,可以正常使用。 我在这里仅仅贴上函数的定于文件。之后项目的整个工程我会用附件的形式贴到帖子的最下面。
/** * This Library is written and optimized by Olivier Van den Eede(4ilo) in 2016 * for Stm32 Uc and HAL-i2c lib's. * * To use this library with ssd1306 oled display you will need to customize the defines below. * * This library uses 2 extra files (fonts.c/h). * In this files are 3 different fonts you can use: * - Font_7x10 * - Font_11x18 * - Font_16x26 * */ #ifndef _SSD1306_H #define _SSD1306_H #include "stm32f1xx_hal.h" #include "fonts.h" // I2c address #ifndef SSD1306_I2C_ADDR #define SSD1306_I2C_ADDR 0x78 #endif // SSD1306_I2C_ADDR // SSD1306 width in pixels #ifndef SSD1306_WIDTH #define SSD1306_WIDTH 128 #endif // SSD1306_WIDTH // SSD1306 LCD height in pixels #ifndef SSD1306_HEIGHT #define SSD1306_HEIGHT 64 #endif // SSD1306_HEIGHT #ifndef SSD1306_COM_LR_REMAP #define SSD1306_COM_LR_REMAP 0 #endif // SSD1306_COM_LR_REMAP #ifndef SSD1306_COM_ALTERNATIVE_PIN_CONFIG #define SSD1306_COM_ALTERNATIVE_PIN_CONFIG 1 #endif // SSD1306_COM_ALTERNATIVE_PIN_CONFIG // // Enumeration for screen colors // typedef enum { Black = 0x00, // Black color, no pixel White = 0x01, // Pixel is set. Color depends on LCD } SSD1306_COLOR; // // Struct to store transformations // typedef struct { uint16_t CurrentX; uint16_t CurrentY; uint8_t Inverted; uint8_t Initialized; } SSD1306_t; // // Function definitions // uint8_t ssd1306_Init(I2C_HandleTypeDef *hi2c); void ssd1306_UpdateScreen(I2C_HandleTypeDef *hi2c); void ssd1306_Fill(SSD1306_COLOR color); void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); char ssd1306_WriteChar(char ch, FontDef Font, SSD1306_COLOR color); char ssd1306_WriteString(const char* str, FontDef Font, SSD1306_COLOR color); void ssd1306_SetCursor(uint8_t x, uint8_t y); void ssd1306_InvertColors(void); // Function to write a number to the screen buffer void ssd1306_WriteNumber(int number, FontDef Font, SSD1306_COLOR color); void ssd1306_Clear(I2C_HandleTypeDef *hi2c); #endif // _SSD1306_H
那么既然屏幕的驱动函数搞定了的话,那么我们接下来要做的就是屏幕数据的解析了。
这里有很多种方式来解析串口数据, 比如说使用中断等。但是我这里偷懒了, 直接在主程序中解析来自ESP8266的数据,当串口有数据的时候则调用一次DisplayWeatherData() 方法使其解析串口收到的数据并且绘制在屏幕上。
/* Function to parse and display data */ void DisplayWeatherData(char *data) { char *location = strtok(data, ","); char *condition1 = strtok(NULL, ","); char *temp1 = strtok(NULL, ","); char *condition2 = strtok(NULL, ","); char *temp2 = strtok(NULL, ","); // Clear the screen and set initial cursor positions ssd1306_Clear(&hi2c1); ssd1306_SetCursor(0, 0); // Display parsed information on OLED if (location) { ssd1306_WriteString(location, Font_7x10, White); } if (condition1 && temp1) { ssd1306_SetCursor(0, 15); ssd1306_WriteString(condition1, Font_7x10, White); ssd1306_WriteString(temp1, Font_7x10, White); } //parse second day // if (condition2 && temp2) { // ssd1306_SetCursor(0, 30); // ssd1306_WriteString(condition2, Font_7x10, White); // ssd1306_WriteString(temp2, Font_7x10, White); // } ssd1306_UpdateScreen(&hi2c1); // Refresh screen }
还记得我在上文中提到过的心知天气的免费请求吗? 这里被注释掉的代码则为解析下一天的数据的。 由于这个Oled屏幕较小,因为我这里注释掉了第二天的数据显示。使其只显示当前天的天气数据。具体的解析逻辑是通过使用"," 分割收到的String,并且解析使其显示。
我的代码中还附带了一个DHT20的湿温度的读取和解析(正确无误)。 由于并不设计到当前的文章之内,ESP8266发送HTTPS请求和STM32接受数据解析已经实现。我这里就不多做阐述了。感兴趣的网友可以下载我的代码自己研究以下。 (代码使用I2C1 和 SSD1306 一个I2C)
效果如下:
附件(编辑器里的文件上传都上传完毕了,不知道为什么不显示上传成功)
通过百度网盘分享的文件:stm32-diy.zip
链接:https://pan.baidu.com/s/1btV5CSLZRXXs_x86WiG_nQ?pwd=vhge
提取码:vhge