- void TIM4_Init(u16 arr,u16 psc)
# F! e7 H; o1 ^( g! \ - { " B: u* q! G7 o1 ?9 T6 S4 A7 d
- TIM4_Handler.Instance=TIM4;' `& f- Y9 W, s$ m
- TIM4_Handler.Init.Prescaler=psc; //分频系数
7 v" s% M! o+ M) K; |% r1 O5 S - TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器
$ J/ _! N/ |1 w - TIM4_Handler.Init.Period=arr; //自动装载值
1 E; n/ K9 j/ `& t0 k - TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
* \: y# ]- u- g3 s. B+ [ \9 H - 8 q4 |$ w8 @8 f4 c
- TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;, v/ J+ J9 w! t) h
- TIM4_Encoder_Handler.IC1Filter=0;/ q: W$ F. f' T& w4 j! I+ r
- TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;+ v6 O8 c( P, R6 F- d
- TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;1 b, T% W# N, ^) b
- TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
3 n1 c: T4 V5 D# [( v -
+ W$ k4 |. M$ _2 B - TIM4_Encoder_Handler.IC2Filter=0;& \: f; \( b2 C Q1 r/ F
- TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;
* g& G, p1 ?+ r - TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;7 }5 |0 e8 r9 ~# A
- TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;
! B0 }+ |# C( d7 m - HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);; R- Q8 o+ ~0 @1 a8 D
- 4 `4 @! x6 f7 R# D5 ]
- HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);
6 L+ U0 G1 F+ [. K, m: g M& U: z - HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
4 f1 @* C4 M' c1 E - TIM4->CNT=1000;
* {# F( h% a% K' m - __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE); //使能更新中断
s! x/ @) ?4 E( q' q - __HAL_TIM_ENABLE(&TIM4_Handler);2 t% U4 X# y- ~" f9 ?) c0 ~$ o7 L
- }
复制代码
# B; s' }7 @ G1 O& ?3 C在这里我们配置编码器模式,开启时钟和溢出中断
+ L6 b: S' \5 `2 n* g- //回调函数,定时器中断服务函数调用$ n8 s1 e) }& c" \4 F" l) ?
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)2 a" b5 ?7 e4 @9 k! }$ |. k$ {! {
- {# g4 J: Q k0 p2 C7 v# j0 h
. e- U3 m0 o; w& T5 V- F; n- 5 d" D8 R. C8 `
- if(htim==(&TIM4_Handler))
5 g1 X6 |; x0 \* K2 ~4 q - {
8 d5 q' v& c& K4 Z( a! s& `, M6 m - if ( (TIM4->CR1&0x0010) == 0 ) //向上计数溢出 {! F6 a; A1 `. l8 t6 A# F
- Interupt_Num++ ;/ n+ f5 h/ T; l a- e: L
- }
' b# z" v- m( G! n+ x/ Y- J - else //向下计数溢出8 w5 L# ~3 @* W( I; k8 S* Z0 S# e' |
- {
# G C2 z2 m/ K. g1 T( P" v. ? - Interupt_Num-- ;
( D( L: Q6 _9 a: b% Y - }
, e% k' F" A% j! m# U% I# n - }) u: J2 t( _% u3 E4 u. \
- }
复制代码
: D5 U! ]6 P: K9 O p
6 [8 a" h4 `9 ^/ [- n
C" M. {6 X8 @+ L! e" ]1 T
在中断回调函数里,我们将TIM4->CR1的第5位不变,假如第五位是0,应选择递增计数,我们让计数器增加1。(0x0010==0000 0000 0001 0000)这里的次数我们是在计算溢出次数。要注意我们在TIM4_Init() 是把计数器CNT的值设为了1000,而ARR设置成了2000,这样计数器每次开始工作都是从1000->2000,0->2000,0->2000这样循环,Interupt_Num的值就是我们记录的溢出总数,而最开始的一次溢出是从1000开始,所以总的脉冲数就是 (溢出总数-1)*2000+1000(最开始的1000)+ CNT(计数器内未达到2000的值),之所以用溢出总数-1是因为我们总的脉冲数里把最开始1000->2000的值加进去了,所以要减去1000->2000的一次溢出次数。, y# Q$ n# n/ W1 r
TIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。
% m: O7 L P: k- }- void Circle_Print() f J: x1 J1 n" F7 _: o! ^
- { * ]( z9 e# N$ ]8 K. A8 |8 @
- AAA =Pulse_Num;! I1 d5 O+ ~! O# H2 Z" e
- if (Interupt_Num ==0 ) //CNT从1000开始,刚开始的时候计算脉冲的方法
/ g* _ ]( H% ]& E/ O - Pulse_Num = TIM4->CNT-1000 ;9 t2 i. V m1 \
- else
# B% ~/ Y8 G9 F% _8 D6 _3 | - { ! q5 r: r& P$ O
- Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法$ R& \$ V7 S0 _' n+ g
- }
5 Y7 h& ^+ `) m, y$ S, ~% b - + n. \2 Q* m- G# a) r
( o8 _! D" o# R- speed =(Pulse_Num-AAA);//每100ms转过的脉冲,近似看成速度了: Y- m ?1 V6 L+ d: Z3 f
- Circle_NUm = Pulse_Num/1560.0f ; //所有人脉冲除以细分数就可以得到转的圈数(正负之分)
3 }$ P, h; w; }2 q. T c - printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f*****本次脉冲为%f\r\n" , Interupt_Num, Pulse_Num , Circle_NUm ,speed );
0 `. f w! K6 T" r* } - }
复制代码 6 ` F( d" {8 J! r; i" i8 q
AAA是我设置用来计算速度的变量。在每次最开始调用Circle_Print()的时候我们首先把测过的总的脉冲数赋给变量AAA,此时AAA=0,,然后在Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法这一句计算总的脉冲数,计算原理我们已经在上一条说过了。然后在这一句speed =(Pulse_Num-AAA);我们用至今为此总的脉冲数减去AAA即为每两次调用Circle_Print()的脉冲差,而我们在主函数中使用一个100ms的延时,所以时间差为100ms,脉冲反映小车路程,可以得到速度。- t& s& ]7 R- \/ z- l
***硬件***1 m' W5 [ S. V3 S9 @) t- H
我使用的编码器(6线,分AB相,客服叫做13相?不太懂)转一圈是390个脉冲,使用四倍频,转一圈即为1560个脉冲。用总脉冲数除以1560即为至今为止转过的圈数。
5 o' c4 ~/ D2 h/ l& J5 h* j小车直径为6.3cm(没找到参数,手动测量的0.0), 周长约为0.204m.
2 c8 h8 N4 w" H& l* q***下载验证***8 F0 A: F; z: B
/ s: O3 t; i8 D; W
9 d- }- E# s7 o- S3 x7 o* u( y
% U& ?/ |' f0 F- Q3 T 可以看到,第一个返回总的溢出数,第二个为总圈数,第三个为速度。* T* k" ^; L/ A( r6 S
因为在主函数中使用一个100ms的延时,每0.1秒转过的脉冲数为160左右,约为0.1圈,每秒转过1圈。% E7 G. I2 t' ]* Q4 j
3 V Z6 C' p. s+ v: D F! i中断回调函数程序里有一句PB0!=PB0;而我的电机一IN1接的就是PB0,我改的时候忘记删掉了这句,然后我的第一个轮子(编码器接的第二个轮子)就一会转一会不转0.0
! O) P! H3 R2 ^* U. ^: i( T: I5 X) p2 W: G8 m: T6 W
在文件中写入了函数之后要在头文件和主函数里添加初始化,否则不会识别。" {2 \" I- V+ P& d3 _
$ ?1 U% m$ Z( ~* Z1 k, a6 P" q2 U- tTIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。4 M# J, `! d6 `! E0 d O! S
[* G6 E3 H- I8 o
————————————————0 h( R( ~# f1 P
版权声明:被大佬糊弄的只会点灯的小菜鸡
: X& P- [( D( ], ?( |! l如有侵权请联系删除. s% R" l' d: l
" a) f; A0 `, ^' z! Q
|