239 lines
5.9 KiB
C
239 lines
5.9 KiB
C
/**
|
||
******************************************************************************
|
||
* @file bsp_touchpad.c
|
||
* @author fire
|
||
* @version V1.0
|
||
* @date 2015-xx-xx
|
||
* @brief 电容按键应用函数接口
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* 实验平台:野火 STM32 H750 开发板
|
||
* 论坛 :http://www.firebbs.cn
|
||
* 淘宝 :https://fire-stm32.taobao.com
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
#include "./touch_pad/bsp_touchpad.h"
|
||
#include "./delay/core_delay.h"
|
||
|
||
TIM_HandleTypeDef TIM_Handle;
|
||
//保存没按下时定时器计数值
|
||
__IO uint16_t tpad_default_val=0;
|
||
//定时器最大计数值
|
||
#define TPAD_ARR_MAX_VAL 0XFFFF
|
||
//阈值:捕获时间必须大于(tpad_default_val + TPAD_GATE_VAL),才认为是有效触摸.
|
||
#define TPAD_GATE_VAL 100
|
||
/**
|
||
* @brief 电容按键放电函数
|
||
* @param 无
|
||
* @retval 无
|
||
*/
|
||
static void TPAD_Reset(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
//配置引脚为普通推挽输出
|
||
GPIO_InitStructure.Pin = TPAD_TIM_CH_PIN;
|
||
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
|
||
HAL_GPIO_Init(TPAD_TIM_CH_PORT, &GPIO_InitStructure);
|
||
|
||
//输出低电平,放电
|
||
HAL_GPIO_WritePin(TPAD_TIM_CH_PORT, TPAD_TIM_CH_PIN ,GPIO_PIN_RESET);
|
||
//保持一小段时间低电平,保证放电完全
|
||
HAL_Delay(5);
|
||
|
||
//清除更新标志
|
||
__HAL_TIM_CLEAR_FLAG(&TIM_Handle,TIM_FLAG_CC1);
|
||
__HAL_TIM_CLEAR_FLAG(&TIM_Handle,TIM_FLAG_UPDATE);
|
||
//计数器归0
|
||
__HAL_TIM_SET_COUNTER(&TIM_Handle,0);
|
||
//引脚配置为复用功能,不上、下拉
|
||
GPIO_InitStructure.Pin = TPAD_TIM_CH_PIN;
|
||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||
GPIO_InitStructure.Alternate = TPAD_TIMx_AF;
|
||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||
HAL_GPIO_Init(TPAD_TIM_CH_PORT,&GPIO_InitStructure);
|
||
}
|
||
|
||
/**
|
||
* @brief 定时器TIMx初始化函数
|
||
* @param 无
|
||
* @retval 无
|
||
*/
|
||
void TIM_Mode_Config(void)
|
||
{
|
||
TIM_IC_InitTypeDef TIM_IC_Config;
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
||
TPAD_TIM_CLK_ENABLE();
|
||
TPAD_TIM_GPIO_CLK_ENABLE();
|
||
|
||
//端口配置
|
||
GPIO_InitStructure.Pin = TPAD_TIM_CH_PIN;
|
||
//复用功能
|
||
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||
GPIO_InitStructure.Alternate = TPAD_TIMx_AF;
|
||
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
|
||
//不带上下拉
|
||
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||
HAL_GPIO_Init(TPAD_TIM_CH_PORT, &GPIO_InitStructure);
|
||
|
||
TIM_Handle.Instance = TPAD_TIMx;
|
||
TIM_Handle.Init.RepetitionCounter = 0;
|
||
|
||
TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||
TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||
TIM_Handle.Init.Period = TPAD_ARR_MAX_VAL;
|
||
//设定定时器预分频器目标时钟为:9MHz(240Mhz/26)
|
||
TIM_Handle.Init.Prescaler = 27 - 1;
|
||
|
||
HAL_TIM_IC_Init(&TIM_Handle);
|
||
|
||
TIM_IC_Config.ICFilter = 0;
|
||
TIM_IC_Config.ICPolarity = TIM_ICPOLARITY_RISING;
|
||
TIM_IC_Config.ICPrescaler = TIM_ICPSC_DIV1;
|
||
TIM_IC_Config.ICSelection = TIM_ICSELECTION_DIRECTTI;
|
||
HAL_TIM_IC_ConfigChannel(&TIM_Handle, &TIM_IC_Config, TPAD_TIM_Channel_X);
|
||
|
||
//启动TIM
|
||
HAL_TIM_IC_Start(&TIM_Handle, TPAD_TIM_Channel_X);
|
||
}
|
||
/**
|
||
* @brief 获取定时器捕获值
|
||
* @param 无
|
||
* @retval TIMx_CCRx寄存器值
|
||
*/
|
||
static uint16_t TPAD_Get_Val(void)
|
||
{
|
||
/* 先放电完全,并复位计数器 */
|
||
TPAD_Reset();
|
||
//等待捕获上升沿
|
||
while(__HAL_TIM_GET_FLAG(&TIM_Handle,TIM_FLAG_CC1) == RESET )
|
||
{
|
||
//超时了,直接返回CNT的值
|
||
if(__HAL_TIM_GET_COUNTER( &TIM_Handle)>TPAD_ARR_MAX_VAL-500)
|
||
return __HAL_TIM_GET_COUNTER(&TIM_Handle);
|
||
};
|
||
/* 捕获到上升沿后输出TIMx_CCRx寄存器值 */
|
||
return HAL_TIM_ReadCapturedValue(&TIM_Handle, TPAD_TIM_Channel_X);
|
||
}
|
||
/**
|
||
* @brief 进行n次采样,获取采样值中的最大值
|
||
* @param n:连续获取的次数
|
||
* @retval n次读数里面读到的最大读数值
|
||
*/
|
||
static uint16_t TPAD_Get_MaxVal(uint8_t n)
|
||
{
|
||
uint16_t temp=0;
|
||
uint16_t res=0;
|
||
while(n--)
|
||
{
|
||
temp=TPAD_Get_Val();//得到一次值
|
||
if(temp>res)res=temp;
|
||
};
|
||
return res;
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化触摸按键函数
|
||
* @note 获得空载的时候触摸按键的取值
|
||
* @param 无
|
||
* @retval 0,初始化成功;1,初始化失败
|
||
*/
|
||
|
||
uint8_t TPAD_Init(void)
|
||
{
|
||
uint16_t buf[10];
|
||
uint32_t temp=0;
|
||
uint8_t j,i;
|
||
|
||
TIM_Mode_Config();
|
||
|
||
for(i=0;i<10;i++)//连续读取10次
|
||
{
|
||
buf[i]=TPAD_Get_Val();
|
||
HAL_Delay(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;
|
||
//取中间的6个数据进行平均
|
||
for(i=2;i<8;i++)
|
||
{
|
||
temp+=buf[i];
|
||
}
|
||
|
||
tpad_default_val=temp/6;
|
||
/* printf打印函数调试使用,用来确定阈值TPAD_GATE_VAL,在应用工程中应注释掉 */
|
||
//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;
|
||
}
|
||
|
||
/**
|
||
* @brief 触摸按键扫描函数
|
||
* @note 获得空载的时候触摸按键的取值
|
||
* @param mode:0,不支持连续触发(按下一次必须松开才能按下一次);1,支持连续触发(可以一直按下)
|
||
* @retval 0,没有按下;1,有按下;
|
||
*/
|
||
uint8_t TPAD_Scan(uint8_t mode)
|
||
{
|
||
//0,可以开始检测;>0,还不能开始检测
|
||
static uint8_t keyen=0;
|
||
//扫描结果
|
||
uint8_t res=0;
|
||
//默认采样次数为3次
|
||
uint8_t sample=3;
|
||
//捕获值
|
||
uint16_t rval;
|
||
|
||
if(mode)
|
||
{
|
||
//支持连按的时候,设置采样次数为6次
|
||
sample=6;
|
||
//支持连按
|
||
keyen=0;
|
||
}
|
||
/* 获取当前捕获值(返回 sample 次扫描的最大值) */
|
||
rval=TPAD_Get_MaxVal(sample);
|
||
/* printf打印函数调试使用,用来确定阈值TPAD_GATE_VAL,在应用工程中应注释掉 */
|
||
//printf("scan_rval=%d\n",rval);
|
||
|
||
//大于tpad_default_val+TPAD_GATE_VAL,且小于10倍tpad_default_val,则有效
|
||
if(rval>(tpad_default_val+TPAD_GATE_VAL)&&rval<(10*tpad_default_val))
|
||
{
|
||
//keyen==0,有效
|
||
if(keyen==0)
|
||
{
|
||
res=1;
|
||
}
|
||
keyen=3; //至少要再过3次之后才能按键有效
|
||
}
|
||
|
||
if(keyen)
|
||
{
|
||
keyen--;
|
||
}
|
||
return res;
|
||
}
|
||
/*********************************************END OF FILE**********************/
|