[综合信息] AT_Command移植

[复制链接]
 楼主| mollylawrence 发表于 2025-5-24 07:27 | 显示全部楼层 |阅读模式
AT_Command 是一款管理AT命令通信交互组件, 适用于Modem、WIFI模块、蓝牙等使用AT命令或者ASCII命令行通信的场景。本次AT连接使用AT_Command移植到STM32F103C8T6进行运行。AT_Command Gitee链接
本次的项目环境为HAL库+CubeMx进行配置开发。
  • 首先需要定义适配器,完成驱动接口及缓冲区设置
    在wifi_uart.c文件中,进行了串口发送和接收回调的实现。
    1. /*
    2. * [url=home.php?mod=space&uid=247401]@brief[/url]            向串口发送缓冲区内写入数据并启动发送
    3. * @param[in]   buf       -  数据缓存
    4. * @param[in]   len       -  数据长度
    5. * [url=home.php?mod=space&uid=266161]@return[/url]             实际写入长度(如果此时缓冲区满,则返回len)
    6. */
    7. unsigned int wifi_uart_write(const void *buf, unsigned int len)
    8. {   
    9.     unsigned int ret;
    10.     ret = ring_buf_put(&rbsend, (unsigned char *)buf, len);  
    11.     HAL_UART_Transmit(&wifi_uart,(unsigned char *)buf,len,0xffff);  // wifi串口数据发送
    12.     return ret;
    13. }
    14. /*
    15. * @brief            WIFI串口接收
    16. * @param[in]   none
    17. * @return             none
    18. */
    19. void WIFI_UART_RxCpltCallback(unsigned char *data, uint8_t len)
    20. {
    21.         ring_buf_put(&rbrecv, data, len);           /*将数据放入接收缓冲区*/  
    22. }

    串口数据接收使用串口2(TX为PA2, RX为PA3)的是DMA+空闲中断的方式进行接收,在stm32f1xx_it.c文件中:
    1. /**
    2.   * @brief This function handles USART2 global interrupt.
    3.   */
    4. void USART2_IRQHandler(void)
    5. {
    6.   /* USER CODE BEGIN USART2_IRQn 0 */

    7.   /* USER CODE END USART2_IRQn 0 */
    8.   HAL_UART_IRQHandler(&huart2);
    9.   /* USER CODE BEGIN USART2_IRQn 1 */
    10.         if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)  // 空闲中断
    11.         {
    12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart2);  // 清除空闲中断标志位
    13.                 HAL_UART_DMAStop(&huart2);  // 停止DMA接收
    14.                
    15.                 if( wifiConnectFlag == 0)  // 未完成配置
    16.                         WIFI_UART_RxCpltCallback(uart2_rx_buf, strlen(uart2_rx_buf));  // 数据处理函数
    17.                 else  // 配置完成 等待设备连接
    18.                         wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf));
    19.                 memset(uart2_rx_buf, 0, strlen(uart2_rx_buf));  // 清除数据
    20.                
    21.                 HAL_UART_Receive_DMA(&huart2, uart2_rx_buf, buf_size);  // 重新打开DMA接收
    22.         }
    23.   /* USER CODE END USART2_IRQn 1 */
    24. }

  • 使用AT适配器创建AT通信对象,在wifi.c文件中:
    1. static at_obj_t at;static at_obj_t at;
    2. /*
    3. * @brief    wifi初始化  配置8266
    4. */
    5. void wifi_init(void)
    6. {
    7.         static char wifi_msg[128] = {0};
    8.         // WIFI 串口初始化
    9.     wifi_uart_init(115200);
    10.     at_obj_init(&at, &at_adapter);
    11.         // 关闭回显
    12.     at_send_singlline(&at, NULL, "ATE0");          // OK
    13.     // AT测试
    14.     at_send_singlline(&at, NULL, "AT");  // OK  ERROR *
    15.         // 配置工作模式 AP模式
    16.         at_send_singlline(&at, NULL, "AT+CWMODE=3");  
    17.         // 创建路由器
    18.         sprintf(wifi_msg, "AT+CWJAP="%s","%s"", SSID, PWD);
    19.         at_send_singlline(&at, NULL, wifi_msg);  
    20.         // 设定域名
    21.         at_send_singlline(&at, NULL, "AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"");  
    22.         // 设定MQTT账号
    23.         at_send_singlline(&at, NULL, "AT+MQTTUSERCFG=0,1,"NULL","username","passwd",0,0,""");  
    24.         // 设定Clinent ID
    25.         at_send_singlline(&at, NULL, "AT+MQTTCLIENTID=0,"clientid注意逗号需反义"");  
    26.         // 链接MQTT
    27.         at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,"host",1883,1");
    28. };

  • 加入轮询任务,wifi.c中实现了wifi_task函数,并在初始化中进行循环调用,如下:
    1. wifi_init();
    2. do
    3. {
    4.         wifi_task();
    5.         HAL_Delay(10);
    6. }while(wifiConnectFlag == 0);

    wifiConnectFlag标志位会在at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,\"host\",1883,1");中的connnect_calback回调函数中进行判断。
    如上进行配置后可基本完成AT_Command的配置,可以进行串口测试。
  • 数据上报,数据上报通常使用标准格式如下:
    首先需要在产品中找到属性上报的Topic类,注意要将${deviceName}替换为设备名。
    1. char sendmsg[256];
    2. 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);
    3. HAL_UART_Transmit(&huart2, (unsigned char *)sendmsg, strlen(sendmsg), 0xffff);  // wifi串口数据发送
    4. HAL_Delay(1000);

  • 云端属性获取,当云上产生设备属性操作时会通过MQTT发送到对应的设备中,此时需要进行相应的解析操作,首先通过判断wifiConnectFlag标志位判断是否链接阿里云成功,若成功后之后的云端下发的属性命令将在wifi.c中的wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf));函数进行解析:
    本部分代码的逻辑为判断字符串数组中是否有特定的三位字符与motorstatus属性吻合,从而解析出对应的属性值。
    1. /*
    2. * @brief    wifi 连接成功后数据解析
    3. */
    4. // +MQTTSUBRECV:0,"/sys/a1U3gCVc2Lh/Device1/thing/service/property/set",104,{"method":"thing.service.property.set","id":"1199288712",
    5. // "params":{"windowControl":3},"version":"1.0.0"}
    6. void wifi_connnect_calback(unsigned char *data, uint8_t len)
    7. {
    8.         int i = 0;
    9.     unsigned char *p ;
    10.             
    11.         p = data;  // 指针p指向接受数组的第一个元素
    12.         for(i=50;i<strlen(data);i++)
    13.         {
    14.                 if(*(p+i)=='t' && *(p+i+1)=='u' && *(p+i+2) == 's')  // 寻找"motorstatus"
    15.                 {
    16.                         motorstatus = *(p+i+5)-0x30;
    17.                 }
    18.         }
    19.         
    20. }


首先,在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函数中,你可以解析接收到的数据,判断是否含有特定的属性命令,并提取属性值。
suncat0504 发表于 2025-5-29 22:01 | 显示全部楼层
支持AT,是不是还得需要有后台的程序支持?否则,如何响应AT指令呢?
suncat0504 发表于 2025-5-29 22:03 | 显示全部楼层
是否可以理解为,AT指令,和按钮也好,菜单也好,执行指定的功能?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

46

主题

1947

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部