一、GPIO定义
GPIO,即通用输入输出端口General Purpose Input Output的缩写。
GPIO端口可以通过程序配置成输入端口或输出端口。
二、GPIO的IO模式
STM8的GPIO口有12种模式设置,其中输入4种,输出8种:
1、GPIO_Mode_In_FL_No_IT浮空输入无中断
2、GPIO_Mode_In_PU_No_IT上拉输入无中断
3、GPIO_Mode_In_FL_IT浮空输入有中断
4、GPIO_Mode_In_PU_IT 上拉输入有中断
5、GPIO_Mode_Out_OD_Low_Fast
开漏-输出低-高速 Output open-drain, low level, 10MHz
6、GPIO_Mode_Out_PP_Low_Fast
推挽-输出低-高速 Output push-pull, low level, 10MHz
7、GPIO_Mode_Out_OD_Low_Slow
开漏-输出低-低速 Output open-drain, low level, 2MHz
8、GPIO_Mode_Out_PP_Low_Slow
推挽-输出低-低速 Output push-pull, low level, 2MHz
9、GPIO_Mode_Out_OD_HiZ_Fast
开漏-输出高阻-高速 Output open-drain, high-impedance level, 10MHz
10、GPIO_Mode_Out_PP_High_Fast
推挽-输出高-高速 Output push-pull, high level, 10MHz
11、GPIO_Mode_Out_OD_HiZ_Slow
开漏-输出高阻-低速 Output open-drain, high-impedance level, 2MHz
12、GPIO_Mode_Out_PP_High_Slow
推挽-输出高-低速 Output push-pull, high level, 2MHz
或者如下图所示:
所以我们其实要弄懂的主要是输入两种模式(上拉和浮空)以及输出的两种模式(推挽和开漏),剩下的只是在这四种模式下根据参数设置不同进一步划分。
1、上拉输入模式
所谓上拉模式,即设置输入模式时,接一个上拉电阻,大概如下图所示:
上图是STM8设置GPIO为上拉模式时的端口内部电路简图,R1经典取值范围为30k~80k,典型值为55k。(弱上拉)
注:上拉电阻R越大,上拉作用越小,则为弱上拉;反之,R越小,上拉作用越大,则为强上拉。外部上拉电阻取值经验值为4.7k~10k。
上下两个二极管起到一个保护电路的作用,防止外部输入电压太高或太低。这个保护电路可以将外部过高电压降到3.8~4.1V,也可以将外部过低电压抬升到-0.6V,从而保护内部电路。
上拉输入模式可以将不确定的浮空端口信号保持在一个高电平,是最常用的GPIO输入模式。
1、浮空输入模式
浮空模式和上拉模式最大的区别就是没有上拉电阻:
这种结构的输入阻抗较高,能最真实地反映外部输入信号,主要用于ADC(数模转化)的场合。
1、推挽输出模式
推挽(PP)输出模式如下图所示:
简单来说,MOS管Q1和Q2,在输出高低电平时分别起作用。 输出高电平的时候,Q1导通,Q2截止;输出低电平的时候,Q1截止,Q2导通。总之,Q1与Q2在工作时总是保持在一个导通和另一个截止的状态。推挽输出模式的优点是损耗小,效率高。
1、开漏输出模式
开漏(OD)输出模式,顾名思义即漏极开路的输出模式,如下图所示:
开漏输出模式和推挽输出模式最大区别在于没有Q1,只能输出低电平状态“0”,而不能直接输出高电平状态“1”。必须外接上拉电阻,才能输出“1”。这其实跟51单片机的P0口是一样的。
开漏输出模式的特点:
(1)开漏模式须外接上拉电阻才能输出高电平,驱动电流大多数是由外部电源经过上拉电阻供给,单片机内部一般只需要提供极小的栅极控制电流即可。降低单片机功耗。
(2)开漏模式可用于电平信号标准的转换。外部上拉电阻外加的电源电压可以是5V也可以是3.3V(STM8端口最高可承受5V电压),开漏结构可以灌入较大电流(20mA),间接实现TTL电平系列或CMOS电平系列的转换。
(3)开漏模式可用于I²C总线,实现“线与”功能。
(4)开漏模式使用外加上拉电阻,则上拉电阻小,上拉作用强,上升沿时间短,速度快;上拉电阻大,上拉作用小,上升沿时间长,速度缓。
注:STM8单片机“真正的”开漏输出模式内部电路:PE1/I²C_SCL与PE2/I²C_SDA(没有连接VDD的保护二极管)
三、GPIO的寄存器设置
GPIO的5个寄存器:
1.输出数据寄存器ODR;
2.引脚输入寄存器IDR;
3.数据方向寄存器DDR;
4.控制寄存器CR1;
5.控制寄存器CR2;
模式配置图,如下图所示
STM8通过DDR、CR1和CR2三个寄存器来配置不同的输入输出模式。用ODR存储要输出的信号,用IDR来读取对应端口的信号。以上5种寄存器都是8位,对应值STM8每组GPIO对应的8个端口(7:0)。
通过寄存器操作GPIO的示例:
int ** in(void)
{
/*设置内部高速时钟16M为主时钟*/
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
GPIOB->DDR = 0x20;//配置GPIOB的方向寄存器,设置pin5为输出模式
GPIOB->CR1 = 0x20;//配置GPIOB_5为推挽输出
GPIOB->CR2 = 0x00;
while(1)
{
GPIOB->DDR = 0x20;//GPIOB_5输出高电平,亮
delay();
GPIOB->DDR = 0x00;//GPIOB_5输出低电平,暗
delay();
}
}
四、GPIO的库函数实现。
所谓库函数,其实就是官方做的驱动程序库,将对寄存器用结构图一一对应并封装起来,并提供了基本的配置函数。我们只要使用官方的库函数就就可以了,不用再花大力气研究寄存器的配置。
简单举例说明:
GPIO_Init(LED1_PORT,LED1_PIN,GPIO_MODE_OUT_PP_HIGH_FAST );
GPIO_Init这个命令是设置或者说定义管教模式的,上面这条命令的意思就是LED1代表的管教设置为推挽输出模式,初始高电平,高速模式。
注:LED1_PORT和LED1_PIN应该在相关的头文件或者别处已注释,如
#define LED1_PIN GPIO_PIN_5
#define LED1_PORT GPIOB
GPIO_WriteLow(LED1_PORT,LED1_PIN);
在LED1这个管脚输出低电平;
GPIO_WriteHigh(LED1_PORT,LED1_PIN);
在LED1这个管脚输出高电平;
GPIO_WriteReverse(LED1_PORT,LED1_PIN);
翻转LED1这个管脚的电平状态;