- void TIM4_Init(u16 arr,u16 psc)
+ ^9 [( P! R% Y+ x- V& f - { 1 W6 P1 _" }7 a
- TIM4_Handler.Instance=TIM4;9 @9 P0 u y7 D" T
- TIM4_Handler.Init.Prescaler=psc; //分频系数$ n2 v. U7 Q, N! X6 G2 d7 a
- TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器2 @; g. ]: l0 {& o
- TIM4_Handler.Init.Period=arr; //自动装载值3 C- O) G' ~6 Z2 V- }; p* S( ^2 B
- TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
( \% } {# H c; [7 ]6 t1 D- G -
% E) Y( j/ g, P- V# N6 ` - TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;
' I' `6 Z& B, D5 Y/ d - TIM4_Encoder_Handler.IC1Filter=0;
, k7 Z3 j* i. P- b' S - TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
) m8 e7 c+ E; F$ T* @6 U - TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;2 K1 E+ D5 N% B: t- I2 ~
- TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
- E/ V! l! {& \2 X9 b4 {! n - / t/ I, ^ V; {, A/ `
- TIM4_Encoder_Handler.IC2Filter=0;
0 {( u o3 h' ?- e( ? - TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;3 v: \& D7 X# v: r& ?" {& L0 j
- TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;6 p# a: a' g( a% p8 b/ ^
- TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;) C- M* G r8 x/ W" @6 A* b
- HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);2 _) [8 Y- T) ], X/ K& i7 T
- ( r7 n+ K4 A5 A) x0 N+ d
- HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);. W4 O% i# D& p% q3 Y% F% E4 ~( v
- HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断& k! ^3 R! N2 \3 X; m/ p% E
- TIM4->CNT=1000;
4 V1 y7 n2 B# }9 M3 j - __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE); //使能更新中断7 m+ v# E& ]$ Q2 [7 i
- __HAL_TIM_ENABLE(&TIM4_Handler);
' J7 {9 Q: ]- y: O6 c - }
复制代码 - O$ d0 u" ~- O. R9 w' }' i6 n' y
在这里我们配置编码器模式,开启时钟和溢出中断
. i8 o) o& X8 f* w& s: Y- //回调函数,定时器中断服务函数调用 e* c: U( [! S
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
1 X6 F- E; X8 m: \6 { - {% j( _ {& c6 a2 N- a$ ~' F# a
- . m7 H$ j3 l9 X0 |' I2 c- M# ^: O
- |" F6 x7 w0 C, \
- if(htim==(&TIM4_Handler))" M4 M) _9 B$ F3 C" D
- {
/ S7 Y2 {3 w& ~. M- C7 L1 \ - if ( (TIM4->CR1&0x0010) == 0 ) //向上计数溢出 {
. M% s# ^' Z A0 x( R) A8 U - Interupt_Num++ ;
9 ?( s2 Z% |' `& q1 |' j; i1 p, Y) ^& O - }/ i! w S, x- E- K: n9 j, _
- else //向下计数溢出
5 a& ?6 \5 I! F6 Z1 k - {( }0 P! V9 o5 T$ n" F
- Interupt_Num-- ;
" C X6 Q/ `+ G: L0 v7 n - } 2 q+ U( M( I p, o3 S
- }
" j" {. @, e' M' g - }
复制代码 # {. w1 h* X; f' s
4 e* x& Z5 U' u3 E/ l" i: @" l
8 n: N+ l6 p+ F- }2 o0 F在中断回调函数里,我们将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的一次溢出次数。
, M9 B# ^/ e( XTIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。5 |0 O4 C. r! |
- void Circle_Print()
3 @: n8 F% {5 ~- D- b9 B+ r - { ; w+ W- Y. u/ N% Y) z
- AAA =Pulse_Num;5 e' k1 ?$ P5 S9 B8 @# E! Q
- if (Interupt_Num ==0 ) //CNT从1000开始,刚开始的时候计算脉冲的方法
; g) P" k, t) X - Pulse_Num = TIM4->CNT-1000 ;1 C/ _8 F" h, m; h1 J" W7 S& o
- else. K2 P( l7 P" Z$ O: g7 R* N
- {
9 l/ Y; `/ Z2 N - Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法& B, h0 o% s S
- }$ j6 r a, |+ w5 P9 e; C! v* P
B3 x1 u; n4 c3 @/ U+ `5 y- 6 v( } m$ @9 k. U X6 Q* ?0 ^
- speed =(Pulse_Num-AAA);//每100ms转过的脉冲,近似看成速度了
5 M& b6 w4 Y! p' Q! A1 _$ w" ?9 V - Circle_NUm = Pulse_Num/1560.0f ; //所有人脉冲除以细分数就可以得到转的圈数(正负之分)9 F# v0 w$ b' ~1 ?- u: [$ b' l
- printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f*****本次脉冲为%f\r\n" , Interupt_Num, Pulse_Num , Circle_NUm ,speed );# H8 L; i6 L7 f
- }
复制代码 9 ~* \) U' W! Q; K+ L& i8 x
AAA是我设置用来计算速度的变量。在每次最开始调用Circle_Print()的时候我们首先把测过的总的脉冲数赋给变量AAA,此时AAA=0,,然后在Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法这一句计算总的脉冲数,计算原理我们已经在上一条说过了。然后在这一句speed =(Pulse_Num-AAA);我们用至今为此总的脉冲数减去AAA即为每两次调用Circle_Print()的脉冲差,而我们在主函数中使用一个100ms的延时,所以时间差为100ms,脉冲反映小车路程,可以得到速度。& ^( g; i. }5 j0 c
***硬件***
- W% O d, L3 E我使用的编码器(6线,分AB相,客服叫做13相?不太懂)转一圈是390个脉冲,使用四倍频,转一圈即为1560个脉冲。用总脉冲数除以1560即为至今为止转过的圈数。& e8 ^- N+ C6 V V+ T' A; O" m
小车直径为6.3cm(没找到参数,手动测量的0.0), 周长约为0.204m.' Z9 s$ C9 c+ F4 T4 e' Z! u+ g% [
***下载验证***8 t; |: O9 u0 [" J; ~& I
0 g' H- _. [* `9 _' q
0 i3 z& P$ ~; E2 J! G
; m& g& @) M( O. x% n' @9 l 可以看到,第一个返回总的溢出数,第二个为总圈数,第三个为速度。
& R( m( ^# Q2 d) r因为在主函数中使用一个100ms的延时,每0.1秒转过的脉冲数为160左右,约为0.1圈,每秒转过1圈。$ f3 y, I- F1 l
+ L! u$ P2 W2 b. D! W- z+ r中断回调函数程序里有一句PB0!=PB0;而我的电机一IN1接的就是PB0,我改的时候忘记删掉了这句,然后我的第一个轮子(编码器接的第二个轮子)就一会转一会不转0.0
1 l% D6 \' H, G9 u! v6 f
& }. Q9 [: |& V2 |; K, c' A* z3 s在文件中写入了函数之后要在头文件和主函数里添加初始化,否则不会识别。
6 i1 L' z1 o. v
+ p/ E- u9 X9 B2 iTIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。 M" w% O& k# _
/ G0 |% A% U, ? c$ b: ~8 I2 j
————————————————3 A" E# A. {$ w% [. Y
版权声明:被大佬糊弄的只会点灯的小菜鸡$ E- S( [0 K* |+ q) R9 |. t
如有侵权请联系删除0 R6 ^$ l% a5 c' F/ @+ z
( j3 }. B. c) H" ^) O5 k
|