历史上的今天
今天是:2024年09月29日(星期日)
2018年09月29日 | STM32f4---电容触摸按键实验代码(02)
2018-09-29 来源:eefocus
//定时器 2通道2 输入捕获配置
//arr:自动重装值
//psc:时钟预分频数
void TIM2_CH1_Cap_Init(u32 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM2_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //TIM2时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2); //PA5复用位定时器2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //GPIOA5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//速度 100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不带上下拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA5
//初始化 TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 初始化定时器2
//初始化通道 1
TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1映射到TIM2
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC2F=0000 配置输入滤波器 不滤波
TIM_ICInit(TIM2, &TIM2_ICInitStructure);//初始化 TIM2 IC1
TIM_Cmd(TIM2,ENABLE ); //使能定时器 2
}
此部分代码包含 6 个函数,我们将介绍其中 4 个比较重要的函数:TIM2_CH1_Cap_Init、TPAD_Get_Val、TPAD_Init和 TPAD_Scan。
首先介绍TIM2_CH1_Cap_Init函数,该函数和上一章的输入捕获函数基本一样,不同的是,这里我们设置的是 TIM2 上一章是 TIM5。通过该函数的设置,我们将可以捕获 PA5 上的上升沿,同样TIM2也是 32 位定时器。
我们再来看看 TPAD_Get_Val 函数,该函数用于得到定时器的一次捕获值。该函数先调用TPAD_Reset,将电容放电,同时设置通过调用函数TIM_SetCounter(TIM2,0)将计数值TIM2_CNT设置为 0,然后死循环等待发生上升沿捕获(或计数溢出),将捕获到的值(或溢出值)作为返回值返回。
接着我们介绍 TPAD_Init 函数,该函数用于初始化输入捕获,并获取默认的 TPAD 值。该函数有一个参数,用来传递系统时钟,其实是为了配置 TIM2_CH1_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则是我们设定的一个门限值(这个大家可以通过实验数据得出,根据实际情况选择适合的值就好了),这里我们设置为 100。该函数,我们还做了一些其他的条件限制,
让触摸按键有更好的效果,这个就请大家看代码自行参悟了。
tpad.h 头文件部分代码比较简单,这里不做介绍。
接下来我们看看主函数代码如下:
int main(void)
{
u8 t=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
LED_Init(); //初始化 LED
TPAD_Init(8); //初始化触摸按键,以 84/4=21Mhz频率计数
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(8)函数执行之后,就开始触摸按键的扫描,当有触摸的时候,对DS1 取反,而DS0 则有规律的间隔取反,提示程序正在运行。注意在修改main函数之后,还需要在main.c里面添加tpad.h头文件,否则会报错哦。
这里还要提醒一下大家,不要把uart_init(115200);去掉,因为在TPAD_Init函数里面,我们有用到 printf,如果你去掉了uart_init,就会导致printf无法执行,从而死机。
至此,我们的软件设计就完成了。
史海拾趣
|
本帖最后由 paulhyde 于 2014-9-15 09:30 编辑 各赛区组委会、各参赛学校: 为进一步规范竞赛组织工作、加强竞赛的公正公平性,全国竞赛组委会决定,2009年全国大学生电子设计竞赛采用网上发题方式,在9月2日开赛时依托数个网站进行竞赛题目下 ...… 查看全部问答> |
|
据国外媒体报道,一家超强的山寨厂最近设计出一种令人匪夷所思的手机,它包含一个点烟器,可以通过隐藏在摄像头孔中的点烟器点香烟。 当然,这上去是个点烟器,实际上也是一台手机,它拥有2.5英寸触摸屏,3波段GSM,支持双SIM卡,还有130万像素摄 ...… 查看全部问答> |
|
学“TI精品讲堂第一课”有感!(感慨多多问题多多,希望各位大神帮忙解答) 刚才学习了TI精品讲堂第一课,感触多多!(帖子没发错位置吧,为节省大家时间下面重点会用加粗加大表示,解答问题的大神可以直接到最后)1课堂设计的界面很不错,河蟹简洁。。。但是为啥不能用chrome浏览器呀!2那位大神(演讲那个叫什么忘了)耐心 ...… 查看全部问答> |
|
我在用MSP430编程给GPRS模块AT指令的时候,GPRS模块会返回比如“OK\"返回值,那么,我想在编程中检测到”ok\"后再进行下一条命令传输,我从哪个寄存器中去检测“ok\"呢?… 查看全部问答> |
|
请问各位大神,ADS1115的通道选择是怎么控制的啊,用AIN四个引脚怎么学配置呢?ADDR和ALERT/RDY引脚是怎么用的?加参考电压应该怎么加啊?转换之后的数据该怎么算呢?(全都选择默认设置:confige register:0x84和0x83)请求各位大神的帮助! … 查看全部问答> |




