STM32接入阿里云(FreeRTOS)-实现数据上传和命令下发

功能介绍:
将传感器采集的数据上传到阿里云,同时可以下发控制板上的LED灯(PC13)

前期准备:
1、首先你得有一个阿里云的账号,没有的话就注册一个
2、在物联网平台创建产品和设备

主要硬件准备:
1、STM32F103C8T6
2、ESP8266-01S模块
3、BH1750光照传感器

模块接线:
ESP8266-01S模块:TX–PA3 RX–PA2 RST–PA4 VCC–3.3 GND–GND
BH1750光照传感器:SDA–PB7 SCL–PB6 VCC–3.3V GND–GNG ADDR–不接

实验现象:
1、串口助手界面
说明下,登陆和订阅失败对接入不影响,具体原因我也不懂。
在这里插入图片描述
2、成功接入阿里云

在这里插入图片描述
3、成功上传光照数据
在这里插入图片描述
4、在线调试里可以下发控制命令
在这里插入图片描述
5、查看自己是否订阅成功
在这里插入图片描述

6、开发Web应用和移动应用,可以上物联网应用开发控制台 应用开发链接
简单开发的手机应用
在这里插入图片描述
代码需要修改的地方
1、设置WIFI名称和密码
在这里插入图片描述
2、阿里云服务器的登陆配置
在这里插入图片描述
前3个参数获取方式:
在这里插入图片描述
后2个参数获取方式:
其中${deviceName}要改为自己设备的名称
在这里插入图片描述
3、数据流名(标识符)修改
将Light、LED修改为你的标识符
在这里插入图片描述
在这里插入图片描述
标识符查看方式:
在这里插入图片描述

部分代码实现
main.c文件

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "bh1750.h"
#include "string.h"

//ESP8266WIFI使用相关头文件
#include "uart2.h"
#include "wifi.h"
#include "timer3.h"
#include "structure.h"

//FreeRTOS系统相关头文件
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

//MQTT协议相关头文件
#include "esp8266_mqtt.h"

//MQTT初始化函数
void ES8266_MQTT_Init(void);

//此处是阿里云服务器的登陆配置
#define MQTT_BROKERADDRESS "a1VPyJEJRjJ.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_CLIENTID "a1VPyJEJRjJ.test01|securemode=2,signmethod=hmacsha256,timestamp=1648914857644|"
#define MQTT_USARNAME "test01&a1VPyJEJRjJ"
#define MQTT_PASSWD "76599f069aff42f644669310490cdc3a9830c5431da41a81ff1467722d2bdb1b"
#define	MQTT_PUBLISH_TOPIC "/sys/a1VPyJEJRjJ/test01/thing/event/property/post"
#define MQTT_SUBSCRIBE_TOPIC "/sys/a1VPyJEJRjJ/test01/thing/service/property/set"

char mqtt_message[300];	//MQTT的上报消息缓存

//服务器IP地址和端口号
char *IP = MQTT_BROKERADDRESS;
int Port = 1883;

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED0_TASK_PRIO		2
//任务堆栈大小	
#define LED0_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define WIFI_TASK_PRIO		3
//任务堆栈大小	
#define WIFI_STK_SIZE 		512  
//任务句柄
TaskHandle_t WIFITask_Handler;
//任务函数
void wifi_task(void *pvParameters);


/* Uart2 - Wifi 的消息接收队列 */
#define Wifi_MESSAGE_Q_NUM   4   		//接收数据的消息队列的数量
QueueHandle_t Wifi_Message_Queue;		//信息队列句柄

float light ;   //光照值
 
//主函数
int main(void)
{	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4 
    delay_init();               //初始化系统时钟
	LED_Init();                 //LED初始化
    uart_init(115200);     	    //初始化串口1
    uart2_init(115200);         //初始化串口2
    Timer3_Configuration(5);    //Tim3定时器,用于wifi-uart2的接收完成
    WiFi_ResetIO_Init();		//wifi - RST引脚初始化
	
    printf("初始化完成,开始创建任务\r\n");
     
    //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
 

 //开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    
    //创建 Uart2 - Wifi 接收消息队列
    Wifi_Message_Queue = xQueueCreate(Wifi_MESSAGE_Q_NUM,1); //队列项数目是Wifi_MESSAGE_Q_NUM,队列项长度是串口DMA接收缓冲区长度
    
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler); 

    //创建wifi_task任务
    xTaskCreate((TaskFunction_t )wifi_task,     	
                (const char*    )"wifi_task",   	
                (uint16_t       )WIFI_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )WIFI_TASK_PRIO,	
                (TaskHandle_t*  )&WIFITask_Handler);   
                
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数 
void led0_task(void *pvParameters)
{
	//光照传感器初始化
    BH1750_Init();
    while(1)
    {
        //printf("led0_task !!!\r\n");
		/* 采集数据 */
		light = LIght_Intensity();	//读取光照强度的值
        vTaskDelay(500);
    }
}   
 
//WIFI任务函数 
void wifi_task(void *pvParameters)
{
	uint8_t pub_cnt = 0,pub_ret;
	uint16_t Counter_MQTT_Heart = 0;
    char *recv;
    //MQTT协议初始化
    ES8266_MQTT_Init();

    while(1)
    {
        //心跳包发送
		if(Counter_MQTT_Heart++>300)
		{
			Counter_MQTT_Heart = 0;
			MQTT_SentHeart();
		}

		/* 发送数据 */
		 pub_cnt++;
		if(0 == pub_cnt%500) //约3S发送一次数据
		{
			pub_cnt = 0;
			memset(mqtt_message, 0, 300);
			//组装数据  
			sprintf(mqtt_message,
			"{\"method\":\"thing.service.property.post\",\"id\":\"1234\",\"params\":{\
			\"Light\":%.1f},\"version\":\"1.0.0\"}", light);
			 //发布数据
			pub_ret = MQTT_PublishData(MQTT_PUBLISH_TOPIC,mqtt_message,0);
			if(pub_ret > 0)
			{
				printf("消息发布成功!!!data=%.1f\r\n", light);
			}
			else
			{
				printf("消息发布失败!!!pub_ret=%d\r\n", pub_ret);
			}
		}
        //收到数据
        if((WifiMsg.U2_RxCompleted == 1) && (Usart2_RxCounter > 1))
        {
            printf("来自服务器数据:%d\r\n", Usart2_RxCounter);
			recv = strstr(Usart2_RxBuff, "LED"); 
            //下发命令后,串口2会接收到这样的数据:
			//...{"method":"thing.service.property.set","id":"1593428732","params":{"LED":1},"version":"1.0.0"}			
            if(recv != NULL)
            {	
				//经过strstr函数后,recv指向了字符串:LED":0}...
				//为拿到LED后面的状态值,指针偏移5个字节
				recv = recv + 3 +2;  //LED占3个字节  ”:占2个字节
                printf("LED=%d\r\n", (*recv)-'0');
                LED0 = !((*recv)-'0');  //根据下发的命令控制PC13处的LED灯
            
                memset(mqtt_message, 0, 300);
                //组装数据  id 1454479553
                sprintf(mqtt_message,
                "{\"method\":\"thing.service.property.set\",\"id\":\"5678\",\"params\":{\
                \"LED\":%d},\"version\":\"1.0.0\"}", (*recv)-'0');
                
                //发布数据
                pub_ret = MQTT_PublishData(MQTT_PUBLISH_TOPIC,mqtt_message,0);
                if(pub_ret > 0)
                {
                    printf("消息发布成功!!!pub_ret=%d\r\n", pub_ret);
                }
                else
                {
                    printf("消息发布失败!!!pub_ret=%d\r\n", pub_ret);
                }
            }
            //将标志位和数据清空
            memset(Usart2_RxBuff, 0, sizeof(Usart2_RxBuff));
            WifiMsg.U2_RxCompleted = 0;
            Usart2_RxCounter = 0;
        } 
        vTaskDelay(10);
    }
} 

如果需要上传多个数据,可以参考下面
同时上传了标识符为Light和myData的数据
在这里插入图片描述

			//上传多个数据
			sprintf(mqtt_message,
			"{\"method\":\"thing.service.property.post\",\"id\":\"1234\",\"params\":{\
			\"Light\":%.1f,\"myData\":%d},\"version\":\"1.0.0\"}", light,myData);

最后附上参考
参考和借鉴了某位大佬的文章文章链接

需要源码的可以自行下载。代码下载链接
下载操作:
在这里插入图片描述

  • 21
    点赞
  • 168
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

⁽⁽ଘ晴空万里ଓ⁾⁾

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

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

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

打赏作者

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

抵扣说明:

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

余额充值