15.4.4 软件设计与实现

更新于 2026年10月10日 版权声明
15.4.4 软件设计与实现

终端设备的软件代码主要在传感器数据采集文件“DHT22.c”“BH1750.c”、ESP8266的AT指令文件“esp8266.c”、MQTT协议报文文件“mqtt.c”和主程序文件“main.c”中。各外设初始化函数、HAL库函数和FreeRTOS代码由STM32CubeMX自动生成MDK的工程文件。程序结构如图15.28所示。应特别注意的是,USART1串口初始化函数中配置接收方式为DMA模式,并开启接收空闲中断,以实现不定长数据接收,其他外设采用常规设置即可。

图示

图15.28 程序结构

1.“main.c”文件代码

“main.c”文件中包括STM32外设初始化、ESP8266初始化,创建3个任务(两个传感器数据采集任务和一个接收数据处理任务)、MQTT的60 s心跳包定时器2中断、串口USART1空闲中断和DMA数据接收程序。

(1)int main()函数。

通过宏定义Wi-Fi名称和密码,定义连接阿里云的MQTT参数的三元组(在阿里云定义的设备里“设备信息”选项卡下的“MQTT连接参数”中可查到),定义MQTT发布和订阅格式(在阿里云定义的产品下的“Topic类列表”选项卡下的“物模型通信Topic”的属性中,将以“post”和“set”结尾的格式替换“deviceName”)。代码如下。

图示

在主函数中完成对STM32F1系列MCU的外设模块初始化、ESP8266和MQTT初始化、开启串口空闲中断DMA接收、创建3个任务和一个信号量。代码如下。

图示

(2)串口空闲中断回调函数接收不定长数据。

STM32F1系列MCU采用USART的空闲中断DMA接收的方式接收ESP8266的不定长数据。这样既可提高STM32F1系列MCU的利用率,又可准确接收不定长数据。USART的空闲中断是自接收到上个字节完成起(RXNE=1),超过一个字节周期时长没接收到新数据,产生空闲中断(USART的SR第4位IDLE被置1),在串口空闲中断回调函数中处理DMA收到的数据,函数代码如下。

图示

图示

(3)ESP8266初始化程序。

该初始化程序的功能是依次完成ESP8266调试、连接热点、连接阿里云IoT服务器、登录阿里云物联网平台、订阅主题。在初始化过程中,会出现一次连接热点或登录阿里云不成功的现象,可通过软件复位的方式再一次初始化(图示NVIC_SystemReset();)。函数代码如下。

图示

图示

(4)数据发送与接收任务。

①温湿度采集任务Task_DHT22通过传感器DHT22实现对环境的温度和湿度的采集,然后上传到阿里云物联网平台。任务程序如下。

图示

②光照度采集任务Task_mlux通过光照度传感器BH1750实现对环境光照度的采集,然后上传到阿里云平台。任务程序如下。

图示

传感器数据上传阿里云物联网平台函数,按照阿里云物联网平台的物模型模式上传数据。输入参数Yu_Identifier为阿里云设备功能标识符,SensorData为传感器数据。程序代码如下。

图示

③数据接收及处理任务接收阿里云下发的指令,分别实现对主灯、加湿器和空调开关的开关操作。数据接收是通过串口1空闲中断DMA接收,为了将数据接收和处理同步,采用二值信号量实现。当串口1空闲中断回调函数接收到阿里云下发的指令时,就释放一个信号量;在接收任务中获取一个信号量,以保障同步。任务代码如下。

图示

函数Proces_MQTT_message()的功能是判断阿里云下发的数据功能,并根据数据的功能执行处理操作。输入参数buf是接收数据内容,len表示数据长度。函数代码如下。

图示

图示

开关状态上传阿里云物联网平台的函数Swi tch_StatusReport()的程序代码与传感器数据上传函数的代码相同。

2.“esp8266.c”文件代码

“esp8266.c”文件里的函数主要通过STM32的串口发送AT指令,来完成ESP8266模块的调试等操作,测试使用的函数为ESP8266_Init(),连接到热点使用的函数为ESP8266_ConnectWi-Fi(),连接到阿里云服务器使用的函数为ESP8266_ConnectServer()。

(1)ESP8266模块的调试函数ESP8266_Init()。

ESP8266模块的调试函数ESP8266_Init()实现的功能有对ESP8266模块执行复位、调试和关闭回显。输出参数返回0表示调试不成功,返回1表示调试成功。

程序代码如下。

图示

(2)连接热点函数。

ESP8266_ConnectWi-Fi()函数的功能首先是通过“AT+C WMODE=1”完成对ESP8266作为客户端的配置,然后通过指令“AT+C WJAP”完成对指定热点的连接。

①输入参数:ssid表示热点名,pwd表示热点密码。

②输出参数:返回0表示连接失败,返回1表示连接成功。(https://www.daowen.com)

程序代码如下。

图示

(3)连接阿里云服务器函数。

ESP8266_ConnectServer()函数的功能包括发送“AT+CIPSTART”指令登录阿里云服务器,并发送“AT+CIPMODE”指令设置透传模式,发送“AT+CIPSEND”指令进入透传发送状态。

①输入参数:mode表示模式(TCP/UDP),ip表示服务器IP地址,port表示接口号。

②输出参数:返回0表示连接失败,返回1表示连接成功。

程序代码如下。

图示

上述代码中的ESP8266_ATSendString()函数用于通过串口1发送字符串,代码如下。

图示

当发送完AT指令后,ESP8266返回的数据通过字符串比较函数String_check()完成检测,检测是否有对应指令的响应。程序代码如下。

图示

3.“MQTT.c”文件代码

该文件中主要是MQTT报文相关的函数,MQTT有14种报文,一般应用中主要会用到连接(CONNECT)、订阅(SUBSCRIBE)、取消订阅(UNSUBSCRIBE)、发布(PUBLISH)和心跳(PINGREQ)。

(1)MQTT主要的响应报文。

MQTT主要的响应报文有正确连接响应报文、断开连接响应报文、心跳回复报文、订阅回复报文等,程序代码如下。

图示

(2)连接报文函数。

连接报文格式=固定报头(0x10+剩余长度)+可变报头[协议名(0x000x04'M"Q"T"T')+协议级别(0x04)+连接标志(0xC2)+保持连接(0x000x64)]+有效载荷(用客户端ID+用户名+密码)。

①输入参数:三元组,ClientID为服务器ID,Username为用户名,Password为密码。

②输出参数:返回1表示成功,返回0表示失败。

该报文函数实现方法如下。

图示

图示

(3)订阅与取消订阅报文函数。

订阅报文格式=固定报头(0x82+剩余长度)+可变报头(0x00 0x01)+有效载荷(阿里云订阅Topic+消息等级)。

取消订阅报文的固定报头的报文类型为0xA2,其他格式和订阅报文一样。

①输入参数:topic表示主题,qos表示消息等级,Sub_UnSub表示订阅/取消订阅请求包(0为取消订阅,1为订阅)。

②输出参数:返回1表示成功,返回0表示失败。

函数代码如下。

图示

图示

(4)发布报文函数。

发布报文的格式=固定长度(0x30+剩余长度)+可变报头(主题名和报文标识符)+有效载荷。

①输入参数:topic表示主题,message表示消息,qos表示消息等级。

②输出参数:返回1表示成功,返回0表示失败。

函数代码如下。

图示

图示

上述代码中的MQTT_SendBuf()函数是通过串口发送定长数据,函数代码如下。

图示

↑上一章 ↓下一章
关注公众号获取验证码
复制内容需要验证码(7.99元/天)