本帖最后由 天意无罪 于 2020-12-6 19:25 编辑
(一)硬件熟悉
CH32V103 系列产品触摸检测控制(TKEY_V)单元,通过将电容量变化转变为频率变化进行采样,实现触摸按键检测功能。检测通道复用 ADC 的 16 路外部通道。应用程序通过数字值的变化量判断触摸按键状态。
TKEY_V单元检测内部复用了ADC模块的通道选择及部分寄存器地址,所用使用 TKEY_V功能需要开启ADC模块(ADON=1),并打开 ADC 时钟以此来访问相关寄存器。然后将TKEY_V_CTLR(ADC_CTLR1)寄存器的TKENABLE 位置1,打开TKEY_V 单元功能。
注:因为共用了采样通道选择,所以ADC和TKEY_V检测功能不能同时使用。
(二)软件设计
实现功能:通过开发板上的两个触摸按键来控制开发板上的两个LED灯的亮灭。
1. 在BSP/src目录下新建一个tkey.c文件,在BSP/inc目录下新建一个tkey.h文件。 2. 在tkey.h文件里面定义相关宏定义、变量声明、以及函数声明等。
#ifndef BSP_INC_TKEY_H_
#define BSP_INC_TKEY_H_
#include "ch32v10x_conf.h"
#define TKEY_GPIO_PORT GPIOA
#define TKEY1_GPIO_PIN GPIO_Pin_1
#define TKEY2_GPIO_PIN GPIO_Pin_2
/* Global define */ //此处查看寄存器时,应查看TKEY寄存器
#define TKEY_CR ADC1->CTLR1 //ADC1->CTLR1寄存器由TKEY_V_CTLR寄存器映射而来,此处查看寄存器时应该查看TKEY_V_CTLR寄存器,而不是ADC1->CTLR1寄存器
#define TKEY_CH ADC1->RSQR3 //ADC1->RSQR3寄存器由TKEY_V_CHANNEL寄存器映射而来,此处查看寄存器时应该查看TKEY_V_CHANNEL寄存器,而不是ADC1->RSQR3寄存器
#define TKEY_SR ADC1->RDATAR //ADC1->RDATAR寄存器由TKEY_V_SDR寄存器映射而来,此处查看寄存器时应该查看TKEY_V_SDR寄存器,而不是ADC1->RDATAR寄存器
void Touch_Key_Init(void);
u16 Touch_Key_GetAdc(u8 ch);
#endif /* BSP_INC_TKEY_H_ */
3. 在tkey.c文件里面实现触摸按键的配置和初始化等。
#include "tkey.h"
void Touch_Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1时钟
GPIO_InitStructure.GPIO_Pin = TKEY1_GPIO_PIN | TKEY2_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(TKEY_GPIO_PORT, &GPIO_InitStructure);
ADC_Cmd(ADC1, ENABLE); //使能开启ADC1
TKEY_CR |= 0x51000000; // 根据TKEY_V 控制寄存器(TKEY_V_CTLR),设置TKEY_V计数周期时基:56MHz;同时使能TKEY模块控制,开启TKEY_V单元。
}
u16 Touch_Key_GetAdc(u8 ch)
{
u16 val;
TKEY_CH = ch; // 选择通道
while(!(TKEY_CR & 0x08000000)); //当未清除计数转换完成标志
val = (u16)TKEY_SR; //TKEY_V计数转换值
return val;
}
4. 在main.c中添加按键检测代码。
int main(void)
{
u16 ADC_VAL;
Delay_Init();
USART_Printf_Init(115200);
LED_Init();
Touch_Key_Init();
printf("SystemClk:%d\r\n",SystemCoreClock);
while(1)
{
ADC_VAL = Touch_Key_GetAdc(ADC_Channel_1);
printf( "TouchKey1:%04d\r\n", ADC_VAL );
if(ADC_VAL & 0x8000)
{
printf("This value is discarded\r\n");
}
else if((ADC_VAL > 0) && (ADC_VAL < 2000) )
{
LED1_ON();
}
TKEY_CR |=0x08000000; //TKEY_V_CTLR寄存器位27,计数转换完成标志,软件写1清0,清除标志位
Delay_Ms(10);
ADC_VAL = Touch_Key_GetAdc(ADC_Channel_2);
printf( "TouchKey2:%04d\r\n", ADC_VAL );
if(ADC_VAL & 0x8000)
{
printf("This value is discarded\r\n");
}
else if((ADC_VAL > 0) && (ADC_VAL < 2000) )
{
LED1_OFF();
}
TKEY_CR |=0x08000000; //TKEY_V_CTLR寄存器位27,计数转换完成标志,软件写1清0,清除标志位
Delay_Ms(10);
}
}
(三) 效果演示
|