STM32F1定时器实验-外部触发脉冲计数
- F/ y3 S: Y% y( w! |; T; p之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
9 Z, K# t. v5 y按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
/ U* `; Q$ _0 s$ `5 n1 R7 O( ]% C$ P
) J n* ~; T( q4 r' g% `* X说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:
/ {7 e7 J7 ~8 {1 C
5 A5 j* u2 Q4 Z1 t
# W, c/ q$ e+ ^8 i
9 O1 V' S0 k9 G) j# x* S
画的只要你自己可以看懂就行 D6 M) w. r) C
- l- q5 [' M7 Z' ]
* a( {; U/ W% u$ M0 s& u7 D
代码讲解
4 U, H- ]; v3 m- r7 I* \首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体* |* g5 T. a8 } M0 ?$ [9 D( Q7 Z. s
- /* USER CODE BEGIN PTD *// X1 W! u0 X; P+ @& G
- typedef enum# i# n0 x! }5 {' {
- {4 e" r$ p2 z9 T. ~$ U" n {4 l [
- KEY_CHECK=0,
( c$ D5 x) z( o9 a - KEY_CONFRIM,
4 N' U. J* S a - KEY_RELAESE& U. s+ F( `' {* D- X5 m" w
- }KEY_STATE;
3 u6 c1 O5 _1 p. c - /* USER CODE END PTD */# Y) i) Z3 O% w' D! @
复制代码 * r7 p6 R; q* C8 T3 X) I
状态变量的定义以及标志位,计数值
& b7 H7 U5 T" o5 r# s9 W. u- /* USER CODE BEGIN PV */! W: z7 S0 P1 T/ |' n H
- KEY_STATE keyState=KEY_CHECK;
: j% v! [7 S3 o7 {/ Z2 ?3 @$ P, D3 _ - int Result=0;
! o$ _& S/ K' L6 i9 _2 r - uint8_t keyvalue=0;# k J* S- z2 J4 T; O6 F
+ Q; L, R- S8 W% o, |- /* USER CODE END PV */
' ]' ?- n; S9 \5 ?7 }$ t% e
复制代码
& x; N9 S: J# w7 f6 a( Y/ F对于按键检测,是在TIM6里处理的,选用KEY1即PE3
) N3 l" n+ {3 @# \; X: `
2 k0 O% m `) Z% r0 A* d
+ H, b! E6 w t$ b8 D! ^+ Q5 Y8 O! ^! E9 v. @ G5 e; [
m/ x6 z* t* w! x3 ?: ] F8 W4 T7 |. Z: J
而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程
5 w1 l. i4 T$ S; b4 b0 i- /* USER CODE BEGIN 4 */; ^2 t) }. M/ n4 }. d
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)7 G+ b) G- o5 ~& u% j5 n
- {
a) w- g. V) T& B! l - if(htim->Instance==TIM6)//判断是否为TIM6中断4 D# t2 H G0 H
- {, R+ d$ E5 |1 Q
- switch(keyState) v5 y, p2 W7 g& l
- {
, A9 f) w& k( T! r - case KEY_CHECK://检测状态下5 h" G/ e, a+ y3 S, l3 Z
- {
/ v2 w! D0 o9 _* V I3 \9 F - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平 F @; U/ `' E% e" ~
- {" q) L7 M! Y" ~& y9 O: r
- keyState=KEY_CONFRIM;//确认按下状态
* N% ~" k, l1 v - }
5 X9 e6 c, F& T4 c2 G: o: _$ [ - break;, E; H5 O( z( Y2 L7 h+ ~% _
- }
7 f C: Q: V* T4 A1 O - case KEY_CONFRIM://确认按下状态下8 [5 x; ~, @3 T5 k+ d% n% ~) d
- {
3 |9 L2 G9 @% e# V C - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断 ( A7 W F; a# q7 y6 ~1 I7 |4 S
- {
0 n! Y$ _% }" s1 v2 D - keyvalue=1;//改变标志位用于触发脉冲信号
5 L5 M2 |1 _& k4 j6 ~! m - keyState=KEY_RELAESE;//按下后释放
4 z" c& I) z4 g1 o% D" ` - }+ S$ O" u& M+ S2 Z i1 }% V
- else : \. f+ W* M1 _; k. x& c h; D
- {
1 j, H% n5 O1 V' w# t9 P/ v9 r) m - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测+ W( @' `- [+ {$ g( c
- }
' |- P' [4 p& G' b- D4 \ - break;6 D9 j! {' O P. F( N3 r
- }
- A O- u# r3 {# i, [ [9 V: j6 S8 P: @ - case KEY_RELAESE://释放状态下
( z5 c( M/ w+ I. A1 d1 Y6 p3 V+ y" m - {4 ^( r6 Y! U2 W8 s5 E. T
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下
5 _7 Q. `6 X5 U0 \2 t - {
& m, i5 Q# F) ^3 i# T% l" E0 P - keyState=KEY_CHECK;//回到检测状态
) l- Q7 h) y0 |& k0 |7 ^, Q - // keyvalue=1;
, |- ^3 { L2 p6 w - }
6 l- W, D( O g9 V% g+ j1 D - break;
' l- J- \* E0 W2 j0 {) W - }
4 |2 @3 n3 F# P" c" N - default: break;8 w. [5 A1 ^4 e( y0 B9 b; O$ G
- }
* w- e, K* L3 I/ { - }* q/ n5 W* t6 u! K1 z5 [
- }& {% a) o. h& |0 U# o
- /* USER CODE END 4 */- p3 o9 v. _3 b0 w
复制代码
- B% E3 c7 a! o; H9 E2 d# F主函数内6 B: O6 V; t# {7 F1 y
- /* USER CODE BEGIN 2 */# R* t' P; l0 m9 A, j* o8 Z% s
- HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数% b6 C7 S, g! \# E h! R
- HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测( s* N& Q: U) B9 u0 G
- printf("Timer counter founction test: \n");//串口起始提示7 r! }6 \" y4 w2 {9 ]
- /* USER CODE END 2 */$ f1 x' }- H* N$ O1 N3 h4 o7 F) G
- : k' _& p6 o. C+ m G7 H
- /* Infinite loop */
5 w, n% Y3 a% `% f+ ~+ L - /* USER CODE BEGIN WHILE */
/ i$ d7 I' H) E X+ I) b- K0 {, l - while (1)* R( L, H$ d: A: g) h
- {: t: L: s% G5 D9 x2 q' n7 n
- /* USER CODE END WHILE */3 P; M2 b) q% q! |
& j, a* q8 j$ S' o- /* USER CODE BEGIN 3 */# \! ]9 M" a& S) c; t8 B7 O8 ^
- if(keyvalue==1)//如果为按下状态
6 F1 s: b+ l2 V j. ?" J - {$ g& e; p* P% u" f
- keyvalue=0;' y* ?& W2 d4 T, ~3 ~" \
- HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);7 A; c# O0 p' v% ?* r
- HAL_Delay(1);
/ S+ S1 A& V, ]" ^! S/ k5 \- ] - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);" i l+ ]5 H/ d
- HAL_Delay(1);//发出周期为2ms的脉冲" |) W" F& X- s: h
- Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值
% t# {: i6 R u) z0 T5 y3 r- w - printf("Counter:%d.\n",Result);
& P& p# @2 U; |$ }! P( R! `$ O - }( \& Y6 o0 |, c' Z- n8 C6 J# r# L
- }
; r" A& S1 k9 P- j& Y8 C& l+ n8 _ - /* USER CODE END 3 */( c( _! b0 a" C
复制代码
) b L5 a m& ?7 O5 oCUBEMX配置
6 w: W0 G8 e' [1 ]1.时钟配置外部晶振,主时钟为72MHz4 s! A8 I! f! _+ |7 G* Y( n# p+ ?
9 m* g& a2 y. A1 T* c% n# p1 F; g; k
v0 {- E Z8 h: O
( ? H( y% _' s, O v! X1 C9 u+ R. p
7 M) C) W/ |9 v9 }7 s% A4 Y6 _% Y+ C, T0 x4 g
2.GPIO:选择PA1输出,PE3输入
6 V: w/ L( y4 H8 q: v Z
7 Z" P0 c! o( U$ ? `. y3 J' D
% j, N2 X/ l4 ], N* d& |
) n- i6 d! L% ~$ `% \
3.TIM:1 T9 h2 T$ c0 A0 O
TIM2:Clock Source:外部触发/ B3 I; z, D2 p" B5 \0 S
4 ~) t ~( d3 F9 i% ?! R( h) q
9 F6 h! h. h1 r& c) c: w- f8 r0 [$ l9 V7 C
这时PA0为你的触发引脚+ ] P" g8 g" i! f0 K( [, d1 O; u. J
$ _% s; _, R; m
; ?: D* E2 _8 Y! t+ t* Y- T& I4 q) _% O
3 R9 d! B- U( `, TTIM6:激活并生成10ms中断2 m% I- ?9 V1 q6 K0 d' b0 P
6 ?6 \: T4 w4 } `5 A
5 d% O9 W" ]: I
; g q, J# d1 |6 l/ C: [0 |
4.usart设置) [+ H% @8 A4 s! E2 _
0 ~! D* N' e! E3 E, q
( T) R- G3 R. T+ |( M
; `) h$ ^" I; x! _
5.Project的设置,& _5 W4 I% D. X% c% v% a+ ?. N5 V
, h3 u" r# q( K+ S+ e* s5 n
! T8 g. I9 w8 `8 z
1 }- B/ a1 L1 e. G) K$ `4 _3 O) Q还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。
8 T5 F+ ]! g. S; L7 ]5 C2 t4 @; l1 f3 S: v; v `
9 s' O+ d' _! x/ n1 |: @5 Z
V# E1 @% V9 q6 L最后生成代码
$ d P& E1 t6 D+ B————————————————4 m6 \; E$ R/ F% m, D; y
版权声明:南山笑2 T7 l$ F- U/ g; P$ [4 G
如有侵权请联系删除7 b: q) O* r# x9 w" n5 K
" j6 x/ X. C: Y2 K3 ]: t+ G$ n0 ~9 h4 D; L A+ k
|