OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7936|回复: 12

【学习笔记】STM32F429使用编码器测速【HAL库版本 】

[复制链接]

16

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2019-9-4
在线时间
52 小时
发表于 2019-9-29 21:57:26 | 显示全部楼层 |阅读模式
*****使用大V  http://openedv.com/?90525  @北名茗水的配置。******本来想艾特他的,但是我不会hhhh
void TIM4_Init(u16 arr,u16 psc)
{  
        TIM4_Handler.Instance=TIM4;
        TIM4_Handler.Init.Prescaler=psc;                     //分频系数
        TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
        TIM4_Handler.Init.Period=arr;                        //自动装载值
        TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子
       
        TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;
        TIM4_Encoder_Handler.IC1Filter=0;
        TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;
        TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
               
        TIM4_Encoder_Handler.IC2Filter=0;
        TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;
        TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;
        HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);
       
        HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);
        HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
        TIM4->CNT=1000;
    __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE);   //使能更新中断
    __HAL_TIM_ENABLE(&TIM4_Handler);
}
在这里我们配置编码器模式,开启时钟和溢出中断
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

        if(htim==(&TIM4_Handler))
        {
                if ( (TIM4->CR1&0x0010) == 0 )  //向上计数溢出                 {
                        Interupt_Num++ ;
                }
                else //向下计数溢出
                {
                        Interupt_Num-- ;
                }               
        }
}
89MVP0O2BU~@CJ){Y]]`JD2.png

在中断回调函数里,我们将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的一次溢出次数。
TIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。
void Circle_Print()
{       
        AAA =Pulse_Num;
        if (Interupt_Num ==0 )                        //CNT从1000开始,刚开始的时候计算脉冲的方法
                Pulse_Num = TIM4->CNT-1000 ;
        else
        {  
                Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法
        }

        speed =(Pulse_Num-AAA);//每100ms转过的脉冲,近似看成速度了
        Circle_NUm =  Pulse_Num/1560.0f                ;                 //所有人脉冲除以细分数就可以得到转的圈数(正负之分)
        printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f*****本次脉冲为%f\r\n" , Interupt_Num, Pulse_Num , Circle_NUm ,speed );
}
AAA是我设置用来计算速度的变量。在每次最开始调用Circle_Print()的时候我们首先把测过的总的脉冲数赋给变量AAA,此时AAA=0,,然后在Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法这一句计算总的脉冲数,计算原理我们已经在上一条说过了。然后在这一句speed =(Pulse_Num-AAA);我们用至今为此总的脉冲数减去AAA即为每两次调用Circle_Print()的脉冲差,而我们在主函数中使用一个100ms的延时,所以时间差为100ms,脉冲反映小车路程,可以得到速度。
***硬件***
我使用的编码器(6线,分AB相,客服叫做13相?不太懂)转一圈是390个脉冲,使用四倍频,转一圈即为1560个脉冲。用总脉冲数除以1560即为至今为止转过的圈数。
小车直径为6.3cm(没找到参数,手动测量的0.0),  周长约为0.204m.
***下载验证***
%WWC@LRAHAOLE7(S(@D[Q_S.png 可以看到,第一个返回总的溢出数,第二个为总圈数,第三个为速度。
因为在主函数中使用一个100ms的延时,每0.1秒转过的脉冲数为160左右,约为0.1圈,每秒转过1圈。
***tips***
在@北名茗水 的中断回调函数程序里有一句PB0!=PB0;而我的电机一IN1接的就是PB0,我改的时候忘记删掉了这句,然后我的第一个轮子(编码器接的第二个轮子)就一会转一会不转0.0





在文件中写入了函数之后要在头文件和主函数里添加初始化,否则不会识别。


TIM4_Init(2000,3);在主函数内初始化TIM4时设置了ARR为2000。


欢迎批评斧正。


89MVP0O2BU~@CJ){Y]]`JD2.png

编码器.zip

10.35 MB, 下载次数: 1177

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

16

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2019-9-4
在线时间
52 小时
 楼主| 发表于 2020-1-10 19:43:18 | 显示全部楼层
最主要的部分是 更新中断。更新中断是计数器溢出时产生的中断。可在回调函数里设计函数完成任务。
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2020-1-11
在线时间
5 小时
发表于 2020-1-27 13:55:44 | 显示全部楼层
帮顶

回复 支持 反对

使用道具 举报

4

主题

91

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1091
金钱
1091
注册时间
2017-11-7
在线时间
311 小时
发表于 2020-1-27 19:09:29 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2019-11-15
在线时间
3 小时
发表于 2020-2-6 12:01:24 | 显示全部楼层
当电机反转时,数值是错的,这是为什么
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2020-2-6
在线时间
1 小时
发表于 2020-2-6 12:14:00 | 显示全部楼层
初始值一开始为什么初始化为0,累计负数编码的时候数值是错的
回复 支持 反对

使用道具 举报

16

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2019-9-4
在线时间
52 小时
 楼主| 发表于 2020-2-10 08:59:38 | 显示全部楼层
林佳鹏 发表于 2020-2-6 12:01
当电机反转时,数值是错的,这是为什么

不好意思,可能是哪里出错了吧……我再考虑一下
回复 支持 反对

使用道具 举报

16

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2019-9-4
在线时间
52 小时
 楼主| 发表于 2020-2-10 09:00:53 | 显示全部楼层
hgknight 发表于 2020-2-6 12:14
初始值一开始为什么初始化为0,累计负数编码的时候数值是错的

你好。能说的清楚些吗?什么的初值?我隐约记得当时我改过一个类似的问题,但是现在记不太清了
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2020-2-6
在线时间
1 小时
发表于 2020-2-19 17:40:11 | 显示全部楼层
邵茂峰 发表于 2020-2-10 09:00
你好。能说的清楚些吗?什么的初值?我隐约记得当时我改过一个类似的问题,但是现在记不太清了

void TIM4_Init(u16 arr,u16 psc)
{  
        TIM4_Handler.Instance=TIM4;
        TIM4_Handler.Init.Prescaler=psc;                     //分频系数
        TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
        TIM4_Handler.Init.Period=arr;                        //自动装载值
        TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频银子
       
        //HAL_TIM_Base_Init(&TIM4_Handler);        //HAL_TIM_OC_Init(&TIM4_Handler);
        //不要用这句话,他是基本定时器的设置,这里使用了编码器模式,没必要配置
       
        TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;
        TIM4_Encoder_Handler.IC1Filter=0;
        TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;
        TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
               
        TIM4_Encoder_Handler.IC2Filter=0;
        TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;
        TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;
        HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);
       
        HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);
        HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
        TIM4->CNT=1000;
    __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE);   //使能更新中断
    __HAL_TIM_ENABLE(&TIM4_Handler);

}
我将TIM4->CNT=1000改为TIM4->CNT=0,当电机反转时,数据理论上应该返回负的,但是却返还一个上千或上万的数据,是不是数据类型的问题?

回复 支持 反对

使用道具 举报

16

主题

74

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2019-9-4
在线时间
52 小时
 楼主| 发表于 2020-2-23 14:03:11 | 显示全部楼层
本帖最后由 邵茂峰 于 2020-2-23 14:50 编辑
hgknight 发表于 2020-2-19 17:40
void TIM4_Init(u16 arr,u16 psc)
{  
        TIM4_Handler.Instance=TIM4;

emmm那你用1000的话可以吗?  
如果可以的话 我猜想应该是递减的时候从0到2000这里出了问题(只是猜测) 之前我看过一些帖子是这么说的。这我就没有再深入过了。好像要涉及到计算机的减法规则
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2020-8-10
在线时间
16 小时
发表于 2020-12-16 16:03:30 | 显示全部楼层
您好,我试验一下,旋转编码器上电之后,不旋转捕获脉冲数也在增加,这就很费解,接了A,B两相。断电之后,捕获脉冲数就不增加了
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2023-5-8
在线时间
10 小时
发表于 2023-8-10 17:59:55 | 显示全部楼层
823168321 发表于 2020-12-16 16:03
您好,我试验一下,旋转编码器上电之后,不旋转捕获脉冲数也在增加,这就很费解,接了A,B两相。断电之后, ...

我也是,请问一下你解决了吗
回复 支持 反对

使用道具 举报

2

主题

5

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
212
金钱
212
注册时间
2015-3-20
在线时间
57 小时
发表于 2024-11-27 14:49:22 | 显示全部楼层
hycrgqb 发表于 2020-1-27 19:09
这里有 http://www.waveshare.net/study/portal.php?mod=list&catid=38

要不要脸了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-1-19 08:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表