STM32F1定时器实验-外部触发脉冲计数1 h. s! h# \0 }$ f+ G" q3 E& D
之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
6 ?6 ]+ X( |$ `6 A按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
) {) V! J0 x0 G0 H; Z) ?: I# q2 _ [7 B+ |- r4 n
说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:' K0 \5 c8 [9 r5 n1 s
7 R8 m) I4 m [
* g: o7 p: b @# L& W5 C# z' L( n( d0 Q6 m
画的只要你自己可以看懂就行
4 Z7 |# b5 y9 r9 ]+ \ f
- ~9 l: ]; p2 L" Z0 q/ ~5 E, i/ z6 a1 b D8 l
代码讲解8 x4 Y Q) Q8 q( {! l* f4 w) T
首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体
4 \# R. S: c0 G6 y0 E- /* USER CODE BEGIN PTD */" i+ j1 A6 [3 h* d- [; F
- typedef enum& [6 G" t: R% M- p' b" E
- {. Q7 l3 x1 K0 {3 Z& k) w
- KEY_CHECK=0,0 N6 D4 ?) H2 s& p" Z6 |
- KEY_CONFRIM,
! r) c+ |- [/ f Z - KEY_RELAESE* P+ x {0 M8 n. D. A
- }KEY_STATE;
( c6 l3 V2 f7 c! C- e' F - /* USER CODE END PTD */% X: G. M/ Q4 z$ z8 `$ h
复制代码 ) z; ?! P1 S8 n% |
状态变量的定义以及标志位,计数值
' V2 Y# ?- s1 F% c0 b: ^- /* USER CODE BEGIN PV */ q& p' \3 H1 T1 f
- KEY_STATE keyState=KEY_CHECK;
1 p6 f# z& a" ^+ u/ u6 R - int Result=0;
5 V& J1 t5 |# c/ @' Z1 B5 ^ - uint8_t keyvalue=0;6 q i5 w5 B1 H; C: B
' t! h3 a0 {" i8 Q0 l- /* USER CODE END PV */2 O' P, L3 \% R. W! Z9 M
复制代码
9 U' ]5 H$ V4 O: M* k3 D% J9 W0 u对于按键检测,是在TIM6里处理的,选用KEY1即PE3
) \. v/ V- m( V# U% K# f9 F7 E3 Z" t" A
3 E$ l' K' S# O1 `* [+ k3 v& C3 k6 C( y+ c# k
1 X8 L& n& [4 E
+ @+ O) ^2 I. p7 Z而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程
1 Y# |4 k: a: x7 O) k% a- /* USER CODE BEGIN 4 */
, R1 o' t( {9 j2 i, I: c, X - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
0 m# |; b2 }( V+ z ` - {
% ]9 S a# G/ o - if(htim->Instance==TIM6)//判断是否为TIM6中断1 K- R! U2 F' X+ G& Z
- {
6 ^5 Y- f6 ~; U* G - switch(keyState)
4 p9 T3 f3 G$ ~& u0 F1 `% V - {& L* h3 |0 A5 ^( _; F) b! M) X
- case KEY_CHECK://检测状态下$ B$ p ~/ c# J4 C2 r
- {, C- Q& m) b4 p
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平7 ~! b4 p: @5 n3 R) R0 T. T7 O
- {
, o# L, y, f. h; \( X - keyState=KEY_CONFRIM;//确认按下状态( J8 K! @4 i9 [& a
- }% i5 I$ U4 B1 y2 d8 Q
- break;
7 T/ l! g7 \, l - }
( A2 b% M3 Q' m6 S - case KEY_CONFRIM://确认按下状态下
* h( Z; ?/ o `0 N5 ]- e) d - {
% {" |8 p1 G9 A: X. \9 Z* y( E9 r - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断 9 w# P) F! m3 A) Y7 ~0 ~! `0 ], m2 a4 P
- {
5 ^7 S9 S* |" q" {! B, H: z) ]$ @ - keyvalue=1;//改变标志位用于触发脉冲信号; }' |# P7 a! W4 O3 l, Z8 e. B
- keyState=KEY_RELAESE;//按下后释放
! t) q; ^+ d6 w, j - }
1 z) x+ e' S( N8 Q- N - else 1 M* [# I8 |8 i- G2 U9 i
- {
0 g, Z1 e" i; \ h/ _ - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测/ _# R5 l6 [ S' i
- }2 T" D# U8 k( |; }
- break;# l' Z8 a F1 r: D
- }
4 V5 ?% B% N/ H5 \) l0 g+ o - case KEY_RELAESE://释放状态下. Y: U" k; O. y6 h* c A7 h
- {" u* l7 J! g, |- w' t8 j
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下 x4 ]9 A0 H2 f0 P, |$ Y3 J
- {
* C& D4 p w! a A# h' i8 E - keyState=KEY_CHECK;//回到检测状态7 ^0 d6 B$ {2 E6 B6 u9 D0 b; w
- // keyvalue=1;
3 c8 f4 N6 a( |! Q8 E: D - }
' A$ G8 {- y& Q* F F" D/ d$ n4 s3 | - break;
6 l+ D! V9 O5 | - }# h6 f: Q6 Z7 I3 D
- default: break;' z. Y- J. @- E6 g, T9 s1 J% x
- }
0 ]) [" v `4 y- w - }3 V/ m& r, {9 H) y$ U1 n9 T' n( n
- }% O: N1 O2 Z \; Z4 f
- /* USER CODE END 4 */
' ^+ g# C i- v/ C9 Q4 x
复制代码
+ r1 u/ F9 a, h! Z2 p* t3 i主函数内" I+ g& y2 r- N& @. h: J
- /* USER CODE BEGIN 2 */$ `5 i, W' v+ P
- HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数
# [! { H6 j& q0 D( z3 C) t/ G" V7 H - HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测: Z4 O. s/ c1 P+ j8 u/ T2 v
- printf("Timer counter founction test: \n");//串口起始提示
0 h3 c) ^% J# O7 }) v/ L" m - /* USER CODE END 2 */
% q4 s0 z/ ?3 \# ]/ b+ N; s/ \
" C+ Z: e9 y5 K# t, o2 K9 y: Q) s* i- /* Infinite loop */
2 g; m$ r2 B# k3 G. N5 k( m - /* USER CODE BEGIN WHILE */1 j- F0 F6 C5 m4 m4 D
- while (1)
; ?, A$ l3 m! l# K - {
; }) j* D9 j( A7 q# V7 W6 K. ? - /* USER CODE END WHILE */
: C/ u" f j; a( }
$ C& _* {0 X1 U' N1 h) {3 W- /* USER CODE BEGIN 3 */
2 N5 J/ R, q& f% a6 F: g1 x - if(keyvalue==1)//如果为按下状态
; H% ~2 R6 R8 k$ ^- B, m5 L - {
9 P9 m# F2 V* E/ L9 X# \$ F - keyvalue=0;: d# b2 y6 H* u8 f5 { c! z1 |
- HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);( ^( G- M9 f5 r9 d, C! q6 O
- HAL_Delay(1);
8 F( f$ L: z& ^; x# ~- o - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);2 N+ h& z3 t( l
- HAL_Delay(1);//发出周期为2ms的脉冲
% [1 [9 E1 I' z - Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值% y: F7 ~& `* M% B. V' Y
- printf("Counter:%d.\n",Result);& @/ I1 s7 O: h. @# m, u' p; ]' M
- }
) F+ x4 ~! e" ]3 D8 C' y0 m3 Z - }: `) O$ T6 O5 x2 v" H
- /* USER CODE END 3 */, T$ i1 ^: [8 c* D
复制代码
2 I1 N( c1 m% g# t( f/ X! tCUBEMX配置- @9 ?7 P; \) w a$ ^
1.时钟配置外部晶振,主时钟为72MHz
' g e: }) R$ I7 h9 w) y1 e' K" a. D
/ T# a, n8 ]/ \0 `$ ^- D
. J. h. G6 k8 o4 u
! R4 P$ @1 v$ o7 l% H( @$ k) |
- C% \9 c" g% O; t. W k' O& z |! o" t( G8 N
2.GPIO:选择PA1输出,PE3输入" n. n. |" p5 E: J1 I) q2 E7 S
4 j6 x* A9 u* c. e
, B3 a6 V9 H2 Q
9 G+ b: p% x0 x
3.TIM:- T7 i. d0 [6 N! [4 C; j
TIM2:Clock Source:外部触发
5 ^. V3 G6 i2 m, ?' k
5 w# w3 O# h: Z5 M7 n
/ k( f5 P# G- `0 ]# ?& |0 f* k
4 @- X" o9 n5 o3 X
这时PA0为你的触发引脚
; {# b: l) ?% U1 a# f3 f3 s6 {: n& S$ n& n
; O% g, J" E( R) C: j
- a6 p- q) C0 r; fTIM6:激活并生成10ms中断9 y( V% W# R6 ?3 x
+ O2 ]& @' c1 N, X0 U1 D
# p) R2 m7 B/ x
& D6 s; P* g5 S
4.usart设置
; w$ M. C; e$ K0 x- {3 ~% C( I/ K0 c3 F4 O( d
: t9 T- ~, P3 u$ p- w* @0 ]7 w6 \/ C; G. e" d; u# r+ x$ c2 Q5 e& u
5.Project的设置,
) H* `+ H V" I2 ^* Y9 m) G2 \; Q m* ]% g+ X# f/ b) o/ F
J/ c. k7 A' [# I' V
3 g( [5 P. T$ B* f( w* g8 a还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。
& y& r1 X# b( Q- x8 J
5 j8 j) ]* n; S$ W! j; Y
5 H) }% w: N0 x+ t7 y7 V
2 R' x; f8 g- n, ^; [: ^. y最后生成代码4 |7 B1 Z& I+ n3 j+ j0 X( O
————————————————
. u }" |! W/ R. Q3 G3 {7 e版权声明:南山笑/ S" F! h4 p9 a- ^
如有侵权请联系删除
; F" @% n- E! f- |, i& y& m
! S3 F p4 j! u
^# L; L, g/ @0 I |