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