【第一章】:物联网简介(什么是物联网)
【第二章】:物联网十大应用场景
【第三章】:什么是MCU?
【第四章】:MCU的应用范围
【第五章】:我们要怎么入门MCU开发?
【第六章】:如何使用STM32Cube MX进行STM32的快速开发
【第七章】:ESP8266+MQTT上[阿里云](https://l.gushuji.site/aliyun)物联网平台实践(附源码)
STM32CubeMX AT指令实现MQTT协议并接入[阿里云](https://l.gushuji.site/aliyun)IOT平台 源码解析
CSDN源代码下载
Github源代码下载
在用cube配置时钟时,有下面两个选项
BYPASS Clock Source(旁路时钟源)
Crystal/Ceramic Resonator(晶体/陶瓷晶振)
下面来解释一下:
所谓HSE旁路时钟源,是指无需使用外部晶体时所需的芯片内部时钟驱动组件,直接从外界导入时钟信号。犹如芯片内部的驱动组件被旁路了。
外部晶体/陶瓷谐振器(HSE晶体)模式该时钟源是由外部无源晶体与MCU内部时钟驱动电路共同配合形成,有一定的启动时间,精度较高。
查看原理图
LED_R——PH10 红灯
LED_G——PH11 绿灯
LED_B——PH12 蓝灯
低电平有效,IO口要设置为推挽输出,上拉
工程配置
选择引脚设置为GPIO_Ooutput
配置标签 LED_R LED_G LED_B,方便工程直接调用
设置上下拉
在文件usart.h中引入标准库stdio.h(里面包含printf)
在文件usart.c中添加printf重定向函数
// 重定向printf函数 int fputc(int ch,FILE *f) { uint8t temp[1]={ch}; HALUART_Transmit(&huart2,temp,1,2); return 0; }
为了方便调试,在main.c中加入以下宏定义
在主函数while(1)循环中添加以下测试代码
usermaindebug("我是USART2测试代码!\n"); HAL_Delay(1000);
设置下载后自动运行,编译运行,连接串口调试助手,观察现象
在main.c 主循环添加以下测试代码
//红灯亮,其它灭 HALGPIOWritePin(LEDRGPIOPort,LEDRPin,GPIOPINRESET); HALGPIOWritePin(LEDGGPIOPort,LEDGPin,GPIOPINSET); HALGPIOWritePin(LEDBGPIOPort,LEDBPin,GPIOPINSET); HALDelay(500); //绿灯亮,其它灭 HALGPIOWritePin(LEDRGPIOPort,LEDRPin,GPIOPINSET); HALGPIOWritePin(LEDGGPIOPort,LEDGPin,GPIOPINRESET); HALGPIOWritePin(LEDBGPIOPort,LEDBPin,GPIOPINSET); HALDelay(500); //蓝灯亮,其它灭 HALGPIOWritePin(LEDRGPIOPort,LEDRPin,GPIOPINSET); HALGPIOWritePin(LEDGGPIOPort,LEDGPin,GPIOPINSET); HALGPIOWritePin(LEDBGPIOPort,LEDBPin,GPIOPINRESET); HALDelay(500);
观察LED灯,间隔500ms依次闪烁红、绿、蓝
图片!!
在main.c 底部添加以下测试代码
/** 按键中断测试代码 */
//KEY1按下动作执行函数 void KEY1Pressed(void) { usermaindebug("我按下了KEY1\r\n"); }
//KEY2按下动作执行函数 void KEY2Pressed(void) { usermaindebug("我按下了KEY2\r\n"); }
//按键中断处理函数 void HALGPIOEXTICallback(uint16t GPIOPin) { switch(GPIOPin)
{
case KEY1Pin:KEY1Pressed();break; case KEY2Pin:KEY2Pressed();break;
default:break;
}
}
编译运行,分别按下按键,观察串口助手
工程验证成功!!
首先去工程中设置定时器1
重新生成工程,来到tim.c,在/* USER CODE BEGIN 1 */中添加以下代码
//使用定时器1来做us级延时函数,温湿度传感器用,量程0-6553us void TIM1Delayus(uint16t nus) { _HALTIM_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 TIM1Delayus(uint16t nus);
到此,自定义us级延时函数添加完毕,在main.c 主循环中添加以下测试代码
// 自定义us级延时函数测试 static uint16t tim1test;
//延时1000个1ms for(tim1test = 0;tim1test<1000;tim1test++) { //延时1ms TIM1Delayus(1000); } usermain_debug("我是us级延时函数测试代码,1s打印一次!\n");
观察串口打印,非常精确比自带的HAL_Delay还准!!
在main.c 中引入头文件"hal_temp_hum.h"
在main.c KEY1_Pressed函数中添加以下测试代码
//KEY1按下动作执行函数 void KEY1Pressed(void) { usermaindebug("按下KEY1\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,观察串口现象
在main.c中引入头文件
添加WIFI热点宏定义
//此处根据自己的wifi作调整
在KEY1_Pressed函数中添加测试代码
//KEY1按下动作执行函数 void KEY1Pressed(void) { usermaindebug("我按下了KEY1\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 观察现象
生成工程,在main.c中/* USER CODE BEGIN 2 */处添加以下代码
//开启USART1接收中断 HALUARTReceiveIT(&huart1,usart1rxone,1);
在在main.c中/* USER CODE BEGIN 4 */处添加以下代码(为了接收服务器的响应)
//USART1 ES8266驱动串口接收中断处理函数 void HALUARTRxCpltCallback(UARTHandleTypeDef *huart) { if(huart->Instance == USART1) // 判断是由哪个串口触发的中断 { //将接收到的数据放入接收usart1接收数组 usart1rxbuf[usart1rxcounter] = usart1rxone[0]; usart1_rxcounter++; //接收数量+1
//重新使能串口1接收中断
HAL_UART_Receive_IT(&huart1,usart1_rxone,1);
}
}
引入头文件
使用我一开始配置好的阿里云IOT进行测试,怎么配置稍后介绍
//此处是阿里云服务器的登陆配置
添加error报错函数
//进入错误模式等待手动重启 void EnterErrorMode(uint8t mode) { HALGPIOWritePin(LEDGGPIOPort,LEDGPin,GPIOPINSET); while(1) { switch(mode){ case 0:usermainerror("ESP8266初始化失败!\r\n");break; case 1:usermainerror("ESP8266连接热点失败!\r\n");break; case 2:usermainerror("ESP8266连接阿里云服务器失败!\r\n");break; case 3:usermainerror("ESP8266阿里云MQTT登陆失败!\r\n");break; case 4:usermainerror("ESP8266阿里云MQTT订阅主题失败!\r\n");break; default:usermaininfo("Nothing\r\n");break; } usermaininfo("请重启开发板"); //HALGPIOTogglePin(LEDRGPIOPort,LEDRPin); HAL_Delay(200); } }
修改KEY1_Pressed函数
/** 按键中断测试代码 */
//KEY1按下动作执行函数 void KEY1Pressed(void) { usermaindebug("我按下了KEY1\r\n");
/* DHT11温湿度传感器测试 */
// uint8t temperature; // uint8t humidity; // uint8t gettimes;
// // 获取温湿度信息并用串口打印,获取十次,直到成功跳出 // for(gettimes=0;gettimes<10;gettimes++) // { // if(!dht11Read(&temperature, &humidity))//Read DHT11 Value // { // usermain_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);
}
//连接[阿里云](https://l.gushuji.site/aliyun)IOT服务器
if(status==2)
{
if(ESP8266_ConnectServer("TCP",MQTT_BROKERADDRESS,1883)!=0)
{
user_main_info("ESP8266连接[阿里云](https://l.gushuji.site/aliyun)服务器成功!\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[阿里云](https://l.gushuji.site/aliyun)MQTT登陆成功!\r\n");
status++;
}
else Enter_ErrorMode(3);
}
//订阅主题
if(status==4)
{
if(MQTT_SubscribeTopic(MQTT_SUBSCRIBE_TOPIC,0,1) != 0)
{
user_main_info("ESP8266[阿里云](https://l.gushuji.site/aliyun)MQTT订阅主题成功!\r\n");
}
else Enter_ErrorMode(4);
}
}
编译,下载运行,按下按键,观察串口打印
MQTT中文网:http://mqtt.p2hp.com/
官网地址:https://help.aliyun.com/product/30520.html
https://help.aliyun.com/document_detail/140507.html?spm=a2c4g.11174283.6.565.3a8b16686rXYnj
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确定的加密方法一致。手动生成方法如下:拼接参数。提交给服务器的clientId、deviceName、productKey和timestamp(timestamp为非必选参数)参数及参数值依次拼接。本例中,clientId值为12345,deviceName值为device,productKey值为alxxxxxxxxx,拼接结果为:clientId12345deviceNamedeviceproductKeyalxxxxxxxxx
加密。通过Client ID中确定的加密方法,使用设备deviceSecret,将拼接结果加密。假设设备的deviceSecret值为abc123,加密计算格式为hmacsha1(abc123,clientId12345deviceNamedeviceproductKeyalxxxxxxxxx)
示例:
User Name: TESTDEVICE01&a1kvAFB5siA Password: E18BFBEE7686EC3FBC5EAB10BEB101FD0913CF39
填入MQTT.fx,进行测试
/sys/a1kvAFB5siA/TESTDEVICE01/thing/service/property/set
推送地址:/sys/a1kvAFB5siA/TESTDEVICE01/thing/event/property/post
推送以下json消息
{ "method":"thing.service.property.set", "id":"354062502", "params":{ "temperature":20.0, "humidity":60.0, "switchledr":1, "switchledg":1, "switchledb":0 }, "version":"1.0.0" }
直接看代码
真机演示