本實驗首先大家自身要有stm32cubemx基礎(chǔ)配置,比如GPIO,、中斷,、串口、SPI等,,FreeRTOS有相關(guān)的調(diào)用函數(shù)基礎(chǔ)及調(diào)度任務(wù)的概念都需要提前理解,。單獨stm32cubemx或FreeRTOS網(wǎng)上很多,這里就不細說了,。 第一步首先打開stm32cubemx軟件,,創(chuàng)建工程之后,,除了把sys、Rcc配置完成還得勾選一下FreeROTS選項enabled如下圖 這樣configuration就生成了FREERTOS的配置參數(shù),,如下圖 點擊進入FREERTOS配置
對于配置參數(shù)的理解,,大家自行網(wǎng)上搜索,因為要寫,,將會寫很長的文本,,不易于閱讀該帖子,本人只介紹如何生成任務(wù)函數(shù)或隊列或信號量,。 由上圖可以添加函數(shù)和隊列,,可以看見添加了3個任務(wù)和1個隊列。 上圖是配置互斥量,、二值量,。可以看到配置了1個互斥量,。 上圖體現(xiàn)的是創(chuàng)建任務(wù),、隊列定時器及信號量所需要的內(nèi)存空間。 之后就可以直接生成工程,,本人生成的是keil工程,。下圖是工程的用戶文件和FreeROTS文件。 修改freertos.c文件來修改自己的任務(wù)及隊列,,當(dāng)然hal也封裝了FreeRTOS一些函數(shù),,但是不影響我們調(diào)用原來擁有的FreeRTOS的API函數(shù)。不過我們也可以使用它們封裝函數(shù)來創(chuàng)建,,發(fā)送,,接收等函數(shù),如果為了通用性,,個人還是覺得調(diào)用以前原來擁有的API也沒什么大問題,,因為原來的API也不需要什么復(fù)雜的參數(shù),很容易實現(xiàn)我們的需求,。下圖是freertos.c文件下定義的變量 由我們cube生成前,,本人確實添加了3個任務(wù)和一個隊列和一個互斥量。 該文件有個FreeRTOS初始化函數(shù)void MX_FREERTOS_Init(void),,如下圖:
上圖是該初始化函數(shù)實現(xiàn)創(chuàng)建任務(wù)的過程,。默認這個任務(wù)函數(shù)的參數(shù)值為NULL,因此如果自身想添加帶函數(shù)參數(shù)的任務(wù)函數(shù),,建議是自己在keil工程下實現(xiàn),,cube生成只適合沒參數(shù)的函數(shù)任務(wù)。由上圖的實現(xiàn)過程可以看得出其已經(jīng)被封裝過了的API,當(dāng)然我們可以不使用其API而用原有的API函數(shù),。 本實驗,,自己在keil工程下創(chuàng)建一個隊列queue_1,因此在freeRTOS初始化函數(shù)下面添加如下: 我們將這個隊列通過函數(shù)參數(shù)傳入兩個任務(wù)里,,因此將原來沒參數(shù)的修改成如下圖: 注意,,因為這個queue_1句柄的使用不需要指針,所以我們定義queue_1時不需要指針變量,,如果是指針變量,,千萬別使用,因為這個是局部變量,,初始化函數(shù)結(jié)束之后,,這個變量將會被釋放,后面如果使用這個變量的地址將會出現(xiàn)內(nèi)存錯誤,。因此由于剛好參數(shù)要的不是指針變量,,因此直接傳局部變量,而不是傳局部變量的地址,,這樣的做法還是可取的,。 下面有我們生成的任務(wù)函數(shù):默認函數(shù)內(nèi)部是一個for(;,;)的空循環(huán),,因此我們修改它實現(xiàn)如下: printf警告的原因是編譯器的誤識別,要消除警告可以在該文件添加頭文件"stm32f1xx_hal.h",。警告就消除了: 從這個函數(shù)我們可以看到xQueeuSendToBack是原本的API函數(shù),。 另外一個任務(wù)函數(shù)做接收并打印實現(xiàn)如下: 編譯燒錄,有以下的結(jié)果: 當(dāng)然我們是目的是實現(xiàn)串口中斷,,首先我們知道中斷服務(wù)程序里面只能調(diào)用一些特殊的FreeRTOS的API,,而不能直接使用xQueueSendToFront()和xQueueSend()等普通的API,能使用的函數(shù)如下: 因此,,在我們在cube環(huán)境配置好uart之后,,在keil工程中,先添加好printf的重定義fputc函數(shù),。這個添加方式網(wǎng)上也有很多教程如何使用printf,同時,,在main函數(shù)下實現(xiàn)uart串口接收回調(diào)函數(shù)void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart),。實現(xiàn)如下: 上圖的第204行至于為什么重新添加HAL_UART_Receive_IT,可以閱讀以下鏈接的解釋:(如果理解可以不需要參考該鏈接) https://bbs./forum.php?mod=viewthread&tid=130&extra= 同時在main函數(shù)之后還得添加HAL_UART_Receive_IT(&huart1,UART_BUF,UART_BUF_SIZE);,如下圖: UART_BUF 和UART_BUF_SIZE的定義在main的全局區(qū)中,,如下圖: 71行這個外部變量聲明的這個隊列,,該隊列是要在main.c文件的串口中斷回調(diào)函數(shù)使用得到該變量,又因為這個隊列是cube生成之后放置在freertos.c文件上的,,因此要在main文件下寫上一個外部聲明的隊列,,這樣調(diào)用這個隊列就不會報錯,。 由于這個UART_BUF_SIZE才4個字節(jié)大小,因此當(dāng)串口調(diào)試助手測試時,,向mcu發(fā)送4個字節(jié),,就能觸發(fā)一次中斷, 我們已經(jīng)實現(xiàn)了串口接收中斷發(fā)送捕獲的數(shù)據(jù)到隊列UartQueueHandle中,,UartQueueHandle這個隊列在上圖可以看到它的外部聲明,,實際定義已經(jīng)在freertos.c文件定義了(由cube配置的隊列)。我們看看第三個任務(wù)函數(shù)實現(xiàn)如下: 因此就是實現(xiàn)了回射功能,,測試功能如下: 因為此時另外兩個任務(wù)在不斷的打印i和j,,因此在發(fā)送端發(fā)送時,就馬上使用暫停查看確實是有1234的值被回射,。 |
|