资讯详情

STM32——电容触摸按键实验

一、电容触摸按键原理

RC电路充放电原理:

R为电阻,CX为电容,按下按钮CX开始充电V1相同。

RC电路充放电公式:Vt=V0 (V1-V0)*[1-exp(-t/RC)]

V0是电容器上的初始电压值;V1.电容器最终可以充放的电压值;VtT时刻电容上的电压值;

当V0=公式简化为:0Vt=V1*[1-exp(-t/RC)]

也就是说,在相同的条件下,电容值C与时间t成正比。电容器越大,充电时间越长。(零状态响应)

电容触摸按键原理图:

R:充放电电阻的外部电容;Cs:TPAD和PCB杂散电容;Cx:按下手指时,手指和TPAD之间形成电容。 开关:电容放电开关由STM32IO口代替;

检测电容触摸按键过程:

1、TPAD引脚设置为推拉输出,输出0,实现电容放电到0。

2、TPAD引脚设置为浮空输入(IO电容器在复位后开始放电。

3、同时开启TPAD引脚的输入捕获开始捕获。

4.等充电完成(充电到底)Vx,检测到上升边)。

5.计算充电时间。

二、程序设计思路

重要函数:

1、void TPAD_Reset(void)函数:复位TPAD

设置IO口为推拉输出输出0,电容放电。放电完成后,设置为浮空输入,开始充电。同时,计数器CNT设置为0。

2、TPAD_Get_Val()函数:获得捕获值(充电时间)

复位TPAD,等待捕获上升沿,捕获后,获得定时器值,计算充电时间。

3、TPAD_Get_MaxVal()函数:

多次调用TPAD_Get_Val()函数获得充电时间,获得最大值。

4、TPAD_Init()函数:初始化TPAD

系统启动后,初始化输入捕获。先调用10次TPAD_Get_Val()函数获取10次充电时间,然后获取中间N(N=8或6)次的平均值作为没有电容触摸按钮的充电时间缺失值tpad_default_val。

5、TPAD_Scan()函数:扫描TPAD

调用TPAD_Get_MaxVal()函数获得多次充电中最大的充电时间和tpad_default_val如果大于某个值,则认为有触摸动作。

6、void TIM5_CH2_Cap_Init(u16 arr,u16 psc)函数:初始化输入捕获通道

任何定时器都可以使用,M3用定时器5,M4用定时器2。

 #define TPAD_ARR_MAX_VAL 0XFFFFFFFF vu16 tpad_default_val=0; u8 TPAD_Init(u8 psc) {   u16 buf[10];  u16 temp;  u8 i,j;  TIM2_CH1_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);  for(i=0;i<10;i  ){  buf[i]=TPAD_Get_Val();  delay_ms(10);  }  for(i=0;i<9;i  )  {  for(j=i 1;j<10;j  )   {   if(buf[i]>buf[j])   {   temp=buf[i];   buf[i]=buf[j];   buf[j]=temp;   }   }  }  temp=0;  for(i=2;i<8;i  )  temp =buf[i];  tpad_default_val=temp/6;  printf("tpad_default_val:%d\r\n",tpad_default_val);  if(tpad_default_val>TPAD_ARR_MAX_VAL/2) return 1;  return 0; } void TPAD_Reset(void) {  GPIO_InitTypeDef GPIO_InitABC;    GPIO_InitABC.GPIO_Mode=GPIO_Mode_OUT;  GPIO_InitABC.GPIO_OType=GPIO_OType_PP;  GPIO_InitABC.GPIO_Pin=GPIO_Pin_5;  GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_DOWN;  GPIO_InitABC.GPIO_Speed=GPIO_Speed_100MHz;   GPIO_Init(GPIOA,&GPIO_InitABC);  GPIO_ResetBits(GPIOA,GPIO_Pin_5);  delay_ms(5);  TIM_ClearITPendingBit(TIM2,TIM_IT_CC1|TIM_IT_Update);  TIM_SetCounter(TIM2,0);    GPIO_InitABC.GPIO_Mode=GPIO_Mode_AF;  GPIO_InitABC.GPIO_OType=GPIO_OType_PP;  GPIO_InitABC.GPIO_Pin=GPIO_Pin_5;  GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_NOPULL;  GPIO_InitABC.GPIO_Speed=GPIO_Speed_100MHz;  GPIO_Init(GPIOA,&GPIO_InitABC); }  u16 TPAD_Get_Val(void) {   TPAD_Reset();  while(TIM_GetFlagStatus(TIM2,TIM_IT_CC1)==RESET)   {   if(TIM_GetCounter(TIM2)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM2);  }  return TIM_GetCapture1(TIM2);   }  u16 TPAD_Get_MaxVal(u8 n) {  u16 temp=0;  u16 res=0;  while(n--)  {  if(temp>res) res=temp;  }  return res; } #define TPAD_GATE_VAL 100 u8 TPAD_Scan(u8 mode) {  static u8 keyen=0;    u8 res=0;  u8 sample=3;  u16 rval;  if(mode)  {   sample=6;   keyen=0;  }  rval=TPAD_Get_MaxVal(sample);   if(rval>(tpad_default_val TPAD_GATE_VAL)&&rval<(10*tpad_default_val))  {           if((keyen==0)&&(rval>(tpad_default_val TPAD_GATE_VAL)))   {    res=1;   }           keyen=3;  }   if(keyen)keyen--;                                     return res; }  void TIM2_CH1_Cap_Init(u32 arr,u16 psc) {  GPIO_InitTypeDef GPIO_InitABC;  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitABC;  TIM_ICInitTypeDef TIM_ICInitABC;     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2);    GPIO_InitABC.GPIO_Mode=GPIO_Mode_AF;  GPIO_InitABC.GPIO_OType=GPIO_OType_PP;  GPIO_InitABC.GPIO_Pin=GPIO_Pin_5;  GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_NOPULL;  GPIO_InitABC.GPIO_Speed=GPIO_Speed_100MHz;  GPIO_Init(GPIOA,&GPIO_InitABC);     TIM_TimeBaseInitABC.TIM_ClockDivision=TIM_CKD_DIV1;  TIM_TimeBaseInitABC.TIM_CounterMode=TIM_CounterMode_Up;  TIM_TimeBaseInitABC.TIM_Period=arr;  TIM_TimeBaseInitABC.TIM_Prescaler=psc;  TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitABC);    TIM_ICInitABC.TIM_Channel=IM_Channel_1;
	TIM_ICInitABC.TIM_ICFilter=0X00;
	TIM_ICInitABC.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitABC.TIM_ICPrescaler=TIM_ICPSC_DIV1;
	TIM_ICInitABC.TIM_ICSelection=TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM2,&TIM_ICInitABC);
	TIM_Cmd(TIM2,ENABLE);
}
int main(void)
{
  u8 t=0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_ms(168);
	uart_init(115200);
	LED_Init();
	TPAD_Init(8);
	while(1)
	{
	if(TPAD_Scan(0))
	{
	LED1=!LED1;
	}
	t++;
	if(t==15)
	{
	t=0;
	LED0=!LED0;
	}
	delay_ms(10);
	}
}

​

STM32电容触摸实验

标签: 判断电阻大小内接外接stm8电容stm电容触摸电容按钮开关电容的if电容16v代替10v

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台