stm32正交编码器学习
- 格式:docx
- 大小:20.38 KB
- 文档页数:8
STM32 16位定时器对正交编码器计数的方法(附检测输入脉冲的方法)发布时间:2009-10-04 14:29:11今天决定在END开博,之前没有工作记录的习惯,从今天起在这里记录下自己工作时的点滴经验,以供日后参考以及与网络朋友交流。
第一篇文章先简要描述下STM32 定时器对正交编码器进行计数控制的方法。
如图,STM32的每个TIMER都有正交编码器输入接口,TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
如下图,编码器使用了A,B两相信号,但是我只需要对TI1信号进行计数(第一行),我也是刚发现了这个错误,原来对两个信号都计数,导致码盘转一周得到不止100个脉冲(100线的光电码盘)。
通过STM32的编码器模块比较两想的电平信号就可以很容易地计算出编码器的运行情况了。
下面是我调试OK的代码:void Encoder_Configration(void){GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;//PC6 A相PC7 B相GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);/* Enable the TIM3 Update Interrupt *//*NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRI ORITY;NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);*//* Timer configuration in Encoder mode */TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // No prescalingTIM_TimeBaseStructure.TIM_Period = 10000;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM8, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;TIM_ICInit(TIM8, &TIM_ICInitStructure);// Clear all pending interruptsTIM_ClearFlag(TIM8, TIM_FLAG_Update);TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);//Reset counterTIM2->CNT = 0;TIM_Cmd(TIM8, ENABLE);}n_Counter = TIM_GetCounter(TIM8);Diled_Disp_Num((float)n_Counter);另外一个值得注意的问题是,STM32 的定时器是16位的,意思是只能计数到65535,有两种方法,一是采用链式的方式用两个定时器将16位扩展为32位,还有一种简单的方法就是开启定时器的溢出中断,每中断一次就代表编码器运转了特定的角度。
STM32 16位定时器对正交编码器计数的方法(附检测输入脉冲的方法)发布时间:2009-10-04 14:29:11今天决定在END开博,之前没有工作记录的习惯,从今天起在这里记录下自己工作时的点滴经验,以供日后参考以及与网络朋友交流。
第一篇文章先简要描述下STM32 定时器对正交编码器进行计数控制的方法。
如图,STM32的每个TIMER都有正交编码器输入接口,TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
如下图,编码器使用了A,B两相信号,但是我只需要对TI1信号进行计数(第一行),我也是刚发现了这个错误,原来对两个信号都计数,导致码盘转一周得到不止100个脉冲(100线的光电码盘)。
通过STM32的编码器模块比较两想的电平信号就可以很容易地计算出编码器的运行情况了。
下面是我调试OK的代码:void Encoder_Configration(void){GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;//PC6 A相PC7 B相GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);/* Enable the TIM3 Update Interrupt *//*NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRI ORITY;NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);*//* Timer configuration in Encoder mode */TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // No prescalingTIM_TimeBaseStructure.TIM_Period = 10000;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM8, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;TIM_ICInit(TIM8, &TIM_ICInitStructure);// Clear all pending interruptsTIM_ClearFlag(TIM8, TIM_FLAG_Update);TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);//Reset counterTIM2->CNT = 0;TIM_Cmd(TIM8, ENABLE);}n_Counter = TIM_GetCounter(TIM8);Diled_Disp_Num((float)n_Counter);另外一个值得注意的问题是,STM32 的定时器是16位的,意思是只能计数到65535,有两种方法,一是采用链式的方式用两个定时器将16位扩展为32位,还有一种简单的方法就是开启定时器的溢出中断,每中断一次就代表编码器运转了特定的角度。
Abstract --- The quadrature encoder which is very popular in the motor servo control application, known as a 2-channel incremental encoder, converts linear displacementinto a pulse signal. By monitoring the number of pulses and the relative phase of thetwo signals you can track the position, the direction of rotation and speed. In ddition,a third channel, or index signal, can be used to reset the position counter.STM3210x which is the MCU based on ARM latest core - Cortex-M3, integrates thequadrature encoder interface. Accordingly STM3210x can handles the encodersignal without any CPU overhead which it is possible for CPU to focus on the vectorcontrol.在马达控制类应用中, 正交编码器可以反馈马达的转子位置及转速信号。
TM32F10x 系列MCU集成了正交编码器接口,增量编码器可与MCU直接连接而无需外部接口电路。
该应用笔记详细介绍了STM32F10x与正交编码器的接口,并附有相应的例程,使用户可以很快地掌握其使用方法。
1正交编码器原理正交编码器实际上就是光电编码器,分为增量式和绝对式,较其它检测元件有直接输出数字量信号,惯量低,低噪声,高精度,高分辨率,制作简便,成本低等优点。
标题:STM32编码器4倍频原理目录1. STM32编码器接口简介2. 编码器的工作原理和应用3. STM32编码器4倍频原理4. STM32编码器4倍频的优势5. 结论1. STM32编码器接口简介STM32系列微控制器是由意法半导体推出的一类MCU产品,具有丰富的外设和强大的性能。
其中,编码器接口是STM32微控制器常见的外设之一,主要用于连接编码器传感器,实现位置或速度的测量和控制。
STM32编码器接口通常包含两个通道(A相和B相)和一个索引信号(Z 相),用于测量编码器的旋转角度和速度。
STM32还提供了丰富的编码器接口工作模式和配置选项,以满足不同应用场景的需求。
2. 编码器的工作原理和应用编码器是一种用于测量旋转角度和速度的传感器,常见的编码器类型包括光电编码器和磁性编码器。
编码器的工作原理是利用编码盘上的光、电、磁信号来生成对应的数字脉冲输出,从而实现旋转角度和速度的测量。
在工业控制和自动化领域,编码器被广泛应用于电机位置控制、轴位移测量和运动控制等领域。
特别是在闭环控制系统中,编码器可以提供准确的位置反馈信号,从而实现精准的位置控制和运动控制。
3. STM32编码器4倍频原理在STM32微控制器中,编码器接口提供了多种工作模式和编码器计数模式。
其中,4倍频模式是一种常用的编码器计数模式,可以有效提高编码器的分辨率和测量精度。
在4倍频模式下,编码器接口可以将编码器信号的脉冲数量扩大4倍输出给微控制器的定时器,从而实现对编码器脉冲数量的有效倍增。
通过4倍频模式,可以在不改变编码器硬件结构的情况下,有效提高编码器的分辨率和灵敏度。
4. STM32编码器4倍频的优势使用STM32编码器4倍频模式具有以下优势:a. 提高分辨率:通过4倍频模式,可以将编码器信号的脉冲数量扩大4倍输出给微控制器的定时器,从而提高了编码器的分辨率和测量精度。
b. 提高灵敏度:4倍频模式可以将编码器的脉冲信号有效放大,从而提高了编码器的灵敏度和反馈精度,在闭环控制系统中具有重要作用c. 保持硬件兼容性:使用4倍频模式可以在不改变编码器硬件结构的情况下,有效提高了编码器的性能,同时保持了硬件的兼容性和稳定性。
STM32的每个TIMER都有正交编码器输入接口,TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
如下图,编码器使用了A,B两相信号,但是我只需要对TI1信号进行计数(第一行),我也是刚发现了这个错误,原来对两个信号都计数,导致码盘转一周得到不止100个脉冲(100线的光电码盘)。
通过STM32的编码器模块比较两想的电平信号就可以很容易地计算出编码器的运行情况了。
下面是我调试OK的代码:void Encoder_Configration(void){GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;//PC6 A相PC7 B相GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 |GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Prescaler =0x0; // No prescalingTIM_TimeBaseStructure.TIM_Period =10000;TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM8,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter =6;//ICx_FILTER;TIM_ICInit(TIM8,&TIM_ICInitStructure);// Clear all pending interruptsTIM_ClearFlag(TIM8, TIM_FLAG_Update);TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);//Reset counterTIM2->CNT = 0;TIM_Cmd(TIM8, ENABLE);}n_Counter = TIM_GetCounter(TIM8);Diled_Disp_Num((float)n_Counter);另外一个值得注意的问题是,STM32的定时器是16位的,意思是只能计数到65535,有两种方法,一是采用链式的方式用两个定时器将16位扩展为32位,还有一种简单的方法就是开启定时器的溢出中断,每中断一次就代表编码器运转了特定的角度。
学会使用正交编码器进行错误检测和纠正正交编码器是一种常用的错误检测和纠正技术,在通信和计算机领域有着广泛的应用。
它通过添加冗余信息,实现对传输数据的错误检测和纠正,提高数据传输的可靠性。
下面将详细介绍正交编码器的原理、应用、优势和局限性。
一、正交编码器的原理1. 编码方式:正交编码器通常使用一种特定的编码方式,最常见的是海明码(Hamming Code)。
海明码将原始数据进行编码,生成冗余位信息,使得接收端可以通过比较校验位和收到的数据,检测出错误的位并进行纠正。
2. 基于异或运算:正交编码器通过使用异或(XOR)运算,对原始数据和校验位进行计算,生成编码后的数据。
接收端再次使用异或运算对接收到的编码数据和校验位进行计算,得到纠正后的数据。
二、正交编码器的应用1. 数据传输:正交编码器在数据传输中起到了重要的作用。
在网络通信中,通过对数据进行正交编码,可以提供更可靠的数据传输,减少传输错误率,提高网络性能。
2. 存储系统:正交编码器也广泛应用于存储系统中。
例如,在硬盘驱动器中,通过使用正交编码器,可以在存储和读取数据时进行错误检测和纠正,确保数据的完整性和可靠性。
3. 无线通信:在无线通信中,正交编码器被用于调制和解调过程中。
通过对数据进行正交编码,可以提高信道容量和抗干扰能力,使得无线通信更加稳定和可靠。
三、正交编码器的优势1. 错误检测和纠正:正交编码器可以检测传输数据中的错误位,并进行纠正,提供更可靠的数据传输。
2. 降低错误率:通过增加冗余位信息,正交编码器可以降低数据传输过程中的错误率,提高数据传输的可靠性。
3. 简单实现:正交编码器的实现相对简单,通常采用异或运算等基本逻辑运算,可以在硬件电路、嵌入式系统或软件程序中实现。
四、正交编码器的局限性1. 传输开销:为了提供更可靠的数据传输,正交编码器增加了冗余信息,导致传输开销增加。
传输的数据量相对原始数据会增加一些,从而影响传输效率。
2. 纠正能力有限:正交编码器具有一定的纠正能力,但当错误位数量超过纠正能力时,就无法进行纠正,而只能进行错误检测。
文章标题:深入探讨STM32编码器程序中Z相的处理方法在嵌入式系统开发中,STM32系列微控制器广泛应用于各种领域,其强大的性能和丰富的外设资源使得开发人员可以更加灵活和高效地进行开发。
而编码器作为一种常见的位置传感器,被广泛应用于电机控制、机械臂、机床等领域。
在STM32编码器程序中,Z相的处理显得尤为重要,本文将针对这一主题进行深入探讨。
1. 简介从编码器的基本结构出发,我们可以看到编码器通常由A相、B相和Z相组成。
其中A相和B相用于检测转动角度和方向,而Z相则用于检测转动的零点位置。
在实际应用中,Z相的处理对于确保系统的稳定性和精准性至关重要。
2. Z相的读取在STM32编码器程序中,Z相的读取可以通过外部中断的方式来实现。
当Z相的信号发生上升沿或下降沿时,通过外部中断引脚将引发中断,从而执行相应的处理函数。
在处理函数中,可以进行位置计数的清零、角度标定等操作,以确保系统在启动时能够准确获取零点位置。
3. 程序设计针对Z相信号的处理,我们需要设计相应的程序逻辑来确保系统的稳定性和精准性。
在程序设计中,我们可以采用状态机的方式来处理Z相信号,通过状态机的切换来实现位置标定、零点校准等功能。
还应该考虑到Z相信号可能存在的抖动和干扰,采取相应的滤波和消抖措施来确保信号的稳定性和可靠性。
4. 总结STM32编码器程序中Z相的处理方法对于系统的性能和稳定性具有重要影响。
通过合理的硬件设计和程序实现,我们可以确保系统能够准确地获取零点位置,并实现精准的位置控制。
在实际开发中,开发人员需要综合考虑硬件和软件两方面的因素,以便更好地实现Z相的处理和应用。
个人观点与理解对于STM32编码器程序中Z相的处理,我认为关键在于综合考虑硬件和软件两方面的因素。
在硬件设计中,需要充分考虑Z相信号的稳定性和可靠性,选择合适的电路方案和滤波措施来确保信号质量。
而在软件实现中,需要设计合理的程序逻辑和状态机,以确保系统能够准确获取零点位置,并实现精准的控制。
正交编码器原理正交编码器是一种用于数字通信系统的编码器,常用于传输二进制数据。
正交编码器的原理基于将输入数据映射到正交码空间中,以便在接收端更容易进行解码。
以下是正交编码器的基本原理:1.基本概念:正交编码的核心思想是将输入比特流映射到一个正交的码空间,以提高在传输过程中的抗干扰性和可靠性。
2.正交性:在正交编码中,使用了正交的码字,即码字之间的内积为零。
这种特性使得在信道中的干扰可以更容易地被检测和纠正。
3.相位变化:正交编码常常利用相位变化来表示不同的比特。
例如,考虑使用正交相移键控(QPSK)的正交编码,其中每个符号代表两比特,通过相位的不同变化表示不同的比特组合。
4.映射方式:输入比特流经过映射,转换为正交码空间中的点。
这个映射通常采用调制技术,如相移键控(PSK)或正交振幅调制(QAM)。
5.抗多径效应:正交编码器在某种程度上能够抵抗多径效应,因为它使用正交的码字,有助于区分来自不同路径的信号。
6.解调过程:在接收端,正交编码器的信号需要进行解调和解码。
解调过程涉及到从接收到的信号中提取出相位信息,而解码则是将相位信息映射回原始的比特流。
7.误码率性能:正交编码器通常具有较好的误码率性能,尤其是在高信噪比条件下。
这使得它在许多数字通信系统中得到广泛应用。
8.复杂度:正交编码器的复杂度取决于所选择的具体编码方案。
一些正交编码器可能较为简单,而其他可能涉及更复杂的调制和解调技术。
9.应用领域:正交编码器在许多通信系统中使用,如Wi-Fi、蜂窝通信、卫星通信等,以提高通信的可靠性和性能。
总体而言,正交编码器的原理基于将输入数据映射到正交的码空间,以便更好地应对传输中的噪声和干扰。
我最近有一个项目要利用stm32的编码器模式计数,我很苦恼,我想用原子的寄存器设置模式,库函数的我没有很好的接触,我自己也配置了,可是lcd上始终显示不到数字,这是库函数的程序:void ENC_Init(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APBPeriph_ENCODER_TIMER, ENABLE); // ENCODER_T IMER时钟初始化RCC_APB2PeriphClockCmd(RCC_APBPeriph_ENCODER_GPIO, ENABLE); // ENCODER_GPIO 时钟初始化GPIO_StructInit(&GPIO_InitStructure); //TI1 TI2初始化GPIO_InitStructure.GPIO_Pin = ENCODER_TI1 | ENCODER_TI2;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(ENCODER_GPIO, &GPIO_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = TIMER_IRQChannel; //设置ENCODER_TIMER 的优先级NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORIT Y;NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* Timer configuration in Encoder mode */ //设置ENCODER_TIMER 为编码器模式TIM_DeInit(ENCODER_TIMER); //ENCODER_TIMER复位TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 无分频TIM_TimeBaseStructure.TIM_Period = (4*ENCODER_PPR)-1; //计数器重载值设置了在下一个更新事件装入活动的自动重装载寄存器周期的值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,TIM_ICPolarity_Ri sing, TIM_ICPolarity_Rising); //编码器接口初始化//TIM_ICPolarity_Rising: TIM输入捕获上升沿TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER; // TIM_ICFilter选择输入比较滤波器。
电机编码器的使&STM32的定时器编码器模式一、基础知识:编码器是小车测速反馈必不可少的模块,在做自平衡和速度的精确控制需要有编码器读取电机的转速和方向上图为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。
电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。
我们做的自平衡是用的是SK3530高性能直流减速电机采用光栅测速单圈输出448*30个AB相脉冲也就是13440相位差90度接线说明:从白线到蓝线一次为:白线:A相;绿线:B相;红线:3.3V-5V;黑线;GND黄线和蓝线为电机两根接线柱的线,通常接电机驱动。
正转A相超前B相90度,也就是说,A相进入下降沿的时候,B相是高电平,反转的时候A相落后B 相90度,也就是说A相进入下降沿的时候,B相是低电平,通常用法:A相接入单片机的中断IO口,B相接入单片机的普通IO口。
二、stm32编码器模式接口:在通用定时器和高级定时器中有这个功能从图上中可以看出,TI1波形先于TI2波形90°时,每遇到一个边沿变化是,计数器加1(可以通过寄存器设置加减),可以看出一个光栅,被计数了4次。
TI1波形后于TI2波形90°时,每遇到一次边沿变化,计数器减1。
也就是说13440个脉冲计数了13440*4=53760次简单的计数显示程序:由于DJ_jishu_L是int16_t即(signed)int类型数据范围-32768~32767 TIM_GetCounter返回值是unsigned int类型转换为int类转动一圈DJ_jishu_L变化情况:即从0到-32768到32767到11579计数器变化值=32768+(32767-11579)= 53956与之前的53760相差不大程序如下两个定时两个通道PA6PA7左电机PB6PB7右电机。
最近做一个项目,主控芯片用STM32RBT6,要用到光栅尺,本来带一个控制器的,通过控制器的232可以读取光栅尺的数据,但这个控制器太大,设备中放不下,于是,考虑自己做一个,网上看到很多有用CPLD的方案,后来无意间发现stm32的定时器可以配置成编码器,甚喜高兴之余,突然发现stm32的定时器是16位的,我的光栅尺的计数会超过65535,于是在21ic论坛上和几位高手请教,最终确定的方案工作过程是配置TIM3为正交编码器模式,并定一个10ms的中断,每10ms读取一次计数值,10ms的前提是在10ms内计数器不溢出(这个思想要感谢21ic的lxyppc)以下是部分代码:(这些代码修改于ST官方的例程,但我的工程用的是V3的固件库,他们的例程貌似是0.3的,所以有些地方有改动)下面是初始化TIM3为正交编码器模式void ENC_Init(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;/* Encoder unit connected to TIM3, 4X mode */GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;/* TIM3 clock source enable */ 使能端口时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/* Enable GPIOA, clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_StructInit(&GPIO_InitStructure);/* Configure PA.06,07 as encoder input */设置端口为输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Enable the TIM3 Update Interrupt */使能定时器3更新中断NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMx_PRE_EMPTION_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* Timer configuration in Encoder mode */ 配置编码器模式TIM_DeInit(ENCODER_TIMER);TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // No prescalingTIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(ENCODER_TIMER, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);// Clear all pending interruptsTIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);//Reset counterTIM2->CNT = COUNTER_RESET;// ENC_Clear_Speed_Buffer();TIM_Cmd(ENCODER_TIMER, ENABLE);}以下为获取一次计数值,此算法来自lxyppc,可以规避超过16位的情况,具体细节见/viewthread.php?tid=110623的讨论s16 ENC_Get_Electrical_Angle(void){static u16 lastCount = 0;u16 curCount = ENCODER_TIMER->CNT;s32 dAngle = curCount - lastCount;if(dAngle >= MAX_COUNT){dAngle -= ENCODER_TIM_PERIOD;}else if(dAngle < -MAX_COUNT){dAngle += ENCODER_TIM_PERIOD;}lastCount = curCount;return (s16)dAngle;}以下为系统滴答的初始化和中断函数void TB_Init(void){/* Setup SysTick Timer for 10 msec interrupts */if (SysTick_Config(SystemFrequency / 100)){/* Capture error */while (1);}}void SysTick_Handler(void){/*if (hTimebase_display_500us != 0){hTimebase_display_500us --;}*/if (hSpeedMeas_Timebase_500us !=0){hSpeedMeas_Timebase_500us--;}else{hSpeedMeas_Timebase_500us = SPEED_SAMPLING_TIME;CurrentCount += ENC_Get_Electrical_Angle();//ENC_Calc_Average_Speed must be called ONLY every SPEED_MEAS_TIMEBASE ms//ENC_Calc_Average_Speed();}}以上代码已通过测试,固件库版本为:V3.1.2ST官方例程和中文说明文档:http://www.stmicroelectronics.co ... oder_AN%28CH%29.pdf http://images.stmicroelectronics ... 32F10xxx_Encoder_AN(CH).zip最后抱怨一句,st为啥不把定时器做成32位的呢,能增加1分钱成本吗原创文章:"/bbs/redirect.php?tid=1092&goto=lastpost"【请保留版权,谢谢!】文章出自我爱方案网。
这个是我经常用的编码器读取方法s16 Enc_GetCount(void){static u16 lastCount = 0;u16 curCount = ENCODER_TIM->CNT;s32 dAngle = curCount - lastCount;if(dAngle >= MAX_COUNT){dAngle -= ENCODER_TIM_PERIOD;}else if(dAngle < -MAX_COUNT){dAngle += ENCODER_TIM_PERIOD;}lastCount = curCount;return (s16)dAngle;}既然你1s都不会溢出,那你可以做个每10ms产生一次的中断在中断中调用上面的代码上述代码中MAX_COUNT是10ms内可能出现的计数最大值还要大的值ENCODER_TIM_PERIOD是定时器的period值,最好比MAX_COUNT大然后定义一个32位的有符号变量,如currentCount然后每隔10ms执行一次currentCount += Enc_GetCount();你只需要去读取currentCount的值就可以得到位移信息了。
在这种情况下计数器的值变化是这样的,假设计数器周期值为999:初始值995正转10 995+10=>1000+5=5反转7 5-7=>-2+1000 = 998最终值998因此总共转了998-995 = 3个步长,与实际情况相同/****************************************************************************** ** Function Name : TIM2_IRQHandler* Description : This function handles TIM2 global interrupt request.* Input : None* Output : None* Return : None/void TIM2_IRQHandler(void){GPIO_InitTypeDef GPIO_InitStructure;static u16 Seg_Old;if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET){TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);if (var == 0) /* OCMP_1 */{var++;/* Segments(lcdcr) to be turned on are loaded with the value 1 otherwise 0 */ Seg_Old = frame[lcdcr];GPIO_Write(GPIOE,Seg_Old);/* com(lcdcr) is set to low, other coms set to Vdd/2 *//* Configure all coms as Floating Input */GPIO_InitStructure.GPIO_Pin = COMPORT;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);/* com(lcdr) is set to low PP */GPIO_ResetBits(GPIOC,com[lcdcr]);GPIO_InitStructure.GPIO_Pin = com[lcdcr];GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOC, &GPIO_InitStructure);}else /* OCMP_2 */{var = 0;/* Segments(lcdcr) values are inverted */Seg_Old = (u16)(~Seg_Old);GPIO_Write(GPIOE,Seg_Old);/* com(lcdcr) is set to high, other coms set to Vdd/2 *//* Configure all coms as Floating Input */GPIO_InitStructure.GPIO_Pin = COMPORT;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);/* com(lcdr) is set to high PP */GPIO_SetBits(GPIOC,com[lcdcr]);GPIO_InitStructure.GPIO_Pin = com[lcdcr];GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOC, &GPIO_InitStructure);lcdcr++;if (lcdcr>3) lcdcr =0;}}else if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);/* All seg and coms off to decrease VRMS */GPIO_Write(GPIOE,0); /* Clear segments on portE */GPIO_ResetBits(GPIOC,COMPORT); /* Clear segments on portC *//* Configure all coms as PP_output */GPIO_InitStructure.GPIO_Pin = COMPORT;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);}}**************************************************************************/stm32编码器使用方法作者:平凡的阳光2011-08-23 08:05 星期二晴stm32具有16位的编码器模式,使用它时,16位会带来困扰;这里归结如下。