本文以正点原子精英板子为例
触摸按键原理:触摸按键类似于一个电容,开发板内部也接了一个电容。利用定时器的输入捕获功能来捕获到这个电路上电容的充放电时间,当按下的时候相当于是两块电容,充电时间较长。最终就是通过比较充电的的时间来判断触摸按键有没有被按下。
一、CubeMX设置:
1. 还是老规矩,先打开sys的调试:
2.打开RCC时钟:
3.时钟设置为72MHZ:
4.因为这里使用了正带你原子的开发板,对应的捕获充电时间的GPIO口是PA1,这里对应的TIM5,channel2进行捕获,所以这里进行设置一下:
5.设置下面的参数,这里进行了6分频,使能重装载寄存器,下面2通道也设置为上升沿触发:
6.点击GPIO,设置一下TIM5,channel2对应的GPIO口(PA1)的参数,命名和设置为下拉模式:
7.打开PB5和PE5的输出模式:
8.将这两个GPIO口重新命名,以及分别设置为输出高电平(因为这里的开发板中,LED灯一段已经连接了高电平,所以GPIO输出低电平才会亮,所以这里初始状态要设置为高电平),推挽输出,上拉模式,高速模式:
之后保存生成代码。
二、代码部分:
1.新增代码
这里需要添加tpad.c, tpad.h,和正点原子的sys.c, sys.h 文件(tpad.c和tpad.h也是正点原子提供的的,不过我稍加了改动)。
(1). tpad.c:
#include "tpad.h"
#include "tim.h"
/* 空载的时候(没有手按下),计数器需要的时间
* 这个值应该在每次开机的时候被初始化一次
*/
volatile uint16_t g_tpad_default_val = 0; /* 空载的时候(没有手按下),计数器需要的时间 */
/* 静态函数, 仅限 tapd.c调用 */
static void tpad_reset(void); /* 复位 */
static uint16_t tpad_get_val(void); /* 得到定时器捕获值 */
static uint16_t tpad_get_maxval(uint8_t n); /* 读取n次, 获取最大值 */
/**
* @brief 初始化触摸按键
* @param psc : 分频系数(值越小, 越灵敏, 最小值为: 1)
* @retval 0, 初始化成功; 1, 初始化失败;
*/
uint8_t tpad_init(uint16_t psc)
{
uint16_t buf[10];
uint16_t temp;
uint8_t j, i;
MX_TIM5_Init();
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;
for (i = 2; i < 8; i++) /* 取中间的6个数据进行平均 */
{
temp += buf[i];
}
g_tpad_default_val = temp / 6;
if (g_tpad_default_val > TPAD_ARR_MAX_VAL / 2)
{
return 1; /* 初始化遇到超过TPAD_ARR_MAX_VAL/2的数值,不正常! */
}
return 0;
}
/**
* @brief 复位TPAD
* @note 我们将TPAD按键看做是一个电容, 当手指按下/不按下时容值有变化
* 该函数将GPIO设置成推挽输出, 然后输出0, 进行放电, 然后再设置
* GPIO为浮空输入, 等待外部大电阻慢慢充电
* @param 无
* @retval 无
*/
static void tpad_reset(void)
{
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.Pin = TPAD_Pin; /* 输入捕获的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM; /* 中速 */
HAL_GPIO_Init(TPAD_GPIO_Port, &gpio_init_struct);
HAL_GPIO_WritePin(TPAD_GPIO_Port, TPAD_Pin, GPIO_PIN_RESET); /* TPAD引脚输出0, 放电 */
HAL_Delay(5);
htim5.Instance->SR = 0; /* 清除标记 */
htim5.Instance->CNT = 0; /* 归零 */