- void TIM4_Init(u16 arr,u16 psc)
' H. @1 p: E! J - { . b% a6 k9 ?9 W$ J) q+ W
- TIM4_Handler.Instance=TIM4;7 r9 Z2 ~ C- }
- TIM4_Handler.Init.Prescaler=psc; //分频系数- {+ E: Y9 p/ {$ l
- TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上计数器, h- R$ b: k& _/ t( r/ w. Q
- TIM4_Handler.Init.Period=arr; //自动装载值3 N, G% h$ V: o1 S6 d+ e% N
- TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
8 {$ n3 N- K M3 s3 Z: g -
$ t3 t9 T' e: h - TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;7 a6 L% w- k! y( z. q8 v
- TIM4_Encoder_Handler.IC1Filter=0;
& K0 O2 P, w. y7 f" h - TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
t9 P2 x# B/ S- _( m+ d8 k - TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;+ J; z8 f( W) R" t, }5 S8 z. X( V
- TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
9 V2 L1 v, |4 v - 9 y* H- O* ^! F. d. c
- TIM4_Encoder_Handler.IC2Filter=0;
9 i+ Y0 P3 S2 L" \3 ^ - TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;( r; w- x9 C" Q3 V- e
- TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;
! v' s- S& w, W: w" Q% w - TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;8 z1 S. c6 Q) _5 s
- HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);7 r; H0 u( }* y7 _: N+ _7 ^" k/ u
- / I$ ?$ h! O) c7 v/ u$ ~- l
- HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL); }6 s8 W; `- _+ K3 Y, x+ V
- HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
* b- G5 [" R# p: W0 o8 v. Q! c) ^' T - TIM4->CNT=1000;
% x) d1 {$ ~( e - __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE); //使能更新中断1 q4 b4 E9 j+ q7 q' _/ f# H: }
- __HAL_TIM_ENABLE(&TIM4_Handler);0 w% g6 G! ?, J, [
- }
复制代码 , m0 i1 `; c! i5 U; F
在这里我们配置编码器模式,开启时钟和溢出中断
+ a. |4 ?! j2 L) H2 Z' w- //回调函数,定时器中断服务函数调用0 i/ s7 o- r. a/ E0 z- K
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)/ ] z& m% j8 D
- {7 K# C% K! w, Q/ a
- / F* P3 n1 e$ _% a
- . B( O+ U5 R& N' s# c: o" Y: d
- if(htim==(&TIM4_Handler))# g2 O, i: t( j, T$ M
- {. R/ v$ P0 F6 Z( P# r7 t0 S
- if ( (TIM4->CR1&0x0010) == 0 ) //向上计数溢出 {, A, P0 l: K6 P' O
- Interupt_Num++ ;% J1 k' p3 y, a5 o5 b
- }; X4 J" d7 m* X7 N& `! s# x/ d
- else //向下计数溢出
7 K# D5 q7 Q7 `+ t% M - {
% [) x. q8 x6 F4 `6 v - Interupt_Num-- ;
7 I. N- E" P E! u - }
; r: \ _! b4 d - }& p/ _# x2 V/ B" `" x( R0 Q
- }
复制代码
4 x7 A0 ~9 S8 ^0 j& ?
3 h, L, W" u; K) w
0 ^6 q+ Y& ~7 z W- J, i" Q在中断回调函数里,我们将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的一次溢出次数。
' ~% |' [4 E. n6 Y+ F ~: RTIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。
9 S J/ b) ]$ b: d- void Circle_Print()0 K* y% _1 Y8 D* U ?
- {
, V: {" q( g" d - AAA =Pulse_Num;2 D0 y. x. ?' i! q+ p% S0 d. Q/ |: `+ p- I
- if (Interupt_Num ==0 ) //CNT从1000开始,刚开始的时候计算脉冲的方法& ?3 `( B* L& f$ Z" I8 @5 ]
- Pulse_Num = TIM4->CNT-1000 ;+ @& l9 M. I; Z u1 L0 P/ p" ?: w
- else& @0 l4 { |- {, |- |8 n
- {
% @! ?, @7 {0 [# m - Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法: L0 y/ w1 a4 S8 B* ^% f& @
- }& \8 @4 m5 r/ k. ?- H/ m4 K
I* L1 A) _; R1 W/ Y4 p- 7 A* z2 n. T% S3 [
- speed =(Pulse_Num-AAA);//每100ms转过的脉冲,近似看成速度了: j9 G1 C1 C' i+ L I
- Circle_NUm = Pulse_Num/1560.0f ; //所有人脉冲除以细分数就可以得到转的圈数(正负之分)( f- p0 w/ R/ s+ I, a K
- printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f*****本次脉冲为%f\r\n" , Interupt_Num, Pulse_Num , Circle_NUm ,speed );7 Z* ~ ~( w+ y
- }
复制代码
* S" H9 q5 n0 H3 r! bAAA是我设置用来计算速度的变量。在每次最开始调用Circle_Print()的时候我们首先把测过的总的脉冲数赋给变量AAA,此时AAA=0,,然后在Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法这一句计算总的脉冲数,计算原理我们已经在上一条说过了。然后在这一句speed =(Pulse_Num-AAA);我们用至今为此总的脉冲数减去AAA即为每两次调用Circle_Print()的脉冲差,而我们在主函数中使用一个100ms的延时,所以时间差为100ms,脉冲反映小车路程,可以得到速度。
( e1 Y$ b9 T: G0 K, ^***硬件***5 f" p. n/ N* Q
我使用的编码器(6线,分AB相,客服叫做13相?不太懂)转一圈是390个脉冲,使用四倍频,转一圈即为1560个脉冲。用总脉冲数除以1560即为至今为止转过的圈数。
8 T+ u& @; }4 Z" C o' X$ h小车直径为6.3cm(没找到参数,手动测量的0.0), 周长约为0.204m.: y/ _9 ^6 e7 L8 U6 {2 l$ M( }
***下载验证***
4 a! W- d. l7 x
& E6 N4 l% ~; o1 T
7 n5 _5 A3 X' l2 i& {0 W! E! k- Y, F% W+ F/ ~* ?$ u+ b8 T
可以看到,第一个返回总的溢出数,第二个为总圈数,第三个为速度。
$ m Q/ Z% Y7 s9 L. N9 J因为在主函数中使用一个100ms的延时,每0.1秒转过的脉冲数为160左右,约为0.1圈,每秒转过1圈。, L+ w6 [! V/ |2 p" A6 ?
0 t0 b3 ~- F0 ?) E1 g: ~' B
中断回调函数程序里有一句PB0!=PB0;而我的电机一IN1接的就是PB0,我改的时候忘记删掉了这句,然后我的第一个轮子(编码器接的第二个轮子)就一会转一会不转0.0
; w ]: I3 L8 f/ ~+ }" s' \6 N' a
在文件中写入了函数之后要在头文件和主函数里添加初始化,否则不会识别。& w! b! x( b; a. Q: N3 V" D
2 S5 z: X* X9 Y) N$ Y1 U3 HTIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。0 ~+ v5 \ j! d: \4 B( D8 V
7 p, H5 ?; B S9 N/ D
————————————————5 f7 P: e( [4 o" j: `$ P( X \
版权声明:被大佬糊弄的只会点灯的小菜鸡
' q6 s. q' D) e: T3 K1 `如有侵权请联系删除
n% v( w: b/ E4 b
! W+ `+ C4 U* t |