開發環境:
MDK:Keil 5.30
開發板:GD32F207I-EVAL
MCU:GD32F207IK
1 GPIO工作原理
熟悉單片機的朋友都知道,學習的第一個例程就是流水燈,要想實現流水燈,首先必須了解GPIO的工作原理。GPIO的基本結構如下圖所示。
GD32 的 IO 口可以由軟件配置成如下 8 種模式:
- 輸入模式
- 浮空輸入:浮空(floating)就是邏輯器件的輸入引腳即不接高電平,也不接低電平。由于邏輯器件的內部結構,當它輸入引腳懸空時,相當于該引腳接了高電平。一般實際運用時,引腳不建議懸空,易受干擾。通俗講就是讓管腳什么都不接,浮空著。信號進入芯片內部后,既沒有接上拉電阻也沒有接下拉電阻,經由觸發器輸入。配置成這個模式后,用電壓變量引腳電壓為1點幾伏,這是個不確定值。由于其輸入阻抗比較大,一般把這種模式用于標準的通訊協議,比如IIC、USART的等。該模式是GD32復位之后的默認模式。
- 上拉輸入:上拉就是把電位拉高,比如拉到Vcc。上拉就是將不確定的信號通過一個電阻嵌位在高電平,電阻同時起限流作用,弱強只是上拉電阻的阻值不同,沒有什么嚴格區分。上拉輸入就是信號進入芯片后加了一個上拉電阻,再經過施密特觸發器轉換成0、1信號,讀取此時的引腳電平為高電平。
- 下拉輸入:就是把電壓拉低,拉到GND。與上拉原理相似。下拉輸入就是信號進入芯片后加了一個下拉電阻,再經過施密特觸發器轉換成0、1信號,讀取此時的引腳電平為低電平。
- 模擬輸入:信號進入后不經過上拉電阻或者下拉電阻,關閉施密特觸發器,經由另一線路把電壓信號傳送到片上外設模塊。模擬輸入是指傳統方式的輸入,數字輸入是輸入PCM數字信號,即0、1的二進制數字信號,通過數模轉換,轉換成模擬信號,經前級放大進入功率放大器,功率放大器還是模擬的。比如傳送給ADC模塊,由ADC采集電壓信號。所以可以理解為模擬輸入的信號是未經處理的信號,是原汁原味的信號。
- 輸出模式
- 開漏輸出:一般用在電平不匹配的場合,如需要輸出5V的高電平。輸出端相當于三極管的集電極,要得到高電平狀態需要上拉電阻才行。適合于做電流型的驅動,其吸收電流的能力相對強(一般20mA以內)。
- 復用開漏輸出:可以理解為GPIO口被用作第二功能時的配置情況(即并非作為通用IO口使用)。端口必須配置成復用開漏功能輸出模式。
- 推挽式輸出:可以輸出高、低電平,連接數字器件;推挽結構一般是指兩個三極管分別受兩個互補信號的控制,總是在一個三極管導通的時候另一個截止。高低電平由IC的電源決定。推挽電路是兩個參數相同的三極管或MOSFET,以推挽方式存在于電路中,各負責正負半周的波形放大任務,電路工作時,兩只對稱的功率開關管每次只有一個導通,所以導通損耗小、效率高。輸出既可以向負載灌電流,也可以從負載抽取電流。推拉式輸出級既提高電路的負載能力,又提高開關速度。
- 推挽式復用輸出:可以理解為GPIO口被用作第二功能時的配置情況(即并非作為通用IO口使用)。端口必須配置成復用推挽功能輸出模式。
2 I/O復用和重映射
2.1 I/O復用
GD32 有很多的內置外設,這些外設的外部引腳都是與 GPIO 復用的。也就是說,一個 GPIO如果可以復用為內置外設的功能引腳,那么當這個 GPIO 作為內置外設使用的時候,就叫做復用。當I/O端口被配置為復用功能時:
● 在開漏或推挽式配置中,輸出緩沖器被打開
● 內置外設的信號驅動輸出緩沖器(復用功能輸出)
● 施密特觸發輸入被激活
● 弱上拉和下拉電阻被禁止
● 在每個APB2時鐘周期,出現在I/O腳上的數據被采樣到輸入數據寄存器
● 開漏模式時,讀輸入數據寄存器時可得到I/O口狀態
● 在推挽模式時,讀輸出數據寄存器時可得到最后一次寫的值
大家都知道,MCU 都有串口,GD32 有好幾個串口。比如說 GD32F207IK有 8個串口,我們可以查手冊知道,串口 0 的引腳對應的 IO 為 PA9,PA10.PA9, PA10 默認功能是 GPIO, 所以當PA9,PA10 引腳作為串口0的 TX,RX 引腳使用的時候,那就是端口復用。
USART0_TX | PA9 |
---|---|
USART0_RX | PA10 |
關于串口的內容后面的章節會詳細講解。
2.2 I/O重映射
為了使不同器件封裝的外設 IO 功能數量達到最優,可以把一些復用功能重新映射到其他一些引腳上。 GD32 中有很多內置外設的輸入輸出引腳都具有重映射(remap)的功能。 我們知道每個內置外設都有若干個輸入輸出引腳,一般這些引腳的輸出端口都是固定不變的,為了讓設計工程師可以更好地安排引腳的走向和功能,在 GD32中引入了外設引腳重映射的概念,即一個外設的引腳除了具有默認的端口外,還可以通過設置重映射寄存器的方式,把這個外設的引腳映射到其它的端口。
復用功能 | USART1_REMAP = 0 | USART1_REMAP = 1 |
---|---|---|
USART0_TX | PA9 | PB6 |
USART0_RX | PA10 | PB7 |
從表中可以看出,默認情況下,串口 0復用的時候的引腳位 PA9、PA10,同時我們可以將 TX 和 RX 重新映射到管腳 PB6 和 PB7 上面去。所以重映射我們同樣要使能復用功能的時候講解的 2 個時鐘外,還要使能 AFIO 功能時鐘,然后要調用重映射函數。
3 GPIO流水燈硬件電路分析
發光二極管是屬于二極管的一種,具有二級管單向導電特性,即只有在正向電壓(二極管的正極接正,負極接負)下才能導通發光。PF6引腳接發光二極管(LED1)的正極,所以PF6引腳輸出高電平LED1亮,PF6引腳輸出低電平LED1熄滅,其他LED同理。
值得注意的,不同的開發板,LED連接的GPIO一般是不同的,請注意修改。
4 GPIO流水燈寄存器分析
要想真正掌握一款單片機,分析寄存器是必不可少,但是對于GD32來再說,GD已經將寄存器操作封裝成庫函數,開發者只需要調用庫函數即可,對于初學者來說,只需學會使用使用函數即可,對于沒有基礎的讀者朋友就不必細究每個寄存器,當學到一定程度,再來一探究竟吧,筆者再這里只是給出GPIO的寄存配置相關配置表,在后面的章節也是如此。好了,繼續進入正題吧。
每個GPIO端口都有兩個32位配置寄存器(GPIO_CTL0 ,GPIO_CTL1) ,兩個16位數據寄存器 (GPIO_ISTAT和GPIO_OCTL),一個32位置位寄存器(GPIO_BOP),一個16位復位寄存器(GPIO_BC),一個16位鎖定寄存器(GPIO_LOCK)。每個I/O端口位可以自由編程。
點亮LED,基本步驟是:配置寄存器;控制寄存器。庫開發只是將傳統的配置方式編程函數,是的單片機開發變得簡單方便快捷。
我們常用的 IO 端口寄存器只有 4 個: GPIO_CTL0、GPIO_CTL1、 GPIO_OCTL、 GPIO_BOP。其中GPIO_CTL0、GPIO_CTL1 控制著每個 IO 口的模式及輸出速率。
GPIO_CTL0、GPIO_CTL1類似,讀者朋友可以參看《GD32F10x_User_Manual_EN_Rev2.4》數據輸入輸出寄存器是將對應的IO口置位,從而進行數據的輸入與輸出。
5 GPIO 流水燈實現流程
筆者在上文已經分析了GPIO的原理及操作步驟,現在我們就來寫代碼吧。
GPIO是開發GD32最基本的配置,所以掌握GPIO的配置顯得尤為重要。要實現流水燈,一般步驟可以總結為如下:
- GPIO 時鐘使能;
- GPIO 端口模式設置;
- 初始化IO口;
- 編寫處理函數;
6 GPIO 流水燈實現
6.1 GPIO庫函數
GPIO庫函數相關的庫函數如下:
- gpio_deinit 復位外設GPIO
- gpio_afio_deinit 復位AFIO
- gpio_init GPIO參數初始化
- gpio_bit_set 置位引腳值
- gpio_bit_reset 復位引腳值
- gpio_bit_write 將特定的值寫入引腳
- gpio_port_write 將特定的值寫入一組端口
- gpio_input_bit_get 獲取引腳的輸入值
- gpio_input_port_get 獲取一組端口的輸入值
- gpio_output_bit_get 獲取引腳的輸出值
- gpio_output_port_get 獲取一組端口的輸出值
- gpio_pin_remap_config 配置GPIO引腳重映射
- gpio_pin_remap1_config 配置GPIO引腳重映射1
- gpio_exti_source_select 選擇哪個引腳作為EXTI源
- gpio_ethernet_phy_select 以太網MII或RMII PHY選擇
- gpio_event_output_config 配置事件輸出
- gpio_event_output_enable 事件輸出使能
- gpio_event_output_disable 事件輸出禁能
- gpio_pin_lock 相應的引腳配置被鎖定
6.2 流水燈代碼實現
主函數代碼如下:
/*
brief main function
param[in] none
param[out] none
retval none
*/
int main(void)
{
/* configure LED1 GPIO port */
led_init(LED1);
/* configure LED2 GPIO port */
led_init(LED2);
/* configure LED3 GPIO port */
led_init(LED3);
/* configure LED4 GPIO port */
led_init(LED4);
while(1)
{
/* turn on LED1, turn off LED4 */
led_on(LED1);
led_off(LED4);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED2, turn off LED1 */
led_on(LED2);
led_off(LED1);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED3, turn off LED2 */
led_on(LED3);
led_off(LED2);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED4, turn off LED3 */
led_on(LED4);
led_off(LED3);
/*delay about 500ms*/
delay(0xffffff);
}
}
代碼還是比較簡單的,首先開啟GPIO的時鐘,然后對GPIO初始化,主要是設置模式和速率,GPIO的初始化代碼如下:
/*
brief configure led GPIO
param[in] lednum: specify the led to be configured
arg LED1
arg LED2
arg LED3
arg LED4
param[out] none
retval none
*/
void led_init(led_typedef_enum lednum)
{
/* enable the led clock */
rcu_periph_clock_enable(GPIO_CLK[lednum]);
/* configure led GPIO port */
gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN[lednum]);
GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
}
然后就可以控制GPIO高低電平了。
7 實驗現象
將編譯好的程序下載到板子中,可以看到四個LED燈依次閃爍。
審核編輯:湯梓紅
-
mcu
+關注
關注
146文章
16984瀏覽量
350294 -
led燈
+關注
關注
22文章
1592瀏覽量
107835 -
流水燈
+關注
關注
21文章
432瀏覽量
59636 -
GPIO
+關注
關注
16文章
1196瀏覽量
51914 -
GD32
+關注
關注
7文章
403瀏覽量
24218
發布評論請先 登錄
相關推薦
評論