MDK:Keil 5.30 MCU:GD32F207IK
2.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,电路中存在推拉方式,负责正负波形放大半周。电路工作时,两个对称的电源开关管每次只有一个导通,导通损耗小,效率高。输出可以向负载灌注电流,也可以从负载中提取电流。推拉输出级不仅提高了电路的负载能力,而且提高了开关速度。
? 推挽式复用输出
2.2 I/O复用和重映射
2.2.1 I/O复用
GD32 内置外设很多,这些外设的外引脚都是和 GPIO 复用的。也就是说,一个 GPIO如果可以重用作内置外设的功能引脚,那么当这个 GPIO 用作内置外设时,称为复用。I/O当端口配置为复用功能时: ● 输出缓冲器在泄漏或推拉配置中打开 ● 信号驱动输出缓冲器(复用功能输出)内置外设 ● 激活施密特触发输入 ● 禁止弱上拉和下拉电阻 ● 在每个APB2时钟周期,出现在I/O将脚上的数据采样到输入数据寄存器 ● 读取输入数据寄存器时,可以获得泄漏模式I/O口状态 ● 在推拉模式下,在读取输出数据寄存器时,可以得到最后一个值
大家都知道,MCU 都有串口,GD32 有几个串口。 GD32F207IK有 我们可以查手册了解八个串口。 0 引脚对应 IO 为 PA9,PA10.PA9, PA10 默认功能是 GPIO, 所以当PA9,PA10 引脚作为串口0 TX,RX 使用引脚时,即端口复用。
引脚 | pin |
---|---|
}USART0_TX | PA9 |
USART0_RX | PA10 |
以下章节将详细说明串口的内容。
2.2.2 I/O重映射
外设用于包装不同的设备 IO 当功能数量达到最佳时,一些复用功能可以重新映射到其他引脚上。 GD32 内置外设的许多输入输出引脚都有重映射(remap)的功能。 我们知道每个内置外设都有几个输入输出引脚。一般来说,这些引脚的输出端口是固定的。为了让设计工程师更好地安排引脚的方向和功能, GD32介绍了外设引脚重映射的概念,即外设引脚除了默认端口外,还可以通过设置重映射寄存器将外设引脚映射到其他端口。
复用功能 | USART1_REMAP = 0 | USART1_REMAP = 1 |
---|---|---|
USART0_TX | PA9 | PB6 |
USART0_RX | PA10 | PB7 |
从表中可以看出,在默认情况下,串口 0重用引脚位置时 PA9、PA同时,我们可以 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面。因此,我们也应该在重用功能时解释重映射。 2 除了时钟,还要使能 AFIO 功能时钟,然后调用重映射函数。
2.3 GPIO流水灯硬件电路分析
发光二极管是一种二极管,具有二次管单向导电的特点,即只有在正电压二极管正负)下才能导致发光。PF六引脚接发光二极管(LED1)正极,所以PF6引脚输出高电平LED1亮,PF6引脚输出低电平LED1熄灭,其他LED同理。
不同的开发板值得注意,LED连接的GPIO一般不同,请注意修改。
2.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口位,从而输入和输出数据。
2.5 GPIO 流水灯实现流程
笔者在上文已经分析了GPIO现在我们来写代码。
GPIO是开发GD32最基本的配置,所以掌握GPIO配置尤为重要。要实现流水灯,一般步骤可总结如下:
1)GPIO 时钟使能; 2)GPIO 端口模式设置; 3)初始化IO口; 4)编写处理函数;
2.6 GPIO 流水灯实现
2.6.1 GPIO库函数
GPIO与库函数相关的库函数如下: ? gpio_deinit 复位外设GPIO ? gpio_afio_deinit 复位AFIO ? gpio_init GPIO参数初始化 ? gpio_bit_set 置位引脚值
2.6.2流水灯代码实现
核心代码如下:
/* Includes*********************************************************************/
#include "gd32f20x.h"
/*简单延时函数*/
void delay(uint32_t xms);
/* brief main function param[in] none param[out] none retval none */
int main(void)
{
/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOF);
/* configure LED1 GPIO port */
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED1 GPIO pin */
gpio_bit_reset(GPIOF, GPIO_PIN_6);
/* configure LED2 GPIO port */
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
/* reset LED2 GPIO pin */
gpio_bit_reset(GPIOF, GPIO_PIN_7);
/* configure LED3 GPIO port */
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
/* reset LED3 GPIO pin */
gpio_bit_reset(GPIOF, GPIO_PIN_8);
/* configure LED4 GPIO port */
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* reset LED4 GPIO pin */
gpio_bit_reset(GPIOF, GPIO_PIN_9);
while(1)
{
/* turn on LED1, turn off LED4 */
gpio_bit_set(GPIOF, GPIO_PIN_6);
gpio_bit_reset(GPIOF, GPIO_PIN_9);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED2, turn off LED1 */
gpio_bit_set(GPIOF, GPIO_PIN_7);
gpio_bit_reset(GPIOF, GPIO_PIN_6);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED3, turn off LED2 */
gpio_bit_set(GPIOF, GPIO_PIN_8);
gpio_bit_reset(GPIOF, GPIO_PIN_7);
/*delay about 500ms*/
delay(0xffffff);
/* turn on LED4, turn off LED3 */
gpio_bit_set(GPIOF, GPIO_PIN_9);
gpio_bit_reset(GPIOF, GPIO_PIN_8);
/*delay about 500ms*/
delay(0xffffff);
}
}
/** * @brief 延时函数 * @param xms 延时长度 * @retval None */
void delay( uint32_t xms)
{
//for(; nCount != 0; nCount--);(方法一)
while(xms--);//(方法二)
}
代码还是比较简单的,首先开启GPIO的时钟,然后对GPIO初始化,主要是设置模式和速率,然后就可以控制GPIO高低电平了。
2.7实验现象
将编译好的程序下载到板子中,可以看到四个LED灯不同地闪烁。
欢迎访问我的网站
BruceOu的哔哩哔哩 BruceOu的主页 BruceOu的博客 BruceOu的CSDN博客 BruceOu的简书 BruceOu的知乎
资源获取方式
1.关注公众号[] 2.在公众号回复关键词[]获取资料提取码