本帖最后由 天意无罪 于 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);
- }
- }
(三) 效果演示
|