用STM32对编码开关实现精确计数

发布者:chwwdch最新更新时间:2016-08-26 来源: eefocus关键字:STM32  编码开关  精确计数 手机看文章 扫描二维码
随时随地手机看文章
机械触点式编码开关,依靠 A 相和 B 相信号的相位差来判断旋转方向,脉冲数计数,输出的理想波形如下图:
用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
实际使用时,其输出的脉冲边沿可能会包含很多毛刺,如果简单的使用上升沿或者下降沿触发,在边沿处会可能产生很多误触发,使用延时等手段虽能缓解,但从方法到结果都有蒙混过关之嫌,不能令人满意。下图是我用示波器随意抓了一个编码开关的下降沿:

用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
为了能够可靠计数,必须避开上升沿和下降沿附近的毛刺,在编码开关输出脉冲信号的脉冲中段取值,如下图所示:
用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
  1、A 相和 B 相信号分别送入具有上升/下降沿触发能力的IO,开启上升沿/下降沿触发中断;
2、在 A 相信号的上升沿/下降沿触发中断中判断 B 相的状态,如上图所示的 T0 时刻,得到 B 相当前的值为 0;
3、在 B 相信号的上升沿/下降沿触发中断中判断 A 相的状态,如上图所示的 T1 时刻,得到 A 相当前的值为 1;
4、建立一个保存 A 相 和 B 相状态的数组,至少可保存 3 组状态值,若得到的状态值和数组中保存的上一个状态值相等,说明该次触发为毛刺,则不更新状态数组,例如 T1 时刻由 B 相信号触发的中断程序中,判断 A 相信号为 1 状态,与 T0 时刻中的 A:0; B:0 状态不同,则更新数组;若 T1 时刻后 B 相的上升沿产生毛刺进入中断程序,则因为读取到的 A 相值仍然为 1,因为和上一个状态相同,不更新状态数组;
5、如此利用 A 相的边沿触发中断读取 B 相的值,B 相的边沿触发读取 A 相的值,就可以保证取样点位于没相信号的中间时刻;
6、在每次状态数组有更新时判断编码开关的旋转方向,如上图蓝色框内的数值组合出现时,可以判断编码器 +1,反之,如下图紫色框内的数值组合出现时,可判断编码器值 -1;
 
用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
7、当编码器出现中途改变方向的情况时,其输出的脉冲如下图所示:
用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
  可以看到,T1、T2、T3时刻编码器产生 +1 的计数脉冲,T5、T6 因为采集到的 A 相和 B 相状态值与 T3 状态没有变化,故不更新状态数组也不做任何处理,到 T7 时刻以后开始更新,则 T3、T7、T8 组合产生 -1 的状态组合。整个过程中都不会发生丢计数的情况,另一种编码器改变旋转方向的情况如下:
用STM32对编码开关实现精确计数 - Marvin - Marvins Blog
  类似上面的分析,也不会发生丢计数的情况。下面给出STM32外部触发程序作为参考:
 
/* Encoder.c */
 
signed char Phase_A, Phase_B; //按bit位来储存A/B相的状态,bit7作为缓存,bit6为最新状态 //值,然后依次是bit5、bit4,需要更新时,使用右移操作,之 //所以使用有符号数,是为了右移时保留bit7的值
 
void EXTI0_IRQHandler(void)                
{
EXTI->PR &= EXTI_PR_PR0; //Clear interrup pending
 
if(COMP->CSR & COMP_CSR_COMP2OUT) //若编码器直接连入IO,此处改为判断IO状态即可,我使 //用的是比较器输出的值来驱动IO产生外部触发,故为此
{
Phase_B |= 0x80; //Phase_B = 1xxx xxxx
}
else
{
Phase_B &= 0x7F; //Phase_B = 0xxx xxxx
}
 
if(((Phase_B << 1)^Phase_B) & 0x80) //判断缓存中的bit7位和bit6位是否相等,若不等,更新缓存
{
Phase_B >>= 1;
Phase_A >>= 1;
 
if( ((Phase_A & 0x70) == 0x30) && ((Phase_B & 0x70) == 0x60) ) //A:0 1 1, B:1 1 0 序列
{
FlashData_Copy.encoder_count += 1;
}
if( ((Phase_A & 0x70) == 0x60) && ((Phase_B & 0x70) == 0x30) ) //A:1 1 0, B:0 1 1 序列
{
FlashData_Copy.encoder_count -= 1;
}
}
}
 
void EXTI2_TSC_IRQHandler(void)            
{
EXTI->PR &= EXTI_PR_PR2; //Clear interrupt pending
 
if(COMP->CSR & COMP_CSR_COMP1OUT)
{
Phase_A |= 0x80; //Phase_A = 1xxx xxxx
}
else
{
Phase_A &= 0x7F; //Phase_A = 0xxx xxxx
}
 
if(((Phase_A << 1)^Phase_A) & 0x80)
{
Phase_A >>= 1;
Phase_B >>= 1;
 
if( ((Phase_A & 0x70) == 0x30) && ((Phase_B & 0x70) == 0x60) )
{
FlashData_Copy.encoder_count += 1;
}
if( ((Phase_A & 0x70) == 0x60) && ((Phase_B & 0x70) == 0x30) )
{
FlashData_Copy.encoder_count -= 1;
}
}
}
 
/******************************************************************************
EXTI0 and EXTI2 interrupt setup
 ******************************************************************************/
void setupEXTI0_2(void)
{
 
/* EXTI0 config */
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA;
 
EXTI->IMR |= EXTI_IMR_MR0;
EXTI->RTSR |= EXTI_RTSR_TR0; //Rising trigger
EXTI->FTSR |= EXTI_FTSR_TR0; //Falling trigger
 
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[EXTI0_IRQn >> 0x05] |=
      (uint32_t)0x01 << (EXTI0_IRQn & (uint8_t)0x1F);
 
/* EXTI2 config */
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI2_PA;
 
EXTI->IMR |= EXTI_IMR_MR2;
EXTI->RTSR |= EXTI_RTSR_TR2;
EXTI->FTSR |= EXTI_FTSR_TR2;
 
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[EXTI2_TSC_IRQn >> 0x05] |=
      (uint32_t)0x01 << (EXTI2_TSC_IRQn & (uint8_t)0x1F);
}
该方案外围电路简单,无需电容滤波,因采样点为脉冲中部,故工作可靠,在编码器的特定位置做上记号用手随意改变方向和速度做测试,最后总能在编码开关回到原位置时归零,缺点是需要IO具有上升/下降沿的双向边沿触发能力,以及使用了中断程序占用了部分资源。
关键字:STM32  编码开关  精确计数 引用地址:用STM32对编码开关实现精确计数

上一篇:基于STM32的大功率数字式电镀电源并联均流系统设计
下一篇:STM32 使用 Flash 存储数据时的一种管理办法

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

STM32外部中断详解
一、基本概念 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组 第0组:所有4bit用于指定响应优先级; 第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级; 第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级; 第3组
[单片机]
STM32+IAR+uC/OS环境下怎样写中断程序
先说说,几个关键函数: bsp_int.c提供几个关键的中断操作函数: void BSP_IntDis (CPU_DATA int_id) //关闭指定中断 void BSP_IntDisAll (void) //关闭所有中断 void BSP_IntEn (CPU_DATA int_id) //使能指定中断 void BSP_IntVectSet (CPU_DATA int_id, CPU_FNCT_VO
[单片机]
STM32 PWM捕获 两种方法详解
前言: STM32 的TIM的捕获PWM波,是为了频率和占空比,这两种数据结果!它 的最基本的原理就是(打个比方):例如一个高电平上升沿过来,捕获的数值就是上升为的高电平的TIM的计数值(TIM定时器,CNT不断增加,再重新装载),这点是最基本的内容!后面就是通过前后的数值计算可以获得占空比 频率。 第一种方法: 官方的正统方法 IC1和IC2为一组通道,IC3和IC4为一组通道,以上图为例可以得到上升沿是IC1的值为600(假设),此时TIMx_CCR2不变,计数器复位为0,然后在下降沿的时候,IC2读取计数值 即为高电平时间300(假设),当道下一个周期的上升沿时,IC1读取为600,计数器复位为0;
[单片机]
<font color='red'>STM32</font> PWM捕获 两种方法详解
一种基于STM32的多路电压测量设计方案及实现
引言 近年来,数据采集及其应用受到了人们越来越广泛的关注,数据采集系统也有了迅速的发展,它可以广泛的应用于各种领域。 数据采集技术是信息科学的重要分支之一,数据采集也是从一个或多个信号获取对象信息的过程。数据采集是工业控制等系统中的重要环节,通常采用一些功能相对独立的单片机系统来实现,作为测控系统不可缺少的部分,数据采集的性能特点直接影响到整个系统。 电压的测量最为普遍性,研究设计并提高电压测量精度的方法及仪器具有十分重要的意义。在电压测量设计中,单片机作为控制器,是整个设计的核心。除此之外,设计中还必须有模数转换器(ADC)。ADC用于直接采集模拟电压并将模拟信号转换成数字信号,它直接影响着数据采集的精度和速度。
[单片机]
一种基于<font color='red'>STM32</font>的多路电压测量设计方案及实现
STM32 USART库函数介绍2
USART_Cmd函数的功能是使能或失能USART串口外设。 例:使能USART1 USART_Cmd(USART1,ENABLE); USART_ITConfig函数的功能是使能或者失能指定的USART串口中断。 USART_IT_PE 奇偶错误中断 USART_IT_TXE 发送中断 USART_IT_TC 传输完成中断 USART_IT_RXNE 接收中断 USART_IT_IDLE 空闲总线中断 USART_IT_LBD LIN中断检测中断 USART_IT_CTS CTS中断 USART_IT_ERR 错误中断 例:使能USART1接收中断 USART_Cmd(USAR
[单片机]
STM32】DMA基本原理、寄存器、库函数(2)
05 DMA中断状态寄存器(DMA_ISR) 作用:可以获取DMA传输的状态标志。 注意:此寄存器为只读寄存器,所以在这些位被置位后只能通过其他的操作来清除。 06 DMA中断标志清除寄存器(DMA_IFCR) 作用:通过往寄存器内写1来清除DMA_ISR被置位的位。 DMA通道配置过程 下面是配置DMA通道x的过程(x代表通道号): 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将是数据传输的源或目标; 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数据将从这个地址读出或写入这个地址; 在DMA_CNDTRx寄存器中设置要传输的数据量
[单片机]
巧用外设复位修改只读寄存器
有STM32开发者用到STM32F429芯片开发产品,并用到其中的CAN外设。在CAN应用过程中有个专门针对收发出错情况进行次数统计的两个计数器,其值通过错误状态寄存器CAN_ESR中的REC 和TEC 两个字段来体现,CAN硬件会根据错误数据大小做适当响应或处理。 根据寄存器描述得知,TEC 和REC 的值在这个寄存器里面是只读的。而此时的STM32用户有个强烈的需求,就是期望能适时地对这两个出错记录字段做清零。他自己也尝试编写一些代码想让二者清零,均以失败告终,便邮件咨询有无解决办法。 我们在阅读CAN_ESR寄存器内容时倒有个发现,即该寄存器的复位值是0x00000000。 也就是说,芯片每次复位后其值一定是0,
[单片机]
巧用外设复位修改只读寄存器
STM32的SPI接口
  STM32的SPI接口支持SPI协议和I2S音频协议,默认为SPI,可通过软件切换为I2S。   SPI接口:   MISO 主设备输入/从设备输出   MOSI 主设备输出/从设备输入   SCK 串口时钟   NSS 从设备选择   初始化例程如下: void SPI_Init(void) {   SPI_InitTypeDef SPI_InitStructure;   GPIO_InitTypeDef GPIO_InitStructure;   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

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

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

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