搜索

[RISC-V MCU 应用开发] 二十二、CH32V103应用教程——触摸按键检测(TKEY)

[复制链接]
252|0
 楼主 | 2020-12-3 19:12 | 显示全部楼层 |阅读模式
本帖最后由 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)内取走数据,否则下一轮的转换将影响数据寄存器的内容。
图片1.png

关于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[2:0]和TKCPS位,选择500us 或1ms周期。单元内部是以AHB时钟计时,所以需要CCSEL[2:0]域与当前 AHB 频率相等,否则会导致采样周期偏大或偏小。
4)配置采样通道,设置TKEY_V_CHANNEL寄存器,此寄存器的写操作会触发新的一轮周期开始。
5)等待TKIF标志置1,表示完成一次转换,可以读取TKEY_V_SDR寄存器中的 TKDR[13:0]计数值。TKSTA指示当前TKDR[13:0]域计数值是否有效。TKIF标志需要软件写1清0。如果置位了TKIEN,在TKIF=1时会同步触发TKEY_V(ADC)中断,进入ADC中断服务函数。
6)重复 3-5 步骤,获取下一次计数值。3-4为可选配置。
根据上述操作步骤,编写程序如下:
tkey.h文件
  1. #ifndef __TKEY_H
  2. #define __TKEY_H

  3. #include "ch32v10x_conf.h"

  4. /* Global define */ //此处查看寄存器时,应查看TKEY寄存器
  5. #define TKEY_CR   ADC1->CTLR1   //ADC1->CTLR1寄存器由TKEY_V_CTLR寄存器映射而来,此处查看寄存器时应该查看TKEY_V_CTLR寄存器,而不是ADC1->CTLR1寄存器
  6. #define TKEY_CH   ADC1->RSQR3   //ADC1->RSQR3寄存器由TKEY_V_CHANNEL寄存器映射而来,此处查看寄存器时应该查看TKEY_V_CHANNEL寄存器,而不是ADC1->RSQR3寄存器
  7. #define TKEY_SR   ADC1->RDATAR  //ADC1->RDATAR寄存器由TKEY_V_SDR寄存器映射而来,此处查看寄存器时应该查看TKEY_V_SDR寄存器,而不是ADC1->RDATAR寄存器

  8. void Touch_Key_Init(void);
  9. u16 Touch_Key_Adc(u8 ch);

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

  2. /*******************************************************************************
  3. * Function Name  : Touch_Key_Init
  4. * Description    : Initializes Touch Key collection.
  5. * Input          : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void Touch_Key_Init(void)
  9. {
  10.     GPIO_InitTypeDef GPIO_InitStructure;

  11.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOA时钟
  12.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );  //使能ADC1时钟

  13.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  14.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  15.     GPIO_Init(GPIOA, &GPIO_InitStructure);

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

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

  19. /*******************************************************************************
  20. * Function Name  : Touch_Key_Adc
  21. * Description    : Returns ADCx conversion result data.
  22. * Input          : ch: ADC channel.
  23. *                    ADC_Channel_0: ADC Channel0 selected.
  24. *                    ADC_Channel_1: ADC Channel1 selected.
  25. *                    ADC_Channel_2: ADC Channel2 selected.
  26. *                    ADC_Channel_3: ADC Channel3 selected.
  27. *                    ADC_Channel_4: ADC Channel4 selected.
  28. *                    ADC_Channel_5: ADC Channel5 selected.
  29. *                    ADC_Channel_6: ADC Channel6 selected.
  30. *                    ADC_Channel_7: ADC Channel7 selected.
  31. *                    ADC_Channel_8: ADC Channel8 selected.
  32. *                    ADC_Channel_9: ADC Channel9 selected.
  33. *                    ADC_Channel_10: ADC Channel10 selected.
  34. *                    ADC_Channel_11: ADC Channel11 selected.
  35. *                    ADC_Channel_12: ADC Channel12 selected.
  36. *                    ADC_Channel_13: ADC Channel13 selected.
  37. *                    ADC_Channel_14: ADC Channel14 selected.
  38. *                    ADC_Channel_15: ADC Channel15 selected.
  39. * Return         : val: The Data conversion value.
  40. *******************************************************************************/
  41. u16 Touch_Key_Adc(u8 ch)
  42. {
  43.   u16 val;

  44.   TKEY_CH = ch;     // 选择通道

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

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

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

  6.     Touch_Key_Init();

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

  11.         if(ADC_val & 0x8000)
  12.         {
  13.             printf("This value is discarded\r\n");
  14.         }

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

4、下载验证
将编译好的程序下载到开发板并复位,串口打印具体情况如下:
图片2.png
手指触摸触摸按键之后,串口打印具体情况如下:
图片3.png




21、TKEY.rar

459.47 KB, 下载次数: 4

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表