GPIO (general port input output ) 即通用端口输入输出。 是我们学习单片接触的第一个外设。想想当初我们点亮第一个流水灯时的欣喜,就像学习C语言的时候写出Hello world 是的惊喜感觉自己会编程了,接触了一个多么伟大的学科。 嘿嘿,上硬菜。
我手上的开发板是野火的MINI板,功能够用,型号是 STM32F103VE 144P个引脚,STM32有多种封装相应的同一种型号也有多种不同的引脚。
STM32 GPIO 有四种输入四种输出。
{
- 浮空输入
- 上拉输入
- 下拉输入
- 模拟输入
- 推挽输出
- 开漏输出
- 推挽式复用功能
- 开漏复用
}
首先我们回顾 数电中学过的, 二进制是0和1 0表示低电平,TTL电平中(0~5V) 02V表示0,35V表示1 ,2~3V为不确定状态,
一个IO 可以有三种状态
{
高阻态
高电平
低电平
}
浮空输入: 就是这个引脚的状态不确定,有三种状态,一把这种模式用来传输数据。
上拉输入: 就是在浮空上接一个电阻和电压(具体看是TTL还是其他)。一般时上拉输入为1
下拉输入: 就是在浮空上接一个电阻和地,一般下拉输入为0 .
模拟输入: 我的认识是 输入模拟信号,一般作为ADC的输入。
四种输出没有具体查资料。先留在这。
到现在基本对STM32的GPIO有了个基本认识。现在让我们认识认识他的寄存器
{
GPIOX__CRL (configuration register low 低位配置寄存器) : 配置:引脚是输出还是输出,输出频率多大。
GPIOX__CRH(C R HIGH 高位位置寄存器)
GPIOX__IDR(input data r 输入数据寄存器)
GPIOX__ODR(output data register 输出数据寄存器)
GPIOX__BSRR(bit set reset register ***位***设置清除寄存器)
GPIOX__BRR(bit reset register ***位***清除寄存器)
GPIOX__LCKR(port lock configuration register 端口配置锁定寄存器 )
}
位设置清除寄存器: 如果寄存器中同时设置了 置位和清除, 则以置位起作用。
现在我们来看具体代码的实现。
例: 点亮一个LED,硬件接口: PC3。
代码如下(下面是MAIN文件里面的函数):
int main(void)
{
led_init();
while(1)
{
stateChange( ENABLE);
delay();
stateChange(DISABLE);
delay();
}
}
void delay()
{
int i,j,k;
for(i=50;i>0;i--)
for(j=50;j>0;j--)
for(k=130;k>0;k--);
}
看下***led_init()***函数里面的具体代码
void led_init()
{
GPIO_InitTypeDef GPIOCI;
//GPIO_Init(GPIO_TypeDef * GPIOx,GPIO_InitTypeDef * GPIO_InitStruct)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIOCI.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOCI.GPIO_Speed=GPIO_Speed_50MHz;
GPIOCI.GPIO_Pin=GPIO_Pin_3;
GPIO_Init(GPIOC,&GPIOCI);
}
GPIO_InitTypeDef GPIOCI; 定义名为GPIOCI的GPIO_InitTypeDef型的变量,看看GPIO_InitTypeDef的来源
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */
GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
可以看出,这个是一个结构体类型。
这里涉及到了***Typedef***这个关键字,关于语言方面的知识,我随后开个专门的博文写这些东西。
GPIO_InitTypeDef 这是一个类型就行了。
在led_init();开始首先定义了一个GPIO_InitTypeDef型的变量用来存储要配置引脚的信息。 然后打开了GPIOC相应得时钟,不懂得朋友可以看我 写的***STM32时钟分析***
用过 RCC->APB2ENR 设置相应的外设。
之后是往GPIO_InitTypeDef里面传值,
GPIOCI.GPIO_Mode=GPIO_Mode_Out_PP; // 设置模式为 推挽输出
GPIOCI.GPIO_Speed=GPIO_Speed_50MHz;// 速度为50MHZ
GPIOCI.GPIO_Pin=GPIO_Pin_3;// 引脚3 .
然后下面这个函数把值传入相应的寄存器。
GPIO_Init(GPIOC,&GPIOCI);
这个函数实际上就是干了一件如下这么的事:
GPIOC->CRL =0x0000 3000;
可是为什么我们不直接这样去写呢,看起来多简单,反而要使用一个代码比较多的函数,等我们以后分析完GPIO_Init();这个函数后就会知道,那个函数写的有多么的美妙,这也是库开发的美妙。
继续,
程序进入一个while(1)死循环。
通过置GPIO__Pin_3 为1 .为0循环,就可以实现LED的一亮一灭。
GPIOx->BSRR = GPIO_Pin; // 置1
GPIOx->BRR = GPIO_Pin; //清零。
好了,完成了这些我们基本就可实现LED的亮灭循环。
由于我们写的只是一个简单的例子,我们使用了死循环,这太浪费资源,开发中最好不要做这样事情,这里只是为了演示方便。