历史上的今天
今天是:2025年03月25日(星期二)
2019年03月25日 | STM32CubeMX学习教程之三:GPIO输入之利用SysTick中断给按键去抖
2019-03-25 来源:eefocus
本文主要讨论软件去抖。实现方法是通过SysTick中断每1ms对按键进行扫描,当检测到连续的稳定无抖动电平信号(长度可设置)之后,才进行相应的逻辑操作。
软件版本:
STM32CubeMX V4.25.0
System Workbench V2.4
硬件:OneNet 麒麟座V2.3
在STM32CubeMX中新建项目,选择正确的MCU型号

然后设置RCC和SYS,然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M)


然后设置GPIO_Output (连接到LED) 和GPIO_Input(连接到按键)。注意上一篇文章里面按键连接的引脚设置为外部中断模式,这里只需要设置为GPIO_Input就可以了。

GPIO_Output的具体设置如下:

GPIO_Input设置如下

这里按键我用了SW1/2/3/4。
同样修改
Project - setting ,ToolChain/IDE选择 SW4STM32

还要勾选这里

然后生成代码,打开项目。
编辑stm32f1xx_it.h,函数声明那里增加一行 :
void Key_Scan(void);
然后编辑stm32f1xx_it.c 增加如下代码:
/* USER CODE BEGIN 0 */
uint8_t sw1Count,sw2Count,sw3Count,sw4Count;
uint8_t pushFlag1,pushFlag2,pushFlag3,pushFlag4;
extern uint8_t swState1,swState2,swState3,swState4;
void Key_Scan(void)
{
/*检测SW1是否按下 */
if( HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET )
{
sw1Count++; //SW1键按下,计数sw1Count加1
if(sw1Count>=32) //1MS中断一次,sw1Count大于等于32,即按键已按下32ms
{
if(pushFlag1==0) //判断有没有重按键,1为有,0为没有
{
swState1=1; //设置按键标志
sw1Count=0;
pushFlag1=1; //设置重按键标志
}
else
sw1Count=0;
}
else
swState1=0;
}
else //无按键按下
{
sw1Count=0; //清零sw1Count
swState1=0; //清除按键标志
pushFlag1=0; //清除重按键标志
}
/*检测SW2是否按下 */
if( HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET )
{
sw2Count++; //SW2键按下,计数sw2Count加1
if(sw2Count>=32) //1MS中断一次,sw2Count大于等于32,即按键已按下32ms
{
if(pushFlag2==0) //判断有没有重按键,1为有,0为没有
{
swState2=1; //设置按键标志
sw2Count=0;
pushFlag2=1; //设置重按键标志
}
else
sw2Count=0;
}
else
swState2=0;
}
else //无按键按下
{
sw2Count=0; //清零sw2Count
swState2=0; //清除按键标志
pushFlag2=0; //清除重按键标志
}
/*检测SW3是否按下 */
if( HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET )
{
sw3Count++; //SW3键按下,计数sw3Count加1
if(sw3Count>=32) //1MS中断一次,sw3Count大于等于32,即按键已按下32ms
{
if(pushFlag3==0) //判断有没有重按键,1为有,0为没有
{
swState3=1; //设置按键标志
sw3Count=0;
pushFlag3=1; //设置重按键标志
}
else
sw3Count=0;
}
else
swState3=0;
}
else //无按键按下
{
sw3Count=0; //清零sw3Count
swState3=0; //清除按键标志
pushFlag3=0; //清除重按键标志
}
/*检测SW4是否按下 */
if( HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET )
{
sw4Count++; //SW4键按下,计数sw4Count加1
if(sw4Count>=32) //1MS中断一次,sw4Count大于等于32,即按键已按下32ms
{
if(pushFlag4==0) //判断有没有重按键,1为有,0为没有
{
swState4=1; //设置按键标志
sw4Count=0;
pushFlag4=1; //设置重按键标志
}
else
sw4Count=0;
}
else
swState4=0;
}
else //无按键按下
{
sw4Count=0; //清零sw4Count
swState4=0; //清除按键标志
pushFlag4=0; //清除重按键标志
}
}
/* USER CODE END 0 */
然后在SysTick中断处理函数增加一行 void Key_Scan(void);, 代码如下:
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
Key_Scan();
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
在gpio.c 中增加如下两处代码:
/* USER CODE BEGIN 1 */
GPIO_TypeDef* GPIO_PORT[] = {LED1_GPIO_Port,
LED2_GPIO_Port,
LED3_GPIO_Port,
LED4_GPIO_Port};
const uint16_t GPIO_PIN[] = {LED1_Pin,
LED2_Pin,
LED3_Pin,
LED4_Pin};
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
void LED_Toggle(Led_TypeDef Led)
{
HAL_GPIO_TogglePin(GPIO_PORT[Led], GPIO_PIN[Led]);
}
/* USER CODE END 2 */
然后编辑main.c,增加如下两处代码:
/* USER CODE BEGIN 0 */
uint8_t swState1,swState2,swState3,swState4;
/* USER CODE END 0 */
/* USER CODE BEGIN WHILE */
while (1)
{
if ( swState1 == 1 )
{
LED_Toggle(LED1);
// HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_Delay(1);
}
if ( swState2 == 1 )
{
LED_Toggle(LED2);
// HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
HAL_Delay(1);
}
if ( swState3 == 1 )
{
LED_Toggle(LED3);
// HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
HAL_Delay(1);
}
if ( swState4 == 1 )
{
LED_Toggle(LED4);
// HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);
HAL_Delay(1);
}
/* USER CODE END WHILE */
注意 如下两个语句是等效的,我注释掉了HAL_GPIO_TogglePin()。因为我们使用枚举重新定义了LED状态切换的函数LED_Toggle()。
1. LED_Toggle(LED1);
2. HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
然后右键点击项目,选择Properties, Run-Debug Settings, 点击右侧的New,在弹出对话框中选择Ac6 STM32 Debugging。

然后任务栏上点击Run图,当然会报错的,原因请查看另一篇我的博客(https://blog.csdn.net/toopoo/article/details/79680323),所以需要右键点击 项目名Run.cfg ,给它改个名字,

然后右键点击项目树里面的项目名称,选择“Propeties”,然后在Run/Debug Settings-选择项目名-Edit-Main-C/C++Application那里点击“Search Project”,然后选择出现的默认的elf文件:

然后在Debugger-User Defined-Browse 那里选择你自己改名的配置文件:

然后右键点击那个新的cfg文件,选择"Open With - Text Editor", 进行如下更改:
source [find interface/stlink.cfg] 更改为 source [find interface/stlink-v2.cfg]
reset_config srst_only srst_nogate connect_assert_srst 这一行改为 reset_config none
然后再Run一下,就可以了。
就实现四个按键分别控制LED的开关切换并实现了软件去抖,不会产生误动作了。
下一篇:STM32Cube-定时器中断
史海拾趣
|
奥笙公司软件部门招聘信息(北京职位) 公司简介 奥笙时代科技(北京)有限公司(www.orpheusys.com) 是成立于2007年的高科技企业,位于中关村腹地才智大厦,毗邻北大、清华和中科院,本公司与中科院声学研究所建立了战略合作关系, ...… 查看全部问答> |
|
STC12C5A32S2这个片子,串口下载的时候,无法下载。出现以下提示 这个片子我按照厂家提供的下载电路搭建的,第一次下载成功了,再下载就无法下载了,上次下的程序还再执行,只要上上电就执行程序,就是不下载,我也按照顺序,先点下载然后再上电,还是不行,哪位给解决一下,谢谢。 Chinese:正在尝试与 MCU/单片 ...… 查看全部问答> |
|
要做个项目,以arm9为基础,控制器是别人开发的,提供接口给我们,我们负责应用程序的开发,自己做的程序需要查询mysql数据库,所以想把mysql集成到板子里去,想请教下这么做是否可行,可行的话要如何做,能推荐几本参考书?谢谢… 查看全部问答> |
|
看了David_Lee https://bbs.eeworld.com.cn/thread-303736-1-1.html 那Grace很不错,跟着他做了个实验,以前用的是CCS3.3,产生一个out 文件,要在file 里load program的,可现在的CCS4没有这个选择,只需要lauch TI debugger,可我的出现下面的 ...… 查看全部问答> |
|
步入社会,你每天要和形形色色的人打交道,在社会的每个角落,你都不可能是孤立的,你必须要通过与其他人合作完成自己的工作任务。如果你在公司里工作,那么,你是否具有团队精神,直接关系到你的业绩。一些大公司招聘人才时,十分注重人才的团 ...… 查看全部问答> |
|
由于资料比较大,附件传不上,只能用百度云分享给大家了。 百度云: http://pan.baidu.com/s/1sjsb76d 密码: a6uk 百度链接经常出问题,如以上链接不能访问请访问我的个人分析空间查找。 地址:http://pan.baidu.com/share/home? ... are#catego ...… 查看全部问答> |




