开发环境:
MDK:Keil 5.30
开发板:GD32F207I-EVAL
MCU:GD32F207IK
熟悉单片机的朋友都知道,学习的第一个例程就是流水灯,要想实现流水灯,首先必须了解GPIO的工作原理。GPIO的基本结构如下图所示。
GD32 的 IO 口可以由软件配置成如下 8 种模式:
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 |
关于串口的内容后面的章节会详细讲解。
为了使不同器件封装的外设 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 功能时钟,然后要调用重映射函数。
发光二极管是属于二极管的一种,具有二级管单向导电特性,即只有在正向电压(二极管的正极接正,负极接负)下才能导通发光。PF6引脚接发光二极管(LED1)的正极,所以PF6引脚输出高电平LED1亮,PF6引脚输出低电平LED1熄灭,其他LED同理。
值得注意的,不同的开发板,LED连接的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口置位,从而进行数据的输入与输出。
笔者在上文已经分析了GPIO的原理及操作步骤,现在我们就来写代码吧。
GPIO是开发GD32最基本的配置,所以掌握GPIO的配置显得尤为重要。要实现流水灯,一般步骤可以总结为如下:
GPIO库函数相关的库函数如下:
主函数代码如下:
/*
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高低电平了。
将编译好的程序下载到板子中,可以看到四个LED灯依次闪烁。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !