STM32 HAL库+ESP8266+华为云物联网平台

文章内容:

    STM32 HAL库通过串口发送AT指令完成与ESP8266的控制实现接入华为云物联网平台,并完成基本通信与控制,包括设备属性上报和命令下发解析与响应。

    文末获取“STM32 HAL库+ESP8266+华为云物联网平台keil工程”下载的链接。

一、华为云物联网平台创建产品与设备

华为云物联网平台创建产品与设备(含MQTT.fx测试)

二、STM32 HAL库+ESP8266+华为云物联网平台

1. esp8266 MQTT固件烧录与AT指令接入华为云测试

(5条消息) ESP8266通过AT指令接入华为云物联网平台_FUNIOT的博客-优快云博客

三、STM32 HAL库+ESP8266+华为云物联网平台

1. 打开STM32CubeMX创建工程

(1)配置串口与LED的GPIO(LED用于华为云命令下发控制)

(2)打开串口并使能串口中断

2. 打开工程,编译,下载,检查无误

3. 串口收发

1) 添加头文件:

#include <stdio.h>
#include <string.h>

2) printf重定向

//支持printf函数串口发送
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
    int handle;
};
FILE __stdout;
void _sys_exit(int x)//避免半主机模式
{
    x=x;
}
int fputc(int ch,FILE *f)
{
    while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
    USART1->DR=(uint8_t)ch;
    return ch;
}
#endif

4. 发送测试

while (1)//主函数中插入
{
    /* USER CODE END WHILE */
      printf("Hello esp8266\r\n");
      delay(4000);
    /* USER CODE BEGIN 3 */
  /* USER CODE END 3 */
}
​
void delay(int t)
​​​​​​​{
  int i,j=0;
  for(i=0;i<5000;i++)
    for(j=0;j<t;j++);
}

 

5. 接收测试

(1)main.c中添加下列声明

char R_data[1024];      //定义结束数据的缓冲区
uint8_t R_length=0;      //定义结束数据的长度
uint8_t R_i=0;        //由于遍历缓冲区数据

(2)重写串口接收中断回调函数

//重写串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  char analysis_Str[256];
  if(huart->Instance == USART1)
  {
    HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1);
    // save char from uart receive
    if(aRxBuffer1!='\n')
      R_data[R_length++]=aRxBuffer1;
                 else 
                        for(R_i=0;R_i<R_length;R_i++)
        printf("%c",R_data[R_i]);
          }
}

(3)在串口初始化后使能串口中断

HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1); //使能串口接收中断

(4)运行测试:

6.  完善主要接入华为云物联网平台的相关代码

(1)接入华为云初始化

void HuaweiIot_init(void)
{
    uint8_t i=0;
    for(i=0;i<10;i++)
    {
        if(at_start_flag==1)
        {
            AT_write("AT\r\n");
            printf("AT+RST\r\n");
            delay(1000);
            AT_write("AT\r\n");
            AT_write("AT+CWMODE=1\r\n");
            AT_write("AT+CWJAP=\"wifi名称\",\"wifi密码\"\r\n");
            AT_write("AT+MQTTUSERCFG=0,1,\"NULL\",\"三元组之Username\",\"三元组之password\",0,0,\"\"\r\n");
            AT_write("AT+MQTTCLIENTID=0,\"三元组之ClientID\"\r\n");
            AT_write("AT+MQTTCONN=0,\"MQTT接入地址\",1883,1\r\n");
            AT_write("AT+MQTTSUB=0,\"$oc/devices/设备ID/sys/properties/report\",1\r\n");
            AT_write("AT+MQTTSUB=0,\"$oc/devices/设备ID/sys/commands/#\",1\r\n");
            AT_write("AT+MQTTSUB=0,\"$oc/devices/设备ID/sys/commands/response/#\",1\r\n");
            break;
        }    
        else
        {
            printf("等待模块就绪...\r\n");
            delay(1000);
        }            
    }
}

 (2) AT命令发送

void AT_write(char atstring[1024])//阻塞等待OK
{
    printf("%s",atstring);
    while(1)
    {
            if(R_data[0]=='O'&&R_data[1]=='K') break;
            else if(R_data[0]=='b'&&R_data[1]=='u'&&R_data[2]=='s'&&R_data[3]=='y')
            {
            }
            else delay(50);
    }
    R_data[0]=R_data[1]=0;
    delay(50);
}

(3) 属性上报

void HuaweiIot_publish(void)
{
    char pubtemp[256];
    if(at_start_flag==1)
    {    
        sprintf(pubtemp,"AT+MQTTPUB=0,\"$oc/devices/设备ID/sys/properties/report\",\"{\\\"services\\\":[{\\\"service_id\\\":\\\"服务ID\\\"\\,\\\"properties\\\":{\\\"属性\\\": %d}}]}\",0,0\r\n",hometemp++);
        AT_write(pubtemp);
    }
}

(4)串口接收中断回调

//重写串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    char analysis_Str[256];
    if(huart->Instance == USART1)
    {
        HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1);
        // save char from uart receive
        if(aRxBuffer1!='\n')
            R_data[R_length++]=aRxBuffer1;
        else
        {
            if(R_length>=5)
            {
                    if(R_data[0]=='r'&&R_data[1]=='e'&&R_data[2]=='a'&&R_data[3]=='d'&&R_data[4]=='y')
                    {
                            at_start_flag=1;
                            printf("检测到ready\r\n");
                            memset(R_data,0,sizeof(R_data));//清空缓存区
                    }
            }
                //我的接收数据长度为201,下面采用JSON字符串硬解析的方式,具体下标请根据自己实际接收的参数处理
    //+MQTTSUBRECV:0,"$oc/devices/61fb2d7fde9933029be5ff9e_esp8266_test01/sys/commands/request_id=4152fb5d-e5ae-4b89-b39d-283ba59cf033",68,{"paras":{"led":1},"service_id":"Dev_data","command_name":"Control"}
            if(R_length>200)
            {
                    strncpy(analysis_Str, R_data, 12);//提取出“+MQTTSUBRECV”
                    if(strcmp(analysis_Str,"+MQTTSUBRECV")==0)
                    {
                            memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区
                            //printf("MQTT命令接收头正确\r\n");
                            strncpy(request_id, R_data+92, 36);        //提取出request_id
                            //printf("request_id=%s\r\n",request_id);
                            strncpy(analysis_Str, R_data+135, 5);    //提取出"paras"
                            //printf("paras=%s\r\n",analysis_Str);
                            if(strcmp(analysis_Str,"paras")==0)        //有效参数体
                            {
                                    memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区
                                    strncpy(analysis_Str, R_data+144,3);    //提取出"led"
                                    //printf("att is %s\r\n",analysis_Str);
                                    if(strcmp(analysis_Str,"led")==0)
                                    {
                                            //printf("led set %c",R_data[149]);
                                            memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区
                                            if(R_data[149]=='0')
                                            {
                                                    //printf("关灯\r\n");
                                                    printf("AT+MQTTPUB=0,\"$oc/devices/设备ID/sys/commands/response/request_id=%s\",\"\",0,0\r\n",request_id);
                                                    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
                                                    memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区    
                                            }
                                           else if(R_data[149]=='1')
                                            {
                                                    //printf("开灯\r\n");
                                                    printf("AT+MQTTPUB=0,\"$oc/devices/设备ID/sys/commands/response/request_id=%s\",\"\",0,0\r\n",request_id);
                                                    memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区        
                                                    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
                                            }                                        
                                    }        
                            }
                    }
                    else
                    {
                        //printf("MQTT命令接收头异常:%s\r\n",analysis_Str);
                        memset(analysis_Str,0,sizeof(analysis_Str));//清空缓存区
                    }
            }
            //else printf("MQTT命令长度异常,长度:%d",R_length);            
            R_length=0;
        }
    }
}

最终效果:

公众号搜索”IOT趣制作“回复关键字“8266at”或者“0327”获取相关下载链接:

<think>好的,用户需要寻找使用STM32 HAL连接华为云并实现点灯功能的示例代码。首先,我需要明确用户的需求:他们可能正在开发一个物联网项目,希望通过STM32微控制器连接到华为云IoT平台,并能够通过云平台控制LED灯。用户可能对STM32HAL有一定了解,但需要具体的实现步骤和示例代码。 接下来,我应该考虑用户可能使用的具体硬件型号。虽然用户没有明确说明,但根据之前的引用中提到小熊派开发板使用STM32L431芯片,推测用户可能在使用类似的开发板,比如BearPi-HM Nano或其他基于STM32L4系列的设备。因此,示例代码需要适配STM32L4系列,并包含相应的头文件,如stm32l4xx.h。 然后,需要确定连接华为云IoT平台的步骤。华为云IoT通常使用MQTT协议进行通信,因此需要集成MQTT客户端STM32HAL本身不包含MQTT实现,因此可能需要使用第三方,如Eclipse Paho MQTT嵌入式客户端,或者华为提供的SDK。此外,华为云IoT需要设备鉴权,通常需要三元组(产品ID、设备ID、设备密钥)来生成连接参数,如客户端ID、用户名和密码。 接下来是代码结构。主函数中需要初始化系统时钟、GPIO(用于LED控制)、串口(用于调试和AT指令通信,如果使用NB-IoT或Wi-Fi模块的话),以及网络模块(如ESP8266或NB-IoT模块的初始化)。然后需要实现华为云的连接逻辑,包括建立MQTT连接、订阅主题、处理云平台下发的命令。此外,还需要实现消息回调函数,当云平台发送控制指令时,解析指令并控制LED的状态。 还需要考虑AT指令的使用,如果通过模块如ESP8266连接网络,可能需要发送AT指令来配置Wi-Fi和建立TCP连接。这部分需要根据具体模块的AT指令集来编写发送和接收处理的函数。同时,需要注意处理可能的网络延迟和重连机制,确保设备在断线后能够自动重新连接。 在代码示例部分,需要提供关键步骤的代码片段,例如初始化函数、MQTT连接函数、消息回调函数以及LED控制函数。同时,应提醒用户替换三元组信息,并根据实际硬件调整GPIO引脚和网络模块的配置。 可能遇到的问题包括头文件缺失(如之前的引用中提到需要修改为正确的stm32l4xx.h),网络模块的驱动问题,以及MQTT协议处理中的错误。因此,在回答中需要包含注意事项,比如检查硬件连接、确保正确导入HAL、处理AT指令的响应等。 最后,生成相关问题需要考虑用户可能的后续需求,比如如何生成设备三元组、如何优化网络连接稳定性、如何进行OTA升级等,这些都可以作为相关问题提出,帮助用户进一步开发。</think>### STM32 HAL连接华为云点灯示例实现 #### 一、硬件准备 1. 小熊派开发板(STM32L431RCT6芯片) 2. 已焊接NB-IoT模组(如BC35-G) 3. LED灯连接在GPIOB_PIN5 #### 二、华为云配置 1. 创建产品时选择MQTT协议 2. 记录设备三元组: - 产品ID: $ProductID$ - 设备ID: $DeviceID$ - 设备密钥: $DeviceSecret$ #### 三、关键代码实现 ```c /* 华为云连接参数 */ #define PRODUCT_ID "your_product_id" #define DEVICE_ID "your_device_id" #define DEVICE_SECRET "your_device_secret" /* LED控制GPIO定义 */ #define LED_PIN GPIO_PIN_5 #define LED_PORT GPIOB /* MQTT主题定义 */ const char* topic_property = "$oc/devices/"DEVICE_ID"/sys/properties/report"; const char* topic_command = "$oc/devices/"DEVICE_ID"/sys/commands/#"; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { // 网络状态变化中断处理 if(GPIO_Pin == NET_STATE_Pin) { handle_network_event(); } } void HuaweiCloud_Connect(void) { // 生成鉴权参数 char clientId[128] = {0}; char username[64] = {0}; char password[128] = {0}; huawei_iot_generate_auth_info(PRODUCT_ID, DEVICE_ID, DEVICE_SECRET, clientId, username, password); // 建立MQTT连接 MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer; connectData.clientID.cstring = clientId; connectData.username.cstring = username; connectData.password.cstring = password; int rc = MQTTConnect(&client, &connectData); if(rc != MQTT_SUCCESS) { printf("连接失败: %d\n", rc); return; } // 订阅命令主题 MQTTSubscribe(&client, topic_command, QOS1, messageHandler); } void messageHandler(MessageData* msg) { // 解析JSON消息 cJSON* root = cJSON_Parse(msg->message->payload); cJSON* led_cmd = cJSON_GetObjectItem(root, "led"); if(led_cmd) { if(strcmp(led_cmd->valuestring, "on") == 0) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); report_property("led_status", "on"); } else { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); report_property("led_status", "off"); } } cJSON_Delete(root); } ``` #### 四、操作流程 1. 初始化HAL时钟 ```c HAL_Init(); SystemClock_Config(); ``` 2. 配置GPIO和中断 ```c __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef gpio = {0}; gpio.Pin = LED_PIN; gpio.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(LED_PORT, &gpio); ``` 3. 连接NB-IoT网络 ```c BC35_Init(); BC35_AttachNetwork(); ``` 4. 上报初始状态 ```c report_property("led_status", "off"); ``` #### 注意事项 1. 需提前在`stm32l4xx_hal_conf.h`中使能GPIO和UART模块 2. AT指令需等待模块返回`OK`才能继续下一条[^1] 3. 建议添加看门狗防止网络阻塞 4. 华为云消息最大支持512字节载荷
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IOT趣制作

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值