你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32实例-电容触摸按键实验

[复制链接]
STMCU小助手 发布时间:2022-6-28 18:32
    我们已经介绍了STM32F1 的通用定时器作为输入捕获的使用方法,
这一章我们就利用输入捕获功能设计一个电容触摸按键。本章要实现的功能是:通过 TIM5的通道 2(PA1)捕获电容触摸按键输入信号的高电平脉宽,根据捕获到高电平时间大小控制D2指示灯开关, 同时D1指示灯不断闪烁表示系统正常运行。
    学习可以参考前面“输入捕获实验”和《STM32F10x 中文参考手册》-14 通用定时器章节。
电容触摸按键介绍
    触摸按键与传统的机械按键相比,不仅美观而且耐用、寿命长,它颠覆了传统意义上的机械按键控制,只要轻轻触摸,就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消费类电子产品中。本文我们就介绍一种简单的触摸按键:电容式触摸按键。
    我们开发板上的电容触摸按键其实就是一小块覆铜区域, 也称之为触摸感应区,如下图中笑脸即为触摸感应区。
微信图片_20220627224939.jpg

0 a. K$ }. F2 v/ L' l1 g  m
    通常我们会将四周的铜片与电路板地信号连通, 触摸感应区设计成方便手指触摸大小,并将其连接在输入捕获通道上。触摸感应区与四周的铜片区域就形成了一个电容, 通过检测电容充放电时间即可判断是否有触摸。电容触摸按键原理,实现原理如下图所示。
微信图片_20220627224934.png
    上图中 R 是外接的电容充电电阻,Cs 是没有触摸按下时 TOUCH(触摸感应区)与四周的铜片区域的杂散电容。而 Cx 则是有手指按下的时候,手指与 TOUCH 之间形成的电容。图中的开关是电容放电开关(实际使用时,由STM32F1 的 IO 代替)。
    先用开关将 Cs(或 Cs+Cx)上的电放尽,然后断开开关,让 R 给 Cs(或
Cs+Cx)充电,当没有手指触摸的时候,Cs 的充电曲线如图中的 A 曲线。而当有手指触摸的时候,手指和 TOUCH 之间引入了新的电容 Cx,此时电容量相当于它们的累加,充电时间自然就长了,Cs+Cx 的充电曲线如图中的 B 曲线。从上图可以看出,A、B 两种情况下,Vc 达到 Vth 的时间分别为 Tcs 和 Tcs+Tcx。
    其中,除了 Cs 和 Cx 我们需要计算,其他都是已知的,根据电容充放电公式:
  1. Vc=V0*(1-e^(-t/RC))
复制代码

* A) x+ ]- @5 |$ y5 v  ^
    其中 Vc 为电容电压,V0 为充电电压,R 为充电电阻,C 为电容容值,e 为自然底数,t 为充电时间。根据这个公式,我们就可以计算出 Cs 和 Cx。因此我们可以把开发板当做一个简单的电容计,直接可以测电容容量了。
    在本文中,其实我们只要能够区分 Tcs 和 Tcs+Tcx,就已经可以实现触摸
检测了,当充电时间在 Tcs 附近,就可以认为没有触摸,而当充电时间大于
Tcs+Tx 时,就认为有触摸按下( Tx 为检测阀值)。
    本文我们使用 TIM5的通道2(PA1)来检测触摸按键是否按下,每次检测前,我们需要先将电容 Cs(或 Cs+Cx)放电,即配置 PA1 引脚为推挽输出模式,输出一个低电平,才能使电容放电。然后配置 PA1 为浮空输入模式,利用外部上拉电阻给电容 Cs(Cs+Cx)充电,同时开启 TIM5_CH2 的输入捕获,配置极性为上升沿,当检测到上升沿的时候,就认为电容充电完成了,完成一次捕获检测。
    每次系统重启时,我们执行一次捕获检测(可认为没有触摸),记录此时捕获到上升沿的值。在后续的捕获检测中,我们就可以通过与记录的值进行对比,判断是否发生触摸。
    关于输入捕获的配置,在上一章我们已经有详细介绍,这里我们就不多说,不清楚的可以回过头看下。

2 Q$ V1 O; e) ?
硬件设计
    本实验使用到硬件资源如下:
(1)D1、D2 指示灯
(2)TIM5 的通道 2
(3)串口 1
(4)电容触摸按键
    D1、D2 指示灯、串口1 电路在前面章节都介绍过,至于 TIM5 的通道2 它属于 STM32F1 芯片内部的资源。电容触摸按键电路如下图所示。
微信图片_20220627224929.png

5 |8 g! h8 _3 X/ C. g
微信图片_20220627225139.jpg
' y4 }. b' g6 l  Z
    原理图中的 TOUCH 即为电容触摸感应区,通过 P_TOUCH 引出。而 TIM5_CH2是在 PA1 脚,它在 P_touch 端子的插针 2 上,要捕获电容触摸按键的信号,我们需要用短接片将 P_touch排针上的 1 和 2 短接(开发板丝印上是 TP 和 A1)。而此端子的 2、3 短接是用于对ADC 的检测,这个在后面章节会介绍到。D1指示灯用来提示系统正常运行,D2 指示灯用来指示触摸是否按下,捕获上升沿值可通过串口 1 的printf 函数打印出来。
    所要实现的功能是:通过 TIM5 的通道 2(PA1)捕获电容触摸按键输入
信号的高电平脉宽,根据捕获到高电平时间大小控制 D2 指示灯开关,同时 D1指示灯不断闪烁表示系统正常运行。程序框架如下:
(1)初始化 PA1 管脚为TIM5 通道 2 输入捕获功能,设置上升沿捕获等
(2)读取一次捕获高电平的值
(3)电容触摸按键初始化
(4)检测电容触摸按键是否按下
(5)编写主函数
    在之前帖子中“输入捕获实验”中就已经讲解如何配置输入捕获。下面我们打开“电容触摸按键实验”工程,在APP 工程组中添加了 touch_key.c 文件(里面包含了电容触摸按键驱动程序),在StdPeriph_Driver 工程组中添加stm32f10x_tim.c 库文件。定时器操作的库函数都放在 stm32f10x_tim.c和stm32f10x_tim.h 文件中, 所以使用到定时器就必须加入 stm32f10x_tim.c文件,同时还要包含对应的头文件路径。
    这里我们分析几个重要函数,其他部分程序大家可以打开工程查看。
6 m) P% S  v3 j
TIM5 的 CH2 初始化函数
    要使用定时器输入捕获功能,我们必须先对它进行配置,代码如下:
  1. /****************************************************************$ P4 R1 o9 T+ Y7 u. H% v4 K
  2. * 函 数 名 : TIM5_CH2_Input_Init) j: ]: Y& ]" p5 C# X  m
  3. * 函数功能 : TIM5_CH2 输入捕获初始化函数9 Y% M' F* i; `' c; F6 I  H7 R
  4. * 输 入 : arr:自动重装载值 psc:预分频系数
    : i/ [4 C# V9 k* Q# f
  5. * 输 出 : 无
    : x) V1 f7 T( ]" }
  6. *****************************************************************/
    0 U, {3 M- u- C4 y
  7. void TIM5_CH2_Input_Init(u16 arr,u16 psc)1 W0 k7 C( x4 X0 d# O$ Q
  8. {( b, f9 u6 _4 n0 o3 Q) N5 X9 S, w: ]
  9.   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    & Q8 }: Z' @' Z6 O% l
  10.   TIM_ICInitTypeDef TIM_ICInitStructure;7 ?" W, [3 Y+ n) i. Q0 e' t& A) q
  11.   GPIO_InitTypeDef GPIO_InitStructure;4 y6 S, V. Q" S0 Z
  12.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    3 l# r; x& \, H8 A
  13.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能 TIM5时钟* N6 Z0 Y$ }- Y
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;- T4 J  A/ v8 S  ?+ m
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式4 l8 {/ X8 W6 }# w5 o3 o
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度为 50MHz  C' k. |1 y# U
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure); // PA0, A, {1 n  N6 ]) i" \5 R. u
  18.   TIM_TimeBaseInitStructure.TIM_Period=arr; //自动装载值$ p0 L9 L6 t+ y* z! q1 G9 g5 v* P
  19.   TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
    0 B* m( Q6 s. v. X" L
  20.   TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;2 @0 w) K3 I' j/ N7 J1 N# l
  21.   TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    : y0 D% @, I& H1 u- J
  22.   //设置向上计数模式
    ( p9 ~6 [4 l  j8 M; A7 e5 c" a4 n" C
  23.   TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);% O' [9 n( W, T, @" _
  24.   TIM_ICInitStructure.TIM_Channel=TIM_Channel_2; //通道2& p) l, t$ Y2 v
  25.   TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波
    ) j! y/ `! v# S/ y0 H
  26.   TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;// 捕获极性
    ( F, _. H/ P: y" i0 j3 N2 S! p
  27.   TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数( F; x: R* ?/ _7 i; d1 L
  28.   TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到 TI1* `" n& ~0 _6 g) l9 ^7 M( v
  29.   TIM_ICInit(TIM5,&TIM_ICInitStructure);
    7 C* @( h$ V1 R1 a* @
  30.   TIM_Cmd(TIM5,ENABLE); //使能定时器9 F5 _' N- K4 L4 W) u* ?6 {
  31. }
复制代码
% Q) c, Z; m( b  J4 N/ @
    TIM5_CH2_Input_Init()函数与前面输入捕获实验的 TIM5 初始化是类似的,只不过换了通道而已。通过这样的设置,我们就可以捕获 PA1 引脚上的上升沿。
    TIM5_CH2_Input_Init()函数有两个参数,用来设置定时器的自动装载值和分频系数,方便大家修改计数器频率,具体计算参考定时器中断实验章节。因为TIM5是16 位的定时器,所以arr 为 u16 类型。
高电平捕获函数
    上一步已经将 PA1 引脚初始化为输入捕获功能, 当电容两端电压逐渐上升置高电平时,就会发生捕获。我们通过查询标志位方式检测是否发生上升沿捕获,代码如下:
  1. /****************************************************************2 t' E: x% K; y5 m8 D
  2. * 函 数 名 : Touch_Get_Val  s8 ~" d0 a/ x* t  K1 Y) w
  3. * 函数功能 : 返回捕获高电平值
    6 V! X* b" \) Y8 s1 [+ L1 E
  4. * 输 入 : 无
    8 ], ]' ^% A2 N8 z3 f
  5. * 输 出 : 捕获高电平值2 b: F( @! l# G: ~$ b# D  {
  6. *****************************************************************/  y9 S0 `5 p" a7 L
  7. u16 Touch_Get_Val(void)9 N. f0 t% E: D5 e
  8. {# _6 {/ w' l% I5 z* h  `5 I
  9.   Touch_Reset();7 b8 W& Y0 Z2 t8 R7 |  H, X  K
  10.   while(TIM_GetFlagStatus(TIM5,TIM_FLAG_CC2)==0) //等待捕获到高电平标志" y/ P2 C! f8 D4 D3 y# ?
  11.   {! U/ o" v! Q1 W% r$ A( x
  12.     if(TIM_GetCounter(TIM5)>Touch_ARR_MAX_VAL-500) //超时了直接返回CNT 值
    3 R) C3 {) `5 n3 \5 i5 w) B
  13.     {' H- _0 {; p8 F. J$ i( q
  14.       return TIM_GetCounter(TIM5);
    % H! U6 }4 S' u# t$ u# P, ~
  15.     }# x' m* f: m; n* B" z
  16.   }" {+ g8 @. I4 w$ C
  17.   return TIM_GetCapture2(TIM5); //返回捕获高电平值6 i7 N6 k' @4 j
  18. }
复制代码
3 _! W' [  W: H- Y- x
    该函数用于得到定时器的一次捕获值。函数内首先调用 Touch_Reset()函
! m" E* t$ s" r  W
数,将 PA1 配置为输出模式,并输出低电平,使电容完全放电。然后清楚定时器相应的状态标志(溢出/捕获)并调用 TIM_SetCounter 库函数将 TIM5 计数器值清零, 同时将 PA1 配置为浮空模式。最后循环等待发生上升沿捕获 (或计数溢出) ,将捕获到的值(或溢出值)作为函数返回值返回。
: E& B7 {: d$ O- x& X9 A
电容触摸按键初始化函数
    电容触摸按键初始化函数代码如下:
  1. /****************************************************************3 j1 D9 n0 s* t: ?
  2. * 函 数 名 : Touch_Key_Init1 \: j* u) O) x% Q. q8 S' L0 ~( E7 k
  3. * 函数功能 : 触摸按键初始化/ \# i% r6 _* O" P1 S3 x
  4. * 输 入 : 无
    & f& n9 ~7 k0 B  I1 Q
  5. * 输 出 :  0:正常  1:不正常
    8 W5 i6 J/ g. v
  6. *****************************************************************/
    1 f: S0 O. a- q6 G
  7. u8 Touch_Key_Init(u8 psc)  ^' N- T5 ?) X% f
  8. {7 N6 S* \) R. C3 V. a2 v/ m0 H/ m: }
  9.   u8 i;
    4 ~8 o5 ?$ }4 N
  10.   u16 buf[10];
    . q$ u$ n$ ^. x
  11.   u8 j;
    8 p6 f* q: L! V& q
  12.   u16 temp;
    7 I9 ^# \8 @9 s& }7 S! K9 C
  13.   TIM5_CH2_Input_Init(Touch_ARR_MAX_VAL,psc);
    7 {$ C0 F+ `! @# @
  14.   for(i=0;i<10;i++) //读取 10 次为按下时候的触摸值) C+ g. ^5 d; J: g1 H) b$ d3 Q
  15.   {+ Z+ ?+ u5 |- L1 y$ w
  16.     buf[i]=Touch_Get_Val();
    9 n/ O* S; p$ N1 M$ b% x
  17.     delay_ms(10);
    7 G4 o) p) G, _; S
  18.   }4 A: [5 P6 r7 u% J
  19.   for(i=0;i<9;i++) //从小到大排序- k' ~7 p0 `, r4 z
  20.   {
    2 ?" r- }/ y& N4 _7 ?  U1 O+ Y% h
  21.     for(j=i+1;j<10;j++); u2 B0 c( I7 v/ k; H  b
  22.     {9 V3 _5 r2 u7 e% W
  23.       if(buf[i]>buf[j])    4 |; d) ]4 O; x8 [& G2 i' x- d# T
  24.       {
    . i9 l) s3 h$ X, L( O
  25.         temp=buf[i];
    4 H. }$ U" A2 }0 X
  26.         buf[j]=buf[j];! x+ A% l9 C& |. l
  27.         buf[j]=temp;
    5 `3 g! q7 @2 v( f  q  K$ L! m5 Q
  28.       }/ Q  I" Q7 d$ m$ z# W9 H+ W0 o1 ?
  29.     }& W' C* F% G; a+ K5 O  n
  30.   }  Z% ^2 i+ Z" s: h9 Y3 V
  31.   temp=0;
    ) q5 B' F( H% Q
  32.   for(i=2;i<8;i++) //取中间 6 个数值求和 取其平均数* P( f% X; h8 J& W3 G2 }6 s: p1 @
  33.   {
    . N, ?# D8 D. c+ u# u
  34.     temp+=buf[i];
    6 W7 t4 c) C" I% g' H0 v
  35.   }
    0 R4 x/ f. `; I/ {6 b- D( G
  36.   touch_default_val=temp/6;/ T% U" U3 l( X( k! Y1 b
  37.   printf("touch_default_val=%d \r\n",touch_default_val);5 |5 T( B# K6 F/ b+ [1 c: N( c7 a
  38.   if(touch_default_val>Touch_ARR_  MAX_VAL/2)
    ; [% b6 J" ]+ w0 l% [! M
  39.   {+ R8 z/ e! d4 |* r( ]3 o
  40.     return 1;//初始化遇到超过 Touch_ARR_MAX_VAL/2 的数值,不正常!2 @7 {" g; r6 t1 o
  41.   }
    . o9 O8 m! e: [' j
  42.   return 0;
    / N: {9 X8 Y, m7 s6 \" f) \. G' L" f
  43. }
复制代码
1 G8 P+ e- u# X, K+ X4 s
由于电容触摸按键是通过 PA1 进行捕获采集的,所以首先调用 TIM5_CH2 初始化函数 TIM5_CH2_Input_Init,此函数具有 2 个参数,用于设置定时器自动重装载值和预分频系数,这里我们将自动重装载值设置为 Touch_ARR_MAX_VAL,它是一个宏,在 touch_key.c 开始处就已定义,其值为 0xffff。预分频系数是通过函数形参传入,通过此参数即可确定计数时钟的大小。然后通过一个 for循环读取 10 次高电平的捕获值,按照由小到大进行排序,取中间 6 个再取平均,这样做可以减少误差。将计算后的值保存到一个 u16 类型的全局变量touch_default_val 中,作为后续触摸判断的标准。
) g0 t: K% H2 W
5 \! ?9 |6 h& {- [# j
电容触摸按键检测函数
    获取了 touch_default_val判断比较值, 我们就可以开始检测电容触摸按键是否按下,代码如下:
  1. /****************************************************************4 [. S0 O6 ?$ [1 i
  2. * 函 数 名 : Touch_Key_Scan
    8 a) r5 m: }6 U6 `& S0 K2 H
  3. * 函数功能 : 触摸按键扫描
    1 Y! U. I7 c1 W! Q) H# ?
  4. * 输 入 :   0:不支持连续触发(按下一次必须松开才能按下一次): G- E( t! t: W+ [- p  n3 T# o3 D
  5.                1:支持连续触发(可以一直按下)
    . j- F+ r6 x$ x. i; H4 ^6 [
  6. * 输 出 :   0:没有按下  1:有按下
    + r0 q) y5 S5 U, @' J. F5 ?
  7. *****************************************************************/* I) |' z3 s8 y- R  c6 E
  8. u8 Touch_Key_Scan(u8 mode)
    + f+ \: U$ I3 S
  9. {# F9 b/ d& E. z; O) p+ f
  10.   static u8 keyen=0; //0,可以开始检测;>0,还不能开始检测1 m4 d' K5 b  J5 q4 T
  11.   u8 res=0;
    ) ], j* X! ?. @3 S+ n! w
  12.   u8 sample=3; //默认采样次数为 3 次
    4 a( A& H1 j! ^9 S, E+ A5 m8 T
  13.   u16 rval;& Z/ L  X6 k2 D( k+ p# R
  14.   if(mode)
    : j4 d/ @5 D4 l& q" D
  15.   {' F3 [9 Z( x2 u9 f
  16.     sample=6; //支持连按的时候,设置采样次数为 6次. K: E/ x1 |3 ?; f. N4 A* y& D
  17.     keyen=0; //支持连按
    7 F1 T: @- I5 d6 B5 C( F9 {( v% l
  18.   }
    / t: S0 B& p: `7 A/ Y
  19.   rval=Touch_Get_MaxVal(sample);
    1 p! t! A% d. S, H5 c/ m
  20.   if(rval>(touch_default_val+TOUCH_GATE_VAL)&&rval<(10*touch_default_val)) // 大 于 touch_default_val+TPAD_GATE_VAL, 且 小 于 10 倍touch_default_val,则有效
    , d' a: V' d- J8 V' r9 p
  21.   {% e4 k, x" p. j4 t! }
  22.     if((keyen==0)&&(rval>(touch_default_val+TOUCH_GATE_VAL))); Y' z" X! U9 f, D$ U0 j
  23.     //大于 touch_default_val+TOUCH_GATE_VAL,有效0 }4 H. t2 ]: |* D! \
  24.     {
    % A6 c/ w# U2 j0 U9 K
  25.       res=1;: X9 p# c6 _8 V% w+ a$ ~
  26.     }; u* {1 f' ^, U. K) d- {
  27.     printf("触摸后捕获高电平值为:%d\r\n",rval);& ]% r2 Q$ p# _5 t" |
  28.     keyen=3; //至少要再过 3 次之后才能按键有效
    - C' t/ `# w, h' h4 k( a/ h
  29.   }+ ~1 t, w+ s& m8 m  P" v
  30.   if(keyen)keyen--;
    - Y" A, Q0 F; [! q  w
  31.   return res;
    2 e% W3 y: [' D3 m* c+ ]
  32. }
复制代码

* @% W' U% {+ T- X& m
$ t% m! v. w& P
/ C, f; Y' m8 f$ D1 L. o
该函数用于检测电容触摸按键是否有触摸,该函数的参数 mode,用于设置是否支持连续触发。如果 mode=1,表示支持连续触摸,如果 mode=0,表示支持单次触摸。该函数还具有返回值,如果是 0,说明没有触摸,如果是 1,则说明有触摸。函数内部定义了一个静态变量,用于检测控制。
    函数中我们通过连续读取 3 次(不支持连续按的时候)捕获高电平的值,取它们中的最大值与 tpad_default_val+TOUCH_GATE_VAL 比较, 如果大于则说明有触摸,如果小于,则说明无触摸。其中 tpad_default_val 是我们在调用Touch_Key_Init 函数的时候得到的值,而 TPAD_GATE_VAL 则是我们设定的一个门限值(这个大家可以通过实验数据得出,根据实际情况选择适合的值就好了),这里我们设置为 100。该函数,我们还做了一些其他的条件限制,让触摸按键有更好的效果,这个就请大家看代码自行参悟了。
主函数
    编写好 TIM5_CH2 初始化和触摸检测函数后,接下来就可以编写主函数了,代码如下:
  1. /****************************************************************( t  m. v: T$ \$ M/ q: D' C. B
  2. * 函 数 名 : main8 d  z+ q! v& R- [( K6 \' l/ R
  3. * 函数功能 : 主函数/ C$ J( N! W& r2 m" v! b; Z0 p
  4. * 输 入 : 无: [; r- ^! a( ?& u4 C6 _
  5. * 输 出 : 无
    ) [. D: m. R! N5 ?- T4 f
  6. *****************************************************************// u8 T- L8 S$ F5 s4 d1 H' Q" n' O
  7. int main()0 u, W& g# F1 X+ `/ E
  8. {8 y( {, s" A% }1 B0 \! v7 Y1 s
  9.   u8 i=0;
    4 i& K6 h1 I7 m) ^+ h4 @1 w3 x
  10.   SysTick_Init(72);
    % m# y" \! n: k; S* U1 p
  11.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组
    6 ^7 J# v1 o+ G$ M; ?- P5 c& a$ k; _' d
  12.   LED_Init();+ A8 W' o5 v; s( ^5 l2 d
  13.   USART1_Init(9600);
    8 W6 {4 n) U& \+ G
  14.   Touch_Key_Init(6); //计数频率为 12M
    9 T* H( p/ o; |$ g" S+ \+ J
  15.   while(1)
    0 f9 d% a4 d4 C( \" ~" G
  16.   {( J7 A4 v) N: y
  17.     if(Touch_Key_Scan(0)==1)
    , ~8 l) G- J) @( P  f+ f* B
  18.     {7 k8 u7 K5 o" q; m  {6 Q; Q6 E# r
  19.       led2=!led2;
    ) k: e& }% Z( N/ B
  20.     }# f; {4 `+ `% }# k
  21.     i++;
    2 x1 Y( I2 r; q
  22.     if(i%20==0)0 y9 a8 j' O' s6 A
  23.     {/ T; Z& A9 y+ c' B
  24.       led1=!led1;
      }8 y- m$ y( F4 [
  25.     }. K9 z$ R: N) q; \, S  S2 L
  26.     delay_ms(10);
    / b6 D, p! p2 H& a9 H& y0 W' B8 b
  27.   }. R4 w+ D) D9 Z0 W' V7 P
  28. }
复制代码
: q! `7 W* K- w' X( I
    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括SysTick 系统时钟,中断分组,LED 初始化等。然后调用我们前面编写的
/ q8 |# ?% H7 G. v- ?4 a
Touch_Key_Init 函数,我们将 TIM5 的预分频系数设置为 6,此时 TIM5 计数频率为 12MHz,即计数 12 次时间为 1us。最后进入 while 循环,调用 Touch_Key_Scan函数,不断检测触摸按键是否按下,如果按下函数返回值为 1,将进入 if 语句控制 D2指示灯状态翻转。D1指示灯会间隔 200ms 闪烁,提示系统正常运行。
    将工程程序编译后下载到开发板内,可以看到 D1 指示灯不断闪烁,表示程序正常运行。当触摸电容按键时,D2 指示灯状态翻转一次,同时打印触摸后捕获高电平值。如果想在串口调试助手上看到输出信息,可以打开“串口调试助手”,首先勾选下标号 1 DTR框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住, 通过 DTR 状态切换下即可。
    然后设置好波特率等参数后, 串口助手上即会收到 printf 发送过来的信息。(前提一定要用短接片将P_touch排针上的TP与A1短接, 图中笑脸即为触摸感应区,串口助手上先勾选下标号1 DTR框,然后再取消勾选)如下图 所示。

0 l% [5 J/ t  P
微信图片_20220627224919.jpg
: ]7 I6 |% y9 h0 f6 p9 N6 C$ U
微信图片_20220627224916.jpg
! L( {; i; v% Z8 G- d+ _( \. F! c. |
赞 收藏 评论0 发布时间:2022-6-28 18:32

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版