K1,K2,K3,K4是四个触摸按键,C15、C16、C20、C21电容起到调节灵敏度的作用;TP0、TP1、TP2、TP3是按键输入,TPQ0、TPQ1、TPQ2、TPQ3是信号输出,接到了单片机的PE0 ~ PE3引脚
硬件电路图没有用单片机引脚控制触摸芯片的功能引脚,而是直接用V_3V3和GND对功能引脚进行初始化,由图可知
AHLB = 1,LPMB = 1,SM = 0,MOT0 = 0
因为该芯片有另一种封装,所以数据手册的引脚与硬件电路图的不太一样,多了几个引脚,但主要功能的引脚一样
根据硬件电路图得出的功能管脚电平,以及数据手册的管脚默认状态可得该触摸芯片设置的模式为:
TOG = 0,OD = 1,AHLB = 1:直接模式, CMOS输出,低电平有效
SM = 0:单键模式
LPMB = 1:快速模式
所以触摸芯片不用单片机引脚控制,当检测到触摸按键被触摸时,就会在对应的输出引脚输出低电平,再给到32单片机的引脚,所以在程序中只需将引脚配置为外部中断下降沿检测,检测引脚电平状态就知道哪个触摸按键被按下了
要记得在NVIC中开启外部中断,因为触摸芯片设置为了单键模式,所以两个按键同时被按下没有效果,中断优先级都可以设一样
CallBack.c
在外部中断回调函数中改变按键的标志位
/*
* @name HAL_GPIO_EXTI_Callback
* @brief 外部中断回调函数
* @param GPIO_Pin:触发外部中断的引脚
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch (GPIO_Pin)
{
case KEY1_Pin: KEY1.KEY_Flag = TRUE; break;
case KEY2_Pin: KEY2.KEY_Flag = TRUE; break;
case KEY3_Pin: KEY3.KEY_Flag = TRUE; break;
case KEY4_Pin: KEY4.KEY_Flag = TRUE; break;
default:printf("错误,外部中断回调函数中,触摸按键键值错误!\r\n\r\n");
}
}
KEY.c
触摸按键1检测函数,与STC15实战的检测函数一样,这里检测单击和长按2秒,其他按键检测与按键1的一样,只是按键号不同而已
继电器的触发函数在Relay.c文件中,比较简单,单片机引脚输出高电平则继电器吸合,输出低电平则继电器断开,是按键4中的按键动作
/*
* @name KEY1_Detect
* @brief 触摸按键1检测
* @param None
* @retval None
*/
static void KEY1_Detect()
{
uint8_t i;
if(KEY1.KEY_Flag == TRUE) //检测按键状态位是否被改变
{
KEY1.Click = FALSE;
KEY1.Press = TRUE;
//触摸按键长按检测
for(i = 0;i < 200;i++)
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_SET)
{
KEY1.Click = TRUE;
KEY1.Press = FALSE;
break;
}
}
//按键动作
//单击
if(KEY1.Click == TRUE)
{
printf("检测到触摸按键1单击\r\n");
LED.LED_Fun(LED1,LED_Flip); //翻转LED1电平状态
}
//长按
if(KEY1.Press == TRUE)
{
printf("检测到触摸按键1长按\r\n");
LED.LED_Fun(LED1,LED_Flip);
HAL_Delay(200);
LED.LED_Fun(LED1,LED_Flip);
}
//清除标志位
KEY1.KEY_Flag = FALSE;
KEY1.Click = FALSE;
KEY1.Press = FALSE;
}
}
System.c
系统运行函数中不断检测按键状态
/*
* @name Run
* @brief 系统运行
* @param None
* @retval None
*/
static void Run()
{
//触摸按键检测
KEY1.KEY_Detect();
KEY2.KEY_Detect();
KEY3.KEY_Detect();
KEY4.KEY_Detect();
}