摘要:使用小熊派開發板,以合宙的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,更好的完成設備管理
