STM32F1定时器实验-外部触发脉冲计数; z: V1 u" `' c
之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。5 V# x/ i% Y$ N& N+ k5 u
按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
( U6 H2 @6 r# c# M- t6 a! C( ]1 r; u8 V8 I U! R6 }
说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:
: G0 z) c$ L6 ?) m! ]& d& d* Y
2 d! P6 Y$ n' _ }5 R/ Y
! J, p8 A2 O% |' x+ ^ ?- q5 e% |2 s, J5 E* J6 g$ \1 E# R* f4 D( q
画的只要你自己可以看懂就行
- D8 ^- Y: A: _5 I8 {8 w
$ u7 Y4 d% v# G6 g1 N6 T( x8 m$ y7 w' |( {( e2 G' g8 m9 S
代码讲解
5 m% t ^- b. i首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体
& q k2 Q1 R/ p% ?- /* USER CODE BEGIN PTD */
$ j. D' j3 n5 p. h$ q) s - typedef enum
0 |5 ~7 i; Z2 z% I/ t W- @ - {2 U2 |2 F3 W2 E0 _4 D# ^) \+ }2 z& q9 Q
- KEY_CHECK=0,' P1 S! n5 ?# u+ H
- KEY_CONFRIM,
& X% T. T3 _. n( t7 i& V7 z# n - KEY_RELAESE
( |, ]8 w: w$ X8 @4 `/ u9 S5 R7 z* O' X - }KEY_STATE;
% o1 N1 c+ s2 D" H# | - /* USER CODE END PTD */0 E1 ~; D, F. d2 x
复制代码 ! {8 @: |4 z! W }
状态变量的定义以及标志位,计数值$ r/ K9 a5 K$ s
- /* USER CODE BEGIN PV */% p# D4 _7 @8 i3 o/ n
- KEY_STATE keyState=KEY_CHECK;
7 A- ]3 R; Q; i Z - int Result=0;8 s0 P7 I, ^! i9 g) F2 V1 f9 a% g1 X' ?
- uint8_t keyvalue=0;8 n0 D4 l. C, v. a
- 4 [" H" |! f0 _# G* ]$ [
- /* USER CODE END PV */
2 m: i7 ~0 S& [/ N( ^' e4 F
复制代码 " h$ X4 T2 s6 n: G& ? J% V4 X
对于按键检测,是在TIM6里处理的,选用KEY1即PE3- o' K, R. J, h+ N
Q9 F. _9 s' E' H. j$ I
; Y+ ^) H& c% P8 h! M
6 {9 q% w! m8 Q R
7 G8 m- Q3 [: x! A' Q2 A: ^
" @- @! T9 n; h! N6 o8 M" M# P5 |而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程
' C9 ?, y5 x# N- /* USER CODE BEGIN 4 */$ x6 U( l5 ^$ M& v
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)- D2 x* R$ ~9 y; J4 ?) \& O
- {
5 x% n b3 K; k+ O% _' t1 q9 } - if(htim->Instance==TIM6)//判断是否为TIM6中断8 n3 y( Z! N; }6 `
- {4 k. @. N( c3 x- J5 F3 O! K/ z
- switch(keyState)7 X: } o4 H9 Z/ _/ c
- {" d; X6 {- V3 N# {1 Y1 k' l
- case KEY_CHECK://检测状态下+ Y2 p0 h( D& O0 F3 |
- {
{9 ~" G: _+ Z - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平, ]+ p6 V) o2 i* i
- {
% N" R% |: Y6 [8 W5 G - keyState=KEY_CONFRIM;//确认按下状态
' w# R3 g. F) H5 j P5 j - }
0 O+ U1 ~0 \" C( F3 ? - break;
; D2 w4 E% E2 P% J( I8 n; X - }% H6 l u$ J* j- X( x2 P6 L
- case KEY_CONFRIM://确认按下状态下
3 i5 S! U0 O9 z, Y - {
1 ~9 Z# u* t3 V" ?; w - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断
O% a+ K' B* i7 G( t& F# E - {
! {, S* v; |8 W - keyvalue=1;//改变标志位用于触发脉冲信号
" A; \, k! l6 _* { - keyState=KEY_RELAESE;//按下后释放
6 f1 a- [, i, ]: | - }
, R A- o* b, L; | - else * o/ ~8 \- J( Q1 m0 D
- {
( |& |2 I1 d9 T' x* ] - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测3 B1 C& ^# Q) @* g' @3 {7 c4 C
- }) @; q7 t" q2 W: D
- break;
- E, V8 V; E" P0 q' f5 x: N& d9 _ - }, l+ d7 @% D/ A5 j
- case KEY_RELAESE://释放状态下$ X7 p3 \" u' z' q ?& U( s
- {$ ?1 S# J' K/ [( |$ @8 e4 Q# u# M
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下
) h% v0 x: [9 c2 ~& A - {* g5 }( z7 J# [/ C4 G5 b( Y1 r
- keyState=KEY_CHECK;//回到检测状态
7 d+ C6 v/ p a - // keyvalue=1;/ S0 b: o4 J$ @
- }
" |/ z! _0 u$ `, F" B& o6 T" X - break;
8 R1 J J1 Q$ U+ w0 E' ]# {' A - }
& `4 q3 _0 A7 m4 } - default: break;6 C, V v. c n: N+ y/ U
- }8 l, C$ ]7 c2 V2 Q) g% K
- }$ Z& p: P) ~. o" h' z. S, m
- }$ i2 t8 t y$ h7 n
- /* USER CODE END 4 */
& b! [9 w, l! {4 K2 H
复制代码
$ y0 q3 `/ }( b; I& t+ k主函数内
6 r4 X9 r/ X$ a# ~8 p- /* USER CODE BEGIN 2 */+ ` j0 P, a0 x3 M9 i! `7 k
- HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数
6 M7 j, {. m1 n/ w' o - HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测) r7 c2 d8 @. q+ [0 p t) e$ J; j
- printf("Timer counter founction test: \n");//串口起始提示
- r2 X6 i! f5 F - /* USER CODE END 2 */
8 W" l4 h; M* {5 A
% w8 a1 ^$ l% H/ z! l7 d- /* Infinite loop */
, s, G9 X, n3 ~9 ? - /* USER CODE BEGIN WHILE */
+ K, ^) z! h& q! {6 ^ - while (1); l6 {0 [& G. D
- {
' b$ ?& C. v) m* L - /* USER CODE END WHILE */
3 [9 d' }" X3 c* k9 x; a - 4 I9 Z# H3 C4 @
- /* USER CODE BEGIN 3 */3 X* B ^* p4 Q( a R# _# Q
- if(keyvalue==1)//如果为按下状态4 b( X( G) w4 S2 ?
- {
2 u: d) A# s, @, R8 T, T5 ~; g - keyvalue=0;
2 C: ^- M0 D5 T% P; @! Q) e# H - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);" P* l% g$ z; I$ i
- HAL_Delay(1);3 M4 m8 R) n; p
- HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
s4 O( G# i$ j - HAL_Delay(1);//发出周期为2ms的脉冲$ [; }+ F3 f, i- f/ n1 l, o' Y6 `
- Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值
9 Y4 ?# v# o2 |) H* g- A; _. J - printf("Counter:%d.\n",Result);
* Y8 s6 D; W5 e t - }2 k" C/ U! _# z& \+ ]" a1 o
- }" i9 I, l: _0 y& O8 @" }
- /* USER CODE END 3 */7 Q `) w6 a6 i6 Z8 h5 }! W' F
复制代码 8 l3 H7 U) [8 ]- R3 Z3 m. a
CUBEMX配置7 {7 W+ i* e/ U- ?& ^$ I1 R
1.时钟配置外部晶振,主时钟为72MHz1 j* G3 e; u$ I: K$ o1 R: F7 {* w
! p$ Q, {$ k* R7 m; g
0 @2 y" E/ q+ R G) b( j) `2 f9 _, s6 E, v: R& E8 o9 H# Z$ A8 T% d3 j# |. d
0 b: }6 x! @; \5 R8 m& I
/ L# O" O w! U. {+ S; {2.GPIO:选择PA1输出,PE3输入
Q" D* ^) w9 ]1 W: @: G
+ l/ |4 l1 K. q! E) J
) G2 o. T8 y4 y, x
$ F; h: w9 I* l' |& x
3.TIM:
7 H1 ^: N# [1 E. P3 T+ N" dTIM2:Clock Source:外部触发& |2 S. z! D) d/ C. ?/ E, ^
6 j0 R% _( @; t% z
7 |( U0 x- x: |, J: z2 p- j
) q! u7 H: v! l. y2 U% }. E
这时PA0为你的触发引脚
5 E* M5 K' o% H: K' B
( p6 X4 P. q# a* m( J, i+ K
' B* T' @# t' H4 `, ?/ w
; R. N* ]$ ^2 p4 A- P( {$ R& a; RTIM6:激活并生成10ms中断
5 ?, g! U( x8 z+ d1 a
1 m% ^& Z! M0 e- `) m, }* U
% F5 R ]$ K: z9 @
3 w1 q) D8 `1 O; l6 [3 ^
4.usart设置
6 X3 z6 Z& p+ @! o1 v4 m3 v# p1 p5 T3 c
. I: L: S7 X3 z* ^0 j
2 s) p( @2 G" [% i, o+ L
5.Project的设置,
! S3 k8 |: M! z; O/ G
/ `9 d, E- e5 U) n3 x, }
6 x( n! J3 _0 f V2 G( a. t0 O! V* e. _* k( q2 f' z
还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。
# ^2 ]0 j. i7 G' _! R
9 H2 i+ I. N& K! Y
5 Y3 C9 k" X r
7 @ _/ |9 g3 v最后生成代码
# r# o' q: }( F2 x* d————————————————
; B( _. R- o* ?7 ^: N版权声明:南山笑
, z1 Z7 n% \- }$ d' X: U) G如有侵权请联系删除
* t( U8 @! W; p# a" @. s2 X9 [% |/ a/ c( U
! X+ U! p& }2 M" |+ p |