【灵动微电子MM32F0121测评】使用esp8266实现数据传输
本帖最后由 scafel 于 2025-7-3 08:25 编辑[!(/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg) 源代码文件:Demo.rar](forum.php?mod=attachment&aid=2420276 "attachment")
#原创申请#
第三篇:【灵动微电子MM32F0121测评】使用esp8266实现数据传输
上篇已成功实现了串口与I2C的通信功能,并完成了LED的显示。接下来,我们将进入物联网(IoT)领域。在物联网项目中,MQTT协议因其轻量级、低功耗和高效性,已成为主流的通信协议。本文将结合ESP8266-01s模块,通过MQTT协议实现LED的远程控制,帮助读者快速掌握物联网设备通信的核心技术。
**硬件清单**
- ESP8266-01s模块
- 板载的LED1和LED2
- 四根杜邦线
**软件和MQTT服务**
- 使用本地搭建的MQTT服务
- 本人编写的小程序
1. 按照接线图链接开发板和ESP8266-01S模块

2. 书写串口代码,并测试是否可用
```c
#include <mm32_device.h>
#include <stdio.h>
#include <string.h>
#include "ESP8266.h"
#define RX_BUFFER_SIZE 128
uint8_t Serial_RxPacket; // 定义接收数据包数组
volatile uint8_t RxState = 0; // 接收状态机状态
uint8_t pRxPacket = 0; //定义表示当前接收数据位置
void ESP8266_Init(void)
{
GPIO_InitTypeDefGPIO_InitStruct;
NVIC_InitTypeDefNVIC_InitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_StructInit(&USART_InitStruct);
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2, &USART_InitStruct);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_4);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_Cmd(USART2, ENABLE);
}
void ESP8266_SendByte(uint16_t Byte)
{
USART_SendData(USART2, Byte); //将字节数据写入数据寄存器,写入后USART自动生成时序波形
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); //等待发送完成
/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
void ESP8266_SendString(char *String)
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); // 禁用接收中断
while (*String != '\0') {
ESP8266_SendByte(*String++);
}
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 重新启用接收中断
}
// 发送AT指令示例
void ESP8266_AT_Command(char *cmd) {
printf("\r\n AT_Command = %s", cmd);
char temp;
snprintf(temp, sizeof(temp), "%s\r\n", cmd); // 安全拼接
ESP8266_SendString(temp); // 发送命令
}
void Parse_MQTT_Data()
{
printf("Mqtt_Data:%s", Serial_RxPacket);
memset(Serial_RxPacket, 0, sizeof(Serial_RxPacket));
}
void USART2_IRQHandler(void)
{
uint8_t RxData;
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
RxState = 1;
RxData = USART_ReceiveData(USART2);
Serial_RxPacket = RxData;
// 清除中断标志位
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) {
RxData = USART_ReceiveData(USART2);
// 清除中断标志位
USART_ClearITPendingBit(USART2, USART_IT_IDLE);
if(RxState > 0)
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
USART_ITConfig(USART2, USART_IT_IDLE, DISABLE);
RxState = 0;
pRxPacket = 0;
Parse_MQTT_Data();
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
}
}
}
// main函数
#include <stdio.h>
#include <mm32_device.h>
#include "MM_Print.h"
#include "MM_Delay.h"
#include "Onboard_LED.h"
#include "Onboard_KEY.h"
#include "ESP8266.h"
char ESP8266_SEND_STR[] =
{
{"AT"},
//0. 设置Wi-Fi模式为 STA模式
{"AT+CWMODE=1"},
//1. 连接到AP,"热点名称","密码"
{"AT+CWJAP=\"CU_ZDR\",\"dbamw4wz\""},
//2. 配置传输模式为 透传模式
// {"AT+CIPMODE=1"},
//3. 配置多重连接模式关闭,关闭多路连接
// {"AT+CIPMUX=0"},
//4. 配置MQTT服务客户端 username,password
{"AT+MQTTUSERCFG=0,1,\"NULL\",\"MEMBER-WSW202410141212003170\",\"2b4eb80c3782b8cd2a35c1a2b6ba18e4\",0,0,\"\""},
//5. clientID
{"AT+MQTTCLIENTID=0,\"MEMBER-WSW202410141212003170\""},
//6. 连接服务器
{"AT+MQTTCONN=0,\"192.168.1.11\",1883,1"},
//7. 订阅指令
{"AT+MQTTSUB=0,\"member/room\",1"},
//8. 发布消息
{"AT+MQTTPUB=0,\"member/room\",\"{\\\"message\\\":\\\"online\\\"}\",1,0"},
};
uint8_t Num = 0;
uint8_t KEY_Num = 0;
int main()
{
MM_InitConsole(9600);
MM_InitDelay();
OnBoard_LED_Init();
OnBoard_KEY_Init();
ESP8266_Init();
while(1)
{
KEY_Num = OnBoard_KEY_Get();
if(KEY_Num == 1)
{
if(Num <= 6)
{
// 本次使用按键进行一步步配置
ESP8266_AT_Command(ESP8266_SEND_STR);
Num++;
}
}
}
}
```
3. 测试截图


可见已经实现链接并支持接收不定长的mqtt数据,下一步就是进行mqtt数据解析和实现指令判断等操作
4. 解析mqtt协议并实现指令控制led灯,开发板按键发送key2到小程序
使用cjson库实现解析,具体解析方式按照自己的处理方式进行即可,无所谓
```c
// 函数:提取以 { 开头、以 } 结尾的数据
char* extract_bracket_data(char* input_str) {
if (input_str == NULL) {return NULL;}
// 1. 定位第一个 '{' 的位置
const char* start = strchr(input_str, '{');
if (start == NULL) {
return NULL; // 没有找到 '{'
}
// 2. 从 start 开始查找对应的 '}'
const char* end = strchr(start, '}');
if (end == NULL) {
return NULL; // 没有找到 '}'
}
// 3. 计算子字符串长度(包括 '{' 和 '}')
size_t length = end - start + 1;
// 4. 分配内存并复制数据
char* result = (char*)malloc(length + 1); // +1 用于终止符
if (result == NULL) {
return NULL; // 内存分配失败
}
strncpy(result, start, length);
result = '\0'; // 确保字符串以 '\0' 结尾
return result;
}
``````c
void to_upper(char *str) {
strcpy(mqtt_key, str); // 缓冲区溢出!
int i = 0;
for (i = 0; mqtt_key != '\0'; i++) {
mqtt_key = toupper(mqtt_key);
}
mqtt_key = '\0';
}
void Action_MqttKey()
{
// Parse_MQTT_Data();
to_upper(MQTT_Data);
if(strcmp(mqtt_key, "LED1") == 0)
{
OnBoard_LED_Toggle(GPIOB, 14);
}
if(strcmp(mqtt_key, "LED2") == 0)
{
OnBoard_LED_Toggle(GPIOB, 15);
}
Clear_MQTT_Data();
}
```
```c
int main()
{
MM_InitConsole(9600);
MM_InitDelay();
OnBoard_LED_Init();
OnBoard_KEY_Init();
ESP8266_Init();
while(1)
{
KEY_Num = OnBoard_KEY_Get();
if(KEY_Num == 1)
{
if(Num <= 6)
{
ESP8266_AT_Command(ESP8266_SEND_STR);
Num++;
}
}
if(KEY_Num == 2)
{
ESP8266_AT_Command("AT+MQTTPUB=0,\"member/room\",\"{\\\"message\\\":\\\"KEY2\\\"}\",1,0");
}
}
}
```
!(data/attachment/forum/202506/13/144039m8dly8yq0cnya33j.gif "420974df32cf51c66d8f09e8126114f5 00_00_00-00_00_30~2.gif")
**总结**
通过ESP8266和MQTT协议,我们成功实现了LED的远程控制,验证了物联网设备通信的基本流程。此项目可作为智能家居、工业自动化等场景的入门基础。后续可通过添加传感器、优化代码逻辑,进一步扩展功能。
推荐使用 3.3V 逻辑电平转换器确保信号兼容性 使用esp8266实现数据传输 能否提供完整的工程代码呢 lemonhub 发表于 2025-7-2 22:36
能否提供完整的工程代码呢
文章最开始有附件下载
页:
[1]