RISCVLAR 发表于 2020-12-3 19:12

二十二、CH32V103应用教程——触摸按键检测(TKEY)

本帖最后由 RISCVLAR 于 2020-12-3 19:11 编辑

CH32V103应用教程——触摸按键检测(TKEY)
本章教程使用CH32V103开发板的触摸按键TK1进行触摸按键检测,并将检测信息通过串口调试助手打印显示。

1、TKEY简介及相关函数介绍
1、TKEY_V 开启
TKEY_V单元检测内部复用了ADC模块的通道选择及部分寄存器地址,所用使用 TKEY_V功能需要开启ADC模块(ADON=1),并打开 ADC 时钟以此来访问相关寄存器。然后将TKEY_V_CTLR(ADC_CTLR1)寄存器的TKENABLE 位置1,打开TKEY_V 单元功能。

注:因为共用了采样通道选择,所以ADC和TKEY_V检测功能不能同时使用。

2、工作原理
一旦开启了TKEY_V功能,硬件内部将自动进行周期性地采样计数转换过程,并在完成一次转换后,通知应用代码在固定时间(tDR)内取走数据,开启下一次转换,此循环过程在TKEY_V开启下是自动进行的。如图所示,硬件内部会提供了用来计数的脉冲源TKCLK,应用软件选择当前硬件计数周期为500us或 1ms,当内部完成周期内的计数统计后,会产生 TKIF 标志通知应用代码读取本次转换数值,应用代码需要在最长43us(tDR)内取走数据,否则下一轮的转换将影响数据寄存器的内容。


关于CH32V103触摸按键检测具体信息,可参考CH32V103应用手册。CH32V103 触摸按键检测所用标准库函数在ADC章节已介绍,在此不再赘述。

2、硬件设计
本章教程所用资源均为开发板内部资源,无需进行硬件设计。

3、软件设计
TKEY_V通过电容改变影响内部振荡频率变化的原理,以统计计数值大小检测触摸按键。具体操作流程如下:
1)开启RCC模块的ADCEN位,打开TKEY_V寄存器操作权限。
2)开启TKEY_V功能,置ACON位为1,唤醒ADC模块。将ADC_CTLR1寄存器的TKENABLE位置1,打开TKEY_V单元。
3)配置采样周期,操作TKEY_V_CTLR寄存器的CCSEL和TKCPS位,选择500us 或1ms周期。单元内部是以AHB时钟计时,所以需要CCSEL域与当前 AHB 频率相等,否则会导致采样周期偏大或偏小。
4)配置采样通道,设置TKEY_V_CHANNEL寄存器,此寄存器的写操作会触发新的一轮周期开始。
5)等待TKIF标志置1,表示完成一次转换,可以读取TKEY_V_SDR寄存器中的 TKDR计数值。TKSTA指示当前TKDR域计数值是否有效。TKIF标志需要软件写1清0。如果置位了TKIEN,在TKIF=1时会同步触发TKEY_V(ADC)中断,进入ADC中断服务函数。
6)重复 3-5 步骤,获取下一次计数值。3-4为可选配置。
根据上述操作步骤,编写程序如下:
tkey.h文件
#ifndef __TKEY_H
#define __TKEY_H

#include "ch32v10x_conf.h"

/* 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_Adc(u8 ch);

#endif
tkey.h文件主要进行相关定义及函数声明;
tkey.c文件#include "tkey.h"

/*******************************************************************************
* Function Name: Touch_Key_Init
* Description    : Initializes Touch Key collection.
* Input          : None
* Return         : None
*******************************************************************************/
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 = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    ADC_Cmd(ADC1, ENABLE);   //使能开启ADC1

    TKEY_CR |= 0x51000000;   // 根据TKEY_V 控制寄存器(TKEY_V_CTLR),设置TKEY_V计数周期时基:56MHz;同时使能TKEY模块控制,开启TKEY_V单元。
}

/*******************************************************************************
* Function Name: Touch_Key_Adc
* Description    : Returns ADCx conversion result data.
* Input          : ch: ADC channel.
*                  ADC_Channel_0: ADC Channel0 selected.
*                  ADC_Channel_1: ADC Channel1 selected.
*                  ADC_Channel_2: ADC Channel2 selected.
*                  ADC_Channel_3: ADC Channel3 selected.
*                  ADC_Channel_4: ADC Channel4 selected.
*                  ADC_Channel_5: ADC Channel5 selected.
*                  ADC_Channel_6: ADC Channel6 selected.
*                  ADC_Channel_7: ADC Channel7 selected.
*                  ADC_Channel_8: ADC Channel8 selected.
*                  ADC_Channel_9: ADC Channel9 selected.
*                  ADC_Channel_10: ADC Channel10 selected.
*                  ADC_Channel_11: ADC Channel11 selected.
*                  ADC_Channel_12: ADC Channel12 selected.
*                  ADC_Channel_13: ADC Channel13 selected.
*                  ADC_Channel_14: ADC Channel14 selected.
*                  ADC_Channel_15: ADC Channel15 selected.
* Return         : val: The Data conversion value.
*******************************************************************************/
u16 Touch_Key_Adc(u8 ch)
{
u16 val;

TKEY_CH = ch;   // 选择通道

while(!(TKEY_CR & 0x08000000)); //当未清除计数转换完成标志
val = (u16)TKEY_SR; //TKEY_V计数转换值

return val;
}tkey.c文件主要进行相关初始化配置以及获取触摸按键检测值
main.c文件
int main(void)
{
    u16 ADC_val;

    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);

    Touch_Key_Init();

    while(1)
    {
      ADC_val = Touch_Key_Adc(ADC_Channel_1);
      printf( "TouchKey:%04d\r\n",ADC_val );

      if(ADC_val & 0x8000)
      {
            printf("This value is discarded\r\n");
      }

      TKEY_CR |=0x08000000;//TKEY_V_CTLR寄存器位27,计数转换完成标志,软件写1清0,清除标志位
    }
}main.c文件主要进行函数初始化以及触摸按键检测计数值的打印输出。

4、下载验证
将编译好的程序下载到开发板并复位,串口打印具体情况如下:

手指触摸触摸按键之后,串口打印具体情况如下:





南岛蜗牛 发表于 2022-2-25 14:53

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;这个改为GPIO_Pin_2,触摸tk2没反应,但触摸tk1就有反应,这是怎么回事

onlycook 发表于 2022-3-7 15:09

TKEY_V功能是什么功能

loutin 发表于 2023-4-15 19:41

这个支持多少路的测量呢            

modesty3jonah 发表于 2023-4-16 22:00

可以测量几路的电容电压            

benjaminka 发表于 2023-4-17 17:59

这个的硬件是怎么设计的            

bestwell 发表于 2023-4-18 08:54

这个测试的敏感度怎么样            

ulystronglll 发表于 2023-4-18 11:04

这个如何调节触摸按键的敏感度            

mmbs 发表于 2023-4-18 11:26

带ADC的I/O口来检测吗            

olivem55arlowe 发表于 2023-4-18 12:00

触摸不是检测充放电的过程吗            

primojones 发表于 2023-4-18 12:03

CH32V103的功能真是强大。

juliestephen 发表于 2023-4-18 12:07

充放电需要多长的时间            

louliana 发表于 2023-5-10 20:39

如何利用单片机检测电容充放电的时间

lzbf 发表于 2023-5-10 21:04

CH32V103单片机可以实现触摸按键么

alvpeg 发表于 2023-5-10 21:12

电容式触摸按键必须需要用专用芯片吗?

burgessmaggie 发表于 2023-5-10 21:37

普通单片机怎样做电容式触摸感应按键

1988020566 发表于 2023-5-10 21:51

如何使用单片机的AD功能实现触摸按键

yeates333 发表于 2023-5-10 22:09

哪个单片机自带触摸按键和lcd功能

benjaminka 发表于 2023-5-10 22:14

电容触摸按键原理是什么            

jonas222 发表于 2023-5-11 15:46

如何实现一个按键的长时间按下?            
页: [1] 2
查看完整版本: 二十二、CH32V103应用教程——触摸按键检测(TKEY)