加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 需要解決的問題
    • 燒寫固件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

保姆級教程,虛擬機(jī)中重復(fù)驗證了三遍,包你順利接入阿里云物聯(lián)網(wǎng)平臺

2020/12/28
201
閱讀需 19 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

周三的網(wǎng)文閱讀量好慘,到了周日還沒過 200,本想暫時不更此方面內(nèi)容了。

但是看到群里的小伙伴在修改 linkkitapp 例程遇到了麻煩,今天再分享一下代碼修改的全過程,本文我在虛擬機(jī)中重復(fù)修改驗證了三遍,包你可以順利移植成功。

本文的實現(xiàn),在上一篇網(wǎng)文的基礎(chǔ)上實現(xiàn),開發(fā)環(huán)境的搭建參見下文:

AliOS Things 物聯(lián)網(wǎng)操作系統(tǒng)學(xué)習(xí)第一步:Windows 下 AliOS Things 開發(fā)環(huán)境搭建

本文我們實現(xiàn) linkkitapp 例程修改、ESP8266 固件的下載、一鍵配網(wǎng)和云智能 APP 綁定設(shè)備。

需要解決的問題

ESP8266 有兩個 UART:UART0 和 UART1。

UART0 有 TX、RX,可以作為系統(tǒng)的打印信息輸出接口和數(shù)據(jù)收發(fā)口。

UART1 的 RX 被 Flash 占用,只有發(fā)送引腳 TX(GPIO2,即 UART1_TXD),所以一般作為打印信息輸出接口(調(diào)試用)。

通常情況下,我們使用 UART0 和外設(shè)通訊,而使用 UART1 作為日志打印端口。

D1 mini ESP8266 模塊兩個串口的所在位置:

ESP8266 D1 mini 模塊

我們使用一個 Micro USB 線與 D1 mini ESP8266 模塊相連,上文編譯后的固件燒錄之后,串口助手中會收到如下打印信息:

我們可以看到默認(rèn)的 linkkitapp 示例,Log 信息是通過 UART0 發(fā)送出來的,而且里面有很多咱們不關(guān)心的信息,應(yīng)該將此部分信息進(jìn)行屏蔽。

所以我們需要做如下幾個工作:

  1. 將串口 0 和串口 1 的比特率設(shè)為一致;交換 UART0 和 UART1,讓 UART1 輸出 Log 日志;UART0 與 STM32 進(jìn)行通信;將 STM32 發(fā)上來的信息,通過 UART0 接收并發(fā)送到云端;將云端下發(fā)的有用的信息通過 UART0 轉(zhuǎn)發(fā)給 STM32。

解決問題 1. 串口的初始化函數(shù)在platformmcuesp8266bspdriveruart.c 411 行 中,初始化 uart1,uart0 的波特率都為 115200。

void
uart_init_new(uart_dev_t?*uart)
{
????UART_WaitTxFifoEmpty(UART0);
????UART_WaitTxFifoEmpty(UART1);

????if?(uart?==?NULL)
????{
????????return;
????}

????if?(uart->port?==?1)
????{
????????//printf("port=?1n?");
????????//uart1?setting
????????UART_ConfigTypeDef?uart_config;
????????uart_config.baud_rate?=?uart->config.baud_rate;
????????uart_config.data_bits?=?UART_WordLength_8b;
????????uart_config.parity?=?USART_Parity_None;
????????uart_config.stop_bits?=?USART_StopBits_1;
????????uart_config.flow_ctrl?=?USART_HardwareFlowControl_None;
????????uart_config.UART_RxFlowThresh?=?120;
????????uart_config.UART_InverseMask?=?UART_None_Inverse;
????????//UART_ParamConfig(UART0,?&uart_config);
????????//uart2?setting?for?log
????????//uart_config.baud_rate?=?uart->config.baud_rate;
????????UART_ParamConfig(UART1,?&uart_config);

????????UART_SetPrintPort(UART1);
????????//UART_intr_handler_register(uart0_rx_isr,?NULL);
????????ETS_UART_INTR_ENABLE();
????}
????else
????{
????????//printf("port=?0?n?");
????????UART_ConfigTypeDef?uart_config;
????????uart_config.baud_rate?=?uart->config.baud_rate;
????????//?uart_config.baud_rate?=?BIT_RATE_921600;
????????uart_config.data_bits?=?UART_WordLength_8b;
????????uart_config.parity?=?USART_Parity_None;
????????uart_config.stop_bits?=?USART_StopBits_1;
????????uart_config.flow_ctrl?=?USART_HardwareFlowControl_None;
????????uart_config.UART_RxFlowThresh?=?120;
????????uart_config.UART_InverseMask?=?UART_None_Inverse;
????????UART_ParamConfig(UART0,?&uart_config);

????????UART_IntrConfTypeDef?uart_intr;
????????uart_intr.UART_IntrEnMask?=?UART_RXFIFO_TOUT_INT_ENA?|?UART_FRM_ERR_INT_ENA?|?UART_RXFIFO_FULL_INT_ENA?|?UART_TXFIFO_EMPTY_INT_ENA;
????????uart_intr.UART_RX_FifoFullIntrThresh?=?100;//10
????????uart_intr.UART_RX_TimeOutIntrThresh?=?10;//2
????????uart_intr.UART_TX_FifoEmptyIntrThresh?=?20;
????????UART_IntrConfig(UART0,?&uart_intr);

????????UART_SetPrintPort(UART0);
????????UART_intr_handler_register(uart0_rx_isr,?NULL);
????????ETS_UART_INTR_ENABLE();
????}
}

解決問題 2. 交換 UART0 和 UART1:修改此文件:AliOS-Thingsplatformmcuesp8266haluart.c 17 行。

int32_t?hal_uart_send(uart_dev_t?*uart,?const?void?*data,?uint32_t?size,?uint32_t?timeout)
{
????int?i?=?0;
????char*?pdata?=?(char?*)data;

????for(i?=?0;?i?<?size;?i++)
????{
????????//uart0_write_char(pdata[i]);
????????if(uart->port?==?1)
????????????uart0_write_char(pdata[i]);
????????else
????????????uart1_write_char(pdata[i]);????????
????}

????return?0;
}

編譯一下,報錯:

去掉platformmcuesp8266bspdriveruart.c 60 行, LOCAL void uart1_write_char(char c) 函數(shù)前面的 LOCAL。

再次編譯正常。

修改串口初始化,文件所在路徑:platformmcuesp8266bspentry.c 60 行,修改后的代碼具體如下:

void?user_init(void)
{
????int?ret?=?0;

????extern?int32_t?hal_uart_init(uart_dev_t?*uart);
????extern?void?key_gpio_init(void);

????key_gpio_init();
????///hal_uart_init(&uart_0);

????uart_config_t?uartConfig0;
????uartConfig0.baud_rate?=?115200;
????uartConfig0.parity?=?0;
????uartConfig0.stop_bits?=?1;
????uart_dev_t?uart0;
????uart0.port?=?0;
????uart0.config?=?uartConfig0;
????hal_uart_init(&uart0);


????uart_config_t?uartConfig1;
????uartConfig1.baud_rate?=?115200;
????uart_dev_t?uart1;
????uart1.port?=?1;
????uart1.config?=?uartConfig1;
????hal_uart_init(&uart1);

????printf("[%d]?--?Message?from?printf?--?user_init?--?rn",(unsigned)aos_now_ms());

????hal_wifi_register_module(&aos_wifi_esp8266);
????ret?=?hal_wifi_init();
????if?(ret){
????????printf("waring:?wifi?init?fail?ret?is?%d?rn",?ret);
????}
#if?defined(SUPPORT_SINGAPORE_DOMAIN)
????aos_task_new("main",?app_entry,?0,?7.5*1024);
#elif?defined(ESP8266_CHIPSET)
????aos_task_new("main",?app_entry,?0,?2*1024);
#else
????aos_task_new("main",?app_entry,?0,?6*1024);
#endif
}

解決問題 3.

  • 下發(fā)有用信息:

修改文件appexamplelinkkitapplinkkit_example_solo.c 109 行。

/**?recv?event?post?response?message?from?cloud?**/
static?int?user_property_set_event_handler(const?int?devid,?const?char?*request,?const?int?request_len)
{
????int?res?=?0;
????EXAMPLE_TRACE("Property?Set?Received,?Request:?%s",?request);

????hal_uart0_send(request,strlen(request));????????//xiaoha?+++

????res?=?IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID,?ITM_MSG_POST_PROPERTY,
?????????????????????????????(unsigned?char?*)request,?request_len);
????EXAMPLE_TRACE("Post?Property?Message?ID:?%d",?res);

????return?0;
}

  • 上發(fā)有用信息:

修改文件 appexamplelinkkitapplinkkit_example_solo.c ?27 行處添加頭文件:

#include?"aos/hal/uart.h"

includeaoshaluart.h文件 102 行后增加兩個函數(shù)聲明:

int32_t?hal_uart0_printf(const?void?*data);
int32_t?hal_uart0_send(const?void?*data,?uint32_t?size);

AliOS-Thingsplatformmcuesp8266haluart.c文件 32 行后增加兩個函數(shù)實現(xiàn):

int32_t?hal_uart0_printf(const?void?*data)
{
????int?i?=?0;
????char*?pdata?=?(char?*)data;
????while(*?pdata)
????????uart0_write_char(*?pdata++);
????return?0;
}

int32_t?hal_uart0_send(const?void?*data,?uint32_t?size)
{
????int?i?=?0;
????char*?pdata?=?(char?*)data;
????for(i?=?0;?i?<?size;?i++)
????{
????????uart0_write_char(pdata[i]);
????}
????uart0_write_char('r');
????uart0_write_char('n');
????return?0;
}

修改文件appexamplelinkkitapplinkkit_example_solo.c ?378 行, 修改上傳屬性的數(shù)據(jù):

/*?Post?Proprety?Example?*/
uint8_t?receive_bytes[255];
memset(receive_bytes,0,255);????// 或者?memset(receive_bytes,0,128*sizeof(char));
int32_t?ret?=?-1;
uint32_t?i,?recv_size?=?0;

uart_dev_t?uart0;
uart0.port?=?0;????

ret?=?hal_uart_recv_II(&uart0,?&receive_bytes,?255,?&recv_size,?20);

if?((ret?==?0))
{
????hal_uart0_printf(receive_bytes);

????char?property_payload[30]?=?{0};
????HAL_Snprintf(property_payload,sizeof(property_payload),"%s",receive_bytes);

????res?=?IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID,ITM_MSG_POST_PROPERTY,
????????????????????????????(unsigned?char?*)property_payload,strlen(property_payload));

????EXAMPLE_TRACE("Post?Property?Message?ID:?%d",res);
}

修改智能設(shè)備的三元組信息:

//?for?demo?only
#define?PRODUCT_KEY??????"a1xHkDXXXXX"
#define?PRODUCT_SECRET???"0miHcO6f4E8XXXXX"
#define?DEVICE_NAME??????"ZNFS0001"
#define?DEVICE_SECRET????"xnOe5VcOkvXFTBAZaik4hz7y67XXXXXX"

登錄阿里云飛燕平臺:https://living.aliyun.com/#/

創(chuàng)建阿里云物聯(lián)網(wǎng)智能設(shè)備的方法請參見下文:

七步快速開啟產(chǎn)品智能化

在產(chǎn)品頁面獲得ProductSecret

在設(shè)備頁面獲得設(shè)備的三元組信息:

?

燒寫固件

?

使用云智能 APP 配網(wǎng)并添加設(shè)備

固件燒寫完成之后,復(fù)位 ESP8266 模塊,可以看到 ESP8266 的串口 1 打印如下信息:

此時雖然在掃描 SSID,但是掃描二維碼并不能正常添加設(shè)備,需要先進(jìn)入配網(wǎng)模式,再掃描二維碼添加設(shè)備。

進(jìn)入配網(wǎng)模式的方法:

使用一個跳線,先把 D5(GPIO14)接 GND,再接 3.3V。

出現(xiàn)如下 Log 即進(jìn)入配網(wǎng)模式:

?

然后使用云智能 APP 掃描上面的二維碼添加設(shè)備并配網(wǎng)。

配網(wǎng)成功,云智能 APP 出現(xiàn)如下界面:

配網(wǎng)成功,串口助手可以收到來自服務(wù)器端的如下 Log 日志:

此時查看阿里云飛燕平臺的后臺,可以看到設(shè)備已經(jīng)成功上線。

?

模擬上傳屬性

經(jīng)過上面的改造之后,我們只需要向 UART0 發(fā)送 JSON 格式的數(shù)據(jù),即可修改服務(wù)器端的數(shù)值,比如發(fā)送:

{"CurrentTemperature":26}

發(fā)送完畢,服務(wù)器端的當(dāng)前溫度值將會修改為 26℃,在運(yùn)行狀態(tài)中可以實時看出來當(dāng)前溫度值是實時變化的。

?

模擬設(shè)置屬性

手機(jī)端 APP 點擊某個按鈕之后,將會將數(shù)據(jù)包發(fā)送至 ESP8266,ESP8266 將有用信息通過 UART0 的 TX 引腳發(fā)送給 STM32,STM32 將收到服務(wù)器端指令,對此指令進(jìn)行解析,進(jìn)而做相應(yīng)的動作,具體邏輯類似下圖所示。

調(diào)試真實設(shè)備中,對電源開關(guān)設(shè)置為 1,即{"PowerSwitch":1},在串口助手中我們收到指令{"PowerSwitch":1};

我們對電源開關(guān)設(shè)置為 0,即{"PowerSwitch":0},可以看到串口助手中,收到對應(yīng)的指令{"PowerSwitch":0}。

STM32 中我們使用 cJSON 對上面字符串進(jìn)行解析即可,然后做相應(yīng)的動作,即完成了云端對設(shè)備的遠(yuǎn)程控制。

細(xì)心的人可能發(fā)現(xiàn)了,為什么我們用 CurrentTemperature 或者 PowerSwitch 來設(shè)置屬性呢?其實他們就是我們創(chuàng)建產(chǎn)品的時候,進(jìn)行功能定義的時候,設(shè)置的標(biāo)識符。

至此,使用 ESP8266 模塊,已經(jīng)完成了燒寫 AliOS Things 3.0 固件,成功配網(wǎng)、添加設(shè)備并連上了阿里云服務(wù)器。

讓 ESP8266 的串口 0 與 STM32 的串口進(jìn)行數(shù)據(jù)通信,發(fā)送模擬上傳屬性中的數(shù)據(jù)完成屬性的上報,串口接收、解析服務(wù)器返回的數(shù)據(jù),根據(jù)解析的結(jié)果進(jìn)而完成對設(shè)備的控制,從而實現(xiàn)了 STM32 和 ESP8266 的雙向通信。

各位小伙伴可以在我的基礎(chǔ)上隨意擴(kuò)展,這樣你的設(shè)備就實現(xiàn)了接入阿里云物聯(lián)網(wǎng)平臺。

阿里巴巴

阿里巴巴

阿里巴巴集團(tuán)經(jīng)營多項業(yè)務(wù),另外也從關(guān)聯(lián)公司的業(yè)務(wù)和服務(wù)中取得經(jīng)營商業(yè)生態(tài)系統(tǒng)上的支援。業(yè)務(wù)和關(guān)聯(lián)公司的業(yè)務(wù)包括:淘寶網(wǎng)、天貓、聚劃算、全球速賣通、阿里巴巴國際交易市場、1688、阿里媽媽、阿里云、螞蟻金服、菜鳥網(wǎng)絡(luò)等。

阿里巴巴集團(tuán)經(jīng)營多項業(yè)務(wù),另外也從關(guān)聯(lián)公司的業(yè)務(wù)和服務(wù)中取得經(jīng)營商業(yè)生態(tài)系統(tǒng)上的支援。業(yè)務(wù)和關(guān)聯(lián)公司的業(yè)務(wù)包括:淘寶網(wǎng)、天貓、聚劃算、全球速賣通、阿里巴巴國際交易市場、1688、阿里媽媽、阿里云、螞蟻金服、菜鳥網(wǎng)絡(luò)等。收起

查看更多

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

公眾號『嵌入式從0到1』,號主:程序員小哈,是一個軟硬件全棧開發(fā)工程師(12年工作經(jīng)驗的老司機(jī)),電子發(fā)燒友論壇鴻蒙版塊版主,公眾號內(nèi)容專注于嵌入式學(xué)習(xí)。堅持原創(chuàng),寫有圖、有視頻的保姆級教程文章,篇篇有干貨。做一個講清楚,說明白,大家學(xué)得會的交流平臺。