天天看點

[stm32] NRF24L01+USART搞定有線和無線通信

前言

一般進行遠端監控時,2.4G無線通信是充當遠端資料傳輸的一種方法。這時就需要在現場部分具備無線資料發送裝置,而在上位機部分由于一般隻有序列槽,是以将采集到的資料送到電腦裡又要在上位機端設計一個資料接收的擴充卡。這裡基于stm32分别設計了現場部分和擴充卡部分,這裡隻是基本通信功能實作的講解,一些複雜的技術比如加密、可靠等要根據具體的應用來設計~

[stm32] NRF24L01+USART搞定有線和無線通信

總體說明

這裡采用stm32作為MCU,采用nRF24L01作為2.4G通信子產品。其中擴充卡中僅僅采用了USART和NRF24L01兩個主要部分,負責将下位機通過2.4G發送過來的資料通過序列槽發送給上位機,或者将上位機的通過序列槽傳來的資料通過2.4G發送給下位機來實作遠端監控(沒有采用uc-os作業系統,也沒有界面,要用序列槽和上位機相連);其中下位機比較複雜,因為一般下位機是一個內建的系統,包括從各種傳感器收集資料、向各種類型的驅動電路發送控制指令、将資料輸給列印機或顯示器、和無線通信或有線通信裝置進行互相通信來實作資料傳輸等,這裡的下位機比較簡單:采用uc-os實時作業系統+uc-gui負責界面顯示,外接7寸TFT液晶顯示屏,和擴充卡類似也包括USART和NRF24L01通信部分,但是因為有了作業系統和可視化互動界面,是以也有點不同,接下來開始介紹。

擴充卡部分

這裡介紹的流程是以main函數為基準,廣度拓寬知識點,最後main函數說完,整個工程的細節也就大緻能了解了~

<a></a>

第4行RCC初始化主要是系統時鐘和外設時鐘配置,這裡注意要使能RCC_APB2Periph_USART1,當時忘了使能這個結果序列槽出現異常,我還以為是初始化和中斷向量什麼的弄錯了呢,浪費了很長時間。

第7行中斷向量初始化設定,主要是設定序列槽接收中斷和NRF24L01中斷的,這樣設定好了之後當序列槽中斷被觸發時其對應的中斷子程式将被執行(這個科班的大概都知道這裡就不多說了),是以我們就要在stm32f10x_it.c裡實作他們各自的中斷子程式了(這個一會再詳細介紹,咱們先把整個架構了解下)。另外說一句,這裡的的優先級組将影響主優先級和子優先級數量具體請參考stm32f10X_的固件庫的NVIC.

第11行的GPIO初始化,主要是對通用IO口的屬性設定和初始化,這裡一定要對序列槽所需的A9和A10配置好!

第12行的SPI2_NRF24L01_Init();主要是驅動NRF24L01的接口初始化,因為NRF24L01采用的是SPI通信,是以這裡免不了SPI的設定和相關操作了,不過幸好都封裝好了~像以前在51上做SPI就得自己模拟SPI,沒有示波器調試起來甚是坑~此外這裡我已經把NRF24L01的整個驅動都封裝在NRF24L01.c這個檔案裡了,當想用的時候隻要在中斷向量裡設定其中斷接收函數,并在it.c裡實作其接收函數;一般主函數裡用到的是其初始化函數SPI2_NRF24L01_Init();和 RX_Mode();,當在過程中想利用NRF24L01向外發資料時隻要調用函數void NRF_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes):

第13行是USART初始化,包括波特率、資料位、停止位等~

同樣的類似于NRF24L01一旦初始化之後,其資料接收一般采用中斷方式、資料發送一般采用直接發送的方式。是以在中斷向量裡也要設定,也要在it.c中實作其接收中斷子函數。其發送直接調用stm32f10的固件庫函數(這裡我稍加封裝了下):其實就是發送一個data之後要監聽是否發送完成才能進行下次發送~

接下來進入while循環,不斷進行監聽看是否有序列槽接收标志位置1或者無線子產品接收标志位置1,如果有表明相應的有資料從該通道傳送過來。當是從序列槽傳來的資料表明資料是從上位機發送來的資料,并且想把該資料通過2.4G發送出去,是以這裡調用:NRF_Send_Data(TxBufferRF,sizeof(TxBufferRF));将資料發送出去;當資料是從2.4G通道中傳過來的,表明資料是從下位機傳送過來的想給上位機,于是調用序列槽發送函數将資料發送給上位機:USART_SendChar(USART1,TxBufferUSART[i]);

[stm32] NRF24L01+USART搞定有線和無線通信

看了上圖擴充卡端的資料交換過程就明白了序列槽中斷和無線中斷大緻要幹的事了,這裡我就不多介紹,看看下面的代碼就明白了(在stm32f10x_it.c中),要再次提醒的是無論是序列槽還是無線其接收都是采用中斷,而發送采用循環直接發送,他們的中斷和中斷向量有關并要在stm32f10x_it.c裡實作相應的中斷子程式~

 序列槽和無線接收中斷子程式

下位機部分

上面說過一般具有遠端通信能力的嵌入式系統其下位機部分往往要幹很多事,這裡我們采用stm32作為MCU并搭載uc-OS實時作業系統負責任務排程,同時采用7寸TFT彩屏和uc-GUI設計可視化人機互動界面。其中任務包括主任務、界面任務和觸摸任務,主任務負責建立其他任務,界面任務中将包含整個人機互動界面的界面重新整理邏輯,觸摸任務負責擷取觸摸位置資料擷取~

[stm32] NRF24L01+USART搞定有線和無線通信

這裡我們還是得從main函數先說起:首先在main函數中進行相關初始化,然後建立主任務并啟動uc-OS核心;接着在主任務中調用App_TaskCreate(); 分别建立界面任務和觸摸任務(如下每個任務的建立類似,要給出指向任務代碼的指針、任務執行時傳遞給任務的參數的指針,配置設定給這個任務的棧資訊,任務優先級等)。這樣當任務建立好之後,其執行權就由作業系統排程了~

這裡以界面任務為例:因為我們在建立界面任務時已經指定其任務代碼指針AppTaskUserIF,是以這裡來寫其對應的函數(也就是說這裡是界面任務的入口)。從下面的代碼可以看出進入界面任務時首先對uc-GUI進行初始化,然後進入死循環不斷執行Fun()函數(有人會疑惑:這裡while死循環不就隻能死在這裡嗎?怎麼執行其他任務呢?哈哈,這就是具有作業系統和不具有作業系統的不同啦~雖然這裡是while死循環,但是當OS要把CPU占有權分給其他任務時就會把目前執行的任務的資訊壓入其對應的棧空間,當再次要把CPU配置設定給該任務時,則把棧裡儲存的上次執行的情況拿出來繼續執行,進而實作搶占與多任務的效果!)

是以接下來我們主要看Fun.c裡的Fun函數:雖然代碼有點長,但是很好了解,其核心思路就是建立整個界面并對界面中的每個控件進行相關設定同時獲得其句柄,在最後又進入了while死循環,在循環中不斷檢測2.4G是否接受到資料(和擴充卡端類似也是中斷子程式中收資料然後置接收标志為1的),然後根據從2.4G收到的資料來重新整理文本顯示區;下面一個if判斷speed_change_flag是否有效來向序列槽發送相應的資料。那麼我們的問題又來了:這個speed_change_flag是在哪裡被改變的呢?這個我們就要參看視窗回調函數了!這裡的視窗回調函數是視窗動作響應函數(就像安卓開發裡的按鈕監聽或MFC裡的按鈕點選事件等),一旦視窗裡的控件有相應的觸發動作就會調用該函數,并把事件類型封裝在WM_MESSAGE裡傳過來,在該函數裡對該消息進行解析并作出相應的動作即可(非常像Win32!!!我懷疑做這個uc-GUI的人有copy微軟的嫌疑,(^∇^*)随便猜測,如有雷同,純屬巧合)。這樣我們就很容易找到send按鈕的監聽用于将資料通過NRF24L01發送出去的相關操作,也就明白了滑動條監聽用來改變speed1~5.上面說了這麼多,少了介紹整個界面是怎麼建立的了~其實整個窗體的布局都要放在一個結構體裡,然後在fun()函數裡調用hWin = GUI_CreateDialogBox(aDialogCreate, GUI_COUNTOF(aDialogCreate), _cbCallback, 0, 0, 0);根據定義的視窗資源和回調函數進行窗體的建立~這樣我們就圓滿地了解了stm32基于uc-OS并搭載uc-GUI的運作邏輯啦!

 Fun()

 視窗回調函數

還要回過頭說說我們的USART和NRF24L01,他們的初始化要看main函數中的BSP_Init();函數,該函數負相關硬體的初始化設定(中文意思是闆級支援包初始化函數,因為uc-OS可以并不隻限于stm32單片機,是以這裡要根據不同平台進行相應的設定)。該函數位于bsp.c函數中,其作用相當于将以前我們在main函數中進行的相關硬體初始化單獨拿出來封裝成一個函數而已~但是,序列槽和無線對應的中斷接收程式卻有點不一樣,因為這裡是作業系統,是以在每個中斷子程式前要調用OS_ENTER_CRITICAL();儲存目前的全局中斷标志,然後OSIntNesting++;中斷嵌套深度加1,最後調用OS_EXIT_CRITICAL();恢複全局中斷标志進入正常的中斷處理,此外在中斷響應函數最後要調用OSIntExit(); 檢測如果有更高優先級的任務就緒了,則執行一次任務切換。  

 序列槽和無線中斷子程式

最後說明 

對于純玩軟體的小夥伴,這裡涉及的東西有點多,不必細究,看看了解即可。但是對于初學stm32,尤其是還在為stm32控制NRF24L01不通的同學,這個還是挺有用滴~下面有工程的連結,裡面有些注釋不規範,一切以我部落格裡說的為準哦~

連結

本文轉自beautifulzzzz部落格園部落格,原文連結:http://www.cnblogs.com/zjutlitao/p/4242734.html,如需轉載請自行聯系原作者

繼續閱讀