sky 发表于 2021-4-25 18:23:59

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

本帖最后由 sky 于 2021-9-10 17:06 编辑

本章教程使用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);

#endiftkey.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、下载验证

将编译好的程序下载到开发板并复位,串口打印具体情况如下:
手指触摸触摸按键之后,串口打印具体情况如下:

TKEY.rar附件下载

链接:https://pan.baidu.com/s/1RIa8PSFCPg3-drDWScXlBQ
提取码:k9c4
复制这段内容后打开百度网盘手机App,操作更方便哦



页: [1]
查看完整版本: 第二十二章:CH32V103应用教程——触摸按键检测(TKEY)