炒冷饭系列-STM32F103之电容按键

淦,搞了好久,这逻辑我理解不了啊啊啊啊啊

#include "stm32f10x.h"
#include "LED.h"
#include "delay.h"
#include "tim.h"
#include "usart.h"
#include "icap.h"

void tpadHandler(uint16_t prer,uint16_t value);
void tpadInitVal(void);
u16 TPAD_Get_Val(void);
void TPAD_Reset();
u16 TPAD_Get_MaxVal(u8 n);
//u8 TPAD_Scan();
u8 TPAD_Scan(u8 mode);

u16 TPAD_ARR_MAX_VAL=0xFFFF;

int main(void)
{	
	u8 t=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init();	    	 //延时函数初始化
	LED_Init();
	uart_init(115200);	 //串口初始化为115200
	
	tpadHandler(6-1,TPAD_ARR_MAX_VAL);
	tpadInitVal();
	while(1)
	{
 		if(TPAD_Scan(0))
		{
			LED0=~LED0;		//LED0取反
		}
		t++;
		if(t==15)
		{
			t=0;
			LED1=~LED1;
		}
		delay_ms(10);
	}
}

//定时器、捕获初始化
void tpadHandler(uint16_t prer,uint16_t value)
{
	
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;

	
	//1、时钟使能 TIM5时钟  GOIPA时钟		PA1->TIM5_CH2
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	
	//2、GPIOA1口的配置
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;// GPIO_Mode_IPD   GPIO_Mode_IN_FLOATING
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//3、TIM5配置
	TIM_TimeBaseInitStruct.TIM_Prescaler=prer;//给TIM时钟分频:范围0x0000~0xFFFF=0~65535,对应预分频寄存器:TIMx->PSC
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数模式:有5种,对应控制寄存器1:TIM_CR1_DIR位4 | TIM_CR1_CMS位[6:5]
	TIM_TimeBaseInitStruct.TIM_Period=value;//自动重装载值:0x0000 and 0xFFFF 对应自动重装载值寄存器:TIMx->ARR
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//TIM_CKD_DIV1//APB1时钟36MHz  分频72MHz    给APB1时钟分频:1,2,4 ,对应控制寄存器1:TIM_CR1_CKD位[9:8]
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStruct);
	
	//4、TIM5输入比较参数配置
	TIM_ICInitStruct.TIM_Channel=TIM_Channel_2;//TIM5_CH2->PA1
	TIM_ICInitStruct.TIM_ICFilter= 0x03;//配置输入滤波器 8 个定时器时钟周期滤波
	TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;//输 入 信 号 的 有 效 捕 获 极 性
	TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;//
	TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;//配置 IC1 直接映射在 TI1 上
	TIM_ICInit(TIM5,&TIM_ICInitStruct);
	
	
	//6、更新中断、捕获中断
	//TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1,ENABLE);
	
	//7、使能TIM5定时器
	TIM_Cmd(TIM5,ENABLE);
}

//原理:没有按下时充电所需要的时间  对比 按下时充电所需要的时间(时间长)

//计算重启后(按键还没按下)充电所需要的时间(需要精确的获取到)
vu16 tpad_default_val=0;//计算重启后(按键还没按下)充电所需要的时间(需要精确的获取到)
void tpadInitVal(void)
{
	u16	buf[10];
	u16 temp=0;
	u8 k=0;
	int i=0;
	int j=0;
	int h=0;
	//不断的充放电来获取10次时间
	for(h=0;h<=10;h++)
	{
		buf[h]=TPAD_Get_Val();
		delay_ms(10);
	}
	
	//将这10个值进行冒泡排序,为了去掉最大最小值
	for(i=0;i<10;i++)
	{
		for( j=i+1;j<10;j++)
		{
			if(buf[i]<buf[j])
			{
				u16 temp1=0;
				temp1=buf[i];
				buf[i]=buf[j];
				buf[j]=temp1;
			}
		}
	}
	
	
	for(k=2;k<8;k++)//取中间的六个值
	{
		temp+=buf[k];
	}
	tpad_default_val=temp/6;//精确计算重启后充电所需要的时间(全局变量) 
	printf("tpad_default_val:%d\r\n",tpad_default_val);	//计算重启后充电所需要的时间    	    	
}

//得到定时器捕获值
//如果超时,则直接返回定时器的计数值.

u16 TPAD_Get_Val(void)
{	
	TPAD_Reset();
	while(TIM_GetFlagStatus(TIM5,TIM_IT_CC2 ))//等待充电完成,出现上升沿
	{
		if(TIM_GetCounter(TIM5)>=TPAD_ARR_MAX_VAL-500)//如果超时,就返回计数器(CNT)的值
		{
			return TIM_GetCounter(TIM5);
		}
	}
	return TIM_GetCapture2(TIM5);//返回捕获值
}

//不断的放电和充电
void TPAD_Reset()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
		//1、时钟使能 TIM5时钟  GOIPA时钟		PA5->TIM5_CH2
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//2、GPIOA5口的配置
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;// 放电,推挽输出低电平
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);//输出低电平,电容放电
	
	delay_ms(10);//等待放电完成
	
	TIM_SetCounter(TIM5, 0);//设置定时器的值为 0,为计算充电时间做准备
	TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中断标志
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;// 放电,浮空输入
	GPIO_Init(GPIOA,&GPIO_InitStruct);
}

扫描触摸按键
返回值:0,没有按下;1,有按下;										  
//#define TPAD_GATE_VAL 	100	//触摸的门限值,也就是必须大于tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.
//u8 TPAD_Scan()
//{
//	u8 res=0;//没有按下时为0,按下为1;
//	
//	u8 max_val=TPAD_Get_MaxVal(5);
//	if(max_val>tpad_default_val+TPAD_GATE_VAL)
//	{
//		res=1;
//		return res;
//	}
//	
//	return res;
//}


//扫描触摸按键
//mode:0,不支持连续触发(按下一次必须松开才能按下一次);1,支持连续触发(可以一直按下)
//返回值:0,没有按下;1,有按下;										  
#define TPAD_GATE_VAL 	100	//触摸的门限值,也就是必须大于tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.
u8 TPAD_Scan(u8 mode)
{
	static u8 keyen=0;	//0,可以开始检测;>0,还不能开始检测	 
	u8 res=0;
	u8 sample=3;		//默认采样次数为3次	 
	u16 rval;
	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,有效
	{							 
		if(keyen==0)res=1;		//keyen==0,有效 
		//printf("r:%d\r\n",rval);		     	    					   
		keyen=3;				//至少要再过3次之后才能按键有效   
	} 
	if(keyen)keyen--;		   							   		     	    					   
	return res;
}	

//采样5次获取最大值
u16 TPAD_Get_MaxVal(u8 n)
{
	u16 temp=0;
	u16 res=0;
	while(n--)
	{
		temp=TPAD_Get_Val();
		if(temp>res)
		{
			res=temp;
		}
	}
	return res;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值