打印
[综合信息]

AT_Command移植

[复制链接]
33|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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文件中,进行了串口发送和接收回调的实现。
    /*
    * [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函数中,你可以解析接收到的数据,判断是否含有特定的属性命令,并提取属性值。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

1830

帖子

1

粉丝