历史上的今天

今天是:2024年09月16日(星期一)

2018年09月16日 | stm32编码器的接口模式

发布者:心愿实现 来源: eefocus关键字:stm32  编码器  接口模式 手机看文章 扫描二维码
随时随地手机看文章

编码器是什么玩意呢,它可是一个好玩的东西,做小车测速必不可少的玩意,下面,我将从编码器的原理讲起,一直到用stm32的编码器接口模式,测出电机转速与方向。

1.编码器

图1 编码器示意图

      图1为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。371电机中的码盘就是这样的,他是334线码盘,具有较高的测速精度,也就是电机转一圈输出334个脉冲,芯片上已集成了脉冲整形触发电路,输出的是矩形波,直接接单片机IO就OK。        
     增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向)。下图为编码器的原理图:

图2 增量式旋转编码器

A,B两点对应两个光敏接受管,A,B两点间距为 S2 ,码盘的光栅间距分别为S0和S1。S0+S1的距离是S2的四倍。这样保证了A,B波形相位相差90度。旋转的反向不同,锯齿波A,B先到达高电平的顺序就会不同,如上图左侧所示,顺序的不同,就可以得到旋转的方向。

2.stm32编码器接口模式(寄存器
        stm32的编码器接口模式在STM32中文参考手册中有详细的说明,在手册273页,14.3.12节。程序是完全按照 下图方式,设置寄存器的。
      

      

图3

         从图3中可以看出,TI1波形先于TI2波形90°时,每遇到一个边沿变化是,计数器加1(可以通过寄存器设置加减),可以看出一个光栅,被计数了4次。TI1波形后于TI2波形90°时 ,每遇到一次边沿变化,计数器减1。


//TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)

//arr:自动重装值 0XFFFF

//psc:时钟预分频数        ,不分频

void TIM2_Encoder_Init(u16 arr,u16 psc)

{

    RCC->APB1ENR|=1<<0;       //TIM2时钟使能

        RCC->APB2ENR|=1<<2;       //使能PORTA时钟

        

    GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置

    GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入

            

    TIM2->ARR=arr;            //设定计数器自动重装值 

    TIM2->PSC=psc;            //预分频器


        TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上

        TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上

        TIM2->CCER |= 0<<1;                  //IC1不反向

        TIM2->CCER |= 0<<5;           //IC2不反向

        TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效

        TIM2->CR1 |= 1<<0;                  //使能计数器

}

3 硬件

用到的模块有STM32核心板、L298电机驱动、371带编码器电机(1:34)。这里主要介绍一下电机,1:34指的是电机轴转动34圈,电机输出1圈。1:X,X值越小,电机的输出转速也就越快,扭矩也就越小;反之,X值越大,电机的输出转速越慢,扭矩也越大。


图4 电机实物图

左边两根黄线是电机两极。绿线和白线是脉冲输出线,分别接编码器的接收管A、B,用一根可以测得速度,两根同时用可测出电机速度与转向。红线和黑线是编码器电源接线,红正黑负,电压3.3V-5V,不不可接反。

4 控制代码

工作指示灯、电机方向与速度控制代码。

//LED IO 初始化 端口PD.2  运行指示灯

void LED_Init(void)

{                    

        RCC->APB2ENR|=1<<5;      //使能PORTD时钟         

        GPIOD->CRL&=0XFFFFF0FF;

        GPIOD->CRL|=0X00000300;  //PD.2推挽输出

        GPIOD->ODR|=1<<2;        //PD.2输出高 

}

//电机旋转方向控制信号端口初始化

//PC1~0推挽输出,输出高

void M_Init(void)

{

        RCC->APB2ENR|=1<<4;      //使能PORTC时钟

        GPIOC->CRL&=0XFFFFFF00;

        GPIOC->CRL|=0X00000033;  //PC1~0推挽输出

        GPIOC->ODR|=0XF<<0;             //PC1~0输出高电平

}


//定时器TIM3,PWM输出初始化,CH1(PA6)

//arr:自动重装值

//psc:时钟预分频数

//设置自动重装值为900,那么PWM频率=72000/900=8Khz

////见STM32参考手册,14.3.9PWM模式。

void TIM3_PWM_Init(u16 arr,u16 psc) //arr设定计数器自动重装值   

                                    //psc预分频器不分频,psc=0

{

        RCC->APB1ENR|=1<<1;       //TIM3时钟使能    

                  

        GPIOA->CRL&=0XF0FFFFFF;//PA6输出

        GPIOA->CRL|=0X0B000000;//复用功能输出           

        GPIOA->ODR|=1<<6;//PA6上拉        


        TIM3->ARR=arr;//设定计数器自动重装值 

        TIM3->PSC=psc;//预分频器不分频

        

        TIM3->CCMR1|=6<<4;  //CH1 PWM1模式        高电平有效         

        TIM3->CCMR1|=1<<3; //CH1预装载使能


        TIM3->CCER|=1<<0;   //OC1 输出使能   


        TIM3->CR1=0x0080;   //ARPE使能 

        TIM3->CR1|=0x01;    //使能定时器3 

}


//电机方向与速度控制,速度调节范围为-100~+100

//大于0时,正转,小于0时,反转

// 占空比低于0.4时电机不转

//(占空比是指高电平在一个周期之内所占的时间比率)

//TIM3->CCR1的设定范围为0~900(因为arr=900)

//见STM32参考手册,14.3.9PWM模式。

void Motor_Speed_Control(s16 motorSpeed)         

{

    s16 speed = 0 ;        

        

    if(motorSpeed>100)  speed = 100;

            else if (motorSpeed<-100)  speed = -100;

                        else  speed = motorSpeed;

        if(speed == 0)

        {

                M_1 = 0;

                M_2 = 0;

        }

            else if(speed > 0)

                {

                        M_1 = 0;

                        M_2 = 1;

                        TIM3->CCR1 = speed * 9;

                }

                        else

                        {

                                M_1 = 1;

                                M_2 = 0;

                                TIM3->CCR1 = -speed * 9;

                        }

}


电机速度与方向检测代码


//TIM2_Encoder_Init,Tim2_CH1(PA0);Tim2_CH2(PA1)

//arr:自动重装值 0XFFFF

//psc:时钟预分频数        ,不分频

//见STM32中文手册 14.3.12编码器接口模式

void TIM2_Encoder_Init(u16 arr,u16 psc)

{

    RCC->APB1ENR|=1<<0;       //TIM2时钟使能

        RCC->APB2ENR|=1<<2;       //使能PORTA时钟

        

    GPIOA->CRL&=0XFFFFFF00;   //PA0、PA1 清除之前设置

    GPIOA->CRL|=0X00000044;   //PA0、PA1 浮空输入

            

    TIM2->ARR=arr;            //设定计数器自动重装值 

    TIM2->PSC=psc;            //预分频器


        TIM2->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上

        TIM2->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上

        TIM2->CCER |= 0<<1;                  //IC1不反向

        TIM2->CCER |= 0<<5;           //IC2不反向

    TIM2->SMCR |= 3<<0;                  //所用输入均在上升沿或下降沿有效

        TIM2->CR1 |= 1<<0;                  //使能计数器

}

//计数寄存器赋值

void TIM2_Encoder_Write(int data)

{

    TIM2->CNT = data;

}

//读计数个数

int TIM2_Encoder_Read(void)

{

    TIM2_Encoder_Write(0);        //计数器清0

        delay_ms(10);          //检测时间,可调节

    return (int)((s16)(TIM2->CNT));           //数据类型转换

                             //记录边沿变化次数(一个栅格被记录4次)

}

复制代码

这里我们只显示边沿变化次数,没有具体的算出速度。

主函数


int main(void)

{

//        motorSpeed的范围为-100 ~ +100;

        s16 motorSpeed = 100; 

        Stm32_Clock_Init(9); //系统时钟设置

        delay_init(72);             //延时初始化

        uart_init(72,9600);  //串口1初始化

        LED_Init();                         //初始化与LED连接的硬件接口

        M_Init();                           ////初始化电机运行方向控制端口

        TIM3_PWM_Init(900,0);          //不分频。PWM频率=72000/900=8Khz

        TIM2_Encoder_Init(0xffff, 0); //计数器自动重装值为最大


        while(1)

    {

                LED =! LED;

            Motor_Speed_Control(motorSpeed);

                printf("编码器值:%d\n ",TIM2_Encoder_Read());

    }                

}

5 估算验证
         这里我们只是大概的估算验证测量值是否正确,不具有完全正确性。
        我们设置motorSpeed = 100 ,得到测量值如下图:

图5 motorSpeed = 100

因为误差是不可避免的,所以看到每次检测的值都是不一样的。我们取462,因为一个光栅被记录了4次,所以在10ms内一共检测到了462/4=115.5,那么得到11.55个/ms,每ms内检测到11.55个光栅。

     通过码表,记录电机输出50圈,用时50.2s,那么这时应该检测到的光栅个数为50*34(电机转34圈,输出1圈)*334(每圈有334个光栅)=567800,除以时间,得到估算值11.31个/ms。可以看出估算值与测量值是相近的,认为测量是准确的。
      设置motorSpeed = -50 ,得到测量值如下图 :

图6 motorSpeed=-50

可以看到测量值是负值,说明电机是反转,与实际设置相符。

      我们读的是计数器TIM2->CNT中的值,此值为什么会是负的,这里为什么这样用?      编码器模式中使用上下计数,假设我们初始化TIM2_Encoder_Init_1(0xff, 0);自动装载值为0xFF,这时,计数器中的值,就会在0x00与0xFF之间循环变化,由0x01减为0x00,再减1时,计数器中的值为0xFF,我们将此数做为有符型整数处理,当然,计数的前提是每个周期的计数个数不能超过0x7F,超过,计数将不准确。
      符号强制转换,return (int)((s16)(TIM2->CNT));里面有个类型转换,强制转换返回有符型数据。数值都是以补码表示的,正整数补码是源码,负整数补码是绝对值取反加1。向下计数时减1,为0时,就需要向高位借位减“1”,可以这样理解,一个8位数00000000B-00000001B,但0不够减1的,就向不存在的第9位借1,100000000B-00000001B=11111111B,数是以补码形式表示的,这样11111111B就为-1了。
      在例程中,初始化自动重装值为0xFFFF可以做个实验,直接输出TIM2->CNT的值看一下:      printf("编码器值1:%x \r\n",TIM2->CNT)。


关键字:stm32  编码器  接口模式 引用地址:stm32编码器的接口模式

上一篇:STM32的16位编码器溢出问题
下一篇:STM32对码盘的正交信号处理

推荐阅读

这是一场围绕半导体生态圈的持久话题。最大赢家我的选择是台积电。他们迎来一个丰收年,而未来也会如此。GF终止7nm让AMD转入台积电帐下,传闻称英特尔也将转移部分产能到台积电,当然苹果和其他产业界已经开始在台积电流片7nm让其继续保持行业领先,可以提前庆祝这一年的胜利了。有消息提到英特尔的动作,称英特尔Coffee Lake处理器的生产已经迁移到台积...
2018年我国芯片进口额为3120.58亿美元,同比增长19.8%,芯片近十年都是我国第一大进口商品。 贸易逆差逐年扩大,2010年集成电路贸易逆差1277.4亿美元,而在2018年集成电路贸易逆差增长到2274.22亿美元。如此大的贸易逆差反映出我国集成电路市场长期严重供不应求,进口替代的市场空间巨大。 半导体材料自给率低在半导体材料领域,由于高端产品技术壁垒高,...
出问题的原因是路径名太长,换个深度浅一点的路径就好了。要注意,更换路径之后,要全部重新编译,否则调试的时侯MDK还会找旧路径的源代码。(嗯,MDK毛病是很多!)
大家好,在示波器前面板的下方,通常会有一排输入端口,但是这一排端口的功能可不是都一样的哦,左侧一般为模拟通道输入端,即我们平时用来插探头测量信号时所用,右侧的一个端子我们称为外部触发输入端,那这个外部触发输入端到底有什么用途呢?不知您有没有遇到过这样的情况,当测试多组上电时序时,比如有8路或者有16路上电时序甚至更多路,很显然示波...

史海拾趣

问答坊 | AI 解惑

什么叫云台?

其实云台就是两个交流电机组成的安装平台,可以水平和垂直的运动。但是要注意我们所说的云台区别于照相器材中的云台,。照相器材的云台一般来说只是一个三脚架,只能通过手来调节方位;而监控系统所说的云台是通过控制系统在远程可以控制其转动以及 ...…

查看全部问答∨

RTOS应用程序开发指南,大量实例!!!!

RTOS应用程序开发指南,大量实例!!!! 一个自己写的RTOS,运行起来很不错,使用与51等RAM,ROM小容量的单片机 转自 ouravr…

查看全部问答∨

襄樊学院电子设计竞赛预测题

本帖最后由 paulhyde 于 2014-9-15 09:32 编辑 里面有几个题目不错,  …

查看全部问答∨

gerber文件可不可以确定零件位置、编号?

本信息来自合作QQ群:电子工程师技术交流(12425841) 群主在坛子ID:Kata …

查看全部问答∨

请教开机LOGO出现横条纹的现象

s3c2440的机器WINCE系统启动时,在快进系统时,开机LOGO中出现一些黑或白的横条纹闪过,请问是否有人遇到过,怎么解决?…

查看全部问答∨

51单片机+ds1302 的 电子钟加日历怎么做啊

向各位大虾请教,51单片机+ds1302  的 电子钟加日历 的程序应该怎么设计啊?…

查看全部问答∨

DS18B20的N个问题彻底解决,感慨万千,写出来让大家共享。

问题:    1、有的DS18B20初始化困难,读数始终为85度。    2、温度读数不平滑,比如2次值:15度 25读的变化,而环境温度基本无变化。    3、系统中有DS18B20的时候频繁自动重启动。 解决:     我 ...…

查看全部问答∨

酷似气泡的LED灯泡可以挂在天花板上作吊灯使用

这些造型酷似气泡的LED灯泡可以挂在天花板上作吊灯使用。每当需要排解压力的时候,这款灯泡正好能成你的发泄道具。挤按的时候,灯泡表面不仅会凹陷进去,还会发出“呜呜”的声音,非常可爱。…

查看全部问答∨

高灵敏度金属探测器电路

本帖最后由 jameswangsynnex 于 2015-3-3 19:54 编辑 时间:2009-10-15 22:48:48   …

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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