STM32F1定时器实验-外部触发脉冲计数
1 n. O" [4 s ]; W: X" ^之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。9 z! w! m4 N2 Y6 R9 k; G2 ]
按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
/ d% S# O( O, A. D7 S0 A7 h8 U! S
. x8 ^, N; e, S说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:" F2 \4 M& F; B) u8 a
0 x1 v) J- u: _- e3 `
' |" U. z) m% o9 s; N( I8 T8 ?
; x" E2 o8 {; @) n: H( `画的只要你自己可以看懂就行
1 E0 U6 b* N& Q! ?' N9 H/ {% P x- [6 E. M
7 u" v- s. A. U9 S$ v9 o% D代码讲解
' i M* P9 E" }$ x H6 `3 ]( \2 F$ t首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体3 M5 x, v' B; g) O! u% V9 s
- /* USER CODE BEGIN PTD */( M6 C0 E. s Q4 C w: B9 W, s
- typedef enum( C2 L: _2 a. k" S7 q
- {
+ r; W' U1 z* ?% U- H0 Z2 e - KEY_CHECK=0,
$ ?' K2 I2 \# l5 B- R; ?1 | - KEY_CONFRIM,
6 u/ Y, a8 a* U6 r1 A0 Z0 F - KEY_RELAESE
% E9 z! |4 S3 Z - }KEY_STATE;1 H" F8 q4 m9 E( C
- /* USER CODE END PTD */6 e4 m2 [3 P8 K8 V" o: J0 x
复制代码 8 g7 L; z7 t: g
状态变量的定义以及标志位,计数值& e% D5 F' S m1 l
- /* USER CODE BEGIN PV */. z* d) y$ S0 l
- KEY_STATE keyState=KEY_CHECK;
( S; n" I% u7 ]1 R& U( r - int Result=0;& f& Q/ M3 g3 R9 h2 ^
- uint8_t keyvalue=0;
" V' i* d* ?7 Q$ U5 S - : c: Y9 P/ g* [) R9 u) c& }
- /* USER CODE END PV */' [- |% o9 _4 h8 v: U' g
复制代码
, l% }" |; M% V) f对于按键检测,是在TIM6里处理的,选用KEY1即PE3) `; Q" a4 M6 J2 G& e, X/ b
, S6 s* _* O2 a2 ^ ~5 H2 D1 P6 b
( [* L j- x) N' X0 r$ k; S. w1 D8 Q+ F9 O! k) Y# l
8 t: A; I2 U |% W+ n' w8 ]
' `3 M4 q8 }1 V$ F
而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程
5 _6 Y2 `+ U$ S! {) `+ e- /* USER CODE BEGIN 4 */9 O/ V% P$ u/ h( d' A
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
2 o, z( z9 t3 x8 X7 H - {
6 Z9 A2 l8 R2 r9 \! ~: ^; @' s1 v - if(htim->Instance==TIM6)//判断是否为TIM6中断; Y) h# H# r/ i1 V
- {/ C; v5 w8 \* L4 Y; A G0 s- I
- switch(keyState)
0 k* n i, ^/ N* A - {/ i- v% P6 R1 J7 J* J" w X; n( D
- case KEY_CHECK://检测状态下
8 K# I+ ]3 _: E1 m - {
8 Z6 C" Z3 P" h& s - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平
) l/ s* U9 s6 q( b* Q! U - {
. s. A4 F8 |- X2 R) W4 }- T - keyState=KEY_CONFRIM;//确认按下状态: v! _2 k# D$ m/ e' x0 S% e9 w
- }
9 q0 a' \- ~8 n0 B+ {: H, l/ j) B - break;
& Y0 n" U0 Y( ^8 }& y0 \" j' V% N - }0 W. B( x, R u
- case KEY_CONFRIM://确认按下状态下. \6 P. M$ s- e A7 U) e* R
- {
C4 c9 Y- D) j- O, _ - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断
/ t9 n8 s2 s4 K( u# \ - {
' @ n R. s( t' B# w; J$ }' z9 c - keyvalue=1;//改变标志位用于触发脉冲信号' b' {" q2 S2 J c8 O! k- O
- keyState=KEY_RELAESE;//按下后释放 p$ c& e1 I$ ^! Q R. S" I4 i
- }
0 t, F- u) p( I0 G6 A/ N - else
0 ^# h' z/ M8 B2 T: s - {
' M: `4 T8 N$ p$ n - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测$ s9 Z- L, z; _0 y
- }; S! v, f% E5 w5 o3 v1 W @
- break;
1 T* d& L1 @/ R- N( m# [ - }
$ F* S; o9 j* \ - case KEY_RELAESE://释放状态下$ j9 e; @& H! T' W [
- {
! D3 b& r0 t2 V7 @; e3 u1 F3 @# N - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下
$ H4 }6 y' s/ I$ G - {/ Z' z/ b- \# ^8 k) i5 B+ G O' A
- keyState=KEY_CHECK;//回到检测状态 ^" @4 D% ?. J
- // keyvalue=1;
! x3 ]" s8 U3 L2 C; t0 k$ `& D1 c - }/ y" C/ e7 J; E0 I8 |# w8 s
- break;. x4 ]( X& Y5 _8 J
- } q' ?8 S) o+ Q
- default: break;7 K0 m0 Q; j. a9 b! C. N& R
- }
$ `) L6 K6 m- x7 i% L4 {5 ]% `. j7 M - }
1 x$ b) I3 m' E7 u, o+ N2 q( n2 q - }+ E& b3 D4 I: N5 p4 H3 s9 q' H2 _
- /* USER CODE END 4 */
- i7 f! V N) w* `0 c* c
复制代码 ( Z: g: L U4 T' `4 a O% \
主函数内% n3 [/ N( l8 }( |0 h7 d
- /* USER CODE BEGIN 2 */9 ?' D5 d: K, k- a& P
- HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数6 W+ P, l6 E( V
- HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测
3 g" H" o+ k; Z% h - printf("Timer counter founction test: \n");//串口起始提示
" d( P: }: [6 p" Y9 p8 P1 v7 G9 ` - /* USER CODE END 2 */% `6 W# C3 j7 R5 J. V6 d5 A$ k
/ J; _6 U& x) O- /* Infinite loop */* q$ n! D( F! [0 p5 n( a* B: a
- /* USER CODE BEGIN WHILE */( X( C5 k$ j+ }4 E3 W1 u% j
- while (1)
3 x3 ^+ b# U3 s2 u& y. u5 S - {
" P5 g' D+ c' Q% m3 @ - /* USER CODE END WHILE */
1 L) ?3 p* W+ M( X6 @" V& H2 y
& W1 p" x9 x& d M2 n- /* USER CODE BEGIN 3 */
8 C+ K9 X6 i. K+ |: J - if(keyvalue==1)//如果为按下状态) h2 f) @( e# d. ^4 ?
- {
/ a- o# i2 a) e o- ^2 N7 ? - keyvalue=0;
/ n4 {4 S; R0 }7 W8 Y - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
8 D. L5 f: N3 m' W3 p - HAL_Delay(1);
4 m, a5 `- l* U# X; b5 ~1 p' k - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
3 f2 z, u, l; o1 K' ] - HAL_Delay(1);//发出周期为2ms的脉冲6 a9 M0 } }* k7 z
- Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值/ I! c6 _ Z A: b f5 E4 o: I
- printf("Counter:%d.\n",Result);
8 J# `% Z4 ?- }7 [. U" c - }
3 |8 g c9 s7 H# g$ j: }3 i - }$ S- m/ u2 R3 E
- /* USER CODE END 3 */1 t; ~( i) |1 m/ A, b( x
复制代码
9 b! \! |* N6 T/ z! OCUBEMX配置
1 f/ _+ j, C7 Z6 {3 `4 B1.时钟配置外部晶振,主时钟为72MHz% I% E! w/ w7 ]
6 m/ | K1 b" a$ O% w+ c; r5 |
8 `. f( S6 q* z- ?; ~/ x$ ]
' _6 t/ t. X+ ?. }
0 O {$ {" M- |* S6 g7 h; z
- e' S" ^, i, d1 T2.GPIO:选择PA1输出,PE3输入, F& T2 {. Y6 S& ?
3 B6 J1 W8 {3 {: u( k0 z9 j/ _
% B3 |! J0 D& L8 a. l8 D4 O U1 G4 O) p1 M" f0 M5 F# O1 E
3.TIM:
8 p7 z) C% D) V" Q- H- c( RTIM2:Clock Source:外部触发+ |- s/ N6 U% C5 `2 C
( l- C' w( ~ m4 b, y
* u4 N0 u4 m: x; P- h) _8 z7 D; S* K8 |$ H
这时PA0为你的触发引脚
0 ^4 n: i6 y+ i+ w7 w- ~( @7 n" l9 J, o0 @! E9 [9 n
6 E, D+ v' a1 g6 t9 w: ?# N' D+ Q. a! t0 A) P8 C
TIM6:激活并生成10ms中断& B8 L O7 H. l. m, s! @* S9 u
% T9 R7 V" L) B& s m4 t
9 O; m: d. J+ E. D3 R" A% x0 s
: X% i5 ]. ^! r5 w5 X4.usart设置
; Z# |0 C$ N3 Y9 E
- _. @$ } d8 m( E' U/ h
( N& y3 {- b& M: P/ C: z7 v# O2 [3 y% M
5.Project的设置,
, x; K+ X* i& m/ L
- }* l1 e w2 T
7 I/ L: [1 W0 d# I' t+ e
, `$ d: ~) }, \& t7 ?) R; \6 d
还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。" O. S# k! [3 |% q; @& O% T
; d4 f: ] @5 s) I3 ]
$ w) j# J3 R a4 e; X/ y3 C2 W3 n( H* h8 b- N* {6 F
最后生成代码1 ^5 S% W" f5 j
————————————————
" i. N, b1 t9 m, ?: j2 K1 {9 S版权声明:南山笑
8 C3 `4 Q! S/ V如有侵权请联系删除
) p( x7 Z6 ~- D+ D' _: Q
# f+ W" t! W# {
: \( ] k8 O$ D# t9 e( ?8 y |