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

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

[复制链接]
STMCU小助手 发布时间:2022-11-21 19:00
主要内容, T6 Q2 s  M3 c3 ?3 J7 g
1) 电容触摸按键原理;
" X: i. v) m% r2)部分实验代码解读。
; k$ ]7 m  s4 s" g4 H. r* ^, C: M实验内容; S" C" _/ v( O
手触摸按键后,LED1灯翻转。& v8 q4 Z% v; X3 W3 Q

, ]: J" ~3 \) Z) S硬件原理图
4 ]0 F$ t2 R+ {7 o2 g" H, H
& f6 e$ t9 c9 \ 2020042917453099.jpg $ g, W% r; y/ p' \3 X
上图,TPAD与STM_ADC用跳线帽相连,即TPAD与PA1引脚相连,而PA1引脚也可复用为TIM5_CH2(定时器5的通道2),因此可以用TIM5_CH2进行输入捕获来识别电容触摸。
* ]4 n2 t% |, F4 a1 G9 e+ B& H: n' Z$ Y8 s8 q3 [$ T
1. 电容触摸按键原理
9 Y+ N( O3 V' ]( S7 y/ ]1.1 RC充放电电路原理# x4 H% B- C, i/ B& ]4 S
" h$ g3 ~7 P% P8 ]$ x; V
2020042917472388.png ! t$ t' y2 G5 `; ^' i+ X
( O& |  h# J# x! S! J. D+ g- F
1.2 RC电路充放电公式
% A) J6 u" f4 R# ~. o; g2 v% o$ G0 y% V* x4 X; d, U( |, R& [2 h, P1 {
Vt = V0+(V1-V0)* [1-e(-t/RC)]" W' c' _9 M- Y  S( ^( `, G0 k

. ?3 k; E4 G; \% o) I7 z. O上式中:V0 为电容上的初始电压值; V1 为电容最终可充到或放到的电压值; Vt 为t时刻电容上的电压值。 如果V0为0,也就是从0V开始充电。那么公式简化为:: n9 F  B* P/ R' M' k
Vt= V1* [1-e(-t/RC)]3 l' T8 W, L7 w  j' L

+ U7 O: n1 H# H结论:同样的条件下,电容值C跟时间值t成正比关系,电容越大,充电到达某个临界值的时间越长。
$ i: Z9 c  e7 u# i5 z# x: a4 ?2 a3 B- ]1.3 电容充电时间与电容大小关系
) k8 H. g# D3 [7 z" S- l5 B" U; N" e. v% ?6 ~# x6 f6 y
20200429221018699.png
7 ?0 w' p+ c  j( X# G# V+ L) X0 S+ x& T
2. 电容触摸按键
% B& R5 C0 E1 f& `6 y2.1 电容触摸按键原理
3 a8 N0 o  e4 c7 ^
& Z% q4 J' J2 C4 T- \% i( L1 w 20200429175215265.jpg ! i5 f3 ]; X; J
( T" c1 y% D& h/ I8 H) `
R:外接电容充放电电阻;
5 ^3 O. T5 K  T( }- NCs:TPAD和PCB间的杂散电容;
8 @; `# `% v  O; A) oCx:手指按下时,手指和TPAD之间的电容;
0 |. @6 X/ d1 z3 `6 ~, V开关:电容放电开关,由STM32 IO口代替。
, U! F6 o4 c0 H- b1 Y9 i: {2.2 检测电容触摸按键过程' A  U! g! Q9 M! E9 y1 I
2.2.1 TPAD引脚设置为推挽输出,输出0,实现电容放电到0;
" ]  }; R$ i( S  u2.2.2 TPAD引脚设置为浮空输入(IO复位后的状态),电容开始充电;% b1 i  B3 P9 U" A
2.2.3 同时开启TPAD引脚的输入捕获开始捕获;
% I6 j8 E; ~$ K* q6 h2.2.4 等待充电完成(充电到底Vx,检测到上升沿);% T# K3 d, V, q; j% q
2.2.5 计算充电时间。
0 V) ]; y) ?. d# X  z没有按下的时候,充电时间为T1(default)。按下TPAD,电容变大,所以充电时间为T2。我们可以通过检测充放电时间,来判断是否按下。如果T2-T1大于某个值,就可以判断有按键按下。/ N8 y- d; i# }, e/ j, q

4 B! b& ]: z- X( K: {; q3. 相关库函数3 F2 c- _1 p; |- Q/ n6 Y
3.1 void TPAD_Reset(void)函数,
  k9 E1 U5 U; \! R作用:复位TPAD8 t: R9 w+ L( J# v7 d: P5 ]
设置IO口为推挽输出输出0,电容放电。等待放电完成之后,设置为浮空输入,从而开始充电。同时把计数器的CNT设置为0。1 _+ Q# M9 H) Q5 P4 l
3.2 TPAD_Get_Val()函数,7 [- p6 D& U9 K) ?$ U- U
作用:获取一次捕获值(得到充电时间)" ^( I2 h" ~: m, M7 B; p
复位TPAD,等待捕获上升沿,捕获之后,得到定时器的值,计算充电时间。
) _# O2 f, a7 Z. R5 G% r3.3 TPAD_Get_MaxVal()函数,
9 V* F1 ~9 u; ~8 Y' B( k0 Z( q多次调用TPAD_Get_Val函数获取充电时间,获取最大的值。& G. I) W9 V" q; l
3.4 TPAD_Init()函数,% G" V8 b0 o7 {/ s
作用:初始化TPAD
6 o" n- {& b, M: C" b在系统启动后,初始化输入捕获。先10次调用TPAD_Get_Val()函数获取10次充电时间,然后获取中间N(N=8或者6)次的平均值,作为在没有电容触摸按键按下的时候的充电时间缺省值tpad_default_val。! x8 K& E) `7 Q+ g0 u
3.5 TPAD_Scan()函数,
$ z0 x* o4 A9 y0 B作用:扫描TPAD; Q! _" B, o' M
调用TPAD_Get_MaxVal函数获取多次充电中最大的充电时间,跟tpad_default_val比较,如果大于某个阈值tpad_default_val+TPAD_GATE_VAL,则认为有触摸动作。
* ~; y9 B! u/ p; Q: z: d3.6 void TIM5_CH2_Cap_Init(u16 arr,u16 psc)函数,
$ I; ]6 Q3 B9 f4 f& e, E作用:输入捕获通道初始化3 A% k- W* q$ l, ^0 z, I4 t6 {6 z
可以使用任何一个定时器。M3使用定时器5,M4使用的定时器2。; X# z5 H- M9 U% |- |: l
3 J# x& h9 x5 `- J6 n
4. 程序思路
8 R9 H8 b2 [( [* ]5 s3 c  m- ^7 P
7 L3 n, g) e3 x. ]$ |
20200429175702921.png
+ L; s6 `# _$ [& H' }
4 H$ w$ \: u& @! ~9 d7 S5. 实验部分代码解读

- K. |( \$ E, L  Q" @5.1 tpad.h头文件3 u0 j& F2 c, P2 i

3 i" [' ?& w: Y( ]+ g' B
  1. #ifndef __TPAD_H# A/ t6 b8 M# {4 A( W2 x2 Y7 S
  2. #define __TPAD_H# `0 `- g5 S3 i& y
  3. #include "sys.h"  
    9 M" E7 b' M% ^* C
  4. //引用在别的文件中申明的变量tpad_default_cal//
      v4 D1 \& u2 C3 V
  5. extern vu16 tpad_default_val;/ H: L- ?6 v+ Q5 R. X
  6. //*****函数一*****//7 Q: A# _% \! {! x
  7. //申明void TPAD_Reset(void)函数,无返回值,无入口参数//               : a8 n) L$ L$ U. L( b7 a. [% Q& }; t
  8. void TPAD_Reset(void);) @& y4 o6 A3 c9 ~8 w; @6 m$ n
  9. //*****函数二*****//
    0 F6 |2 {5 u; h+ `  z! }
  10. //申明u16 TPAD_Get_Val(void)函数,返回u16数据格式的值,无入口参数//
    5 |7 b2 G8 x9 g. x9 J  P
  11. u16  TPAD_Get_Val(void);7 c4 e7 r6 R$ n; \
  12. //*****函数三*****//
    : E8 R% ]1 [9 x) g7 }( w% q, A; X
  13. //申明u16 TPAD_Get_MaxVal(u8 n))函数,返回u16数据格式的值,入口参数为8位的变量n//2 a9 R5 Y+ P  O0 g( u1 b: b
  14. u16 TPAD_Get_MaxVal(u8 n);% f" j% o, B7 X. t# P
  15. //*****函数四->初始化触摸按键*****//' \# C# v5 {# f4 O4 T2 Z- M+ Q
  16. //申明u8 TPAD_Init(u8 psc)函数,返回u8数据格式的值,入口参数为8位的变量psc//
      h/ ?% I3 e/ [9 i: K6 \% a1 K3 h
  17. u8   TPAD_Init(u8 psc);
    0 V1 ]6 _- {8 P' `0 {( B; z
  18. //*****函数五*****//! L; |. H0 s  h% N* p1 j
  19. //申明u8 TPAD_Scan(u8 mode)函数,返回u8数据格式的值,入口参数为8位的变量mode//( _5 t+ i4 n' S0 G* T# v5 j
  20. u8   TPAD_Scan(u8 mode);; N0 n! T) t% t; P+ u; E+ C* v- Q
  21. //*****函数六*****//
    . w+ }+ I# W. s- H9 f' g
  22. //申明void TIM5_CH2_Cap_Init(u16 arr,u16 psc)函数,无返回值,入口参数为16位的两个变量arr和psc//( @3 t* \5 Z7 `2 `8 O2 _; ~/ z
  23. void TIM5_CH2_Cap_Init(u16 arr,u16 psc);   
    ) z! H. p( o/ G3 u4 y
  24. #endif$ V" r+ r$ E% p5 Q, K9 a8 X7 v
复制代码

" t8 _. Q2 J8 @3 h) i% [3 H' Q5.2 tpad.c文件& D" U0 |9 R% D' F

# s8 ?% s- V! I5 D! H, m2 |
  1. #include "tpad.h"
    : \9 J1 z8 h2 |7 m7 r: [  b
  2. #include "delay.h"      8 j, o7 G! W  \9 K' q4 {( t" G# R5 a
  3. #include "usart.h"
    7 I% S% y/ D% p" f; J0 g1 I
  4. //定义TPAD_ARR_MAX_VAL为一常量,即0xFFFF//: Y6 E; a. w  n
  5. #define TPAD_ARR_MAX_VAL  0XFFFF
    8 x, |" O# ]  g; M, @
  6. //定义变量tpad_default_val=0,即空载时候(手没按下),计数器需要的时间//
    & d- N% J1 J7 N) S- h
  7. vu16 tpad_default_val=0;/ T/ ^& n' `# X4 p( D
  8. //*****函数一—>TPAD复位-void TPAD_Reset(void)*****//
    * V+ ^5 t( A! e" d# A
  9. void TPAD_Reset(void); w! z/ j3 T  r: K4 c1 {4 L! \9 m. K
  10. {
    , J) [9 E" D! c& z8 A& M  w
  11.   GPIO_InitTypeDef  GPIO_InitStructure;                  //定义GPIO初始化结构体/// p6 b# v7 N  c, H% O3 e
  12.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能PA端口时钟//
    ( e/ \/ [2 l) }5 K  D: [
  13.   //设置GPIOA.1为推挽输出//+ ?4 e& m0 [+ r. r
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;              //PA1 端口配置, S) A4 }4 N( S  ~" {( m
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
    ) e& s1 n2 ?% ~  y0 r/ |
  16.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //50MHz//& z; G1 Q- V0 L, u2 |8 }8 W7 H
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);           
    # N6 F! E! J! Q& h  y5 E
  18.   GPIO_ResetBits(GPIOA,GPIO_Pin_1);                      //PA.1输出0,放电//  A& n0 [' g" ^8 N# u
  19.   //等待5ms//
    5 A5 Z6 a& H: B
  20.   delay_ms(5);5 ?/ v/ z4 I* R+ o
  21.   TIM_SetCounter(TIM5,0);                                //将TIM5_CNT计数器寄存器的值设0//
    ) `$ x+ ^* `2 a4 Q6 A0 w
  22.   TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除定时器5的捕获2标志和更新标志//# N' d& [4 B, ~
  23.   //设置GPIOA.1为浮空输入//
    # P& ?2 @! |+ v& I) u) [
  24.   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;    //浮空输入//. Q# O8 G" q- p2 E: Z" B" ^  `
  25.   GPIO_Init(GPIOA, &GPIO_InitStructure);                 //再次初始化GPIOA0后,开始充电//                  m7 t7 Y: a% B3 q! ]: K5 b
  26. }1 U" F/ C6 E3 V% D
  27. //*****函数二->获得TPAD捕获值-u16 TPAD_Get_Val(void)*****//
    : E. q& V, ^* h' F! z6 [* U* ^* T' n
  28. //返回值:如果超时,则直接返回定时器5的计数值;如果没超时,则返回定时器5的CCR2寄存器的值//
    4 Q/ v* f: e* P- f. n! |5 Z- W5 c
  29. u16 TPAD_Get_Val(void)
    9 i/ ]  k1 X" g/ L
  30. {       0 B/ l' C# b6 Z# J
  31. TPAD_Reset();( v$ l8 {- U4 B
  32. //针对TIM5_SR状态寄存器,输入模式下,当第[2]位值CC2IF为1时,即通道2捕获到上升沿,则运行下述括号内代码,否则跳过//
    : o1 r4 ~* R3 m& g  h+ b" M
  33. while(TIM_GetFlagStatus(TIM5, TIM_IT_CC2) == RESET)   
      I# x5 p! H1 N5 Z
  34. {
    9 y$ B) a9 S, Q; k: g% J& C
  35.   //针对TIM5_CNT计数器寄存器,若TIM5_CNT的值大于TPAD_ARR_MAX_VAL-500,返回TIM5_CNT的值,表示超时了//
    ) h0 q( o& J& h. u
  36.   if(TIM_GetCounter(TIM5)>TPAD_ARR_MAX_VAL-500)return TIM_GetCounter(TIM5);
    # C$ Z$ q4 J2 m0 [) y$ I# z
  37. }; 8 i% P+ h; S( D! r2 I! ]
  38. //若没超时,返回TIM5_CCR2的值//
    0 }1 j9 M0 J) t3 t* G% I/ f
  39. return TIM_GetCapture2(TIM5);   
    ; ^) N/ F  R+ l
  40. }  
    ' Q6 ^% j* }, `7 i$ |: f( R
  41. //*****函数三->读取n次,取最大值-u16 TPAD_Get_MaxVal(u8 n)*****//9 v( ^2 k% G, l8 |0 ~
  42. //返回值:n次读数里面读到的最大读数值res//
    ! M" e+ V( b# b4 U; ]+ c3 b9 h
  43. u16 TPAD_Get_MaxVal(u8 n)
    " k1 D0 _- ?7 |6 E
  44. {6 X; C6 g0 y& K
  45. u16 temp=0;$ ]% @9 i/ W/ l: h7 f
  46. u16 res=0;$ X- N: [3 S- v. o+ v  G. t
  47. while(n--)* C$ m' s) m- [: S$ o/ F
  48. {# t9 _! |) S9 x: \% i9 w$ |/ c
  49.   temp=TPAD_Get_Val();//得到一次值
    4 `/ Z/ ^: V. j* R6 R
  50.   if(temp>res)res=temp;2 K* I  I# Q4 B  h6 \
  51. };
    ( H1 E: ?" t# F' G+ Y
  52. return res;
    5 j7 U2 A6 N& [
  53. }  4 P" t& t0 z+ \+ y% d
  54. //*****函数四->初始化触摸按键-u8 TPAD_Init(u8 psc)*****//6 E, p- f! j* B+ Y+ L
  55. //作用:获得空载时触摸按键的取值//- ~7 E% U/ |9 q2 q! B! Q
  56. //返回值:0,初始化成功;1,初始化失败//
    8 ]7 X# i/ Z; O2 L) T3 a5 j
  57. u8 TPAD_Init(u8 psc), _' `9 T7 e+ d6 n( j2 n
  58. {! }- C1 |! H' G3 x7 U
  59. u16 buf[10];                                 //一个16位,组数长度为10的变量组//* R) \. V  J# r* u$ j* m# b
  60. u16 temp;                                    //一个16位变量temp//
    ) Z; I$ ^% k* ^7 f1 W
  61. u8 j,i;                                      //两个8位变量j和i//5 ?2 S$ L( Z$ q, v2 F5 b  ^7 z
  62. TIM5_CH2_Cap_Init(TPAD_ARR_MAX_VAL,psc-1);   //以1Mhz的频率计数 ; v  T. T  i0 F' R* r
  63. //10次for循环//
    9 o" h/ g  ^3 K  K
  64. for(i=0;i<10;i++)& I! q2 t  r1 P
  65. {     ) B9 y4 u, W% E$ E5 l4 P% W9 E
  66.   buf<i>=TPAD_Get_Val();                      //将第i次循环获取的TPAD_Get_Val()返回值传至buf<i>中//8 n9 i; _  h$ W# x& n' P" l
  67.   delay_ms(10);                               //10ms延迟//     
    * n# S5 \5 Z+ L8 |
  68. }
    ) Y# y$ v! `4 ~3 m# A
  69. //*****将buf里的10个数值由小到大排列*****//$ Y4 O8 x6 Z5 A/ f+ I( y# }
  70. for(i=0;i<9;i++)
    $ _% @2 M) u* v
  71. {
    % j, n2 r5 L1 r- Y
  72.   for(j=i+1;j<10;j++)8 z% n6 r  O# H) R: A2 u
  73.   {
    9 a1 j$ @5 Y, y+ s% a+ Y! e
  74.    if(buf<i>>buf[j])& `- y# x8 P- S5 t
  75.    {( k. `1 Q6 K( l2 N3 l. @
  76.     temp=buf<i>;6 M8 ]; ~& A; t. C
  77.     buf<i>=buf[j];# x( a5 Y! r* v/ Z) c, b1 c' R/ S
  78.     buf[j]=temp;
      F9 Z. N  n' x% [- |
  79.    }6 Y$ f, i" u) a. c$ y* B# Y4 j4 p
  80.   }4 z7 \+ b2 w' v" i  k: ?3 h+ @: T
  81. }2 n7 d" Y5 m1 n
  82. //*************************************//  v& h; l1 U# v) e! ?
  83. //******buf[2:7]六个数据加起来平均******//- p9 g( A) t$ ?
  84. temp=0;9 @) V! \4 X# a/ M% f, N
  85. for(i=2;i<8;i++)$ m5 m% N2 F/ o! p2 h7 f# T
  86. temp+=buf<i>;
    9 x7 t5 O6 l! G8 h
  87. tpad_default_val=temp/6;              //赋值给tpad_default_val//( C3 r$ E& ^+ R- j' t' f" O
  88. printf("tpad_default_val:%d\r\n",tpad_default_val);
    * x, l% ~8 W7 d/ R7 X# J7 {) ?3 v& K
  89. //若上述计算的均值大于TPAD_ARR_MAX_VAL的一半,则不正常//
    8 |! z9 O: m8 ]* O
  90. if(tpad_default_val>TPAD_ARR_MAX_VAL/2)4 q  f3 A0 J9 R
  91.   return 1;
      W4 ^5 O* V5 Z* M1 x2 w8 C8 }
  92. return 0;                    
    - ]' z2 j' z  f. S1 j! Y
  93. }0 j6 Q$ z! t! n$ O" ^0 D
  94. //*****函数五->扫描触摸按键-u8 TPAD_Scan(u8 mode)*****//) R0 [* @+ \3 J; H5 L- g
  95. //mode:0,不支持连续触发(按下一次必须松开才能按下一次);1,支持连续触发(可以一直按下)//
    * z/ f- K! f5 t3 U: d
  96. //返回值:0,没有按下;1,有按下; //         
    0 l8 j) [! p5 `" l  p+ `% h, g
  97. #define TPAD_GATE_VAL  100 //触摸的门限值,也就是必须大于tpad_default_val+TPAD_GATE_VAL,才认为是有效触摸.//
    % ]! Z* r6 C5 c3 P* l6 W: p
  98. u8 TPAD_Scan(u8 mode)
    , T  L" [( p8 r5 b6 m
  99. {
    5 n3 E; L7 t( Q. m
  100. static u8 keyen=0;              //0,可以开始检测;>0,还不能开始检测//  
      o7 ?# P' Z8 B
  101. u8 res=0;                       //res=0说明按键无效,res=1说明按键有效//' t( V% b+ m2 T0 i+ r; ]0 j$ u( d( I
  102. u8 sample=3;                    //默认采样次数为3次  
    ; p- _/ `! S0 `: M
  103. u16 rval;                       //5 h: E0 k! {  b3 s( ?
  104. if(mode)                        //mode:0,不支持连续触发//
    . t! R0 q8 X5 @" Z; p! K" M) k# a
  105. {
    9 V  A2 X+ ~( Y9 o' @; V
  106.   sample=6;                      //支持连按的时候,设置采样次数为6次& p6 A$ h' @8 k' B4 x0 L  ?3 F
  107.   keyen=0;                       //支持连按   % `5 s$ O$ P& R' ?5 H' Q7 o
  108. } $ |) `8 O& r3 z/ N
  109. rval=TPAD_Get_MaxVal(sample);   //连续采样三次,取最大值//( B9 |, q5 ?" X% o& ^
  110. if(rval>(tpad_default_val+TPAD_GATE_VAL))    //如果rval大于tpad_default_val+TPAD_GATE_VAL,则有效触摸//- j$ f; m4 h. O, Y9 l
  111. {        3 f4 Z& U  o: i! v8 H
  112.   if(keyen==0)                   //0,可以开始检测;>0,还不能开始检测// 9 w. v$ Q0 G. X! A0 S
  113.    res=1;                        //当keyen==0,res至1,触摸有效//
    ) R5 u% H& m, k4 J0 g
  114.    printf("r:%d\r\n",rval);                    & V' M+ {0 s2 c# L
  115.    keyen=3;                      //至少要再过3次之后才能按键有效//   2 [/ G( c8 g2 n7 m
  116. }   
    - ~4 y% c% A/ s' _
  117. if(keyen)keyen--;               //keyen不等于0时,keyen减1//                         % ~+ `) f1 J% k, u0 r+ j
  118. return res;                     //res=0说明按键无效,res=1说明按键有效//. V* ?: s! G/ p  a$ G
  119. } / v/ K  z* x8 N4 A
  120. //*****函数六->定时器2通道2输入捕获配置-void TIM5_CH2_Cap_Init(u16 arr,u16 psc)*****//
    : S5 v- S$ `+ H
  121. void TIM5_CH2_Cap_Init(u16 arr,u16 psc)3 }/ h6 U( E% m+ U
  122. {
    - j, V: L, B  O' W+ Y4 M; y, {
  123. //定义GPIO,TIM时基和TIM输入捕获三个初始化结构//8 B  V- Y6 G# `" }9 Q" _& f
  124. GPIO_InitTypeDef  GPIO_InitStructure;
    ( y# j! n5 A; r! d; J
  125. TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;9 @4 s3 U0 h. W, j
  126. TIM_ICInitTypeDef  TIM5_ICInitStructure;, r" z$ o% s( r9 d, k
  127. //使能TIM5时钟,使能GPIOA的端口时钟//" W& L! Z6 ?+ [. \" `6 g4 ^/ [- A
  128. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);  3 U+ G1 o$ A' T# J+ Y) M5 R" c
  129. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); ; I, ^- A* @) m  w+ S! w" n1 m
  130. //设置GPIOA.1为浮空输入,
    5 s7 c4 B0 B0 k) E
  131. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;     
    # R6 V- d  N$ C/ N
  132. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    5 b% R" D+ M5 u
  133. GPIO_Init(GPIOA, &GPIO_InitStructure);  ) j& Z' t8 E6 V5 l* ^  t3 K
  134. //初始化TIM5时基//  
    ) Y2 ?; M: x( w( ]8 j$ I$ a' H
  135. TIM_TimeBaseStructure.TIM_Period = arr;                       //设定计数器自动重装值   1 }6 P8 u# x- Z' q
  136. TIM_TimeBaseStructure.TIM_Prescaler =psc;                     //预分频器     
    5 E) O: A3 j' {
  137. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割:TDTS = Tck_tim. c- a7 D8 ?) k/ h% Q) D
  138. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数模式! E' R$ f" q" G  z& L
  139. TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
    $ M# h' c; R* r; q8 T! j* P+ ^
  140. //初始化TIM5的捕获通道2//, l/ |3 G2 n/ y, R* K# }
  141. TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2;             //CC1S=01  选择输入端 IC2映射到TI5上
    ' f* g& ~4 Z$ h$ ?5 I
  142. TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  //上升沿捕获/ k1 x7 j6 _7 Q6 @. x# o- g
  143. TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 4 J1 x+ x* ~# A0 N, s
  144. TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;        //配置输入分频,不分频
    5 z5 }: O, B. M# ]
  145. TIM5_ICInitStructure.TIM_ICFilter = 0x03;                     //IC2F=0011 配置输入滤波器 8个定时器时钟周期滤波
    ( w) ?, u. E. `+ p- T
  146. TIM_ICInit(TIM5, &TIM5_ICInitStructure);* X) g7 g% Q8 e5 `) j( d
  147. //使能定时器5//& J3 i6 o) J- B7 E5 `
  148. TIM_Cmd(TIM5,ENABLE );  ) x# {# z) o" W
  149. }</i></i></i></i></i></i>
复制代码
, h2 a. ]9 H1 P$ n
5.3 main.c文件
. k0 ]; e# F! u! q, ]; _; w* U  v7 g
3 o3 p$ l0 @/ m: s7 v) e/ v' M
  1. #include "led.h"$ [- E" d: l  F) g  K0 s
  2. #include "delay.h"& G' O$ y6 n) I* a+ W! U# g
  3. #include "key.h"
    1 ]+ K9 J5 Q2 K
  4. #include "sys.h"
    " H$ P  C3 e" D$ X) o! O
  5. #include "usart.h"
    8 ?9 T! {, H  H4 J
  6. #include "tpad.h"
      F; r8 m. W# W0 h5 }( D. ?* ^4 G
  7. int main(void), d. {4 _* L8 }& r( j! r
  8. {
    3 ]( ?4 E/ G8 |0 x% b. ?! j
  9.   u8 t=0;   
    4 m  r! L, k$ m3 Z* J' \3 |
  10.   delay_init();                                  //延时函数初始化   
    8 J; f  ]1 T8 @( t
  11.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    ! ~. S/ K( u' K" b
  12.   uart_init(115200);                             //串口初始化为1152003 c/ b  i& _; P- R
  13.   LED_Init();                                    //LED端口初始化  E  J% p. R# N; J2 m" v+ G, P
  14.   TPAD_Init(6);                                  //初始化触摸按键# Q2 t" S- F3 W2 ^; ^' I
  15.   while(1)
    3 Y! c* H# g0 p
  16. {  1 P2 V- `4 \$ V. o' c' I' L
  17.    //TPAD_Scan(1)支持连续触发,TPAD_Scan(0)不支持连续触发//
    + N' o; T& J7 N" j
  18.    if(TPAD_Scan(1))          //如果成功捕获到了一次上升沿,if返回1% v$ }: z5 t3 g: O
  19.   {
    8 A! R  v7 `# g/ M
  20.    LED1=!LED1;               //LED1取反//
    ; F1 `9 v, M& n8 z3 U
  21.   }
    % A2 T* n5 f& B! J* Y& }+ D6 p
  22.   t++;5 H, u. G" W' Q9 N5 q  \
  23.   if(t==15)   
    ! t2 p- p' ]! u0 p' @
  24.   {
    1 ^: w8 U6 |- W8 r
  25.    t=0;7 m( J, o4 v, m. ?
  26.    LED0=!LED0;               //LED0取反,提示程序正在运行4 H! }. c% W, R& S
  27.   }
    3 k' f' E$ o7 `0 ^# E: X
  28.   delay_ms(10);$ l& P0 }* D+ D& b6 c$ }' c
  29. }* l" t' B1 ~4 z! E; {
  30. }
复制代码

# q! R$ s; }/ ^
0 D- J6 _) Y! x% d0 L& M————————————————
  ]# U" }! d) p- G版权声明:天亮继续睡/ _7 H6 F6 h, \+ F
1 |- D( O- e' H7 m( Z
& s$ t7 a) n" x+ \; H- ]
赞 收藏 评论0 发布时间:2022-11-21 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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