• 小熊派开发实践丨小熊派+合宙Cat.1接入云服务器


    摘要:使用小熊派开发板,以合宙的AIR724为通信模组(Cat.1),以AT指令方式,通过mqtt协议接入云服务器。

    本贴使用小熊派开发板+合宙的Air724(Cat.1模组),接入自己搭建的EMQ服务器

    一、实验准备

    1.实验环境

    • 一块stm32开发板(推荐使用小熊派),以及数据线
    • 已经安装STM32CubeMX
    • 已经安装KeilMDK,并导入stm32开发板对应的芯片包(小熊派使用的是STM32L431RCT6)
    • 一个Cat.1模块(Uart接口,AT指令)以及杜邦线

    2.目标效果

    • 通过CubeMX创建工程并配置参数
    • 通过串口2,以AT指令控制通信模组
    • Cat.1发送相应的AT指令接入云服务器
    • 通过MQTT协议,完成数据订阅、发布

    二、通过CubeMX生产MDK工程

    A.芯片选择

    • 打开CubeMX,进入芯片选择:

    • 选择自己的stm32芯片(即STM32L431RCT6):

    B.时钟源RCC设置

    • 更改系统时钟源

    系统时钟默认使用内部的高速时钟(HSI),选择使用HSE,时钟更精确

    • 设置外部时钟对应的端口

    • 配置时钟树

    STM32L431RCT6系统时钟最大可以为80MHz,我们配置到最大即可

    C.参数配置(对应端口设置)

    1)配置USART1

    使用USART,模式为异步,波特率为115200,无硬件流控制

    2)配置UART2,连接Cat.1

    Cat.1模组烧录有AT固件,当然合宙的也支持Luat开发,我们为了更方便学习,就是要AT指令开发

    我们使用小熊派的Uart2,小熊派引出的引脚为PA2->USART_TX,PA3->USART_RX

    其他选项,波特率设置为9600,其他默认即可

    3)打开Uart2中断,并开启接收DMA

    开启中断

    打开接收DMA

    最后,生成代码就OK了

    D.工程设置

    一些基础的设置,包括工程名、存储位置、工程环境、工程中各个文件的组成

    E.生成代码

    三、编写相应代码

    1. 串口1输出重定向

    我们知道printf是打印函数,原理是根据传入的字符串参数格式化打印输出到stdout中。我们需要让printf打印到串口之中,只需要在usart.c文件中模仿printf写一个输出函数即可

    • 在添加头文件
    /* USER CODE BEGIN 0 */
    #include <stdarg.h>
    #include <string.h>
    #include <stdio.h>
    /* USER CODE END 0 */
    写输出函数
    /* USER CODE BEGIN 1 */
    void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...)
    {
    
     unsigned char UsartPrintfBuf[296];
     va_list ap;
     unsigned char *pStr = UsartPrintfBuf;
    
     va_start(ap, fmt);
     vsprintf((char *)UsartPrintfBuf, fmt, ap); //格式化
     va_end(ap);
    
     while(*pStr != 0)
     {
      USART1->TDR = *pStr++;
      while((USART1->ISR & 0x40)  == 0);
     }
    }
    
    //注意:在usart.h中添加void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...);
    //使用方法:UsartPrintf(&huart1;,"hello world
    ");
    /* USER CODE END 1 */

    注意:自己添加的代码,需要在begin和end之间

    2.通信的主要代码

    我们创建两个文件,分别是Cat1.h和Cat.c
    同时,完善串口2的收发功能,加入串口回调函数保证数据的完整

    a).串口回调函数

    因为在进行发送AT指令后,接受的数据要进行处理;一方处理速度跟不上,因此加入一个串口回调函数

    //串口回调函数
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        if(huart->Instance == USART2)
        {
            if(Usart2type.UsartRecLen>0)            //证明还有未完成数据
            {
                memcpy(&Usart2type.Usart2RecBuffer[Usart2type.UsartRecLen],Usart2type.Usart2DMARecBuffer,Usart2type.UsartDMARecLen); //转存到待处理区域
                Usart2type.UsartRecLen +=  Usart2type.UsartDMARecLen;
            }
            else
            {
                memcpy(Usart2type.Usart2RecBuffer,Usart2type.Usart2DMARecBuffer,Usart2type.UsartDMARecLen);                          //转存到待处理区域
                Usart2type.UsartRecLen =  Usart2type.UsartDMARecLen;
            }
            memset(Usart2type.Usart2DMARecBuffer, 0x00, sizeof(Usart2type.Usart2DMARecBuffer));                                     //先清空DMA缓冲区
            Usart2type.UsartRecFlag = 1;
        }
    }

    b).串口2空闲中断

    当发送或接受完成一组数据后,进入空闲中断

    函数如下

    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
      if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) ==SET)  //触发空闲中断
        {
            uint16_t temp = 0;                        
            __HAL_UART_CLEAR_IDLEFLAG(&huart2);       //清除串口2空闲中断标志位
            HAL_UART_DMAStop(&huart2);                //关闭DMA
            temp = huart2.Instance->ISR;              //清除SR状态寄存器  F0  ISR
            temp = huart2.Instance->RDR;              //读取DR数据寄存器 F0  RDR    用来清除中断
            temp = hdma_usart2_rx.Instance->CNDTR;    //获取DMA中未传输的数据个数
            Usart2type.UsartDMARecLen = USART2_DMA_REC_SIE - temp;           //总计数减去未传输的数据个数,得到已经接收的数据个数
            HAL_UART_RxCpltCallback(&huart2);          //串口接收回调函数
        }
      /* USER CODE END USART2_IRQn 0 */
      HAL_UART_IRQHandler(&huart2);
      /* USER CODE BEGIN USART2_IRQn 1 */
      HAL_UART_Receive_DMA(&huart2,Usart2type.Usart2DMARecBuffer,USART2_DMA_REC_SIE);  //重新打开DMA接收
    
      /* USER CODE END USART2_IRQn 1 */
    }

    C).AT指令通信流程

    主要的AT指令如下

    tsATCmds ATCmds[] = 
    {
        {"AT
    ","OK",200,NO_REC,10},  //测试
    
        {"AT+CIMI
    ","4600",200,NO_REC,10}, // 移动卡号
    
        {"AT+CSQ
    ","+CSQ",200,NO_REC,10},  //信号
    
        {"AT+CEREG?
    ","+CEREG: 0,1",200,NO_REC,10}, //网络
    
    
        {"AT+CGATT?
    ","+CGATT:1",200,NO_REC,10}, //驻网
    
    
        {"AT+CCLK?
    ","+CCLK",200,NO_REC,10},  //时间
    
        {"AT+MCONFIG=0001,door,2020
    ","OK",200,NO_REC,10}, //MQTT参数
        //{"AT+MCONFIG=111,device1,123456
    ","OK",200,NO_REC,100}, 
        {"AT+MDISCONNECT
    ","",200,NO_REC,5},  //断开MQTT连接
    
        {"AT+MIPCLOSE
    ","",200,NO_REC,5},  //断开TCP连接
        {"AT+MIPSTART=123.56.117.8,1883
    ","CONNECT OK",200,NO_REC,5},  //建立TCP连接 
    
        {"AT+MCONNECT=1,60
    ","CONNACK OK",200,NO_REC,5},  //建立MQTT连接
    
        {"AT+MSUB=","SUBACK",200,NO_REC,5},  //订阅主题
    
        {"AT+MPUB=","OK",200,NO_REC,5},  //发布主题
    
        {"AT+MQTTSTATU
    ","+MQTTSTATU",200,NO_REC,5}, //状态
        //AT+MQTTSTATU 0-离线 1-正常  2-需发送MCONNECT
        {"AT+RESET
    ","",200,NO_REC,5}//重启
    
    
    };

    四、编译+下载

    点击编译后,0 error,0 warning

    小熊派连接在电脑上,代码下载到开发板

    五、连接硬件

    1.将Cat.1的uart1_tx连接小熊派uart2_rx,cat.1的uart1_rx连接小熊派uart2_tx;Gnd连Gnd;

    注意:一定要连接GND哦,需要共地的。

    2.调试

    此时,我们进行最后一次调试;将小熊派串口1用作串口打印,打开串口调试助手,查看运行状态(在每次发送指令后进行printf()打印相应信息)。

    附件中包含CubeMX工程、MDK工程

    下一步,打算将此设备接入华为云IoTDA,更好的完成设备管理

     

    点击关注,第一时间了解华为云新鲜技术~

  • 相关阅读:
    qemu进程页表和EPT的同步问题
    Linux进程虚拟地址空间管理2
    qemu-kvm内存虚拟化1
    LInux进程虚拟地址空间的管理
    Linux下的文件系统2
    LInux中的文件系统1
    Linux IPC之管道通信
    操作系统中的特权级检查
    Linux下的信号机制
    进程的挂起、阻塞和睡眠
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/14107688.html
Copyright © 2020-2023  润新知