GPIO 端口相关寄存器 ( STM32F40x 芯片 )
目标:
++++开关KEY1控制开灯。++++
![](https://file.jishuzhan.net/article/1760455688229752833/1e8777b1261fb0272fcd7b03c21167c4.webp)
分析:
KEY1---PA0--->输入---->浮空输入/下拉输入
KEY1不导通时,PA0输入为低电平,KEY1导通时,PA0输入为高电平。
实现:
按键初始化
①查找PA连接的时钟线,开启时钟。
![](https://file.jishuzhan.net/article/1760455688229752833/f84e63cc94454fc6601e9c68c2b86f6e.webp)
②设置GPIO端口模式---->输入模式
![](https://file.jishuzhan.net/article/1760455688229752833/10ea0979c28dc27217b2bfb770777eb2.webp)
③设置GPIO端口输入模式
![](https://file.jishuzhan.net/article/1760455688229752833/ed4cd90e586b468ffb98d75851209efd.webp)
/*****************************************
函数功能:按键初始化
函数接口:KEY1--PA0--浮空/下拉输入
******************************************/
void KEY_Init(void)
{
RCC->AHB1ENR |= 1<<0; //按键PA0时钟使能
GPIOA->MODER &= ~(3<<0*2); //清零&&输入模式
GPIOA->PUPDR &= ~(3<<0*2); //清零&&浮空
GPIOA->PUPDR |= 2<<0*2; //下拉
}
按键消抖
①获取KEY1/PA0的状态
![](https://file.jishuzhan.net/article/1760455688229752833/8947dc87fe835408d08a5c59b6cfdd5c.webp)
![](https://file.jishuzhan.net/article/1760455688229752833/f076d3c77e9bdd7bee5920a4118263b1.webp)
GPIOA->IDR只允许读,不允许写。获取PA0口的状态需要(GPIOA->IDR & 1<<0)。
②if两次读取GIPA->IDR的第0位,实现消抖。
③设静态变量flag作为标志位,防止已有按键按下时,其他按键按下仍能进行操作
/*****************************************
函数功能:按键消抖
函数接口:KEY1--PA0--浮空/下拉输出
返回参数:返回0:没有按下,返回1:按键按下
******************************************/
uint8_t KEY_Scan(void)
{ static uint8_t flag =0; //0:按键未按下,1:按键已按下
if((flag ==0) && (GPIOA->IDR & 1<<0)) //判断按键是否按下,IDR第0位为1时按下
{
flag = 1;
delay(500);
if(GPIOA->IDR & 1<<0)
{
return 1;
}
}
else if((flag==1)&& !(GPIOA->IDR & 1<<0)) //松手检测
{
flag = 0; //按键松手
}
return 0;
}
位带头文件
++++io_bit.h可以在社区获得。++++
![](https://file.jishuzhan.net/article/1760455688229752833/6e0664f378e025da41f74a00b97421fe.webp)
将位带头文件包含到编辑的头文件中,通过宏定义,可实现更简单操作寄存器。
![](https://file.jishuzhan.net/article/1760455688229752833/9ce049aef7b79027b5c42c970676648c.webp)
点亮LED的方法:
LED6 = 0; //PB3低电平点亮
GPIOB->ODR &= ~(1<<4); //PB4低电平点亮
GPIOB->ODR &= ~(1<<5); //PB5低电平点亮
两个按键检测&&按键位带使用举例:
//双按键检测
uint8_t KEY_Scan2(void)
{
static uint8_t flag = 0;
if((flag == 0)&&(GPIOA->IDR & 1<<0 || GPIOA->IDR & 1<<1))
{
delay(1000);
if(GPIOA->IDR & 1<<0)
{
return 1;
}
if(GPIOA->IDR & 1<<1)
{
return 2;
}
}
else if((flag == 1) && (!(GPIOA->IDR & 1<<0) || !(GPIOA->IDR & 1<<1)))
{
flag = 0;
}
return 0;
}
//位带使用
uint8_t KEY_Scan3(void)
{
static uint8_t flag = 0;
if((flag == 0)&&(KEY1==1 || KEY2 == 1))
{
delay(1000);
if(KEY1==1)
{
return 1;
}
if(KEY2==1)
{
return 2;
}
}
else if((flag == 1) && (KEY1==0 || KEY2==0))
{
flag = 0;
}
return 0;
}