说完了怎么把数据上传到云端,那么来说说怎么在云端下发命令到设备端吧,接下来讲解怎么在云端下发命令控制单片机上LED灯的亮灭。
同样在云端上要定义一个服务来实现这个功能。怎么定义前面已经说过了,不同的就是参数的设置不同,下面是我定义的控制LED灯亮灭的服务。
我们把BC28模块的拨码开关拨到“To BC28”,在云平台上下发命令,然后在串口调试助手上看看收到什么内容。
指令下发的步骤 :
确定之后显示指令下发成功即可。然后再串口调试助手上查看指令下发后收到的返回值。(前提是BC28模块已经联网)
如果显示指令下发成功,但是在串口调试助手上没有收到返回值,那是因为在一段时间内云平台与设备没有进行数据互传,NBIOT模块进入了低功耗模式。所以这时在指令下发开始到指令超时时间内发送一条数据到云端,我们就可以看到指令下发后的返回值了。在上图中可以看到我设置的指令超时时间是66s,所以在这66s发送一条指令到云端重新建立连接,就可以看到发送指令的返回值了。
知道怎么下发指令之后,现在来讲讲MCU怎么接收和解析下发指令收到的返回值,从而控制LED灯的亮灭。
首先是对LED灯引脚的配置,我的是PB7控制绿灯状态,这里我就使用这个引脚。
之前有说过MCU是直接通过串口3与BC28模块进行数据互传,从而与云平台通信。其实云平台下发指令的返回值是存储在串口3的数组里面的,所以我们要从这个数据里面收到的东西进行解析。我采用的是串口中断的方式进行接收数据,之前配置串口3的时候已经使能中断。
首先写一个中断回调函数,在main.c文件下合适位置即可,这是一个内部函数,不需要调用和声明
/*是一个UART接收中断的回调函数,当UART接收到数据时,会调用该函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART3)//过判断huart->Instance来确定是哪个UART实例触发了中断(这里是USART3)
{
if(g_uart3_bytes< sizeof(g_uart3_rxbuf))/*判断g_uart3_bytes是否小于sizeof(g_uart3_rxbuf),如果是,则将接收到的数据存储到g_uart3_rxbuf数组中,并将g_uart3_bytes+1*/
{
g_uart3_rxbuf[g_uart3_bytes++] = s_uart3_rxch;
}
else/*如果g_uart3_bytes已经达到数组的大小,说明数组已满,需要重新开始存储数据,以将g_uart3_bytes重置0,并将接收到的数据存储到g_uart3_rxbuf数组的第1个位置*/
{
g_uart3_bytes = 0;
g_uart3_rxbuf[g_uart3_bytes++] = s_uart3_rxch;
}
HAL_UART_Receive_IT(&huart3,&s_uart3_rxch,1);/*通过调用HAL_UART_Receive_IT函数来重新启动UART接收中断,以便继续接收下一个数据*/
}
}
定义变量s_uart3_rxch
* USER CODE BEGIN 0 */
static int report_tempRH_json(void);//采集温湿
extern int setup_nbiot();//NBIOT联网
int fstr_to_hex(char *fstr, unsigned int fstrlen, char *out);
static uint8_t s_uart3_rxch;
/* USER CODE END 0 */
下面修改while()的代码来实现功能
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
report_tempRH_json();
HAL_Delay(3000);
/*控制LED灯状态*/
HAL_UART_Receive_IT(&huart3,&s_uart3_rxch,200);
HAL_Delay(1000);
printf("%s\r\n",g_uart3_rxbuf);
if (strstr(g_nbiot_rxbuf,"0101"))/*判断是否下发1指令*/
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);/*下发指令1就点亮灯*/
memset(g_uart3_rxbuf,0,sizeof(g_uart3_rxbuf));
}
if (strstr(g_nbiot_rxbuf,"0100") && strstr(g_nbiot_rxbuf,"061F52"))/*判断是否下发0指令*/
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);/*下发指令0就把灯熄灭*/
memset(g_uart3_rxbuf,0,sizeof(g_uart3_rxbuf));
}
}
判断条件是根据数据收到的返回值来确定的,在上面用串口调试助手接收下发指令的返回值我们可以知道,下发1指令有“0101”这子串;下发0指令的时候有“0100”这个字串,但是因为上传数据的时候也会有返回值,而且也会返回“0100”这个字串,从而不能判断是否下发了0指令,所以又增加了一个判断条件“061F52”,这样才能唯一判断是否下发了指令0。
编译运行代码,在云端可以看到温湿度间隔一定时间上报,然后在云端下发指令1可以看到LED灯被点亮,下发指令0看到LED熄灭。