STM32入门——按键(基础版)
简介:通过延时函数对按键进行消抖,实现按键控制LED亮灭循环操作,对按键做了基础介绍,对延时函数做了浅层解释。
注意:文章内容均为浅层次学习过程中的总结,如有错误或侵权请指出
流程图:
1、标准库实现
#include "stm32f10x.h" // Device header
//微秒
void Delay_us(uint32_t xus)
{
SysTick->VAL = 0x00; //清空当前计数值
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK(72MHz),启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,
* @retval 无
*/
void Delay_ms(uint32_t xms)//以微秒为基准
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,
* @retval 无
*/
void Delay_s(uint32_t xs)//以毫秒为基准
{
while(xs--)
{
Delay_ms(1000);
}
}
uint8_t KeyNum=0;//全局变量用于储存按键状态
uint8_t key()//按键识别函数
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==1)//判断按键是否按下
{
Delay_ms(20);//延时20ms,防止误判
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==1);//维持按下的状态
Delay_ms(20);//按键松开,消抖
KeyNum=!KeyNum;//取反,刷新按键标志位刷新0-1-0-1
}
return KeyNum;//返回按键状态
}
void Gpio_init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//启用GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure1;//创建GPIO初始化结构体
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_Out_PP;//配置模式-推挽输出
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_0; //指定相应引脚 GPIOA0
GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;//输出速度
GPIO_Init(GPIOA, &GPIO_InitStructure1);//初始化GPIOA,初始化完成,GPIOA0默认为高电平
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//将GPIOA0变为低电平
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//启用GPIOB的时钟
GPIO_InitTypeDef GPIO_InitStructure2;//创建GPIO初始化结构体
GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_IPD;//配置模式-上拉输入模式
GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_1; //指定相应引脚 GPIOA1
GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;//输出速度
GPIO_Init(GPIOA, &GPIO_InitStructure2);//初始化GPIOB
}
int main(void)
{
Gpio_init();
while (1)
{
key();//检测按键
if(key() == 0)//判断状态
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);//将GPIOA0置高电平
}
if(key() == 1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//将GPIOA0置低电平
}
}
}
2、按键
按键为什么要消抖:按键出现抖动(Bounce)主要是由于机械开关的物理特性所引起的。当按下或释放一个物理按键时,开关触点并不会立即稳定地接通或断开,而是会在接触瞬间产生多次快速的接通与断开,形成一系列的不稳定信号,这就是所谓的“按键抖动”。
常见的电子设计者使用的按键一般有两种,一种为两引脚的,一种为四引脚的。四引脚一般是对角连接,中间有条横线为分界,按下则对角导通。
![cd0d87caf8c75ec0dce253ca6ab122f3](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fraw.githubusercontent.com%2Fxiayexingkongsihai%2Fpicgo%2Fmain%2F202407051745194.jpg&pos_id=img-FARtICdN-1720175164943%29)
按键抖动的时间一般为20ms左右,按下和松开都有抖动时间,所以基础的按键消抖可以通过简单的延时函数进行消抖,但是也有一些弊端来源于延时函数。还有其他消抖方法如硬件消抖(RC滤波电路、触发器等)、软件消抖(定时器消抖)等,此处不做介绍,后面学习后再补充。
3、延时函数
void Delay_us(uint32_t xus)
{
SysTick->VAL = 0x00; //清空当前计数值
SysTick->LOAD = 72 * xus; //设置定时器重装值,系统的频率是72MHZ,72*xus即 72*xus/72*10^6 即微秒
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK(72MHz),启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0,while循环,只有循环结束才会执行别的代码
SysTick->CTRL = 0x00000004; //关闭定时器
}
System Tick是ARM Cortex-M系列微控制器中的一个定时器,主要用于提供一个可编程的周期性中断。它本质上是一个递减计数器,能够以固定的频率产生中断,常用于实现延迟、轮询、RTOS(实时操作系统)的任务调度以及其他需要定时的应用场景。
SysTick定时器的寄存器包括:
- CTRL:控制和状态寄存器,用于开启/关闭定时器,设置时钟源,以及读取中断状态。
- LOAD:重载值寄存器,用于设置计数器的重载值,即计数器到达0后会重新加载的值。
- VAL:当前值寄存器,显示计数器当前的值。
- CALIB:校准寄存器,包含一个预设的值,用于计算SysTick定时器的精度。
使用延时函数占用CPU资源,极易造成程序阻塞,由于延时函数简单,便于使用,在入门学者普遍使用,但是要记得,延时函数有时会和中断造成冲突,造成程序卡死现象。
算SysTick定时器的精度。
使用延时函数占用CPU资源,极易造成程序阻塞,由于延时函数简单,便于使用,在入门学者普遍使用,但是要记得,延时函数有时会和中断造成冲突,造成程序卡死现象。
在Cortex-M3权威指南和编辑手册中有详细有关systick的冲突问题和寄存器讲解和举例,本人能力有限不做赘述。