- 實驗目的 .2
- 實驗板原理圖.2
- GPIO寄存器…2
- GPIO控制函數…3
- 時鐘使能函數…9
- 流水燈實現程序…10
- 本人做實驗的嘗試、問題與思考….11
- 使用HAL庫編寫的流水燈(STM32cubeMX配合KEIL編程)……12
通過對GPIO口的設置使LED燈亮滅,初步認識GPIO(通用輸入輸出寄存器)的性質和相關控制函數。對時鐘使能有一定概念。 1. 可以看到,板上放置在一起的共有五個LED燈,可以看到,燈五右接電阻、電源左接地,并不受引腳控制,即開啟開發板電源即自動點亮。 2. 燈1、2、3、4分與STM32引出的PD9、10、11、12相連。待會兒我們即控制該四個引腳輸出高低電平達到控制燈亮滅的目的。 - STM32F407系列有GPIOA-GPIOK共11個GPIO接口,每個接口又引出0-15共十六個引腳,引腳即可以單一外接某一器件,也可以多接(這時選擇讀入輸出信號的對象要使用復用功能選擇,本點燈過程不接觸)。
- 以下是我們要設置到的GPIO寄存器,關于GPIO所有寄存器的信息可以在官方提供的《STM32F4XX參考手冊》中找到。
- GPIO端口模式寄存器(Mode Register)可控制各引腳使輸入、輸出、復用功能還是模擬模式,我們控制LED燈要使引腳處于輸出模式。
- 端口輸出類型寄存器(Output Type Register)可選擇開漏或推挽模式。在推挽模式下,輸出的高低電平與STM32對引腳的設置一致(與輸出數據寄存器中設置的狀態一致);而在開漏模式下,高電平輸出為高阻態(可理解為非高或低電平或高低電平不確定不予響應)。們控制LED燈要使引腳處于推挽模式。
- 上下拉寄存器(PullUpPullDown Register),上拉時引腳高電平,下拉時引腳低電平,既不上拉也不下拉時為介于高低電平中的不定電壓值。
- 輸出速度寄存器(Output Speed Register),設置其輸出頻率。
- 輸入數據寄存器和輸出數據寄存器即設置為輸入模式時數據的存入處和設置為輸出模式時外部對數據進行讀入處。這兩個寄存器如圖都是低十六位有效的(高十六位保留),一一對應每個GPIO的十六個引腳。
- 置位復位寄存器:我們修改輸出數據寄存器時不直接對其操作,而是通過置位復位寄存器對它進行設置。
該寄存器低十六位相應位置1使輸出數據寄存器對應位為1,高十六位相應位置1使對應位為0。這高低十六位置0對輸出數據寄存器則無作用。 - 在哪兒查看這些函數的相關信息?控制函數定義在哪兒?
- STM官方提供了詳細介紹所有標準庫函數的文檔(稱為固件庫),這個文檔是相關程序自動生成的(生成原理不必了解),里面詳細的提及了函數的定義、功能、對應參數的可選范圍、宏定義以及他們的源代碼都在哪些文件中。
- STM32F407的固件庫名為
《STM32F40x/41x/427/437/429/439/401/410/411xE/412xG/413xx/423xx/446/469/479 DSP and Standard Peripherals Library》 Moudles->STM32F4xx_StdPeriph_Driver->GPIO->Functions 要使用的函數如下 可以看到函數被定義在stm32f4xx_gpio.c文件中。結構體類型和相應的宏分別被定義在stm32f4xx_gpio.h和stm32f4xx.h頭文件中。 重點在看看GPIO_Init函數中的一個參數GPIO_InitTypeDef的結構體類型。包含了,GPIO_Mode、GPIO_Otype、GPIO_Pin、GPIO_PuPd、GPIO_Speed五個成員,對這五個成員可賦的實參已經在途中列出,例如GPIO_Pin的十五個引腳的宏定義。
- 看過上面的函數定義和結構體定義后,這三個函數的參數一目了然如上一般。
功能分別是對輸出數據寄存器相應位置零、置一和反轉。即在初始化GPIO口后,用這三個函數控制燈的亮滅。
以上的函數使完全能夠控制燈了,但實際控制燈之前還有一件事要做,就是使能時鐘。CPU是有工作時序的,可以理解為每一個操作都是單位時間的整數倍,設置好這個單位時間(對內的CPU工作,對外每類接口、外設的 這個單位時間未必相同),即時鐘頻率的倒數,放能工作。 但目前我們還未正式學到時鐘的配置,所以只需要使能對應外設口的時鐘,頻率由STM32自動設置。 現在來看一下這個時鐘使能函數- 我們開啟GPIOD對應的時鐘,另一個參數為ENABLE。
- 現在我們做好了所有的準備工作,可以來跑流水燈了。
(函數部分由兩個右括號沒有截圖下來,但不影響閱讀)
- 由于子函數只有兩個,所以就直接定義在main函數之上了。
- 子函數一個用于延時,一個用于點亮對應燈,延時等待亮一會兒,然后關閉。
- 主函數無非分為三個步驟,使能時鐘、初始化需要用到的與燈相連的GPIO引腳和做完這些準備工作后正式開始控制燈的亮滅。
- 在我第一次點燈的時候,突發奇想能否使用c語言中所學的隨機函數并聯合數組
設置電燈序列。由隨機函數設置一連串燈的亮滅控制?煽刂频膮捣謩e由選擇的燈、燈是亮是滅、燈的顏色(當時使用的是F429的板子外接的燈是彩燈)。 那么這樣,在每次RESET板子重啟程序的時候,燈光的閃爍將是隨機的,將構成一 支“燈光舞蹈”,那可能很有趣。 - 我滿懷興趣的去做了,但最終沒有成功。根本原因是C語言中隨機數本質上是偽隨機數,采用的是UNIX時鐘戳作為隨機種子生成隨機數,每個種子多次生成的結果是一樣的,但由于時鐘戳讀取的當前時間(從1970年1月1日起的每一秒都是一個的時鐘戳,本質上是一個浮點數)每秒都不一樣,所以也算是隨機數了。但STM32的標準庫中并不包括時間戳讀取函數,所以必然無法這樣做了。
-
- 那么為什么會不包含這個函數呢?
其實這個問題很無聊,沒有就是沒有嘛,用不到所以沒有。這個解釋實際上,真的沒毛病,相關的需要用到時間的操作通過系統時鐘的控制和定時器可以完成,這個似乎并沒有什么用處。另外我的一個看法是,本身芯片就只有1M甚至512KB的RAM,無用的函數越多,燒錄進去時可用的空間越少。限于外部原因嵌入式編程代碼精簡是應該的。 - 后來我退而求其次,選擇宏定義一個時間種子,手動修改,那么每個修改的數在程序中處理后也是一支不同的舞蹈了嘛。
- 你是否也有其他關于控制燈的想法呢?
如果用STM32cube來寫就會稍微簡單一些,而且在用標準庫寫例程時,我們僅僅使能了時鐘函數,并沒有配置相關的分、倍頻等系數,在STM32cubeMX中,我們簡單的來配置一下。
- 打開STM32CubeMX,創建一個新項目。
- 在搜索欄中找到我們的芯片STM32F407ZE系列,雙擊進入配置
- 在芯片圖的右下角找到我們的PD9,PD10,PD11,PD12四個引腳,右鍵設置為輸出模式。
- 在左邊欄中找RCC設置,設置HSE為第三個選項,如圖4
- 進入
Clock Configuration,將時鐘相關選擇和系數因子設置如幾個圈中,大致介紹在圖中文字可見。 具體介紹要到后面學習RCC時鐘控制器方具體學習。- 進入Configuration選項的GPIO選項。設置PD9,10,11,12的狀態都為低電平,推挽,上拉,低速模式,則程序燒入后立即全部燈都亮起來。
- 如圖所示創建工程,最后點擊Open Project打開創建的工程,則軟件會自動用KEIL打開這個工程。
- 上面的main.c的程序是自動生成的同時并不是全部,我只截取了部分,可以看的出來,其中自動生成的注釋非常的多。內容也比較多,主要關注下左邊紅點標注了的語句。
主函數里就三個部分,第一部分是根據我們在STM32CubeMx中配置的時鐘關系來設置時鐘的SystemClock_Config();函數的使用。第二部分是根據我們在設置的引腳狀態來配置引腳的MX_GPIO_Init()的使用。第三個是一個while(1)的空循環。 這三條語句執行后的結果就是所有燈亮然后保持著直到RESET(滅了然后重啟程序)或關閉電源。- 我們再來看看定義在stm32f4xx_hal_gpio.c中的函數HAL_GPIO_WritePin()和HAL_GPIO_TogglePin()。前者你去生成該工程后,可以在MX_GPIO_Init()函數中發現它被調用。這兩個函數是不是很眼熟,其功能與標準庫中的GPIO_SetBits()和GPIO_ToggleBits()相同,只不過HAL庫中生成的函數的取名帶有
明顯的HAL庫的特征(如MX_GPIO_Init和HAL_GPIO_WritePin); - 在用STM32CubeMX生成工程后,這些個相關的頭文件,c文件都被自動添加到了工程中,而要被用到函數,宏定義的都在這些個文件里。本人暫時沒有找到類似標準庫的固件庫的HAL固件庫文檔,所以暫時采用找相關文件直接看里面的宏定義、函數代碼的方式來了解程序。
流水燈需要添加的內容有:
1.找到HAL庫下用來置位復位的函數,上圖的HAL_GPIO_WritePin和HAL_GPIO_TogglePin就剛剛好夠用。 - 做一個延時函數用于使燈亮一會兒后再滅之。(為了看的方便直接加在主函數下面且不截圖上面的聲明。)
完整的Word格式文檔51黑下載地址:
http://www.zg4o1577.cn/bbs/dpj-152520-1.html
|