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

STM32心得:电容触摸按键实验及相关代码解读

[复制链接]
STMCU小助手 发布时间:2022-11-21 19:00
主要内容9 [4 s3 X2 w; x6 y% E# t) M8 `+ `
1) 电容触摸按键原理;1 L7 ?; Z6 M5 m& u; r# L" i
2)部分实验代码解读。
7 K6 i3 ^; M; l& Y% L0 G实验内容
6 t! h5 }1 X: R1 I9 }手触摸按键后,LED1灯翻转。; o# ?% P' X) u  f
% H0 N8 n: {" C: @4 n
硬件原理图
) @8 q* P1 u' P$ d; v$ ~: j% H  \4 t  @0 F
2020042917453099.jpg / M8 ^: D* t# B
上图,TPAD与STM_ADC用跳线帽相连,即TPAD与PA1引脚相连,而PA1引脚也可复用为TIM5_CH2(定时器5的通道2),因此可以用TIM5_CH2进行输入捕获来识别电容触摸。6 y- x& w  O( h4 N/ w. K6 e+ Y" Y# x
* y2 g" w, d1 c0 q
1. 电容触摸按键原理& H# ?8 `* E9 c* f" |# }
1.1 RC充放电电路原理
- d4 m- D) G$ [9 ^- e1 c+ h$ z2 |' u5 g% A' m
2020042917472388.png   L6 S1 w4 {1 i# X6 F  m$ }6 X
3 N, h5 K1 c, f: h( W2 D) i) C
1.2 RC电路充放电公式
" v6 w, M. N5 W+ F# o7 \$ ^2 p! f; S4 N& y, [
Vt = V0+(V1-V0)* [1-e(-t/RC)]# j& T5 O4 {$ Q
$ O- i9 D( K0 P# x$ W. [( B! D
上式中:V0 为电容上的初始电压值; V1 为电容最终可充到或放到的电压值; Vt 为t时刻电容上的电压值。 如果V0为0,也就是从0V开始充电。那么公式简化为:3 d, U. d8 ~+ `( z' }: v; h$ @$ }
Vt= V1* [1-e(-t/RC)]; J9 b, d! [2 U5 m+ ^5 d, F

3 ^# W) U9 b" l4 Y! L6 f结论:同样的条件下,电容值C跟时间值t成正比关系,电容越大,充电到达某个临界值的时间越长。
+ u) w) u0 @- M( v# D/ V* S1.3 电容充电时间与电容大小关系
* `; h: H2 k7 \7 M9 K% D+ n2 L4 ]8 q5 a: C  ^, G- S
20200429221018699.png
7 `' ~# e* L: \2 d  W  E4 H7 g; ^( I' G& e. C/ m
2. 电容触摸按键+ u5 g4 }7 y9 P* v
2.1 电容触摸按键原理* s7 S* l0 d* r+ t4 y9 p2 z* b4 Z: N

! o6 t. M! A% D1 y3 Z: r( ~/ F& {; k 20200429175215265.jpg 2 f& e2 l+ e# [8 p% V6 T
' D$ {. X: p  w
R:外接电容充放电电阻;$ u, ~3 j* m9 }8 N1 J
Cs:TPAD和PCB间的杂散电容;
' F) T, [' Q' {; I0 H. OCx:手指按下时,手指和TPAD之间的电容;
4 Q" C( Y* Z1 [1 Q  s$ |8 Z开关:电容放电开关,由STM32 IO口代替。) ?5 t* Q6 M# |( R- t) @
2.2 检测电容触摸按键过程, M% v0 n( M5 A0 s! ?
2.2.1 TPAD引脚设置为推挽输出,输出0,实现电容放电到0;6 j+ D) `, x! h
2.2.2 TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电;! _7 W: X( D3 n2 A( @$ t
2.2.3 同时开启TPAD引脚的输入捕获开始捕获;
& D& x' `: j6 @6 M/ R2.2.4 等待充电完成(充电到底Vx,检测到上升沿);  ~+ @1 u2 n9 `* c/ N1 ~8 E" d
2.2.5 计算充电时间。
$ S& ^5 Z# \/ a* i( ~没有按下的时候,充电时间为T1(default)。按下TPAD,电容变大,所以充电时间为T2。我们可以通过检测充放电时间,来判断是否按下。如果T2-T1大于某个值,就可以判断有按键按下。
3 y* O( m) z' Y, h. [8 ]/ e* S9 n# k' {9 |4 j; `
3. 相关库函数
0 V4 d: W0 ?8 h. m. {3.1 void TPAD_Reset(void)函数,) N! @% b  B3 {+ D
作用:复位TPAD
4 c6 r$ v1 a& y: r4 [设置IO口为推挽输出输出0,电容放电。等待放电完成之后,设置为浮空输入,从而开始充电。同时把计数器的CNT设置为0。1 R; Q( u2 E5 f! Q
3.2 TPAD_Get_Val()函数,
. V: O6 w  x0 [作用:获取一次捕获值(得到充电时间)
. D: h3 ], }0 Y, P! W复位TPAD,等待捕获上升沿,捕获之后,得到定时器的值,计算充电时间。3 ]0 i% x& S2 Y7 I: F
3.3 TPAD_Get_MaxVal()函数,* M4 x# ~* _6 k2 P- E6 k
多次调用TPAD_Get_Val函数获取充电时间,获取最大的值。
/ c6 a) ?0 X2 ~' E3 T! d+ _3.4 TPAD_Init()函数,
1 T3 y  T0 p& g- L% K5 M6 o作用:初始化TPAD6 X4 A$ z9 {' R/ A& ?: a
在系统启动后,初始化输入捕获。先10次调用TPAD_Get_Val()函数获取10次充电时间,然后获取中间N(N=8或者6)次的平均值,作为在没有电容触摸按键按下的时候的充电时间缺省值tpad_default_val。
9 X4 \( S9 T2 l& z% P' y5 c) n" g3.5 TPAD_Scan()函数,
' w' a" p5 u4 L! ]& S$ ?作用:扫描TPAD  j, Q$ i6 I0 g) u* y$ t. T
调用TPAD_Get_MaxVal函数获取多次充电中最大的充电时间,跟tpad_default_val比较,如果大于某个阈值tpad_default_val+TPAD_GATE_VAL,则认为有触摸动作。. i) l( p  }& J
3.6 void TIM5_CH2_Cap_Init(u16 arr,u16 psc)函数,: e+ K' _$ \, ~7 v0 {! ^; X1 C( H
作用:输入捕获通道初始化' s. A! q9 T) Y- ?# P7 H
可以使用任何一个定时器。M3使用定时器5,M4使用的定时器2。. \% l( A- [8 o5 H. l, N' {2 j
% N0 y" `- u: Y' c$ M5 Q/ N. N' [
4. 程序思路1 [7 Z1 i  B8 ], z

5 R: m) W- E& ~! `! j
20200429175702921.png , V. L/ q2 p. j- C5 g
+ a" `9 {0 C  ~/ G- m0 O3 b$ x
5. 实验部分代码解读
, _' H6 a6 T! f% e
5.1 tpad.h头文件6 _3 d1 Y* {  i$ ^
  q& K" e' n) ~* b, p# W
  1. #ifndef __TPAD_H7 S6 s, w: j, f) m" ~
  2. #define __TPAD_H
    0 w6 \# j- l0 {+ N* Q5 g8 L
  3. #include "sys.h"  ( Y( h( r6 l) e/ |% r9 S2 m
  4. //引用在别的文件中申明的变量tpad_default_cal//
    + f. F6 G7 m' W; A$ O# h/ q  E
  5. extern vu16 tpad_default_val;/ U- ?) C8 W' ~. k) c! Z8 R- @
  6. //*****函数一*****//3 r/ R9 \- m+ n) i) H7 R
  7. //申明void TPAD_Reset(void)函数,无返回值,无入口参数//               9 ~% M* B8 T8 Z+ o
  8. void TPAD_Reset(void);* L" t+ G  I$ q; i7 r7 J1 V* m
  9. //*****函数二*****//
      ~' g6 y; u( p# X
  10. //申明u16 TPAD_Get_Val(void)函数,返回u16数据格式的值,无入口参数//" [8 V+ _2 u" ?' G% f. S2 i
  11. u16  TPAD_Get_Val(void);
    ) V/ ]8 G! c/ r8 W: f  O
  12. //*****函数三*****//! _% G3 h  U4 G$ b, F( v/ W5 P& y
  13. //申明u16 TPAD_Get_MaxVal(u8 n))函数,返回u16数据格式的值,入口参数为8位的变量n//
    % e: h" s/ W9 u0 r/ Z$ g
  14. u16 TPAD_Get_MaxVal(u8 n);1 w5 z8 r+ T0 E
  15. //*****函数四->初始化触摸按键*****//
    1 b' F/ j, @$ [5 Q. \* m# l3 C* C
  16. //申明u8 TPAD_Init(u8 psc)函数,返回u8数据格式的值,入口参数为8位的变量psc//$ N9 Y! y. b" Q8 p* Z
  17. u8   TPAD_Init(u8 psc);  x2 q4 _7 V; O4 \7 O, S8 R
  18. //*****函数五*****//2 |. [2 b" m7 t% w
  19. //申明u8 TPAD_Scan(u8 mode)函数,返回u8数据格式的值,入口参数为8位的变量mode//( \3 K! J, `# P. x. N: T$ }
  20. u8   TPAD_Scan(u8 mode);
    ) L- p, J1 x; ]
  21. //*****函数六*****//
    * o9 C/ Y( f3 X  X" u  R: Q) E6 r
  22. //申明void TIM5_CH2_Cap_Init(u16 arr,u16 psc)函数,无返回值,入口参数为16位的两个变量arr和psc//
    " T3 _9 L; Q( _) ?% O
  23. void TIM5_CH2_Cap_Init(u16 arr,u16 psc);   
    + g  {) B  e& g# x7 h
  24. #endif& d$ o  A& K$ H% f+ t7 w
复制代码
; R  d  n& u  V. O
5.2 tpad.c文件4 t$ w% T2 r- |" d& M
9 X6 X: V" B* x; i# f" Y
  1. #include "tpad.h"
    : a' @9 Q* O& I( d$ O$ u
  2. #include "delay.h"      
    " A0 J8 t0 {. r1 h! I
  3. #include "usart.h"
    . i+ w) a' `  m" k
  4. //定义TPAD_ARR_MAX_VAL为一常量,即0xFFFF//9 }/ L( w% o: ]+ x
  5. #define TPAD_ARR_MAX_VAL  0XFFFF
    5 U9 I+ L5 z. g$ W' c- b
  6. //定义变量tpad_default_val=0,即空载时候(手没按下),计数器需要的时间//. r- S/ z% P9 J+ I3 ~% x- g9 b2 }
  7. vu16 tpad_default_val=0;! @- W2 {5 G% B( e; ^; d  m
  8. //*****函数一—>TPAD复位-void TPAD_Reset(void)*****//
      k5 ]1 l4 f" u) g/ z/ X
  9. void TPAD_Reset(void)
    5 f6 ?7 G9 G2 b8 U1 N9 S
  10. {
    ' [  ]6 {$ u4 C- H$ D/ [
  11.   GPIO_InitTypeDef  GPIO_InitStructure;                  //定义GPIO初始化结构体//
    - g, P) c; p" ]
  12.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能PA端口时钟// # ]; L; b  A- |/ v: ]5 e" Q- F
  13.   //设置GPIOA.1为推挽输出//4 c$ f+ p" [1 h& K
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;              //PA1 端口配置, j) \! ]! v: [0 X. M
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出/ K# M' M* D1 Z: w' F
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //50MHz//7 x9 N! c% }# N# B% c: z: d
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);           
    ( ?6 h9 [2 z6 z: D
  18.   GPIO_ResetBits(GPIOA,GPIO_Pin_1);                      //PA.1输出0,放电//
    + c2 j5 z9 \4 z- j8 y0 L/ n
  19.   //等待5ms//# t1 Y5 e9 Q  D# p
  20.   delay_ms(5);+ x3 ?- F9 P3 e: u
  21.   TIM_SetCounter(TIM5,0);                                //将TIM5_CNT计数器寄存器的值设0//3 M8 L# H# ^; v3 N. C
  22.   TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除定时器5的捕获2标志和更新标志//! ]' k* T/ x) B  M: ]0 a+ j+ K
  23.   //设置GPIOA.1为浮空输入//
    3 ^) w9 X% z1 C6 o$ i# i/ o9 z
  24.   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;    //浮空输入//
    # l+ N1 t; o0 o3 A
  25.   GPIO_Init(GPIOA, &GPIO_InitStructure);                 //再次初始化GPIOA0后,开始充电//               
    ( |: q* g. @2 ]7 z
  26. }
    / M' P% _- h8 i: e1 W
  27. //*****函数二->获得TPAD捕获值-u16 TPAD_Get_Val(void)*****//
    ) u! K& q. ^6 [+ E! w' G/ T
  28. //返回值:如果超时,则直接返回定时器5的计数值;如果没超时,则返回定时器5的CCR2寄存器的值//
    ) |8 v( ]) M( t# `( e: ]
  29. u16 TPAD_Get_Val(void)
    % H- w$ X1 K& q2 Z# i6 o
  30. {       # [" f- c  s  b+ `7 N$ Y
  31. TPAD_Reset();
    / ]7 t) h, |- ^7 Q
  32. //针对TIM5_SR状态寄存器,输入模式下,当第[2]位值CC2IF为1时,即通道2捕获到上升沿,则运行下述括号内代码,否则跳过//
    & m* c  Q0 ~2 B. n: B" W1 T
  33. while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)    9 c! B% z5 b+ w2 K/ Q" B: w+ j
  34. {- {; T9 n4 n- A( J/ r' e1 w! q) P
  35.   //针对TIM5_CNT计数器寄存器,若TIM5_CNT的值大于TPAD_ARR_MAX_VAL-500,返回TIM5_CNT的值,表示超时了//
    5 n0 p! g9 g- e3 j
  36.   if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);" B$ {1 l5 D6 v* h
  37. }; ! K/ Q3 a4 |2 w6 l2 ~9 |
  38. //若没超时,返回TIM5_CCR2的值//
    9 ?% @3 F9 ]0 S# Y& n2 k& q2 n/ R
  39. return TIM_GetCapture2(TIM5);   
    ; z# ~1 u; x' w+ F
  40. }  
    9 j" b$ y% G6 _. [" x" T( Z
  41. //*****函数三->读取n次,取最大值-u16 TPAD_Get_MaxVal(u8 n)*****//
    . [6 @- d3 X$ K) }3 f0 z* J. L
  42. //返回值:n次读数里面读到的最大读数值res//
    & O5 j* w" }* r% z8 n0 M
  43. u16 TPAD_Get_MaxVal(u8 n)' |& T1 K* C8 s+ m) Q' o% f" y
  44. {
    % a" Q6 I) k0 W3 x. F
  45. u16 temp=0;
    2 X/ I7 c& j9 _% I  \7 E
  46. u16 res=0;
    9 b. C- I) {% Z0 Q7 Z, N
  47. while(n--)6 k1 b, D" L0 |# b
  48. {
    4 Z" H3 ~1 G& F2 _
  49.   temp=TPAD_Get_Val();//得到一次值
    & f: q; V2 o( r  E. E' L
  50.   if(temp>res)res=temp;
    ) s+ Y8 C) K0 M' q9 \/ N' W- x  G
  51. };9 s# `. R* x* s- N9 p+ ]" F6 Q
  52. return res;+ S) ]% D% I! L7 {( w% N' z
  53. }  
    ' }  T- t# b8 D0 `
  54. //*****函数四->初始化触摸按键-u8 TPAD_Init(u8 psc)*****//
    5 c" i- |4 B2 z% @1 T1 T9 p# c6 }
  55. //作用:获得空载时触摸按键的取值//; N% ]2 I+ v9 u. y- Q( j( d
  56. //返回值:0,初始化成功;1,初始化失败//  M+ u1 d% ?- K
  57. u8 TPAD_Init(u8 psc)
    1 }9 Y+ O+ u# o$ Q2 D4 O- y8 b4 U
  58. {6 Y& m; v" ?+ k3 K
  59. u16 buf[10];                                 //一个16位,组数长度为10的变量组//6 p# }; N0 V5 l4 X4 `
  60. u16 temp;                                    //一个16位变量temp//
      H, A2 L9 |# c, R# U# t0 }
  61. u8 j,i;                                      //两个8位变量j和i//
    ) ]8 H. A0 S2 r  f4 K' M2 x- ]
  62. TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);   //以1Mhz的频率计数 3 s# e" F7 ~$ w8 r6 A+ R
  63. //10次for循环//( k; W. o( p' g! t) @7 ~9 n
  64. for(i=0;i<10;i++)
    1 a9 T0 N1 T+ N- \
  65. {     $ @/ ?3 A7 J, e$ R6 q# y
  66.   buf<i>=TPAD_Get_Val();                      //将第i次循环获取的TPAD_Get_Val()返回值传至buf<i>中//
    # J% x) @5 {+ f! G  w
  67.   delay_ms(10);                               //10ms延迟//     ! T1 S  p+ v  Y/ a- A
  68. }
    3 S7 {4 v0 N; B2 X( S1 @, _7 D
  69. //*****将buf里的10个数值由小到大排列*****//
    % n, K) D, N6 U+ |, K
  70. for(i=0;i<9;i++)9 b& {. X7 E( [: s6 u& O6 E
  71. {5 B7 q. j9 ~5 J
  72.   for(j=i+1;j<10;j++)- }4 ?5 G: h, g, q" N8 z6 P
  73.   {
    # y: ]4 B( D. A/ {
  74.    if(buf<i>>buf[j]); \6 e- X( z' B4 ~. \, Y
  75.    {/ V0 c/ X4 A2 i' _
  76.     temp=buf<i>;
    ' i( V1 n4 O; B1 m# V+ s' Z
  77.     buf<i>=buf[j];  P& P) i6 S! V# n
  78.     buf[j]=temp;6 V3 U5 A1 B0 _. ]. ]$ [* Q
  79.    }
    / @3 T+ `2 C2 \' N7 }
  80.   }* G' L+ a; s! f9 z& f# [: `
  81. }
    ! X6 r4 v* m5 Y& n5 K6 C* D! W" |! P
  82. //*************************************//  B" M3 N, A: [9 N- d. e% T/ z
  83. //******buf[2:7]六个数据加起来平均******//5 V* V+ J& |; N5 j( p! J' j& [
  84. temp=0;7 m7 f4 O  x& R8 B  y& ]7 S$ @" _4 P% M
  85. for(i=2;i<8;i++)1 r1 n6 a9 d) @: ^" H5 W+ o  N
  86. temp+=buf<i>;
    . Y4 |+ i# l: L0 @7 K* o
  87. tpad_default_val=temp/6;              //赋值给tpad_default_val//% [! B/ T" A. H( t. g+ S6 `
  88. printf("tpad_default_val:%d\r\n",tpad_default_val);
    . G  L5 t& i) \; U9 ^/ J7 c
  89. //若上述计算的均值大于TPAD_ARR_MAX_VAL的一半,则不正常//
    - C) A  f+ V. T) J/ Z: }8 q
  90. if(tpad_default_val>TPAD_ARR_MAX_VAL/2)
    $ a" p# n3 O+ w1 I# p/ ^# H3 I
  91.   return 1;! ~. Z- g* W9 G  B
  92. return 0;                    
    - F% }8 L5 |7 ~0 A4 Z$ A; w
  93. }8 n" p5 R& `, Q
  94. //*****函数五->扫描触摸按键-u8 TPAD_Scan(u8 mode)*****//
    ' i$ a" \6 o, n- J
  95. //mode:0,不支持连续触发(按下一次必须松开才能按下一次);1,支持连续触发(可以一直按下)//
    - D( e8 L; ]. m" B7 M) c
  96. //返回值:0,没有按下;1,有按下; //         
    # U) n( R/ H( `2 y4 r& `
  97. #define TPAD_GATE_VAL  100 //触摸的门限值,也就是必须大于tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.//
    5 w, I8 Z$ b( H: U" ]6 f" g/ X  Q
  98. u8 TPAD_Scan(u8 mode)
    6 y+ C$ o- s& w+ j# m" J
  99. {4 y4 v" W0 V9 @# y* B+ F1 O7 B
  100. static u8 keyen=0;              //0,可以开始检测;>0,还不能开始检测//  
    5 Y& X& w" K; B+ \/ O8 z
  101. u8 res=0;                       //res=0说明按键无效,res=1说明按键有效//
    % u& i, \1 Q% \+ Q& Z2 _/ w$ t
  102. u8 sample=3;                    //默认采样次数为3次  1 V3 g4 s3 X* j; w: j$ i: e
  103. u16 rval;                       //
    - C8 H# g, ?" T" |4 r7 v
  104. if(mode)                        //mode:0,不支持连续触发//
    0 N0 ?$ S5 V& K3 ~( V
  105. {7 s8 M  _# j7 [  r
  106.   sample=6;                      //支持连按的时候,设置采样次数为6次. G0 w3 z/ c" ?: `
  107.   keyen=0;                       //支持连按   
    " i) p, S! x( E' \% Y
  108. }
    : i! R; K0 P/ f# l4 c, i
  109. rval=TPAD_Get_MaxVal(sample);   //连续采样三次,取最大值//. x) _- x! h- ?: @) U
  110. if(rval>(tpad_default_val+TPAD_GATE_VAL))    //如果rval大于tpad_default_val+TPAD_GATE_VAL,则有效触摸//3 ^* ^3 G# b$ g; w# x# Z
  111. {        
    / ]) E/ S, V: g" R1 g
  112.   if(keyen==0)                   //0,可以开始检测;>0,还不能开始检测// 9 y! N7 h- ~  r, h
  113.    res=1;                        //当keyen==0,res至1,触摸有效//
    # n! E3 R+ A( k$ z( y& }% E
  114.    printf("r:%d\r\n",rval);                    
    5 h; S( v$ t& L5 x9 U. P
  115.    keyen=3;                      //至少要再过3次之后才能按键有效//   1 g9 g; f8 z: J* A5 g4 |3 k/ K
  116. }   ) A, z( V: U# E9 l4 Z8 `
  117. if(keyen)keyen--;               //keyen不等于0时,keyen减1//                        
    9 ]/ d8 n2 X4 O& N( o* `/ j; \  p+ y! H
  118. return res;                     //res=0说明按键无效,res=1说明按键有效//) U: a  u5 O% g" S  w% }
  119. }
      k+ L' w+ r  W
  120. //*****函数六->定时器2通道2输入捕获配置-void TIM5_CH2_Cap_Init(u16 arr,u16 psc)*****//2 c1 A1 ~$ M6 R) Z( g/ g  Z0 x3 S
  121. void TIM5_CH2_Cap_Init(u16 arr,u16 psc)- D4 Q1 P3 G0 I7 k
  122. {
    1 R: s3 n2 w: p7 G3 d' @! S' R
  123. //定义GPIO,TIM时基和TIM输入捕获三个初始化结构//) I# F! {% C; o( O) A" s. \4 P- W* n
  124. GPIO_InitTypeDef  GPIO_InitStructure;
    6 z) r1 F& O3 ~4 B3 a2 f  Z! q
  125. TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;0 K( a, x0 E3 o
  126. TIM_ICInitTypeDef  TIM5_ICInitStructure;  a9 }7 x+ l3 W" i
  127. //使能TIM5时钟,使能GPIOA的端口时钟//7 N: h0 k& K  y$ ?& g
  128. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  
    + K# d" L% e1 y( t5 t
  129. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    * z$ X  @/ d% y6 u7 E0 b1 g/ h
  130. //设置GPIOA.1为浮空输入,
    * n0 V+ a$ J# C* P+ T0 k  g9 t8 ~% P
  131. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;     
    5 b5 |& ]$ ^" U
  132. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    ; o7 j6 H  B3 F. A! M
  133. GPIO_Init(GPIOA, &GPIO_InitStructure);  
    3 R- H2 W! \/ u' k% C# g
  134. //初始化TIM5时基//  
    ! f$ _+ e' O2 o
  135. TIM_TimeBaseStructure.TIM_Period = arr;                       //设定计数器自动重装值   % G' v$ g/ l+ e
  136. TIM_TimeBaseStructure.TIM_Prescaler =psc;                     //预分频器     . |# Y, J4 ]& v- u4 A2 q0 Y2 s1 `
  137. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割:TDTS = Tck_tim
    8 n9 r* W- R, _
  138. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数模式
    5 }; y% p" m* b; W3 y2 W) y
  139. TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
    ' N$ z' R5 {! [
  140. //初始化TIM5的捕获通道2//
    , g4 y1 _5 {2 O$ H, `* l
  141. TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2;             //CC1S=01  选择输入端 IC2映射到TI5上2 k' z; P6 D1 n7 ^6 p/ ^4 j
  142. TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  //上升沿捕获
    . l8 K( `/ p3 \5 a( Z6 L; u' e9 Y
  143. TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    ( U% I" d3 o) j7 `0 o3 T+ X5 x
  144. TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;        //配置输入分频,不分频
    ; _) l% T+ j0 h( t
  145. TIM5_ICInitStructure.TIM_ICFilter = 0x03;                     //IC2F=0011 配置输入滤波器 8个定时器时钟周期滤波
    6 @8 L7 A, U5 q
  146. TIM_ICInit(TIM5, &TIM5_ICInitStructure);  ]/ p  t* y7 b1 B0 e
  147. //使能定时器5//
    4 M9 S$ h4 `% T# o# t7 M% g
  148. TIM_Cmd(TIM5,ENABLE );  
    ; }1 G( A, G8 {( ?+ g. h
  149. }</i></i></i></i></i></i>
复制代码

$ Z. A( u* U" r8 Y0 {5.3 main.c文件
3 p5 O* {! _& p' `# Q
7 ?& L& P9 T* k6 i8 y3 u$ l
  1. #include "led.h", {0 X: }6 R. k0 b
  2. #include "delay.h"
    # W: e1 G  f) }9 }
  3. #include "key.h". P4 L( H) Y6 [$ b$ [
  4. #include "sys.h"( j/ E6 S+ {3 b' V9 [
  5. #include "usart.h"
    3 \2 z- m3 I5 w/ k) W- @8 s5 t
  6. #include "tpad.h"
    7 b4 W! M% i( O& S
  7. int main(void)
    9 J9 y( P& @) d& F; E
  8. {
    / j& p( g9 I% \' ]/ O
  9.   u8 t=0;   % A9 [5 E( o+ U# P* ~2 u  k  ^
  10.   delay_init();                                  //延时函数初始化   
    # E& k3 g3 r2 m
  11.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    4 U5 L2 N" R8 ?) _( M8 b
  12.   uart_init(115200);                             //串口初始化为115200
    / |, e( B- I$ m
  13.   LED_Init();                                    //LED端口初始化
    " z/ D  d! `8 S7 z* Q* j, j. Z% n
  14.   TPAD_Init(6);                                  //初始化触摸按键
    ! f1 T( c& R  j! B
  15.   while(1)8 S- P. b6 E3 |% H+ X7 h
  16. {  
      |' _3 a! J, Y* ?+ I* ~" e
  17.    //TPAD_Scan(1)支持连续触发,TPAD_Scan(0)不支持连续触发//
    8 R  F/ I, w5 }2 n. y! h
  18.    if(TPAD_Scan(1))          //如果成功捕获到了一次上升沿,if返回1
    6 `- |) }- T: Q- S; K$ B
  19.   {
    ' |( Y) ~1 z% T0 Q9 |7 @* R0 X% i
  20.    LED1=!LED1;               //LED1取反//
    5 j( ^9 e; {# G
  21.   }
      d3 v4 [5 Z4 U1 \7 O
  22.   t++;
    ' S, d3 F& r! O. ^! n/ ?
  23.   if(t==15)   $ h4 @) v, k- J# G) e/ H( H1 T
  24.   {
    ) |- t& i0 v  I5 c+ m
  25.    t=0;% H% K: k; k( p* s* Y6 g  w0 x, A
  26.    LED0=!LED0;               //LED0取反,提示程序正在运行/ z) t% M, p; z$ ?8 D
  27.   }
    0 o9 t  c0 D9 |* P! i
  28.   delay_ms(10);
    $ ?& d! `) T5 B
  29. }* W/ g' t  w  T- \3 ^
  30. }
复制代码

  A/ z1 W4 n: `9 ?
+ b0 D7 i" V" j3 x% V; _4 n————————————————; z; b. c& Y/ t' j0 i* U$ n
版权声明:天亮继续睡( B: N! L- H) F; {" q, H1 Z# H
% r+ G) i" {6 K# i
$ J6 s5 k9 W* z0 G  s& }
收藏 评论0 发布时间:2022-11-21 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版