STM32 ES8266上阿里雲IOT MQTT實踐【第七章】:ESP8266+MQTT上阿里雲物聯網平臺實踐

課程大綱

【第一章】:物聯網簡介(什麼是物聯網)
【第二章】:物聯網十大應用場景
【第三章】:什麼是MCU?
【第四章】:MCU的應用範圍
【第五章】:我們要怎麼入門MCU開發?
【第六章】:如何使用STM32Cube MX進行STM32的快速開發
【第七章】:ESP8266+MQTT上阿里雲物聯網平臺實踐(附源碼)

STM32CubeMX AT指令實現MQTT協議並接入阿里雲IOT平臺 源碼解析
CSDN源代碼下載
Github源代碼下載

7. 實踐:STM32使用ESP8266+MQTT上阿里雲物聯網平臺實踐

7.1 項目整體介紹

7.1.1 硬件資源
  • STM32F429IGT6開發板:核心
  • ST-Link下載器:下載程序用
  • USB轉232串口線:串口通信,調試用
  • USB供電線:給開發板供電
  • DHT11溫溼度模塊:採集環境溫溼度
  • ATK-ESP8266:聯網上傳數據

image-20200504195716268

7.1.2 軟件資源
  • 串口調試助手(調試用)

image-20200504200038516

7.1.3 其它資源
  • STM32F429IGT6開發板原理圖
  • DHT11溫溼度傳感器編程手冊
  • ATK-ESP8266編程手冊
  • ESP8266樣例程序
  • 阿里雲MQTT樣例程序

7.2 新建工程

  • 選擇通過選擇MCU創建工程

image-20200504200445596

  • 選擇芯片

image-20200504200612470

  • 建立成功

image-20200504200759484

7.3 基礎工程配置

7.3.1 時鐘配置
  • 高速時鐘:選擇外部晶振

image-20200507105624694

  • 高速時鐘選擇Crystal/Ceramic Resonator

在用cube配置時鐘時,有下面兩個選項
BYPASS Clock Source(旁路時鐘源)
Crystal/Ceramic Resonator(晶體/陶瓷晶振)
下面來解釋一下:
所謂HSE旁路時鐘源,是指無需使用外部晶體時所需的芯片內部時鐘驅動組件,直接從外界導入時鐘信號。猶如芯片內部的驅動組件被旁路了。
外部晶體/陶瓷諧振器(HSE晶體)模式該時鐘源是由外部無源晶體與MCU內部時鐘驅動電路共同配合形成,有一定的啓動時間,精度較高。

image-20200507105818756

  • 配置時鐘爲180MHz

image-20200507110045846

7.3.2 下載接口設置,設置爲串行下載

image-20200507110151989

7.3.3 LED燈配置
  • 查看原理圖

    LED_R——PH10 紅燈

    LED_G——PH11 綠燈

    LED_B——PH12 藍燈

    低電平有效,IO口要設置爲推輓輸出,上拉

image-20200507110347395

  • 工程配置

    • 選擇引腳設置爲GPIO_Ooutput

    • 配置標籤 LED_R LED_G LED_B,方便工程直接調用

    • image-20200507110609310

    • 設置上下拉

    • image-20200507110918931

7.3.4 按鍵輸入中斷設置
  • 查看原理圖
  • image-20200507111139923
  • 工程設置
  • image-20200507111415830
  • image-20200507111426161
  • image-20200507111439585
  • 設置中斷等級,不能太高
  • image-20200507111507573
  • image-20200507111541714
7.3.5 調試串口設置
  • 查看開發板原理圖,找到RS232

image-20200504202324034

  • 修改跳帽方向

image-20200504202114680

  • 串口參數配置

image-20200504202531112

  • 修改PD5爲USART2_TX

image-20200504202632483

  • 修改PD6爲USART2_RX

image-20200504202705527

  • PA2 PA3自動取消定義

image-20200504202843344

image-20200507112042637

7.3.6 ES8266串口設置

image-20200507112200157

7.3.7 DHT11數據採集IO

image-20200507112422533

7.3.8 工程概覽

image-20200507112914628

7.4 生成並驗證工程

7.4.1 生成工程
  • 點擊Project Manager並設置工程

image-20200507112544875

  • 勾選上單獨生成.c.h文件

image-20200504203158452

  • 點擊生成工程

image-20200504203313895

  • 查看工程
    • 平臺已經自動生成USART1、USART2驅動和GPIO驅動
    • 用戶只用專注於程序邏輯代碼,實現快速開發

image-20200507121925003

7.4.2 編寫USART2串口調試驗證代碼
  • 在文件usart.h中引入標準庫stdio.h(裏面包含printf)
#include "stdio.h"
  • 在文件usart.c中添加printf重定向函數
// 重定向printf函數
int fputc(int ch,FILE *f)
{
    uint8_t temp[1]={ch};
    HAL_UART_Transmit(&huart2,temp,1,2);
	return 0;
}
  • 爲了方便調試,在main.c中加入以下宏定義
#define USER_MAIN_DEBUG

#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf( format "\r\n",##__VA_ARGS__)
#define user_main_info(format, ...) printf("【main】info:" format "\r\n",##__VA_ARGS__)
#define user_main_debug(format, ...) printf("【main】debug:" format "\r\n",##__VA_ARGS__)
#define user_main_error(format, ...) printf("【main】error:" format "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#define user_main_info(format, ...)
#define user_main_debug(format, ...)
#define user_main_error(format, ...)
#endif
  • 在主函數while(1)循環中添加以下測試代碼
user_main_debug("我是USART2測試代碼!\n");
HAL_Delay(1000);
  • 設置下載後自動運行,編譯運行,連接串口調試助手,觀察現象

image-20200507123750198

image-20200507123848921

  • 測試成功!!
7.4.3 編寫三色燈測試代碼
  • 在main.c 主循環添加以下測試代碼
//紅燈亮,其它滅
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
HAL_Delay(500);
//綠燈亮,其它滅
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
HAL_Delay(500);
//藍燈亮,其它滅
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
  • 觀察LED燈,間隔500ms依次閃爍紅、綠、藍

圖片!!

  • 測試成功!!
7.4.4 編寫按鍵中斷測試代碼
  • 在main.c 底部添加以下測試代碼
/******************************  按鍵中斷測試代碼  *****************************/

//KEY1按下動作執行函數
void KEY1_Pressed(void)
{
	user_main_debug("我按下了KEY_1\r\n");
}

//KEY2按下動作執行函數
void KEY2_Pressed(void)
{
	user_main_debug("我按下了KEY_2\r\n");
}

//按鍵中斷處理函數
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    switch(GPIO_Pin)  
    {  
        case KEY_1_Pin:KEY1_Pressed();break;  
        case KEY_2_Pin:KEY2_Pressed();break;   
        default:break;  
    }  
}
  • 編譯運行,分別按下按鍵,觀察串口助手

image-20200507125155015

  • 測試成功!!

工程驗證成功!!

7.5 移植DHT11溫溼度傳感器驅動程序

7.5.1 利用TIM1實現us級延時(編寫DHT11驅動時會用)
  • 首先去工程中設置定時器1

    image-20200507130101274

  • 重新生成工程,來到tim.c,在/* USER CODE BEGIN 1 */中添加以下代碼

//使用定時器1來做us級延時函數,溫溼度傳感器用,量程0-6553us
void TIM1_Delay_us(uint16_t n_us)
{
	__HAL_TIM_SetCounter(&htim1, 0);//htim1

	/* 開啓定時器1計數 */
	__HAL_TIM_ENABLE(&htim1);

	while(__HAL_TIM_GetCounter(&htim1) < (10 * n_us));//計數頻率10MHz,10次即爲1us
	/* Disable the Peripheral */
	__HAL_TIM_DISABLE(&htim1);
}
  • 在tim.h中添加函數定義
void TIM1_Delay_us(uint16_t n_us);
  • 到此,自定義us級延時函數添加完畢,在main.c 主循環中添加以下測試代碼
// 自定義us級延時函數測試
static uint16_t tim1_test;

//延時1000個1ms
for(tim1_test = 0;tim1_test<1000;tim1_test++)
{
    //延時1ms
    TIM1_Delay_us(1000);
}
user_main_debug("我是us級延時函數測試代碼,1s打印一次!\n");
  • 觀察串口打印,非常精確比自帶的HAL_Delay還準!!

image-20200507131303080

7.5.2 添加DHT11驅動文件到工程中
  • 來到工程目錄下,添加BSP文件夾

image-20200507131516946

  • 將事先準備好的DHT11驅動文件夾拷貝進去

image-20200507131620652

  • 裏面包含這兩個文件

image-20200507131641449

  • Keil工程添加工程文件

image-20200507131757306

  • 添加頭文件地址

image-20200507131850975

7.5.3 修改驅動.c .h程序文件
  • 修改文件 “hal_temp_hum.c"

image-20200507132338750

  • 修改文件 “hal_temp_hum.h"

image-20200507133711271

  • 在main.c 中引入頭文件"hal_temp_hum.h"
#include "hal_temp_hum.h"

image-20200507132539145

  • 在main.c KEY1_Pressed函數中添加以下測試代碼
//KEY1按下動作執行函數
void KEY1_Pressed(void)
{
    user_main_debug("按下KEY_1\r\n");
    
	uint8_t temperature;
	uint8_t humidity;
	uint8_t get_times;

	// 獲取溫溼度信息並用串口打印,獲取十次,直到成功跳出
	for(get_times=0;get_times<10;get_times++)
	{
		if(!dht11Read(&temperature, &humidity))//Read DHT11 Value
		{
				user_main_info("temperature=%d,humidity=%d \n",temperature,humidity);
				break;
		}
	}
}
  • 編譯,下載運行,按下KEY_1,觀察串口現象

image-20200507133812297

  • 成功!!

7.6 移植ESP8266 AT指令WIFI驅動模塊

7.6.1 連接硬件

image-20200507140111603

7.6.2 添加ESP8266串口驅動文件到工程中
  • 與DHT11一樣,將ESP8266驅動文件放到BSP目錄下

image-20200507134337359

image-20200507134346098

  • 工程中加入文件

image-20200507134447790

  • 添加頭文件路徑

image-20200507134636295

  • 在main.c中引入頭文件
#include "esp8266_at.h"

image-20200507134709421

7.6.3 驅動程序分析
  • 直接看代碼~
7.6.4 測試ESP8266驅動程序
  • 添加WIFI熱點宏定義
//此處根據自己的wifi作調整
#define WIFI_NAME "HappyOneDay"
#define WIFI_PASSWD "1234567890"
  • 在KEY1_Pressed函數中添加測試代碼
//KEY1按下動作執行函數
void KEY1_Pressed(void)
{
	user_main_debug("我按下了KEY_1\r\n");

	/* ESP8266測試代碼 */
	uint8_t status=0;
	//初始化
	if(ESP8266_Init())
	{
		user_main_info("ESP8266初始化成功!\r\n");
		status++;
	}

	//連接熱點
	if(status==1)
	{
		if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
		{
			user_main_info("ESP8266連接熱點成功!\r\n");
			status++;
		}
	}
}
  • 編譯,燒錄運行,按下KEY_1 觀察現象

image-20200507135513552

  • 測試成功!!

7.7 移植MQTT驅動

7.7.1 添加驅動文件到工程中
  • 將驅動賦值到BSP文件目錄下

image-20200507135708766

image-20200507135724735

  • 將文件加入工程

image-20200507135820349

  • 添加頭文件路徑

image-20200507135853187

7.7.2 使能USART1接收中斷,添加接收函數
  • 打開中斷

image-20200507142128079

  • 優先級修改爲3

image-20200507142213561

  • 生成工程,在main.c中/* USER CODE BEGIN 2 */處添加以下代碼
//開啓USART1接收中斷
HAL_UART_Receive_IT(&huart1,usart1_rxone,1);
  • 在在main.c中/* USER CODE BEGIN 4 */處添加以下代碼(爲了接收服務器的響應)
//USART1 ES8266驅動串口接收中斷處理函數
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1)	// 判斷是由哪個串口觸發的中斷
	{
		//將接收到的數據放入接收usart1接收數組
		usart1_rxbuf[usart1_rxcounter] = usart1_rxone[0];
		usart1_rxcounter++;	//接收數量+1
		
		//重新使能串口1接收中斷
		HAL_UART_Receive_IT(&huart1,usart1_rxone,1);		
	}
}
7.7.3 在main.c中引入頭文件,測試代碼
  • 引入頭文件
#include "esp8266_mqtt.h"

image-20200507135946011

  • 使用我一開始配置好的阿里雲IOT進行測試,怎麼配置稍後介紹
//此處是阿里雲服務器的登陸配置
#define MQTT_BROKERADDRESS "a1lAoazdH1w.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_CLIENTID "00001|securemode=3,signmethod=hmacsha1|"
#define MQTT_USARNAME "BZL01&a1lAoazdH1w"
#define MQTT_PASSWD "51A5BB10306E976D6C980F73037F2D9496D2813A"
#define	MQTT_PUBLISH_TOPIC "/sys/a1lAoazdH1w/BZL01/thing/event/property/post"
#define MQTT_SUBSCRIBE_TOPIC "/sys/a1lAoazdH1w/BZL01/thing/service/property/set"
  • 添加error報錯函數
//進入錯誤模式等待手動重啓
void Enter_ErrorMode(uint8_t mode)
{
	HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
	while(1)
	{
		switch(mode){
			case 0:user_main_error("ESP8266初始化失敗!\r\n");break;
			case 1:user_main_error("ESP8266連接熱點失敗!\r\n");break;
			case 2:user_main_error("ESP8266連接阿里雲服務器失敗!\r\n");break;
			case 3:user_main_error("ESP8266阿里雲MQTT登陸失敗!\r\n");break;
			case 4:user_main_error("ESP8266阿里雲MQTT訂閱主題失敗!\r\n");break;
			default:user_main_info("Nothing\r\n");break;
		}
		user_main_info("請重啓開發板");
		//HAL_GPIO_TogglePin(LED_R_GPIO_Port,LED_R_Pin);
		HAL_Delay(200);
	}
}
  • 修改KEY1_Pressed函數
/******************************  按鍵中斷測試代碼  *****************************/

//KEY1按下動作執行函數
void KEY1_Pressed(void)
{
	user_main_debug("我按下了KEY_1\r\n");
	
	/* DHT11溫溼度傳感器測試 */
//	uint8_t temperature;
//	uint8_t humidity;
//	uint8_t get_times;

//	// 獲取溫溼度信息並用串口打印,獲取十次,直到成功跳出
//	for(get_times=0;get_times<10;get_times++)
//	{
//		if(!dht11Read(&temperature, &humidity))//Read DHT11 Value
//		{
//				user_main_info("temperature=%d,humidity=%d \n",temperature,humidity);
//				break;
//		}
//	}
	
	/* ESP8266&MQTT測試代碼 */
	uint8_t status=0;

	//初始化
	if(ESP8266_Init())
	{
		user_main_info("ESP8266初始化成功!\r\n");
		status++;
	}
	else Enter_ErrorMode(0);

	//連接熱點
	if(status==1)
	{
		if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
		{
			user_main_info("ESP8266連接熱點成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(1);
	}
	
	//連接阿里雲IOT服務器
	if(status==2)
	{
		if(ESP8266_ConnectServer("TCP",MQTT_BROKERADDRESS,1883)!=0)
		{
			user_main_info("ESP8266連接阿里雲服務器成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(2);
	}
	
	//登陸MQTT
	if(status==3)
	{
		if(MQTT_Connect(MQTT_CLIENTID, MQTT_USARNAME, MQTT_PASSWD) != 0)
		{
			user_main_info("ESP8266阿里雲MQTT登陸成功!\r\n");
			status++;
		}
		else Enter_ErrorMode(3);
	}

	//訂閱主題
	if(status==4)
	{
		if(MQTT_SubscribeTopic(MQTT_SUBSCRIBE_TOPIC,0,1) != 0)
		{
			user_main_info("ESP8266阿里雲MQTT訂閱主題成功!\r\n");
		}
		else Enter_ErrorMode(4);
	}
}
  • 編譯,下載運行,按下按鍵,觀察串口打印

image-20200507142647550

  • 測試成功!!!

7.8 MQTT協議簡單介紹

MQTT中文網:http://mqtt.p2hp.com/

image-20200507143425086

image-20200507143437970

7.9 阿里雲物聯網平臺介紹

官網地址:https://help.aliyun.com/product/30520.html

7.9.1 創建產品
  • 點擊創建產品

image-20200507143608350

  • 按以下格式創建

image-20200507143720005

  • 查看產品詳情

image-20200507143821968

7.9.2 定義產品功能
  • 編輯草稿

image-20200507143857884

  • 添加自定義功能

image-20200507143946099

  • 添加溫度屬性

image-20200507144125329

  • 添加溼度屬性

image-20200507144348668

  • 添加紅燈控制開關

image-20200507144531497

  • 添加綠燈控制開關

image-20200507144540793

  • 添加藍燈控制開關

image-20200507144549003

  • 發佈上線

image-20200507144612140

7.9.3 添加具體設備
  • 添加設備

image-20200507144814845

image-20200507144834281

  • 查看設備屬性

image-20200507144854827

  • 查看設備證書**(關鍵)**

image-20200507144924761

7.9.4 使用MQTT.fx模擬硬件進行連接
  • 使用MQTT.fx接入物聯網平臺:

https://help.aliyun.com/document_detail/140507.html?spm=a2c4g.11174283.6.565.3a8b16686rXYnj

  • MQTT.fx官網:

https://mqttfx.jensd.de/index.php/download?spm=a2c4g.11186623.2.20.17b67908o3uJ8y

此處對應着官方文檔進行講解

參數 說明
Profile Name 輸入您的自定義名稱。
Profile Type 選擇爲MQTT Broker
Broker Address 連接域名。格式:${YourProductKey}.iot-as-mqtt.${region}.aliyuncs.com。其中,${region}需替換爲您物聯網平臺服務所在地域的代碼。地域代碼,請參見地域和可用區。如:alxxxxxxxxx.iot-as-mqtt.cn-shanghai.aliyuncs.com
Broker Port 設置爲1883。
Client ID 填寫mqttClientId,用於MQTT的底層協議報文。格式固定:${clientId}|securemode=3,signmethod=hmacsha1|。完整示例:12345|securemode=3,signmethod=hmacsha1|。其中,${clientId}爲設備的ID信息。可取任意值,長度在64字符以內。建議使用設備的MAC地址或SN碼。securemode爲安全模式,TCP直連模式設置爲securemode=3,TLS直連爲securemode=2。signmethod爲算法類型,支持hmacmd5和hmacsha1。說明 輸入Client ID信息後,請勿單擊Generate
地域名稱 所在城市 Region ID 可用區數量
華北 1 青島 cn-qingdao 2
華北 2 北京 cn-beijing 8
華北 3 張家口 cn-zhangjiakou 2
華北 5 呼和浩特 cn-huhehaote 2
華東 1 杭州 cn-hangzhou 8
華東 2 上海 cn-shanghai 6
華南 1 深圳 cn-shenzhen 5
華南 2 河源 cn-heyuan 2
西南 1 成都 cn-chengdu 2
  • 示例:
Broker Address:	a1kvAFB5siA.iot-as-mqtt.cn-shanghai.aliyuncs.com
Broker Port:	1883
Client ID:		00001|securemode=3,signmethod=hmacsha1|
參數 說明
User Name 由設備名DeviceName、符號(&)和產品ProductKey組成。固定格式:${YourDeviceName}&${YourPrductKey}。完整示例如:device&alxxxxxxxxx
Password 密碼由參數值拼接加密而成。說明 如果您使用的MQTT.fx版本,在粘貼Password後不顯示具體的字符串,只要光標已從輸入框的前部移至了後部,則表示粘貼成功,請勿重複粘貼。您可以使用物聯網平臺提供的生成工具自動生成Password,也可以手動生成Password。單擊下載Password生成小工具。解壓縮下載包後,雙擊sign文件,即可使用。使用Password生成小工具的輸入參數:productKey:設備所屬產品Key。可在控制檯設備詳情頁查看。deviceName:設備名稱。可在控制檯設備詳情頁查看。deviceSecret:設備密鑰。可在控制檯設備詳情頁查看。timestamp:(可選)時間戳。clientId:設備的ID信息,與Client ID中${clientId}一致。method:選擇簽名算法類型,與Client ID中signmethod確定的加密方法一致。手動生成方法如下:拼接參數。提交給服務器的clientIddeviceNameproductKeytimestamp(timestamp爲非必選參數)參數及參數值依次拼接。本例中,clientId值爲12345,deviceName值爲device,productKey值爲alxxxxxxxxx,拼接結果爲:clientId12345deviceNamedeviceproductKeyalxxxxxxxxx加密。通過Client ID中確定的加密方法,使用設備deviceSecret,將拼接結果加密。假設設備的deviceSecret值爲abc123,加密計算格式爲hmacsha1(abc123,clientId12345deviceNamedeviceproductKeyalxxxxxxxxx)
  • password生成小工具(一個離線網頁)

image-20200507150142511

  • 示例:
User Name:	TESTDEVICE01&a1kvAFB5siA
Password:	E18BFBEE7686EC3FBC5EAB10BEB101FD0913CF39
  • 填入MQTT.fx,進行測試

image-20200507150255329

  • 點擊connect

image-20200507150320960

  • 連接成功!!!
7.9.5 訂閱消息調試
  • 來到設備屬性,物模型通信Topic

image-20200507150454316

  • MQTT.fx訂閱/sys/a1kvAFB5siA/TESTDEVICE01/thing/service/property/set

image-20200507150544732

  • 訂閱消息成功,嘗試平臺下發消息

image-20200507150614904

  • 來到這裏進行下發

image-20200507150632532

  • 設備成功收到消息

image-20200507150714719

7.9.6 使用MQTT.fx模擬設備進行消息推送
  • 推送地址:/sys/a1kvAFB5siA/TESTDEVICE01/thing/event/property/post

  • 推送以下json消息

    • 溫度:20.0攝氏度
    • 溼度:60%
    • 紅燈:開
    • 綠燈:開
    • 藍燈:關
{
    "method":"thing.service.property.set",
    "id":"354062502",
    "params":{
        "temperature":20.0,
        "humidity":60.0,
        "switch_led_r":1,
        "switch_led_g":1,
        "switch_led_b":0
    },
    "version":"1.0.0"
}

image-20200507151023439

  • 來看平臺收到的消息日誌

image-20200507151109459

  • 可視化查看設備上報的數據

image-20200507151140341

  • 至此,MQTT.fx調試完成!!!下一步,使用單片機進行該項工作

7.10 STM32 使用MQTT接入阿里雲平臺過程詳解

直接看代碼

7.11 STM32傳感器數據上傳、平臺數據下發效果展示

真機演示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章