- /*
- * [url=home.php?mod=space&uid=247401]@brief[/url] 向串口发送缓冲区内写入数据并启动发送
- * @param[in] buf - 数据缓存
- * @param[in] len - 数据长度
- * [url=home.php?mod=space&uid=266161]@return[/url] 实际写入长度(如果此时缓冲区满,则返回len)
- */
- unsigned int wifi_uart_write(const void *buf, unsigned int len)
- {
- unsigned int ret;
- ret = ring_buf_put(&rbsend, (unsigned char *)buf, len);
- HAL_UART_Transmit(&wifi_uart,(unsigned char *)buf,len,0xffff); // wifi串口数据发送
- return ret;
- }
- /*
- * @brief WIFI串口接收
- * @param[in] none
- * @return none
- */
- void WIFI_UART_RxCpltCallback(unsigned char *data, uint8_t len)
- {
- ring_buf_put(&rbrecv, data, len); /*将数据放入接收缓冲区*/
- }
串口数据接收使用串口2(TX为PA2, RX为PA3)的是DMA+空闲中断的方式进行接收,在stm32f1xx_it.c文件中:
- /**
- * @brief This function handles USART2 global interrupt.
- */
- void USART2_IRQHandler(void)
- {
- /* USER CODE BEGIN USART2_IRQn 0 */
- /* USER CODE END USART2_IRQn 0 */
- HAL_UART_IRQHandler(&huart2);
- /* USER CODE BEGIN USART2_IRQn 1 */
- if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) // 空闲中断
- {
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); // 清除空闲中断标志位
- HAL_UART_DMAStop(&huart2); // 停止DMA接收
-
- if( wifiConnectFlag == 0) // 未完成配置
- WIFI_UART_RxCpltCallback(uart2_rx_buf, strlen(uart2_rx_buf)); // 数据处理函数
- else // 配置完成 等待设备连接
- wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf));
- memset(uart2_rx_buf, 0, strlen(uart2_rx_buf)); // 清除数据
-
- HAL_UART_Receive_DMA(&huart2, uart2_rx_buf, buf_size); // 重新打开DMA接收
- }
- /* USER CODE END USART2_IRQn 1 */
- }
使用AT适配器创建AT通信对象,在wifi.c文件中:
- static at_obj_t at;static at_obj_t at;
- /*
- * @brief wifi初始化 配置8266
- */
- void wifi_init(void)
- {
- static char wifi_msg[128] = {0};
- // WIFI 串口初始化
- wifi_uart_init(115200);
- at_obj_init(&at, &at_adapter);
- // 关闭回显
- at_send_singlline(&at, NULL, "ATE0"); // OK
- // AT测试
- at_send_singlline(&at, NULL, "AT"); // OK ERROR *
- // 配置工作模式 AP模式
- at_send_singlline(&at, NULL, "AT+CWMODE=3");
- // 创建路由器
- sprintf(wifi_msg, "AT+CWJAP="%s","%s"", SSID, PWD);
- at_send_singlline(&at, NULL, wifi_msg);
- // 设定域名
- at_send_singlline(&at, NULL, "AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"");
- // 设定MQTT账号
- at_send_singlline(&at, NULL, "AT+MQTTUSERCFG=0,1,"NULL","username","passwd",0,0,""");
- // 设定Clinent ID
- at_send_singlline(&at, NULL, "AT+MQTTCLIENTID=0,"clientid注意逗号需反义"");
- // 链接MQTT
- at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,"host",1883,1");
- };
加入轮询任务,wifi.c中实现了wifi_task函数,并在初始化中进行循环调用,如下:
- wifi_init();
- do
- {
- wifi_task();
- HAL_Delay(10);
- }while(wifiConnectFlag == 0);
wifiConnectFlag标志位会在at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,\"host\",1883,1");中的connnect_calback回调函数中进行判断。
如上进行配置后可基本完成AT_Command的配置,可以进行串口测试。
数据上报,数据上报通常使用标准格式如下:
首先需要在产品中找到属性上报的Topic类,注意要将${deviceName}替换为设备名。
- char sendmsg[256];
- sprintf(sendmsg,"AT+MQTTPUB=0,"/sys/a1Tt5wtm2af/${deviceName}/thing/event/property/post","{\\"id\\":1685082419785\\\,\\"params\\":{\\"motorstatus\\":%d}\\\,\\"version\\":\\"1.0\\"\\\,\\"method\\":\\"thing.event.property.post\\"}",1,0\r\n", motorstatus);
- HAL_UART_Transmit(&huart2, (unsigned char *)sendmsg, strlen(sendmsg), 0xffff); // wifi串口数据发送
- HAL_Delay(1000);
云端属性获取,当云上产生设备属性操作时会通过MQTT发送到对应的设备中,此时需要进行相应的解析操作,首先通过判断wifiConnectFlag标志位判断是否链接阿里云成功,若成功后之后的云端下发的属性命令将在wifi.c中的wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf));函数进行解析:
本部分代码的逻辑为判断字符串数组中是否有特定的三位字符与motorstatus属性吻合,从而解析出对应的属性值。
- /*
- * @brief wifi 连接成功后数据解析
- */
- // +MQTTSUBRECV:0,"/sys/a1U3gCVc2Lh/Device1/thing/service/property/set",104,{"method":"thing.service.property.set","id":"1199288712",
- // "params":{"windowControl":3},"version":"1.0.0"}
- void wifi_connnect_calback(unsigned char *data, uint8_t len)
- {
- int i = 0;
- unsigned char *p ;
-
- p = data; // 指针p指向接受数组的第一个元素
- for(i=50;i<strlen(data);i++)
- {
- if(*(p+i)=='t' && *(p+i+1)=='u' && *(p+i+2) == 's') // 寻找"motorstatus"
- {
- motorstatus = *(p+i+5)-0x30;
- }
- }
-
- }
首先,在wifi_uart.c文件中实现了串口发送和接收回调函数。wifi_uart_write函数用于向串口发送缓冲区写入数据并启动发送,同时使用HAL_UART_Transmit函数进行串口数据发送。WIFI_UART_RxCpltCallback函数用于处理串口接收到的数据,将数据放入接收缓冲区。
在stm32f1xx_it.c文件中,使用DMA和空闲中断的方式进行串口2的接收。当空闲中断触发时,会调用WIFI_UART_RxCpltCallback函数处理接收到的数据。
在wifi.c文件中,创建AT适配器对象,并在wifi_init函数中进行AT指令的配置和发送。通过调用at_send_singlline函数发送AT命令。在wifi_task函数中循环调用,通过判断wifiConnectFlag标志位判断是否连接成功。
对于数据上报,你可以根据标准格式构造要发送的数据,使用sprintf函数将数据格式化为AT命令的形式,然后通过HAL_UART_Transmit函数发送到串口。例如,使用sprintf函数将motorstatus属性格式化为要发送的字符串,然后通过HAL_UART_Transmit函数发送到串口。
对于云端属性获取,当云端发送设备属性操作时,通过判断wifiConnectFlag标志位和解析接收到的数据进行相应的操作。在wifi_connnect_calback函数中,你可以解析接收到的数据,判断是否含有特定的属性命令,并提取属性值。