|
开发环境:
IDE:MounRiver Studio
MCU:CH585
1 GPIO工作原理
熟悉单片机的朋友都知道,学习的第一个例程就是流水灯,要想实现流水灯,首先必须了解GPIO的工作原理。GPIO的基本结构如下图所示。

Figure 1‑1 I/O 端口的基本结构
CH585的 IO 口可以由软件配置成如下 8 种模式:
- 输入模式
- 浮空输入:浮空(floating)就是逻辑器件的输入引脚即不接高电平,也不接低电平。由于逻辑器件的内部结构,当它输入引脚悬空时,相当于该引脚接了高电平。一般实际运用时,引脚不建议悬空,易受干扰。 通俗讲就是让管脚什么都不接,浮空着。信号进入芯片内部后,既没有接上拉电阻也没有接下拉电阻,经由触发器输入。配置成这个模式后,用电压变量引脚电压为1点几伏,这是个不确定值。由于其输入阻抗比较大,一般把这种模式用于标准的通讯协议,比如IIC、USART的等。该模式是GD32复位之后的默认模式。

Figure 1‑2 输入浮空模式
- 上拉输入:上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平,电阻同时起限流作用,弱强只是上拉电阻的阻值不同,没有什么严格区分。上拉输入就是信号进入芯片后加了一个上拉电阻,再经过施密特触发器转换成0、1信号,读取此时的引脚电平为高电平。

Figure 1‑3 输入上拉模式
- 下拉输入:就是把电压拉低,拉到GND。与上拉原理相似。下拉输入就是信号进入芯片后加了一个下拉电阻,再经过施密特触发器转换成0、1信号,读取此时的引脚电平为低电平。

Figure 1‑4 输入下拉模式
- 模拟输入:信号进入后不经过上拉电阻或者下拉电阻,关闭施密特触发器,经由另一线路把电压信号传送到片上外设模块。模拟输入是指传统方式的输入,数字输入是输入PCM数字信号,即0、1的二进制数字信号,通过数模转换,转换成模拟信号,经前级放大进入功率放大器,功率放大器还是模拟的。比如传送给ADC模块,由ADC采集电压信号。所以可以理解为模拟输入的信号是未经处理的信号,是原汁原味的信号。

Figure 1‑5 模拟输入模式
- 输出模式
- 开漏输出:一般用在电平不匹配的场合,如需要输出5V的高电平。输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内)。

Figure 1‑6 开漏输出模式
- 复用开漏输出:可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)。端口必须配置成复用开漏功能输出模式。

Figure 1‑7 开漏复用功能
- 推挽式输出:可以输出高、低电平,连接数字器件;推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由IC的电源决定。推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

Figure 1‑8 推挽式输出

Figure 1‑9 推挽式复用功能
2 GPIO流水灯硬件电路分析
发光二极管是属于二极管的一种,具有二级管单向导电特性,即只有在正向电压(二极管的正极接正,负极接负)下才能导通发光。GPIO接发光二极管的负极,所以GPIO输出高电平LED灭,GPIO输出低电平LED亮。

Figure 2‑1 LED电路图
值得注意的,不同的开发板,LED连接的GPIO一般是不同的,请注意修改。这里将LED0接到PB8,LED1接到PB17。
3 GPIO 流水灯实现
3.1 GPIO 流水灯实现流程
笔者在上文已经分析了GPIO的原理及操作步骤,现在我们就来写代码吧。
GPIO是开发CH585最基本的配置,所以掌握GPIO的配置显得尤为重要。要实现流水灯,一般步骤可以总结为如下:
1) GPIO 时钟使能;
2) GPIO 端口模式设置;
3) 初始化IO口;
4) 编写处理函数;
3.2 流水灯代码实现
主函数代码如下:
#include "CH58x_common.h"
void Delay_Ms(uint32_t ms) {
for(uint32_t i = 0; i < ms; i++) {
for(uint32_t j = 0; j < 8000; j++) {
__asm__("nop");
}
}
}
int main()
{
HSECFG_Capacitance(HSECap_18p);
SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
GPIOB_ModeCfg(GPIO_Pin_8 | GPIO_Pin_17,
GPIO_ModeOut_PP_5mA);
GPIOB_SetBits(GPIO_Pin_8 | GPIO_Pin_17);
while(1)
{
GPIOB_SetBits(GPIO_Pin_17);
GPIOB_ResetBits(GPIO_Pin_8);
Delay_Ms(200);
GPIOB_SetBits(GPIO_Pin_8);
GPIOB_ResetBits(GPIO_Pin_17);
Delay_Ms(200);
}
}
代码还是比较简单的,首先开启GPIO的时钟,然后对GPIO初始化,主要是设置模式和速率然后就可以控制GPIO高低电平了。
3.3 实验现象
将编译好的程序下载到板子中,可以看到LED灯依次闪烁。
|