STM32F1定时器实验-外部触发脉冲计数
& p6 H; k& x- ]' U之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
( e- W5 ] N* ~% c按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
4 v2 e6 b$ ]+ X. I! L& x
_& X" \) Z# @3 a说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:, s; a6 K2 w6 _1 b" P
+ V8 @% p. ]/ }/ z" N/ d
& y6 U+ Q# L* A7 H% E& r, n0 }4 w# d0 U9 E0 v" Q9 o6 ]
画的只要你自己可以看懂就行. p" E. k) f+ }( z2 a
1 L) Z8 L+ Y& ~; t/ g& p+ _9 Q7 }5 ?( U0 D) P& g
代码讲解
$ @. ~* X$ D3 ]$ o6 s+ p# Q, W首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体 w4 E4 W- J! u" t
- /* USER CODE BEGIN PTD */; m, P! B) Q7 r' P2 H& y* x
- typedef enum
* f+ k( ? q& E5 k - {
& M# @: [4 T8 X; [- l - KEY_CHECK=0,
: l9 v2 `' ^" j8 O - KEY_CONFRIM,
- Y, m$ t& X9 k - KEY_RELAESE
! J$ e1 R2 O# Z D - }KEY_STATE;' a9 p1 F* d# O' b) w$ h
- /* USER CODE END PTD */% X) `6 n' j9 o9 ~8 }0 b G k' a
复制代码
0 q/ H3 s! l6 |) u7 C. B, p状态变量的定义以及标志位,计数值
$ D1 {# p" b) W5 U! z/ c- /* USER CODE BEGIN PV */& ?3 c4 A; W/ T, ~: w. F
- KEY_STATE keyState=KEY_CHECK;. R' t+ P& M B
- int Result=0;
0 t. o& _3 m1 B, L' E - uint8_t keyvalue=0;- [6 S- Q8 f5 e( X6 n& q
- 5 Y7 c) B3 E3 A
- /* USER CODE END PV */
9 f1 b) u" |7 e
复制代码 & n) Q5 q0 |! V4 H
对于按键检测,是在TIM6里处理的,选用KEY1即PE38 s; n9 R6 _9 S/ I9 ^+ A
; m9 o# p2 }' ~( w" ~4 t
7 W: D& G- c4 v$ v
L3 E7 {; s$ K% N+ c; J' y- ?
7 U G+ s# Y0 J5 |3 Q/ {2 c/ b0 Z. W( {4 Y
而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程
* U7 v$ ~. _0 G) Z/ W- /* USER CODE BEGIN 4 */4 ?5 O9 l/ h- R3 x( |& h, h
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
8 ^+ h( O. B& m) t% v$ I0 A - {
$ V5 f, M+ t) {: ]' [ - if(htim->Instance==TIM6)//判断是否为TIM6中断
4 ?4 _/ n9 \! K. P9 [% p - {
% m) {9 o0 A W2 _! } - switch(keyState)
' f8 W- d/ A3 n' H! F - {( d9 k1 j" e2 r0 a' G; j
- case KEY_CHECK://检测状态下
: d* `/ x! ^, T2 X3 U - {( @' D4 t; k; B: O1 e
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平
; C# \) P2 Q! z7 V! M8 ?+ H - {! Q2 X& [7 U/ A% k$ F4 N
- keyState=KEY_CONFRIM;//确认按下状态* s& e2 i" ]; z
- }
" [! ~9 T4 \8 k3 R - break;0 G+ ^. W2 p9 C7 K& {
- }5 O: B {4 V& e( Y: o
- case KEY_CONFRIM://确认按下状态下& j$ y" g2 |/ l" J0 j; f! q
- {
6 C% B5 O8 R; Y8 d% w8 M2 p - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断 / R# q. d! Z; x8 j( A
- {# a8 z- w# ?% z1 d
- keyvalue=1;//改变标志位用于触发脉冲信号% y4 a& P8 f ~4 G
- keyState=KEY_RELAESE;//按下后释放
1 l& M5 R3 L2 T1 M; e# n - }. G ?# i" g- E; e* t2 `6 S4 }: r) u
- else
( T3 G( Q7 d: W - {
9 P* U5 d6 B% k& A1 d1 f+ X+ [9 r - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测. `3 H% B: o/ y
- }
/ I+ a- v/ g! P7 g& P. u& w - break;" @% \6 S Y b5 g; X
- }
4 {) R+ w* m: T' i( `$ ^, O - case KEY_RELAESE://释放状态下
0 T1 E' ^% ~9 Y/ q - {
9 \, g6 ~" X% z% J - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下4 k6 x' w$ j9 E* H: _8 Z4 x( h1 ^
- {
: n7 N5 {$ E& x" I' |% c - keyState=KEY_CHECK;//回到检测状态
/ Q& z4 K% q- I" t$ F% l: G - // keyvalue=1;
% ?" q- H) K) A. E. }5 G$ w& d: O" I; l - }
! p; W5 Q% j8 w. S$ h - break;
4 k3 A2 H# K% g7 S/ k8 v$ W - }
1 X9 N8 _/ O/ O2 `5 L/ @( V2 V - default: break;
8 d2 F. j- l! n% ^2 [' h% l - }
6 _! C P; @$ r& H - }4 \0 @- x- w# q, o' g( E
- }2 E2 E9 k8 v4 n6 T& b9 F. D9 F. N
- /* USER CODE END 4 */
$ j* ^" D- R) x3 f* S0 u( B
复制代码 + ^/ g) H3 H6 v
主函数内: L# F& {% s( K5 A9 q
- /* USER CODE BEGIN 2 */
: P* X z) P1 C0 @! T/ Q+ d - HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数
1 ]( _9 t; U/ y. K1 _" [ - HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测
/ h9 E6 P& @; e5 Q) O - printf("Timer counter founction test: \n");//串口起始提示
+ D. \4 c+ K' K1 P2 y0 ^# x - /* USER CODE END 2 */. h( A/ b: Y' P6 x1 i1 f
- ! \8 O/ |# L& f) p
- /* Infinite loop */
0 T- _3 R! E/ q+ T - /* USER CODE BEGIN WHILE */% {; x8 Z# p, u: H V6 @
- while (1)
; @9 d5 j! {- L - {9 ~2 n7 t" x8 h% x: k6 x9 |$ W
- /* USER CODE END WHILE */
1 V$ a- j* H$ E; D/ w' G% S
7 B+ c2 @ k9 }/ x" J$ Z- /* USER CODE BEGIN 3 */+ Z. D% z9 `1 `6 N/ {8 j
- if(keyvalue==1)//如果为按下状态
, G" [ j& V, v$ D - {$ X j' \- j) h* b3 ~
- keyvalue=0;
- b9 J* [, ]% P% s( D/ d - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);' n/ z6 ]) t' _
- HAL_Delay(1);
5 Q: y! u$ I4 H! ^# N$ ^. a6 _ - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);+ \% z; a, Z9 G# H/ l% b F& g% q S
- HAL_Delay(1);//发出周期为2ms的脉冲
/ K( s% ]1 C& F% h/ ~ - Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值
4 Z4 i0 ~0 j& F. X- k - printf("Counter:%d.\n",Result);
5 k* {1 F; I, g# @, l - }
% `! }# H6 `& r E/ `! D - }( @! y9 Z, g$ c5 x
- /* USER CODE END 3 */9 I6 o* \& I4 \7 {1 k7 X
复制代码 0 t; a2 [" P4 a5 d6 k2 P
CUBEMX配置7 g' N5 ~0 N' W+ X1 w d
1.时钟配置外部晶振,主时钟为72MHz5 y) y$ v9 J3 d" Z$ y
6 o- b) b: x- ~
8 j/ W' L3 {8 W/ Q/ N& S) K; S
, l, x0 o" n9 `+ P# L
" u8 x; q' c$ K' f+ R1 q+ D5 G) t" Z2 P
2.GPIO:选择PA1输出,PE3输入, c# n5 o9 t& a( G; g) Y
8 ]5 b- m7 N- u1 ~. ?5 ^( Y
/ k% |+ i8 X+ r1 y% c& |; o
& V6 o/ }6 r0 Y9 n4 S6 k3.TIM:) |; H/ E1 q+ m, `
TIM2:Clock Source:外部触发5 ] y+ I& \; h0 a7 @! [
5 @3 U- V9 @% k: W& W% [6 }. W2 h* W
+ b7 g: q+ f7 ]/ j3 W8 A7 ]9 R$ u) _) G
+ t; u/ m: c4 | a9 s这时PA0为你的触发引脚& o+ {! r7 b8 J
: H; B6 V( E# X' h. F0 r
/ X" g# P, E/ k# |7 P2 O; `1 |! w
$ q0 ^+ m8 `+ s3 K" i2 I+ V2 L6 ]TIM6:激活并生成10ms中断
+ m# z$ i6 d: F1 d! z' ~( B
4 w. c- B# H% O! E* m! c' _- h
1 j( Z2 ]/ P) w$ J8 S
7 c2 w/ _3 L0 x0 w. u4.usart设置
8 |( d" y! {6 h% |
: `, x9 f& |+ @. k9 Z ]( d
4 I0 X3 C m, \9 u' Q; K s2 u1 e. J
5.Project的设置,
# N+ C, o; z; _+ f0 J: [$ O- ~; e! {0 a' R! G& h
. M) g1 ~& K5 u1 @$ _! W2 S
9 j2 I1 U$ D) R, p还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。
3 z( X: }# X+ y; ~, {& W
& s* K4 ]" x8 I) Z% l
8 R, j+ O6 H$ n- N: N0 v7 u% [( x# G! u
最后生成代码( j8 B7 N! s) A* N& Q# W9 A/ ]
————————————————$ u- x6 R! i& E- l
版权声明:南山笑
1 h" M* m2 U8 F. V如有侵权请联系删除2 ]1 O1 K3 B7 y; K/ u& k
8 X$ A l/ t+ @4 u/ g
7 P) ^$ t3 S* h& Z6 [ L) { |