1. 程式人生 > 實用技巧 >小熊派開發實踐丨小熊派+合宙Cat.1接入雲伺服器

小熊派開發實踐丨小熊派+合宙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\r\n");
/* 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\r\n","OK",200,NO_REC,10},  //測試

    {"AT+CIMI\r\n","4600",200,NO_REC,10}, // 移動卡號

    {"AT+CSQ\r\n","+CSQ",200,NO_REC,10},  //訊號

    {"AT+CEREG?\r\n","+CEREG: 0,1",200,NO_REC,10}, //網路


    {"AT+CGATT?\r\n","+CGATT:1",200,NO_REC,10}, //駐網


    {"AT+CCLK?\r\n","+CCLK",200,NO_REC,10},  //時間

    {"AT+MCONFIG=0001,door,2020\r\n","OK",200,NO_REC,10}, //MQTT引數
    //{"AT+MCONFIG=111,device1,123456\r\n","OK",200,NO_REC,100}, 
    {"AT+MDISCONNECT\r\n","",200,NO_REC,5},  //斷開MQTT連線

    {"AT+MIPCLOSE\r\n","",200,NO_REC,5},  //斷開TCP連線
    {"AT+MIPSTART=123.56.117.8,1883\r\n","CONNECT OK",200,NO_REC,5},  //建立TCP連線 

    {"AT+MCONNECT=1,60\r\n","CONNACK OK",200,NO_REC,5},  //建立MQTT連線

    {"AT+MSUB=","SUBACK",200,NO_REC,5},  //訂閱主題

    {"AT+MPUB=","OK",200,NO_REC,5},  //釋出主題

    {"AT+MQTTSTATU\r\n","+MQTTSTATU",200,NO_REC,5}, //狀態
    //AT+MQTTSTATU 0-離線 1-正常  2-需傳送MCONNECT
    {"AT+RESET\r\n","",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,更好的完成裝置管理

點選關注,第一時間瞭解華為雲新鮮技術~