stm32 stm32按键实验怎么工作,我明明上拉输入 ,为什么一烧入就两个小灯一起亮。

每一个优秀的人,都有一段沉默的时光。那一段时光,是付出了很多努力,忍受了很多的孤独和寂寞,不抱怨不诉苦,只有自己知道。而当日后说起时,连自己都能被感动的日子。...
STM32——按键
STM32——按键
宗旨:技术的学习是有限的,分享的精神是无限的。
一、GPIO工作模式
1、当I/O端口配置为输入时:
输出缓冲器被禁止
施密特触发输入被激活
根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接
出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
对输入数据寄存器的读访问可得到I/O状态
2、当I/O端口被配置为输出时:
输出缓冲器被激活
─ 开漏模式:输出寄存器上的’0’激活 N-MOS,而输出寄存器上的’1’将端口置于高阻状态(P-MOS 从不被激活)。
─ 推挽模式:输出寄存器上的’0’激活 N-MOS,而输出寄存器上的’1’将激活 P-MOS。
施密特触发输入被激活
弱上拉和下拉电阻被禁止
出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器
在开漏模式时,对输入数据寄存器的读访问可得到I/O状态
在推挽式模式时,对输出数据寄存器的读访问得到最后一次写的值。
二、库函数GPIO_ReadInputDataBit
typedef enum
Bit_RESET = 0,
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx, uint16_t GPIO_Pin) // 返回输入引脚电平的状态
uint8_t bitstatus = 0x00;
/*Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if((GPIOx-&IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
bitstatus = (uint8_t)Bit_SET; // 按键没被按下返回1
bitstatus = (uint8_t)Bit_RESET; // 按键按下返回0
}&span style="font-family: Arial, Helvetica, sans- background-color: rgb(255, 255, 255);"& &/span&
三、按键【消抖】
#ifndef _KEY_H_
#define _KEY_H_
#include "stm32f10x.h"
*按键按下标置
#define KEY_ON
#define KEY_OFF 1
void KeyGPIOConfig(void);
uint8_t KeyScan(GPIO_TypeDef *GPIOx, u16 GPIO_Pin);
#endif /* _KEY_H_ */#include "key.h"
void Delay(__IO u32 count)
while(count--);
void KeyGPIOConfig(void)
GPIO_InitTypeDef GPIO_InitS
/*开启按键端口(PE5)的时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // GPIO输入模式时,不用配置速率
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOE, &GPIO_InitStructure);
uint8_t KeyScan(GPIO_TypeDef* GPIOx, u16 GPIO_Pin)
/*检测是否有按键按下 */
if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON )
/*延时消抖*/
Delay(10000);
if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON )
/*等待按键释放 */
while(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON);
return KEY_OFF;
return KEY_OFF;
1、利用 GPIO_ReadInputDataBit() 读取输入数据,若从相应引脚读取得的数据等于 0 (KEY_ON),低电平,表明可能有按键按下,调用延时函数。否则返回 KEY_OFF,表示按键没有被按下。
2、 延时之后再次利用 GPIO_ReadInputDataBit() 读取输入数据,若依然为低电平,表明确实有按键被按下了。否则返回 KEY_OFF,表示按键没有被按下。
3、 循环调用 GPIO_ReadInputDataBit()一直检测按键的电平,直至按键被释放,被释放后,返回表示按键被按下的标志 KEY_ON。
没有更多推荐了,21ic官方微信-->
ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU
STM32输入捕获做的电容触摸按键功能
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
本帖最后由 zhangyang86 于
12:09 编辑
第十五章 电容触摸按键实验 上一章,我们介绍了STM32的输入捕获功能及其使用。这一章,我们将向大家介绍如何通过输入捕获功能,来做一个电容触摸按键。在本章中,我们将用TIM5的通道2(PA1)来做输入捕获,并实现一个简单的电容触摸按键,通过该按键控制DS1的亮灭。
15.1 电容触摸按键简介 触摸按键相对于传统的机械按键有寿命长、占用空间少、易于操作等诸多优点。大家看看如今的手机,触摸屏、触摸按键大行其道,而传统的机械按键,正在逐步从手机上面消失。本章,我们将给大家介绍一种简单的触摸按键:电容式触摸按键。我们将利用战舰STM32开发板上的触摸按键(TPAD),来实现对DS1的亮灭控制。这里TPAD其实就是战舰STM32开发板上的一小块覆铜区域,实现原理如图15.1.1所示:
图15.1.1 电容触摸按键原理& && & 这里我们使用的是检测电容充放电时间的方法来判断是否有触摸,图中R是外接的电容充电电阻,Cs是没有触摸按下时TPAD与PCB之间的杂散电容。而Cx则是有手指按下的时候,手指与TPAD之间形成的电容。图中的开关是电容放电开关(由实际使用时,由STM32的IO代替)。& && & 先用开关将Cs(或Cs+Cx)上的电放尽,然后断开开关,让R给Cs(或Cs+Cx)充电,当没有手指触摸的时候,Cs的充电曲线如图中的A曲线。而当有手指触摸的时候,手指和TPAD之间引入了新的电容Cx,此时Cs+Cx的充电曲线如图中的B曲线。从上图可以看出,A、B两种情况下,Vc达到Vth的时间分别为Tcs和Tcs+Tcx。& && & 其中,除了Cs和Cx我们需要计算,其他都是已知的,根据电容充放电公式:Vc=V0*(1-e^(-t/RC))& && & 其中Vc为电容电压,V0为充电电压,R为充电电阻,C为电容容值,e为自然底数,t为充电时间。根据这个公式,我们就可以计算出Cs和Cx。利用这个公式,我们还可以把战舰开发板作为一个简单的电容计,直接可以测电容容量了,有兴趣的朋友可以捣鼓下。& && & 在本章中,其实我们只要能够区分Tcs和Tcs+Tcx,就已经可以实现触摸检测了,当充电时间在Tcs附近,就可以认为没有触摸,而当充电时间大于Tcs+Tx时,就认为有触摸按下(Tx为检测阀值)。& && & 本章,我们使用PA1(TIM5_CH2)来检测TPAD是否有触摸,在每次检测之前,我们先配置PA1为推挽输出,将电容Cs(或Cs+Cx)放电,然后配置PA1为浮空输入,利用外部上拉电阻给电容Cs(Cs+Cx)充电,同时开启TIM5_CH2的输入捕获,检测上升沿,当检测到上升沿的时候,就认为电容充电完成了,完成一次捕获检测。在MCU每次复位重启的时候,我们执行一次捕获检测(可以认为没触摸),记录此时的值,记为tpad_default_val,作为判断的依据。在后续的捕获检测,我们就通过与tpad_default_val的对比,来判断是不是有触摸发生。关于输入捕获的配置,在上一章我们已经有详细介绍了,这里我们就不再介绍。至此,电容触摸按键的原理介绍完毕。 15.2 硬件设计 本实验用到的硬件资源有:1)&&指示灯DS0和DS12)&&定时器TIM53)&&触摸按键TPAD前面两个之前均有介绍,我们需要通过TIM5_CH2(PA1)采集TPAD的信号,所以本实验需要用跳线帽短接多功能端口(P14)的TPAD和ADC,以实现TPAD连接到PA1。如图15.2.1所示。
图 15.2.1 TPAD与STM32连接原理图硬件设置(用跳线帽短接多功能端口的ADC和TPAD即可)好之后,下面我们开始软件设计。
15.3 软件设计 前面讲解过,触摸按键我们是通过输入捕获实现的,所以使用的库函数依然是分布在stm32f10x_tim.c和stm32f10x_tim.h中。同时我们在HARDWARE组下面增加了tpad.c和tpad.h文件用来存放我们的触摸按键驱动代码。打开tpad.c可以看到,我们在tpad.c里输入了如下代码: #define TPAD_ARR_MAX_VAL 0XFFFF&&//最大的ARR值vu16 tpad_default_val=0;//空载的时候(没有手按下),计数器需要的时间//初始化触摸按键//获得空载的时候触摸按键的取值.//返回值:0,初始化成功;1,初始化失败u8 TPAD_Init(){& &u16 buf[10] ,& && & u8 j,i;//以1Mhz的频率计数& && & TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,SystemCoreClock/); & && & for(i=0;i&10;i++){& && && && & //连续读取10次& && && && &&&buf=TPAD_Get_Val();delay_ms(10);& && && &&&& && & }& && && && && && && && && && && && & for(i=0;i&9;i++)& && && && &&&//排序& && & {&&for(j=i+1;j&10;j++)& && && && &&&{&&if(buf&buf[j])& && & //升序排列& && && && && && && &{& &temp=buf;buf=buf[j];buf[j]=& && && && && && && &}& && && && &&&}& && & }& && & temp=0;& && & for(i=2;i&8;i++)temp+=buf;& &//取中间的8个数据进行平均& && & tpad_default_val=temp/6;& && & printf(&tpad_default_val:%d\r\n&,tpad_default_val);& & //初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常!& && & if(tpad_default_val&TPAD_ARR_MAX_VAL/2)return 1;& &return 0;& && && && && && && && & }//复位一次void TPAD_Reset(void){& && &GPIO_InitTypeDef&&GPIO_InitS & && & RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA时钟& && & //设置GPIOA.1为推挽使出& && &GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;& && && && && && && && && & //PA1 端口配置& && &GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;& && && && && && &&&//推挽输出& && &GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;& && &GPIO_Init(GPIOA, &GPIO_InitStructure);& && && && && && && & //初始化GPIOA.1& && &GPIO_ResetBits(GPIOA,GPIO_Pin_1);& && && && && && && && && && && && && && &//PA.1输出0,放电& && & delay_ms(5);& && && && && && && && && && && && && && && &&&//延时5ms& && & TIM_SetCounter(TIM5,0);& && && && && && && && && && && && && & //归0& && & TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update);& &&&//清除中断标志& && & GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;& && &//GPIOA.1浮空输入& && & GPIO_Init(GPIOA, &GPIO_InitStructure);}//得到定时器捕获值,如果超时,则直接返回定时器的计数值.u16 TPAD_Get_Val(void){& && && && && && && && && &&&& && & TPAD_Reset();& && & while(TIM_GetITStatus(TIM5, TIM_IT_CC2) != RESET)&&//等待溢出& && & {& && && && &&&if(TIM_GetCounter(TIM5)&TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);& && && && && && & //超时了,直接返回CNT的值& && & };& & & && & return TIM_GetCapture2(TIM5);& & }& && & //读取n次,取最大值u16 TPAD_Get_MaxVal(u8 n){& &u16 temp=0, res=0;& && & while(n--){& && && && &&&temp=TPAD_Get_Val(); //得到一次值& && && && &&&if(temp&res)res=& && & };& && &}&&//扫描触摸按键//mode:0,不支持连续触发(按下一次必须松开才能按下一次);1,支持连续触发(可以一直按)//返回值:0,没有按下;1,有按下;& && && && && && && && && && && && && && && && && && && && && && && &#define TPAD_GATE_VAL& &80& & //触摸的门限值,也就是必须大于//tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.u8 TPAD_Scan(u8 mode){& &static u8 keyen=0;& && && &//0,可以开始检测;&0,还不能开始检测&&& && & u8 res=0, sample=3;& && && && && && &&&//默认采样次数为3次& & & && & u16& && & if(mode){& && && && &&&sample=6;& && && && &&&//支持连按的时候,设置采样次数为6次& && && && &&&keyen=0;& && && && &//支持连按& && && && && & }& && & rval=TPAD_Get_MaxVal(sample); & && & if(rval&(tpad_default_val+TPAD_GATE_VAL))//大于//tpad_default_val+TPAD_GATE_VAL,有效& && & {& &&&rval=TPAD_Get_MaxVal(sample);& && && && &&&& && && && &&&if((keyen==0)&&(rval&(tpad_default_val+TPAD_GATE_VAL)))//大于//tpad_default_val+TPAD_GATE_VAL,有效& && && && &&&{ res=1;& && && && &&&}& && && && && && && && && && && && && && && && && && && && && && && && && && && &&&keyen=5;& && && && && &&&//至少要再过5次之后才能按键有效& && && & }else if(keyen&2)keyen=2; //如果检测到按键松开,则直接将次数将为2,以提高响应速度& && & if(keyen)keyen--;& && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && & & && &} //定时器2通道2输入捕获配置void TIM5_CH2_Cap_Init(u16 arr,u16 psc){& && & GPIO_InitTypeDef&&GPIO_InitS & &&&TIM_TimeBaseInitTypeDef&&TIM_TimeBaseS& && & TIM_ICInitTypeDef&&TIM5_ICInitS& && & RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);& &//使能TIM5时钟& && & RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);&&//使能PA时钟& && & //设置GPIOA.1为浮空输入& && & GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;& && && && && && && && && &&&//PA1 端口配置& && &GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;& && && &&&//速度50MHz& &&&GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;& && & //浮空输入& && & GPIO_Init(GPIOA, &GPIO_InitStructure);& && && && && && && & //初始化GPIOA.1
& &&&//初始化TIM5&&& && & TIM_TimeBaseStructure.TIM_Period =& && && && && &&&//设定计数器自动重装值& && && & TIM_TimeBaseStructure.TIM_Prescaler =& && && && && & //预分频器& && & & && & TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // TDTS = Tck_tim& && & TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;&&//向上计数模式& && & TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);& && & //根据参数初始化TIMx& && & //初始化TIM5通道2 & && &TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择输入端 IC2映射到TI5上& && &TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_R //上升沿捕获& && &TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; & && &TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;&&//配置输入分频,不分频 & && &TIM5_ICInitStructure.TIM_ICFilter = 0x03;//配置输入滤波器 8个定时器时钟周期滤波& && &TIM_ICInit(TIM5, &TIM5_ICInitStructure);//初始化I5 IC2
& & TIM_Cmd(TIM5,ENABLE );& && && && &&&//使能定时器5}此部分代码包含6个函数,我们将介绍其中4个比较重要的函数:TIM5_CH2_Cap_Init、TPAD_Get_Val、TPAD_Init和TPAD_Scan。首先介绍TIM5_CH2_Cap_Init函数,该函数和上一章的输入捕获函数基本一样,不同的是,这里我们设置的是CH2通道,并开启了输入滤波器。通过该函数的设置,我们将可以捕获PA1上的上升沿。关于配置的详细介绍大家可以看第15章输入捕获实验讲解。我们再来看看TPAD_Get_Val函数,该函数用于得到定时器的一次捕获值。该函数先调用TPAD_Reset,将电容放电,同时设置TIM5_CNT寄存器为0,然后死循环等待发生上升沿捕获(或计数溢出),将捕获到的值(或溢出值)作为返回值返回。接着我们介绍TPAD_Init函数,该函数用于初始化输入捕获,并获取默认的TPAD值。该函数有一个参数,用来传递系统时钟,其实是为了配置TIM5_CH2_Cap_Init为1us计数周期。在该函数中连续10次读取TPAD值,将这些值升序排列后取中间6个值再做平均(这样做的目的是尽量减少误差),并赋值给tpad_default_val,用于后续触摸判断的标准。 最后,我们来看看TPAD_Scan函数,该函数用于扫描TPAD是否有触摸,该函数的参数mode,用于设置是否支持连续触发。返回值如果是0,说明没有触摸,如果是1,则说明有触摸。该函数同样包含了一个静态变量,用于检测控制,类似第八章的KEY_Scan函数。所以该函数同样是不可重入的。在函数中,我们通过连续读取3次(不支持连续按的时候)TPAD的值,取这他们的最大值,和tpad_default_val+TPAD_GATE_VAL比较,如果大于则说明有触摸,如果小于,则说明无触摸。其中tpad_default_val是我们在调用TPAD_Init函数的时候得到的值,而TPAD_GATE_VAL则是我们设定的一个门限值(这个大家可以通过实验数据得出,根据实际情况选择适合的值就好了),这里我们设置为80。该函数,我们还做了一些其他的条件限制,让触摸按键有更好的效果,这个就请大家看代码自行参悟了。头文件tpad.h主要是函数申明,这里省略讲解。接下来,我们看看主程序里面的main函数如下:int main(void){& & & && &u8 t=0;& && && && && & delay_init();& && && && && & //延时函数初始化& && && && && & NVIC_Configuration();& && && &//设置NVIC中断分组2:2位抢占优先级,2位响应优先级& && & uart_init(9600);& && && & //串口初始化波特率为9600& && &LED_Init();& && && && && && &//LED端口初始化& && &TPAD_Init();& && && && && & //初始化触摸按键& &&&while(1)& && & {& && && && && && && && && && && && && && && && && && && && && && && && && && && && && & & && && && & if(TPAD_Scan(0))&&//成功捕获到了一次上升沿(此函数执行时间至少15ms)& && && && &&&{& && && && && && && &LED1=!LED1; //LED1取反& && && && &&&}& && && && &&&t++;& && && && &&&if(t==15)& && &&&& && && && &&&{& &t=0;& && && && && && && &LED0=!LED0; //LED0取反,提示程序正在运行& && && && &&&}& && && && &&&delay_ms(10);& && & }}该main函数比较简单,TPAD_Init()函数执行之后,就开始触摸按键的扫描,当有触摸的时候,对DS1取反,而DS0则有规律的间隔取反,提示程序正在运行。这里还要提醒一下大家,不要把uart_init(9600);去掉,因为在TPAD_Init函数里面,我们有用到printf,如果你去掉了uart_init,就会导致printf无法执行,从而死机。 至此,我们的软件设计就完成了。15.4 下载验证 在完成软件设计之后,将我们将编译好的文件下载到战舰STM32开发板上,可以看到DS0慢速闪烁,此时,我们用手指触摸ALIENTEK战舰STM32开发板上的TPAD(右下角的LOGO标志),就可以控制DS1的亮灭了。不过你要确保TPAD和ADC的跳线帽连接上了!如图15.4.1所示:
图15.4.1 触摸区域和跳线帽短接方式同时大家可以打开串口调试助手,每次复位的时候,会收到tpad_default_val的值,一般为70左右,根据15.1节提到的公式,我们可以计算出Cs的容值 为27pF左右。& && && && && && && && && && && &
本帖子中包含更多资源
才可以下载或查看,没有帐号?
高级技术员, 积分 916, 距离下一级还需 84 积分
高级技术员, 积分 916, 距离下一级还需 84 积分
高级技术员, 积分 916, 距离下一级还需 84 积分
高级技术员, 积分 916, 距离下一级还需 84 积分
分享学习了。
实习生, 积分 12, 距离下一级还需 38 积分
实习生, 积分 12, 距离下一级还需 38 积分
实习生, 积分 12, 距离下一级还需 38 积分
实习生, 积分 12, 距离下一级还需 38 积分
实习生, 积分 3, 距离下一级还需 47 积分
实习生, 积分 3, 距离下一级还需 47 积分
实习生, 积分 3, 距离下一级还需 47 积分
实习生, 积分 3, 距离下一级还需 47 积分
看看呗~~~~
助理工程师, 积分 1073, 距离下一级还需 927 积分
助理工程师, 积分 1073, 距离下一级还需 927 积分
助理工程师, 积分 1073, 距离下一级还需 927 积分
助理工程师, 积分 1073, 距离下一级还需 927 积分
好,学习了。
实习生, 积分 34, 距离下一级还需 16 积分
实习生, 积分 34, 距离下一级还需 16 积分
实习生, 积分 34, 距离下一级还需 16 积分
实习生, 积分 34, 距离下一级还需 16 积分
不错 good!
实习生, 积分 5, 距离下一级还需 45 积分
实习生, 积分 5, 距离下一级还需 45 积分
实习生, 积分 5, 距离下一级还需 45 积分
实习生, 积分 5, 距离下一级还需 45 积分
这个很好,正要做这方面的东西呢,学习了!!!!!!
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
egren 发表于
这个很好,正要做这方面的东西呢,学习了!!!!!!
实习生, 积分 45, 距离下一级还需 5 积分
实习生, 积分 45, 距离下一级还需 5 积分
实习生, 积分 45, 距离下一级还需 5 积分
实习生, 积分 45, 距离下一级还需 5 积分
看了很有用,请问下楼主,我现在用的板子上自带了触摸按键,可是连接的引脚没有复用定时器捕获的功能,请问怎么实现这个呢?
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
中级工程师, 积分 3376, 距离下一级还需 1624 积分
Eurekaseven 发表于
看了很有用,请问下楼主,我现在用的板子上自带了触摸按键,可是连接的引脚没有复用定时器捕获的功能,请问 ...
有的。你可以看看
实习生, 积分 9, 距离下一级还需 41 积分
实习生, 积分 9, 距离下一级还需 41 积分
实习生, 积分 9, 距离下一级还需 41 积分
实习生, 积分 9, 距离下一级还需 41 积分
楼主英勇。。我按例子增加了一个电容按键。配置是相同的。问题是扫描什么的是如何配。。求教。。
助理工程师, 积分 1340, 距离下一级还需 660 积分
助理工程师, 积分 1340, 距离下一级还需 660 积分
助理工程师, 积分 1340, 距离下一级还需 660 积分
助理工程师, 积分 1340, 距离下一级还需 660 积分
初级工程师, 积分 2659, 距离下一级还需 341 积分
初级工程师, 积分 2659, 距离下一级还需 341 积分
初级工程师, 积分 2659, 距离下一级还需 341 积分
初级工程师, 积分 2659, 距离下一级还需 341 积分
0x2系列的触摸更爽一些啊
资深技术员, 积分 326, 距离下一级还需 174 积分
资深技术员, 积分 326, 距离下一级还需 174 积分
资深技术员, 积分 326, 距离下一级还需 174 积分
资深技术员, 积分 326, 距离下一级还需 174 积分
很有參考價值, 講得很透徹
初级技术员, 积分 96, 距离下一级还需 4 积分
初级技术员, 积分 96, 距离下一级还需 4 积分
初级技术员, 积分 96, 距离下一级还需 4 积分
初级技术员, 积分 96, 距离下一级还需 4 积分
扫描二维码,随时随地手机跟帖
技术奇才奖章
人才类勋章
甘甜之泉水
发帖类勋章
时间类勋章
希望之星奖章
等级类勋章
技术新星奖章
人才类勋章
时间类勋章
涓涓之细流
发帖类勋章
时间类勋章
技术高手奖章
人才类勋章
时间类勋章
时间类勋章
您需要登录后才可以回帖业精于勤荒于嬉,行成于思毁于随。
嵌入式系统学习——STM32之按键输入
  之前写了两篇关于STM32 GPIO的介绍和运用,跑马灯用到了GPIO的推挽输出,但是对于输入还是没有用到,这次就运用一下GPIO的上拉输入。实验还是和以前51做的实验一样,就是判断按键的输入,然后控制LED灯。这次没有直接配置寄存器,而是调用库函数和位操作结合。
注:每一块开发板对应电路都不相同,编写代码需要对应自己的板子,本人两个LED灯对应的GPIO为:GPIOD13和GPIOD14,并且是共阴极。两个按键对应的GPIO为:GPIOC13和GPIOE0,并且共阴极。
首先,LED初始化和上一篇博客中的跑马灯初始化一样,只需拷贝就可以了。
LED初始化函数:
#include "sys.h"
#define LED1 PDout(13)// PB13
#define LED2 PDout(14)// PB14
void LED_Init(void)
GPIO_InitTypeDef GPIOINIT;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
GPIOINIT.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOINIT.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIOINIT.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIOINIT);
GPIO_ResetBits(GPIOD, GPIO_Pin_13 | GPIO_Pin_14);
按键输入最关键的是对按键的初始化和输入判断。这里按键的初始化与LED的初始化不同的是GPIO的模式不一样了,LED是推挽输出,按键则相反,是输入,这个时候要考虑是哪一种输入方式,这里我的板子上按键是共阴极的,所以当按键按下的时候IO口输入的低电平,所以我需要在IO口接上拉电阻,使用上拉输入模式。
按键初始化函数:
#include "stm32f10x.h"
#define KEY0 GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)
//读取GPIOC13的输入
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_0)
//读取GPIOE0的输入
#define KEY0_PRESS 1
#define KEY1_PRESS
void KEY_Init(void)
GPIO_InitTypeDef GPIOI
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE, ENABLE);
GPIOInit.GPIO_Mode = GPIO_Mode_IPU;
GPIOInit.GPIO_Pin = GPIO_Pin_13;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIOInit);
GPIOInit.GPIO_Mode = GPIO_Mode_IPU;
//上拉输入
GPIOInit.GPIO_Pin = GPIO_Pin_0;
GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIOInit);
对于按键输入来说,怎么判断是连续按,还是不连续按,这是一个重点。以前是将两种情况分开考虑,写成了两个函数,然后判断,其实,这个可以写成一个函数,只需添加一个选择形参,然后对形参进行判断操作即可。
按键输入函数:
//按键处理函数
//返回按键值
//mode:0不支持连续按;1支持连续按
//0,没有按键按下
//1,key0按下
//2,key1按下
unsigned char KEY_Scan(unsigned char mode)
static unsigned char key_up = 1;
//按键松开标志
key_up = 1;
//支持连续按
if(key_up && (KEY0 == 0 || KEY1 == 0))
delay_ms(10);
key_up = 0;
if(KEY0 == 0)
return KEY0_PRESS;
else if(KEY1 == 0)
return KEY1_PRESS;
else if(KEY0 == 1 && KEY1 == 1)
key_up = 1;
//无按键按下
#include "led.h"
#include "key.h"
#include "stm32f10x.h"
#include "delay.h"
int main(void)
LED_Init();
delay_init();
KEY_Init();
key = KEY_Scan(0);
if(key == 1)
LED1=!LED1;
else if(key == 2)
LED3=!LED3;
delay_ms(10);
STM32(二)之GPIO操作(2)——通过按键控制LED灯的开关
stm32-独立按键
STM32入门之旅(第三天)-------按键电路、时钟体系
STM32F103(按键控制流水灯方向)
stm32按键输入
stm32下状态机编程按键
STM32按键控制灯
STM32入门开发--按键模块实现按键点灯
STM32之GPIO按键实验
STM32按键程序
没有更多推荐了,

我要回帖

更多关于 stm32用在哪些地方 的文章

 

随机推荐