今日嘗試配通倆個C8T6單片機之間的無線串口通信,文章提供原理,源碼,測試效果圖,測試工程下載:
目錄
傳輸不規范問題:
串口通信資源:
單個串口資源理解:
單片機串口資源:
測試目標與測試硬件連接:
串口初始化與串口中斷接收邏輯:
串口初始化:
初步測試能否收發:
?階段測試效果:
規范接收:
幾個串口配置方面的注意點:
測試接收:
今日學習加強 :倆片單片機之間的串口通信
單片機的串口通信要想配置好發送與接收,都很簡單,如果沒有任何意外,我們甚至不需要定義過于規范的 幀頭、幀尾 就能實現最簡單的倆個單片機的通信;
傳輸不規范問題:
但在實際的數據傳輸的過程中,難免會出現:
1.某次傳輸不小心丟失數據,該次傳輸所得需作廢。
2.發送 或者 接收 了一次偶爾的錯誤幀。
3.發送方開機比較快,接收方的第一個數據是從中間開始接收的。
............
以上這些不對勁的接收情況的數據是需要直接剔除的,直到接收到正確的數據。
本文會使用一個額外的無線通信模塊,大家可從下文了解其配置,如果有自己的無線串口模塊,一樣配置好接上使用即可,沒有無線串口模塊,可以勉強使用杜邦線代替,但用杜邦線就模擬不了誤傳情況了~
DL_20無線串口模塊_NULL指向我的博客-CSDN博客
串口通信資源:
單個串口資源理解:
引腳方面,STM32每一個串口都有至多五個引腳:(有的串口只有TX RX )
1.TX 和 RX? 發送與接收
2.SCLK??????? 時鐘
3.nRTS ?????? 請求發送
4.nCTS??????? 允許發送
?其中最常用的、必不可少的就是TX與RX了,SCLK是同步時鐘,是同步通信時用到的,而我們此次的無線通信屬于異步通信,因此用不到,3、4是硬件流控制的引腳,我們也用不到。
單片機串口資源:
這是我之前文章總結的串口資源: STM32 F103 C8T6共有三個串口:
?這里其余沒有特別需要注意的地方,但在初始化時USART1與2、3有區別,我們除了更改引腳之外,同時需要注意:
USART1是掛載在APB2總線上的外設接口(更快),而其余倆個串口都是掛載在APB1總線上的,因此在初始化開啟端口時鐘時此處需要額外注意。
?
測試目標與測試硬件連接:
測試目標:
1.實現倆片單片機的無線通信
2.單片機1的串口1 接無線通信模塊,并不斷發送數據
3.單片機2的串口1接無線通信模塊,接收單片機1的數據,串口2接串口轉USB模塊,將接受到的數據回傳到上位機電腦(注意有沒有安裝CH340等類似驅動)
?
串口初始化與串口中斷接收邏輯:
串口初始化:
這部分不用細講,本文主要是寫串口接收方邏輯,串口初始化配置方面,不清楚的可以看這篇文章:
STM32 F103C8T6學習筆記3:串口配置—串口收發—自定義Printf函數_NULL指向我的博客-CSDN博客
?
初步測試能否收發:
?單片機1的程序帶有一個定時器每秒使用串口1發送12345的程序,串口1是連接了無線模塊的,因此同樣在串口1連接了無線模塊的單片機2會在串口1中斷接收到這個數據,而我們先不寫任何判斷,接收到就返還數據看看~進行初步的測試,這個過程的測試程序,沒法存下任何有用的數據,只是簡單的返還而已:
單片機1 定時器每秒進中斷,使用串口1發送一次12345:
?單片機2 串口1中斷接收到數據 直接通過串口2鏈接了串口轉USB模塊外傳給上位機:
?階段測試效果:
下載程序到倆個單片機,查看階段測試效果:
測試結果中:看似一給單片機1通電了,單片機2就能收到信息反饋給上位機,分毫不差,但這個過程單片機2其實并未將數據保存下來,也就是它并不知道自己接受到的是怎么回事,只是無腦地轉發消息罷了:
規范接收:
幾個串口配置方面的注意點:
1.倆片單片機收發的時間點要岔開,嚴格杜絕一個程序都寫了收和發,卻下載給倆個單片機,這樣容易會使得倆個單片機變成“永動機”,卡在那,建議剛開始就單個只管發送,關閉接收中斷,另一個只管接收
2.注意其他中斷源(尤其是定時器中斷),即使是1s進一次定時器中斷,也可能會對接收方的串口中斷、主程序CPU處理過程 造成毀滅性的打斷(時機不湊巧),因此在進入主程序處理接收操作時,應該要想辦法關閉其余中斷,處理完畢再打開其余中斷。
3.注意標志位的正確時機勿忘記清除:中斷標志位,數據接收完成標志位,數組緩存下標,甚至是緩存數組也要在處理完后及時清零。
4.其余配置有中斷的外設,如果在系統運行時有進入中斷的時機,(尤其是定時器溢出中斷,這個必定會進)一定要給其配好中斷服務函數,并且中斷服務函數要寫好清除標志位等退出中斷的操作,否則程序容易在中斷服務函數那卡住。
這樣接收,就能將數據存在數組進行下一步處理了:
#include "USART1.h"char usart_buf[25];
char usart_flag=0;
char usart_xb=0;void USART1_IRQHandler(void)
{//接收中斷if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){//清除標志:USART_ClearFlag(USART1, USART_FLAG_RXNE);//數組承接數據usart_buf[usart_xb]=USART_ReceiveData(USART1);//如果接收到數據結尾:if(usart_buf[usart_xb]=='\n' && usart_buf[usart_xb-1]== '\r') {usart_flag=1;}//下標最大不超25if(usart_xb==25) {usart_xb=0;memset(usart_buf,0,sizeof(usart_buf));}//下標移動usart_xb++;}}//確保你已經包含了相應的頭文件,例如`#include <stm32f10x.h>`。
// __enable_irq(); // 開啟總中斷
// __disable_irq(); // 關閉總中斷
// __disable_irq(); // 屏蔽中斷
// __enable_irq(); // 恢復中斷void handle_uart1(void)
{if(usart_flag==1){__disable_irq(); // 屏蔽中斷UsartPrintf (USART2,"\r\n");UsartPrintf (USART2,"%s",usart_buf); usart_xb=0;memset(usart_buf,0,sizeof(usart_buf)); //處理完命令別忘了將數組清零,以便接收下個命令usart_flag=0;__enable_irq(); // 恢復中斷}
}
測試接收:
接收情況正常:
?測試工程下載:
https://download.csdn.net/download/qq_64257614/88212346?spm=1001.2014.3001.5503