利用stm32自带的正交编码器检测增量式编码器流程总结

发布者:hylh2008最新更新时间:2017-11-02 来源: eefocus关键字:stm32  正交编码器  增量式编码器 手机看文章 扫描二维码
随时随地手机看文章
  1. 由于手术的工频升级机需要自动平层功能,于是着手开始做这方面的工作。硬件选择的是增量式编码器,100脉冲每转,后来了解到stm32的每个定时器的通道1和通道2内置了正交编码器模块,可以直接使用。之前的公司工程师都是用定时器捕捉脉冲,然后自行处理的,我看了下代码挺麻烦的,现在用了stm32自带的感觉就容易多了。找了官方的软件说明,看了下网上已有的例子,一个下午就基本在我的系统架构中添加了这个设备,然后对这个设备初始化,设置上层接口API。最后看些例子将16位计数器软件扩展到32位。就顺利的完成了基本模块的第一步工作了。以后则需要将采集的到数据与楼层做一个好的数据结构结合在一起,方便调用和维护了。  

下面贴上我的基本思路和相关软件代码。


第一步:了解什么事增量式编码器。这就需要百度了,这个自行研究。也很好理解的。


第二步:看网上先人有的实战经验,主要在stm32论坛,21IC论坛里。百度相关关键词就可以找到。


第三步:分析stm32模块使用正交编码检测的原理。这个部分由一个官方手册,也可百度到。

下面是相关初始化代码,由于网上的例子基本用的都是TIM3,而我用的是TIM1,所以需要我自己参照修改的。


  1. void InitializeEncoder(void)  

  2. {  

  3.           

  4.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  

  5.         TIM_ICInitTypeDef TIM_ICInitStructure;  

  6.   

  7.               

  8.         GPIO_InitTypeDef GPIO_InitStructure;  

  9.         //NVIC_InitTypeDef NVIC_InitStructure;  

  10.   

  11.           

  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能TIM1时钟  

  13.           

  14.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟  

  15.   

  16.         GPIO_StructInit(&GPIO_InitStructure);  

  17.           

  18.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;  

  19.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//PA8 PA9浮空输入  

  20.         GPIO_Init(GPIOA, &GPIO_InitStructure);  

  21.   

  22.           

  23.         //NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;  

  24.         //NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  

  25.         //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY;  

  26.         //NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;  

  27.         //NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

  28.         //NVIC_Init(&NVIC_InitStructure);  

  29.   

  30.           

  31.         TIM_DeInit(ENCODER_TIMER);  

  32.         TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  

  33.   

  34.         TIM_TimeBaseStructure.TIM_Prescaler = 0x0;  // No prescaling //设定计数器分频系数为0,不分频  

  35.         //TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1;  //设定计数器重装值   

  36.         TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD-1;  

  37.           

  38.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置时钟分割 T_dts = T_ck_int   

  39.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数  

  40.         TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);  

  41.   

  42.         TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,   

  43.                                  TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3  

  44.         TIM_ICStructInit(&TIM_ICInitStructure);  

  45.         TIM_ICInitStructure.TIM_ICFilter =ICx_FILTER;//选择输入比较滤波器  

  46.         TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);  

  47.   

  48.         // Clear all pending interrupts  

  49.         TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);//清除TIM1的更新标志位  

  50.         TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);  

  51.   

  52.         //ENC_Clear_Speed_Buffer();  

  53.   

  54.         //Reset counter  

  55.         TIM1->CNT = 0;  

  56.         //CurrentCount = TIM1->CNT;  

  57.   

  58.         TIM_Cmd(ENCODER_TIMER, ENABLE);  

  59.   

  60.   

  61.         System.Device.Encoder.Enc_GetCount = Enc_GetCount;  

  62. }  

然后就可以读取TIM1->CNT的值来获取正交编码值了。

这样还存在着位数不够的问题,参照网上大神的例子,要领会后自己做了我自己的修改,多谢先人。


  1. System.Device.Encoder.Enc_GetCount = Enc_GetCount;  

上面这个接口函数就是我调给上层应用读取的数据,大概每1s或10调用一次,这个参照自己需求定义。


  1. s16   Enc_GetCount(void)  

  2. {  

  3.         static  u16   lastCount = 0;  

  4.         u16  curCount = ENCODER_TIMER->CNT;//获取编码值  

  5.         s32 dAngle = curCount - lastCount;  

  6.         if(dAngle >= MAX_COUNT)  

  7.         {  

  8.             dAngle -= ENCODER_TIM_PERIOD;  

  9.         }  

  10.         else if(dAngle < -MAX_COUNT)  

  11.         {  

  12.             dAngle += ENCODER_TIM_PERIOD;  

  13.         }  

  14.         lastCount = curCount;  

  15.         return (s16)dAngle;  

  16. }  

下面则贴出我自己的相关定义。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

  1. //20141213  

  2. #define ENCODER_TIMER   TIM1  // Encoder unit connected to TIM3  

  3. #define ENCODER_PPR           (u16)(100)   // number of pulses per revolution  

  4. #define SPEED_BUFFER_SIZE 8  

  5.   

  6. #define COUNTER_RESET   (u16)0  

  7. #define ICx_FILTER      (u8) 6 // 6<-> 670nsec  

  8.   

  9. #define TIMx_PRE_EMPTION_PRIORITY 1  

  10. #define TIMx_SUB_PRIORITY 0  

  11.   

  12. #define ENCODER_TIM_PERIOD 0xffff//最大值预分频是65536-1  

  13. #define MAX_COUNT          10000//10000也就是1ms内不会超过10000个脉冲  


主要的函数就是上面了。调用的话就在应用层处理使用就可以了。这个是在msOS架构上搭建的,很实用。


第四步:构建编码计数器值和楼层的数据关系结构。将其封装在一起,应用层调用更加方便,接下来就会做的。


关键字:stm32  正交编码器  增量式编码器 引用地址:利用stm32自带的正交编码器检测增量式编码器流程总结

上一篇:stm32对编码器计数
下一篇:J-Flash下载STM32用J-link的设置方法

推荐阅读最新更新时间:2024-03-16 15:42

stm32编码器模式
选择编码器接口模式的方法是:如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的 SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则 置SMS=011 TI1FP1和TI2FP2 是TI1和TI2在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则TI1FP1=TI1, TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号 的跳变顺序,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应的设置。 不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数,在任一输入端(TI1或者 TI
[单片机]
关于STM32GPIO口配置命令
以下代码摘自原子的stm32开发指南 //初始化 PB5 和 PE5 为输出口.并使能这两个口的时钟 void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能 PB,PE 端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PB.5 推挽输出 GPIO_InitStructure.GPIO_M
[单片机]
STM32直流风机通过按键PWM调速同时各参数在LCD上显示
依然还记得当时学完STM32之后感觉什么都不会,然后基本上是靠单片机的知识撑过期末的测试的,然后其实一直想把STM32学好,但是感觉学太多也不好吧,总感觉这是样,学得多并不是坏事 ,但是总觉得吧,应该要在你学的技能中有一项是你非常突出的。 // //Design:直流电机调速,通过按键改变占空比以达到调速目的,同时显示各参数 //Author:Touch //Time :2017.6.5 // #include led.h #include delay.h #include sys.h #include usart.h #include lcd.h #include key.h #include pwm.h int main(v
[单片机]
如何修改STM32系统时钟
一般的STM32控制板搭载的是8M晶振。我们也熟悉了8M晶振的使用方法。但是,当遇到12M晶振是如何修改STM32系统时钟呢? 具体步骤如下: 第一步,全局搜索HSE_VALUE #define HSE_VALUE ((uint32_t)8000000) /*! Value of the External oscillator in Hz */ 修改为: #define HSE_VALUE ((uint32_t)12000000) /*! Value of the External oscillator in Hz */ 第二步,打开system_stm32f10x.c,修改PLL参数,将 /* PLL
[单片机]
stm32 Flash 模拟EEPROM
/* *STM32的闪存模块由:主存储器、信息块和闪存存储器接口寄存器等3部分组成。 * 对于大容量产品 每页2K字节 * 小容量和中容量产品则每页只有1K字节 * */ /* * *闪存的读取 *内置闪存模块可以在通用地址空间直接寻址, *任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。 *这里要特别留意一个闪存等待时间,因为CPU运行速度比FLASH快得多, *STM32F103的FLASH最快访问速度 24Mhz,如果CPU频率超过这个速度, *那么必须加入等待时间,比如我们一般使用72Mhz的主频,那么FLASH等待周期就必须设置为2, *该设置通过FLASH_ACR寄存器设置。
[单片机]
<font color='red'>stm32</font> Flash 模拟EEPROM
STM32笔记(十三)---ADC
一、ADC简介 以STM32f103 系列为例,3 个 ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道。其中ADC1 和 ADC2 都有 16 个外部通道, ADC3 根据 CPU 引脚的不同通道数也不同,一般都有8 个外部通道。 ADC 的模式非常多,功能非常强大,具体的我们在功能框图中分析每个部分的功能。 ADC功能框图 图1 单个ADC功能框图 ①电压输入范围 ADC 输入范围为: VREF- ≤ VIN ≤ VREF+。由 VREF-、 VREF+ 、 VDDA 、 VSSA、这四个外部引脚决定。 在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,
[单片机]
<font color='red'>STM32</font>笔记(十三)---ADC
stm32专题五:时钟树(二)系统配置时钟函数分析
分析stm32的系统时钟函数,对于我们实现自定义时钟配置非常重要,以下是标准库函数中的时钟配置函数。 static void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ /* Enable HSE */ // 使能HSE RCC- CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready
[单片机]
STM32单片机特性解析
STM32单片机 由ST厂商推出的STM32系列单片机,行业的朋友都知道,这是一款性价比超高的系列单片机,应该没有之一,功能及其强大。其基于专为要求高性能、 低成本、低功耗的嵌入式应用专门设计的ARM Cortex-M内核,同时具有一流的外设:1μs的双12位ADC,4兆位/秒的UART,18兆位/秒的SPI等等,在功耗和集成度方面也有不俗的表现,当然和MSP430的功耗比起来是稍微逊色的一些,但这并不影响工程师们对它的热捧程度,由于其简单的结构和易用的工具再配合其强大的功能在行业中赫赫有名。其强大的功能主要表现在: 特性 1、内核:ARM32位Cortex-M3CPU,最高工作频率72MHz,1.25DMIPS/MHz,单周
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved