淦,搞了好久,这逻辑我理解不了啊啊啊啊啊
#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;
}