STM32H750XB_RT-THREAD/38-SAI—音频/SAI—录音与回放/User/touch_pad/bsp_touchpad.c
2025-07-21 14:34:29 +08:00

242 lines
6.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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(200Mhz/22)
TIM_Handle.Init.Prescaler = 23 - 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)
{
uint16_t temp;
/* 先放电完全,并复位计数器 */
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寄存器值 */
temp = HAL_TIM_ReadCapturedValue(&TIM_Handle, TPAD_TIM_Channel_X);
// printf("scan_rval=%d\n",temp);
return temp;
}
/**
* @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**********************/