AT_Command 是一款管理AT命令通信交互组件, 适用于Modem、WIFI模块、蓝牙等使用AT命令或者ASCII命令行通信的场景。本次AT连接使用AT_Command移植到STM32F103C8T6进行运行。AT_Command Gitee链接
本次的项目环境为HAL库+CubeMx进行配置开发。 首先需要定义适配器,完成驱动接口及缓冲区设置
在wifi_uart.c文件中,进行了串口发送和接收回调的实现。 /*
* [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函数中,你可以解析接收到的数据,判断是否含有特定的属性命令,并提取属性值。 |
|