STM32实现编码器M法测速接线

发布者:Xiangsi最新更新时间:2024-09-13 来源: elecfans关键字:STM32  编码器 手机看文章 扫描二维码
随时随地手机看文章

接线

编码器电机电机驱动(这里用的L298n)、STM32、电源(可以是12V电池)的接线如下

图片

3.3 代码编写

encoder.h中的内容


#ifndef _ENCODER_H_

#define _ENCODER_H_


#include 'stm32f1xx.h'


//电机1的编码器输入引脚

#define MOTO1_ENCODER1_PORT GPIOA

#define MOTO1_ENCODER1_PIN  GPIO_PIN_0

#define MOTO1_ENCODER2_PORT GPIOA

#define MOTO1_ENCODER2_PIN  GPIO_PIN_1


//定时器

#define ENCODER_TIM htim2

#define PWM_TIM     htim3

#define GAP_TIM     htim4


#define MOTOR_SPEED_RERATIO 45u    //电机减速比

#define PULSE_PRE_ROUND 11 //一圈多少个脉冲

#define RADIUS_OF_TYRE 34 //轮胎半径,单位毫米

#define LINE_SPEED_C RADIUS_OF_TYRE * 2 * 3.14

#define RELOADVALUE __HAL_TIM_GetAutoreload(&ENCODER_TIM)    //获取自动装载值,本例中为20000

#define COUNTERNUM __HAL_TIM_GetCounter(&ENCODER_TIM)        //获取编码器定时器中的计数值


typedef struct _Motor

{

    int32_t lastCount;   //上一次计数值

    int32_t totalCount;  //总计数值

    int16_t overflowNum; //溢出次数

    float speed;         //电机转速

    uint8_t direct;      //旋转方向

}Motor;



#endif

encoder.c中的内容


#include 'encoder.h'



Motor motor1;



void Motor_Init(void)

{

    HAL_TIM_Encoder_Start(&ENCODER_TIM, TIM_CHANNEL_ALL);      //开启编码器定时器

    __HAL_TIM_ENABLE_IT(&ENCODER_TIM,TIM_IT_UPDATE);           //开启编码器定时器更新中断,防溢出处理

    HAL_TIM_Base_Start_IT(&GAP_TIM);                       //开启100ms定时器中断

    HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_2);            //开启PWM

    HAL_TIM_PWM_Start(&PWM_TIM, TIM_CHANNEL_1);            //开启PWM

    __HAL_TIM_SET_COUNTER(&ENCODER_TIM, 10000);                //编码器定时器初始值设定为10000

    motor1.lastCount = 0;                                   //结构体内容初始化

    motor1.totalCount = 0;

    motor1.overflowNum = 0;                                  

    motor1.speed = 0;

    motor1.direct = 0;

}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数,用于计算速度

{

    if(htim- >Instance==ENCODER_TIM.Instance)//编码器输入定时器溢出中断,用于防溢出                   

    {      

        if(COUNTERNUM < 10000) motor1.overflowNum++;       //如果是向上溢出

        else if(COUNTERNUM >= 10000) motor1.overflowNum--; //如果是向下溢出

        __HAL_TIM_SetCounter(&ENCODER_TIM, 10000);             //重新设定初始值

    }

    else if(htim- >Instance==GAP_TIM.Instance)//间隔定时器中断,是时候计算速度了

    {

        motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上计数(正转),返回值为0,否则返回值为1

        motor1.totalCount = COUNTERNUM + motor1.overflowNum * RELOADVALUE;//一个周期内的总计数值等于目前计数值加上溢出的计数值

        motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10;//算得每秒多少转

        //motor1.speed = (float)(motor1.totalCount - motor1.totalCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 10 * LINE_SPEED_C//算得车轮线速度每秒多少毫米

        motor1.lastCount = motor1.totalCount; //记录这一次的计数值

    }

}

使用时需要在main.c的循环之前调用Motor_Init函数进行初始化。


如果发现无法进入编码器中断导致totalCount经常溢出归零,可以尝试换一种防溢出的方法,代码如下


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器回调函数,用于计算速度

{  

    if(htim- >Instance==GAP_TIM.Instance)//间隔定时器中断,是时候计算速度了

    {

        motor1.direct = __HAL_TIM_IS_TIM_COUNTING_DOWN(&ENCODER_TIM);//如果向上计数(正转),返回值为0,否则返回值为1

        motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值

        

        if(motor1.lastCount - motor1.totalCount > 19000) // 在计数值溢出时进行防溢出处理

        {

            motor1.overflowNum++;

            motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值

        }

        else if(motor1.totalCount - motor1.lastCount > 19000) // 在计数值溢出时进行防溢出处理

        {

            motor1.overflowNum--;

            motor1.totalCount = COUNTERNUM_1 + motor1.overflowNum * RELOADVALUE_1;//一个周期内的总计数值等于目前计数值加上溢出的计数值

        }

        

        motor1.speed = (float)(motor1.totalCount - motor1.lastCount) / (4 * MOTOR_SPEED_RERATIO * PULSE_PRE_ROUND) * 3000;//算得每秒多少转,除以4是因为4倍频

        motor1.lastCount = motor1.totalCount; //记录这一次的计数值

}


关键字:STM32  编码器 引用地址:STM32实现编码器M法测速接线

上一篇:国产单片机替代-CH32替代STM32
下一篇:在STM32CubeIDE中创建工程

推荐阅读最新更新时间:2026-03-23 08:20

STM32:TIM的编码器模式
本文是基于STM32G431的编码器模式。代码为裸机版。 先上一个编码器的信号输出图。 编码器信号输出.png 编码器有3个输出信号:A相、B相和Z相。编码器旋转一圈,Z相输出1个脉冲,A相和B相输出200个脉冲(我手上的编码器E6A2-CWZ3C是输出200个脉冲)。 初始化 直接贴代码 void bsp_encoder_init(void) { LL_TIM_InitTypeDef TIM_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB2_GRP
[单片机]
基于STM32的正交编码器驱动电机设计
1。编码器原理 什么是正交?如果两个信号相位相差90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向。 这里使用了TI12模式,例如当T1上升沿,T2在低电平时;T1下降沿,T2在高电平时,向上计数,这样的好处是当有毛刺产生的时候,会自动+1 -1过滤掉毛刺。 2。编码器的中断 由于编码器是基于定时器的,所以编码器的中断实际上就是定时器的中断。也就是说定时器是每隔一定时间加一个数(或减一个数 ),当数到达预设值时就产生中断,而编码器是每一个有效脉冲就加一个数(或减一个数 ),当数到达预设值时就产生中断。若预设值为1000则编码器与定时器中断不同的是,当编码器反转时值到达999产生一次
[单片机]
基于<font color='red'>STM32</font>的正交<font color='red'>编码器</font>驱动电机设计
STM32编码器模式详解(一)---理论
一、编码器接口模式 选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011。 通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以对输入滤波器编程。 两个输入TI1和TI2被用来作为增量编码器的接口。参看表77,假定计数器已经启动(TIMx_CR1寄存器中的CEN=’1’),计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。TI1FP1和TI2FP2是TI1和TI2在通过输入滤波器和极性控制后的信号;如果没有滤波
[单片机]
<font color='red'>STM32</font><font color='red'>编码器</font>模式详解(一)---理论
STM32编码器接口,以及应用编程
Ⅰ 关于编码器 编码器的种类有很多,什么增量式编码器、绝对值编码器,有轴或者无轴编码器,电压输出、推拉输出、集电极开路输出等等。但不管什么类型的编码器,其目的都类似,得到转动的角度,角速度、位移等。 本文讲述常见的增量式编码器,增量式编码器也可以叫正交编码器,也就是说可以通过其A、B的相位知道编码器是正转,还是反转,还可以根据编码器参数得出旋转了多少角度等。 常见的增量式编码器A、B、Z三根线代表什么意思呢?使用过编码器的人不难理解,这里简单给初学者讲述一下: A、B两线提供相位相差90度的脉冲信号,用其来计算旋转的角度;Z线为过零点线,也就是说每转一转,经过某一点都会输出一个脉冲信号,主要用于“过零校正”,三
[单片机]
<font color='red'>STM32</font><font color='red'>编码器</font>接口,以及应用编程
STM32编码器接口模式
1.编码器 图1 编码器示意图 图1为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。 2.stm32编码器接口模式(寄存器) STM32的编码器接口模式在STM32中文参考手册中有详细的说明。 图2 STM芯片编码器接口模式说明 下图是一个计数器操作的实例,显示了计数信号的产生和方向控制。它还显示了当选择了双边沿时,输入抖动是如何被抑制的;抖动可能会在传感器的位置靠近一个转换点时产生。在这个例子中,我们假定配置如下: 图3 编码器模式下的计数器操作实例 TI 1波形先于TI 2波形90°时,
[单片机]
<font color='red'>STM32</font><font color='red'>编码器</font>接口模式
STM32编码器模式学习
一、编码器模式理论储备 通常为了提高精度我们会选择在上升沿和下降沿都进行计数! 还有一个非常重要的图这里也记录下 其中让人费解的应该是在第二列的相对信号的电平,这里就来详细谈一下吧。 其实也不难理解哈,我们上面也说了通常为了提高精度会在A、B两相的上升沿和下降沿都进行计数,那么对应在一个周期就可以计数四次,计数次数的增加也就意味着精度的提高! 编码器模式下,如果此时处于正转,那么这四次计数应该都是加的。同理,如果是反转,那么这四次计数都是减的。那么问题来了,如何判断正反转呢? 不就是在相对电平的基础上嘛!!! 仔细对照图中,在正转或者反转的情况下,A相对B的电平高低以及上表中的计数方向
[单片机]
<font color='red'>STM32</font>之<font color='red'>编码器</font>模式学习
STM32 定时器正交编码器模式 寄存器配置程序
void Encoder_Init(void) { RCC- APB1ENR|=1 1; //TIM3时钟使能 RCC- APB2ENR|=1 2; //使能PORTA时钟 GPIOA- CRL&=0XF0FFFFFF;//PA6 GPIOA- CRL|=0X04000000;//浮空输入 GPIOA- CRL&=0X0FFFFFFF;//PA7 GPIOA- CRL|=0X40000000;//浮空输入 TIM3- DIER|=1 0; //允许更新中断 TIM3- DIER|=1 6; //允许触发中断 MY_NVIC_Init(1,3,TIM3_IRQChannel,2); TIM3- PSC = 0x0;/
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved