(示例:stm32f103c8t6+esp01s串口AT指令模式)
流程簡介:
一、 MQTT透傳AT固件燒錄
? ? ? 本期教程使用的是stm32+AT指令控制esp01s接入華為云聯(lián)網平臺完成數據上報與命令處理,在先前如果使用Arduino開發(fā)過后的esp8266可能已經無法使用AT指令,或者出廠固件不支持全部的MQTT功能,這里我們首先對esp8266進行MQTT固件燒錄,如果平時一直在使用原廠固件開發(fā),可跳過第一步,若AT指令無效再按第一步操作。
1. 官網下載燒錄工具和固件
燒錄工具鏈接:https://docs.ai-thinker.com/tools
固件鏈接:
https://docs.ai-thinker.com/%E5%9B%BA%E4%BB%B6%E6%B1%87%E6%80%BB
大家根據自己需要選擇相應的版本,我使用的是esp01s,下載的是1471號
2. 打開固件燒錄工具
連接usb轉ttl模塊,點擊START,然后保持esp01s的IO0拉低后重新上電
?文章來源地址http://www.zghlxwxcb.cn/news/detail-431446.html
打開串口助手,按下復位,輸入命令”AT”,注意要取消勾選十六進制發(fā)送,勾選發(fā)送新行,然后檢查串口打印工作狀況,下圖表示正常:
3. 串口調試
我們即將用到的AT指令可以從官方手冊中學習:
https://docs.ai-thinker.com/%E5%9B%BA%E4%BB%B6%E6%B1%87%E6%80%BB
1) AT+CWMODE=1
設置模塊為STA模式
2) AT+CWJAP="填寫wifi名稱","填寫WiFi密碼"
連接WiFi,需略微等待片刻,等顯示連接后再進行下面的操作
3) AT+MQTTUSERCFG=0,1,"NULL","填寫用戶名","填寫密碼",0,0,""
設置MQTT的登陸用戶名與密碼
用戶名與密碼為華為云MQTT三元組的相關信息,可以在下面的網站生成:https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
具體可以參考之前的文章
4) AT+MQTTCLIENTID=0,"填寫ClientID"
設置MQTT的ClientID,ClientID華為云MQTT三元組的相關信息,在上一步驟中獲取的三元組中查看
5) AT+MQTTCONN=0,"填寫MQTT接入的地址",1883,1
設置MQTT接入地址,華為云物聯(lián)網平臺的地址,比如iot-mqtts.cn-north-4.myhuaweicloud.com,具體參考控制臺首頁的平臺接入地址
6) AT+MQTTSUB=0,"訂閱的主題tpoic",1
完成屬性上報的話需要先訂閱設備屬性上報的主題,此處可填寫為:
$oc/devices/填寫設備ID/sys/properties/report
7) AT+MQTTPUB=0," 訂閱的主題tpoic ","上報的json數據",0,0
訂閱的主題:
$oc/devices/填寫設備ID/sys/properties/report
上報的json數據:
{\"services\":[{\"service_id\":\"填寫服務ID\"\,\"properties\":{\"填寫設備屬性\": 填寫屬性數據值}}]}
建議大家完成這步時,先使用MQTT.fx進行設備屬性上報測試,確保數據無誤正常上傳,具體參數因個人的配置而異
在完成上面的每一步時,系統(tǒng)都會打印一個OK,正常效果如下:
????
????此時我們可以查看華為云物聯(lián)網平臺的設備屬性以及消息記錄:
8) AT+MQTTSUB=0,"訂閱的主題topic ",1
此時我們在這填寫的是平臺下發(fā)命令的主題:$oc/devices/填寫設備ID/sys/commands/#
9) ?進入華為云物聯(lián)網平臺的->監(jiān)控運維->在線調試,完成命令下發(fā)
服務ID與下發(fā)命令的創(chuàng)建方法參考以前的文章:
此時設備會接收到下發(fā)的命令:
接收到命令后我們需要對命令進行響應,即下一步的步驟
10) 特別注意?。?!下面兩步的操作時間建議接收到命令后的20s以內,超時后平臺會認定為同步命令設備響應異常!
11)?AT+MQTTSUB=0,"$oc/devices/填寫設備ID?/sys/commands/response/request_id=填寫接收到的request_id ",1
訂閱設備響應平臺命令主題,其中接收到的request_id在上圖接收到的數據中,我們需要把它拿出來放到新訂閱的tpoic的對應位置里
12) ?AT+MQTTPUB=0,"填寫上面訂閱的含request_id的完整主題","填寫響應值,可以為空",0,0
例如:AT+MQTTPUB=0,"$oc/devices/填寫設備id/sys/commands/response/request_id=填寫request_id ","",0,0
13) 完成上面的三步操作后,我們可以看到華為云物聯(lián)網平臺已經完成了命令的接收與響應
此時,我們的設備屬性上報與設備命令的接收響應功能就已經完成了,接下來我們完成STM32代替串口助手完成對esp8266的上述控制。
二、 STM32編程
1. 打開STM32CubeMX創(chuàng)建工程
(1)配置串口與LED的GPIO
(2)打開串口并使能串口中斷
2. 打開工程,編譯,下載,檢查無誤
3. 串口收發(fā)
1) 添加頭文件:
#include <stdio.h>
#include <string.h>
2) printf重定向
//支持printf函數串口發(fā)送
#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);//循環(huán)發(fā)送,直到發(fā)送完畢
USART1->DR=(uint8_t)ch;
return ch;
}
#endif
4. 發(fā)送測試
-------------------------------
-------------------------------
//主函數中插入
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]; //定義結束數據的緩沖區(qū)
uint8_t R_length=0; //定義結束數據的長度
uint8_t R_i=0; //由于遍歷緩沖區(qū)數據
(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); //使能串口接收中斷
運行測試:
6. ?完善主要接入華為云物聯(lián)網平臺的相關代碼
(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命令發(fā)送
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));//清空緩存區(qū)
}
}
//我的接收數據長度為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));//清空緩存區(qū)
//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));//清空緩存區(qū)
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));//清空緩存區(qū)
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));//清空緩存區(qū)
}
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));//清空緩存區(qū)
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));//清空緩存區(qū)
}
}
//else printf("MQTT命令長度異常,長度:%d",R_length);
R_length=0;
}
}
}
最終效果:
上述教程完成基本功能的核心代碼已經給出,如果需要keil項目文件,可公-眾,號搜索“IOT趣制作”,回復關鍵字“8266at”即可。
文章來源:http://www.zghlxwxcb.cn/news/detail-431446.html
?
到了這里,關于stm32+AT指令+ESP8266接入華為云物聯(lián)網平臺并完成屬性上報與命令響應的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!