STM32F1定时器实验-外部触发脉冲计数
( F* |1 U0 g# Y" U7 C之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
6 R! r; r- }, j i( ]按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
# N/ o/ f, }& }$ G
8 u$ J, e. O, K; O7 j说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:! c% E6 w) t: J, [) B
8 M+ d- G- K. _$ i' N" Y
/ O6 i, `' {9 \. x8 M" \8 |( D
7 G3 P! [$ B2 f. g) h画的只要你自己可以看懂就行
+ E* {3 X: Q( I7 Q8 w. I3 e( R
: C/ r" e" K: O7 j$ c g; [* x: D4 C5 S3 M/ `
代码讲解' @ G' _2 |5 D4 @' z0 ~7 A
首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体: F9 [0 U0 U" k* D6 O4 D- Y
- /* USER CODE BEGIN PTD */
6 Q; b* x9 n! N7 J0 x - typedef enum( Y l% N6 J% h6 }6 U% M; f6 b
- {
/ x# W( M9 U5 ?4 @) F - KEY_CHECK=0,. h2 k4 A, j$ ^2 E j' r# Q7 X% G
- KEY_CONFRIM,
/ D& D( i- [: G0 q$ t - KEY_RELAESE0 M8 h' I T3 }& k+ b4 m
- }KEY_STATE;
3 \) E$ H: c {- H0 Z9 m: L! Q - /* USER CODE END PTD */; h; q" [0 ]& t2 K8 |
复制代码 7 n! c( }! V7 ?9 {
状态变量的定义以及标志位,计数值
7 v0 ~" P) E' K- /* USER CODE BEGIN PV */( P% |8 j" ^6 v+ N' }8 U' ]$ f; [
- KEY_STATE keyState=KEY_CHECK;
5 B* s; k1 u- a7 i - int Result=0;
* j& ~. Z0 P* j; b: b: e9 W1 @ - uint8_t keyvalue=0;1 n1 o- s3 g) h2 O$ F
$ M% n0 C3 `4 S0 `7 W/ S8 T3 j5 n- /* USER CODE END PV */4 [* f& x6 a) {$ i% i
复制代码
* O9 H0 P5 l3 c3 C6 |# ~( f对于按键检测,是在TIM6里处理的,选用KEY1即PE3( H) ^& T x4 i
: w" \' B: i6 m' X, @: E
7 Q+ J9 X5 X9 Y1 k/ m; P
* }& j- c3 `: z3 N5 s* E2 n' W
/ s! k P) x# H, C$ V" d
1 \* d2 }& _3 U* S而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程4 |( ~9 V; L1 P/ F5 s) s" `
- /* USER CODE BEGIN 4 */
3 E; f, ~% z# B% x6 z9 ? - void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
. A5 o2 r0 N: P, c2 I! C- W - {
( u: ?% D, O# F - if(htim->Instance==TIM6)//判断是否为TIM6中断
( d+ F' _8 ]: g8 ?3 x - {
4 h& M( O: X. X' x, I9 K - switch(keyState); c3 {3 z( R7 O. @
- {
0 N% m, f# W. @, C+ r8 q2 i6 o8 R9 h - case KEY_CHECK://检测状态下2 F" x5 q1 G1 `4 j
- {. n/ h/ [ A* h
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平: m7 ~: ]# K; a( \$ b
- {
/ V; _+ Z* U* O$ W5 k D - keyState=KEY_CONFRIM;//确认按下状态) m& Q4 F5 }% q; K) t
- }
+ m& C6 u/ ?# N O. L( D- K - break;' q+ j6 Q2 _& }5 j, d9 C& C
- }
1 n+ I0 B: F/ z+ B; @% q" S4 b - case KEY_CONFRIM://确认按下状态下" n9 B- A. y5 R- Z: R
- {
" e& a8 V, W1 y9 ^ - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断 " A# @2 i9 T" q2 K" E
- {
0 m8 Y: j5 H/ S# x3 t - keyvalue=1;//改变标志位用于触发脉冲信号
3 t- L- s- V/ A6 G Z$ f - keyState=KEY_RELAESE;//按下后释放5 }2 h6 @/ L; N' x9 H
- }* o @) M( B% t/ G* ]) M6 x
- else 8 s; [: C* i* b1 A( Z/ C( X; j
- {
' k# C/ N6 a5 T3 g: h - keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测
; a+ m6 C$ q+ P; c" B7 w - }8 v6 |$ p5 \: B5 i+ e! V
- break;
i7 w' [& M* o+ M( r* u' t2 _7 e - }3 i+ W1 g8 A& S. Q% o% t& C$ u) H+ @
- case KEY_RELAESE://释放状态下& Q5 H9 ~# B5 p; @( Q. k3 E
- {. C* ?; Y5 t( b( d
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET) //判断按键未按下/ ~$ ^* M$ r3 G7 `4 O
- {
% t) S$ m+ K2 o: D - keyState=KEY_CHECK;//回到检测状态9 D; R5 w5 K u$ G- G2 _9 Y
- // keyvalue=1;
7 }/ ^7 D/ t; a, E7 c - }6 Y' w1 C& M+ I, G9 A+ Y9 Q3 @1 j
- break;: C7 B3 C) m0 ^1 D# z* R
- }
) Q0 T" z% T2 }3 o; i+ H - default: break;$ r9 q3 ]) d6 G- E: d; ^8 _
- }
! i0 z U# C! o6 E2 D - }
' _6 f) J* }- a, E* ~3 }+ u8 M - }$ Q6 e7 g) G, E5 P
- /* USER CODE END 4 */$ _8 R$ j. ?. j ?9 F2 P
复制代码
1 ~+ A* S7 ^0 Y( P, R主函数内
/ y# s' Z+ v3 [ D( R% A" \- /* USER CODE BEGIN 2 */
! b) w0 d2 u7 } M' R - HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数8 P% n) h& Q0 A9 b
- HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测7 I! f* D* X+ R: c! p
- printf("Timer counter founction test: \n");//串口起始提示8 m# ?) |( E+ z) {4 z' k: a
- /* USER CODE END 2 */
. ]" W$ O, k- L# a( [7 G - 7 K% e' M W0 ? ^$ P3 ^) ]6 C6 \
- /* Infinite loop */) }3 Z, R& ?* V! w: s4 |' ]
- /* USER CODE BEGIN WHILE */
2 T+ i+ b% z! ~& h- N! _8 N8 f - while (1)
! }$ }, |4 G- F0 q' c* P1 c - {
$ v, X6 M i7 X$ X" m* ~. f - /* USER CODE END WHILE */
" s! R/ j/ `+ y
3 C1 w4 s2 _" C9 w% J- /* USER CODE BEGIN 3 */! J9 g) f) H4 L. H6 c* o
- if(keyvalue==1)//如果为按下状态
. A. ?+ u7 h- \$ V6 F - {& R- A* v% D) H' d7 L* p' Y
- keyvalue=0;) s0 H. h1 j& x+ Q! t' {
- HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
5 Y0 }+ @6 q7 z' ^1 z3 X1 I - HAL_Delay(1);
' N. B- E- q3 T G( \9 M6 ]! k# P% X - HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
8 Y2 p0 `; U- { - HAL_Delay(1);//发出周期为2ms的脉冲
( s$ i8 [! b/ k. W; p - Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值5 K, w# f3 k5 @ m: x0 n
- printf("Counter:%d.\n",Result);
: ]4 E% `) X/ v" d; _2 I4 \ - }( U' ~- i5 o) F, j3 ?* q
- }
7 Y4 E. C5 e3 a7 s9 X - /* USER CODE END 3 */
/ `' c- x0 E; b( I4 U3 E, L+ {
复制代码 4 [, J& a$ U4 f" Y9 f% @
CUBEMX配置4 b5 g2 o* w0 {: x$ j1 b
1.时钟配置外部晶振,主时钟为72MHz
$ s1 ~% _- J4 g- `9 s! o& { B0 U& J! ^
: Y; h4 n- {( M; n* D7 ]/ B" a
& p0 [, ]8 U( f) s1 D- P9 J2 [
! w9 c; u* V& r w$ O$ I2.GPIO:选择PA1输出,PE3输入
$ U6 Q) R* M, i/ K z
$ O* C/ A* D! l3 q
2 Z! c, h% A% W. l) X n/ v
. ^; J' S% S1 d% ]2 c3.TIM:
! L# q; [3 o& V7 _" C) qTIM2:Clock Source:外部触发
! \: O9 [3 ~' J0 A% f- ^8 D6 D' N2 W
7 i' l' t0 h6 W
* j/ R$ n2 l" D
( I! D/ T& a% k: e. j* r' ^2 j
这时PA0为你的触发引脚
; e3 N ]4 F3 n6 ]8 Y
, c7 N, z2 K. K$ D# T
% ?9 B5 ?6 ?$ q$ w* s
. j. X* g5 c8 \& {) q7 o9 wTIM6:激活并生成10ms中断
: Q5 B4 `% {4 N5 d$ t) u5 k
3 d; o0 j @3 ?1 l
- J6 z$ O5 _# r4 t$ c. i7 V
7 ~( u, l! [- B6 I4.usart设置
' ]& G1 X+ l, y& |& V2 C* ~5 E( t9 N
9 `. F; M, F( {& r3 S- `, f# u6 Y! F, W8 W4 Z
5.Project的设置,$ D/ Q" ?" i/ _' A+ y
9 j. ]# w: w$ O! z& ^3 A5 C
# Q1 V+ z, p: R" l1 _8 _- v& L: l1 ]2 B T
还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。% T! ?' J6 i: z( P0 q# @
4 }% Q$ Y* F4 b9 l, e% s
. U! V5 n" R5 }& U8 n l
# p: ?# M7 y0 e1 f, |* F4 s/ k5 R最后生成代码
# b) z& D6 c% I————————————————, j1 k6 ], m& R/ |
版权声明:南山笑
4 B. V0 [, Q7 g8 h如有侵权请联系删除! T$ F& t& N* }8 d: p x5 h' l8 G
5 Q2 }4 I' e) w0 `& q$ j8 o, I
2 h: |9 h( c1 ^5 G4 o( Y |