精华内容
下载资源
问答
  • STM32 TIM 编码器模式采集编码器信号

    千次阅读 2019-10-26 10:22:25
    对于常用增量式编码器,光学编码器,采用带槽圆盘,一侧是发射光线的发射端,而光电晶体管在相对的一侧。当圆盘转动时,光程被阻断,得到的脉冲指示轴的转动和方向。通常的说法是1000线的编码器,即转一圈会产生1000...

    layout: post
    tags: [STM32]
    comments: true

    什么是正交解码?

    对于常用增量式编码器,光学编码器,采用带槽圆盘,一侧是发射光线的发射端,而光电晶体管在相对的一侧。当圆盘转动时,光程被阻断,得到的脉冲指示轴的转动和方向。通常的说法是1000线的编码器,即转一圈会产生1000个方波脉冲,马盘上刻了1000个栅格,中间被镂了1000个空,举个例子,未免显得有点啰嗦,下面直奔主题,至于什么是编码器还是搜索引擎说的明明白白。
    增量编码器通常有A,B两相信号,相位相差90°,所以也叫正交,还有一个复位信号是机械复位,即转了一圈,复位信号会有一个跳变沿。具体如下图所示:
    编码器
    所以,正交解码,就是把解码A,B两相的方波信号,检测相位,以及脉冲数和转向,当然也可以计算出转速,加速度,以及转动到相应的位置。

    编码器接口模式

    参考《STM32 参考手册中文版》,可以看到,对于TIM定时器中通用的功能,普遍支持编码器接口模式,下面配合手册和标准库进行配置。

    标准库接口

    首先看到标准库的代码stm32f10x_tim.h中的接口,先简单分析以下源码,找到以下四个数据类型:

    • TIM_TimeBaseInitTypeDef:时基单位,配置定时器预分频参数,计数器模式(上溢/下溢),周期频率以及分频系数;
    • TIM_OCInitTypeDef:振荡输出单元,可以用于产生PWM波形;
    • TIM_ICInitTypeDef:输入捕获单元,可以用于检测编码器信号的输入;
    • TIM_BDTRInitTypeDef:适用于TIM1TIM8作为插入死区时间配置的结构体;

    所以,综合以上,只需要关注时基单元输入捕获单元即可,下面对于其成员的以及其注释做一下简单解释;

    TIM_TimeBaseInitTypeDef

    typedef struct
    {
     uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                          This parameter can be a number between 0x0000 and 0xFFFF */
    
     uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                          This parameter can be a value of @ref TIM_Counter_Mode */
    
     uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                          Auto-Reload Register at the next update event.
                                          This parameter must be a number between 0x0000 and 0xFFFF.  */ 
    
     uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                         This parameter can be a value of @ref TIM_Clock_Division_CKD */
    
     uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                          reaches zero, an update event is generated and counting restarts
                                          from the RCR value (N).
                                          This means in PWM mode that (N+1) corresponds to:
                                             - the number of PWM periods in edge-aligned mode
                                             - the number of half PWM period in center-aligned mode
                                          This parameter must be a number between 0x00 and 0xFF. 
                                          @note This parameter is valid only for TIM1 and TIM8. */
    } TIM_TimeBaseInitTypeDef;       
    

    TIM_ICInitTypeDef

    typedef struct
    {
    
      uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                      This parameter can be a value of @ref TIM_Channel */
    
      uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                      This parameter can be a value of @ref TIM_Input_Capture_Polarity */
    
      uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                      This parameter can be a value of @ref TIM_Input_Capture_Selection */
    
      uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                      This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
    
      uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                      This parameter can be a number between 0x0 and 0xF */
    } TIM_ICInitTypeDef;
    
    

    寄存器接口

    配置寄存器,可以直接参考《STM32 参考手册中文版》的十三章的编码器接口模式,详细内容可以参考一下手册,这里结合前面标准库的结构体,将重点的内容做一下提炼,编码器接口大概需要进行以下几项的配置:

    • 编码器接口模式的配置:
      • 上升沿触发
      • 下降沿触发
      • 跳变沿触发
    • 极性配置
    • 滤波器配置

    以下是官方给出的配置方案:

    ● CC1S=01(TIMx_CCMR1寄存器, IC1FP1映射到TI1)
    ● CC2S=01(TIMx_CCMR2寄存器, IC2FP2映射到TI2)
    ● CC1P=0(TIMx_CCER寄存器, IC1FP1不反相, IC1FP1=TI1)
    ● CC2P=0(TIMx_CCER寄存器, IC2FP2不反相, IC2FP2=TI2)
    ● SMS=011(TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).
    ● CEN=1(TIMx_CR1寄存器,计数器使能)
    

    这意味着计数器TIMx_CNT寄存器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计
    数)。具体如下图所示;

    官方正交解码时序

    检测方法

    综上所述,如果想得到转速,和方向:

    • 在间隔固定时间Ts,读取TIMx_CNT寄存器的值,假设是1000线的编码器,转速:n = 1/Ts*TIMx_CNT*1000;
    • 根据TIMx_CNT的计数方向判断转向,不同极性,TIMx_CNT增长方向也不同,这里要加以区分;

    标准库配置

    下面是基于标准库V3.5的代码,基于STM32F103系列的单片机,硬件接口:

    • TIM3通道1,Pin6和Pin7;
    • 机械复位信号;

    可以通过encoder_get_signal_cnt接口读取当前编码的脉冲数,采用M法测速;

    关于计数器溢出的情况

    TIM3_IRQHandler中断通过判断SR寄存器中的上溢和下溢标志位,检测定时器可能溢出的方向,通过N做一个补偿,encoder_get_signal_cnt中未考虑到定时器溢出的情况;

    #ifndef ENCODER_H
    #define ENCODER_H
    #include <stdint.h>
    /*
    QPEA--->PA6/TIM3C1
    QPEB--->PA7/TIM3C1
    ---------------------------
    TIM3_UPDATE_IRQ
    EXTI_PA5
    ---------------------------
    */
    typedef enum{
    	FORWARD = 0,
    	BACK
    }MOTO_DIR;
    
    /**
     * 	@brief init encoder pin for pha phb and zero
     *		   and interrpts		
     */
    void encoder_init(void);
    
    /**
     *	@brief get encoder capture signal counts
     */
    int32_t encoder_get_signal_cnt(void);
    
    /**
     *	@brief get encoder running direction
     */
    MOTO_DIR encoder_get_motor_dir(void); 
    
    #endif
    
    #include "encoder.h"
    #include "stm32f10x.h"
    #include "stm32f10x_gpio.h"
    #include "stm32f10x_rcc.h"
    #include "stm32f10x_tim.h"
    #include "stm32f10x_exti.h"
    #include "misc.h"
    
    #define SAMPLE_FRQ 	10000L
    #define SYS_FRQ		72000000L
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    volatile int32_t N = 0;
    volatile uint32_t EncCnt = 0;
    
    /* Private function prototypes -----------------------------------------------*/
    /* Private functions ---------------------------------------------------------*/
    
    static void encoder_pin_init(void){
    	GPIO_InitTypeDef GPIO_InitStructure;
    	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(GPIOA, &GPIO_InitStructure);
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    
    static void encoder_rcc_init(void){
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
    }
    
    static void encoder_tim_init(void){
    
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_ICInitTypeDef TIM_ICInitStructure; 		
    	
    	TIM_TimeBaseStructure.TIM_Period = ENCODER_MAX_CNT;
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    	
    	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12, 
    									TIM_ICPolarity_Rising, 
    									TIM_ICPolarity_Rising);
    
    	//must clear it flag before enabe interrupt
    	TIM_ClearFlag(TIM3,TIM_FLAG_Update);
    	TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);	
    	
    	//TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
    	TIM_SetCounter(TIM3,ENCODER_ZERO_VAL);
    	TIM_ICInit(TIM3, &TIM_ICInitStructure);
    	TIM_Cmd(TIM3, ENABLE);
    	
    //	TIM3->CCMR1 |= 0x0001;
    //	TIM3->CCMR2 |= 0x0001;
    //	TIM3->CCER &= ~(0x0001<<1);
    //	TIM3->CCER &= ~(0x0001<<5);
    //	TIM3->SMCR |= 0x0003;
    //	TIM3->CR1 |= 0x0001;
    
    }
    
    /**
      * @brief  Configure the nested vectored interrupt controller.
      * @param  None
      * @retval None
      */
    static void encoder_irq_init(void)
    {
    	NVIC_InitTypeDef NVIC_InitStructure;
    	EXTI_InitTypeDef EXTI_InitStructure;
    
    	/* Enable the TIM3 global Interrupt */
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    
    	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);
    	EXTI_InitStructure.EXTI_Line = EXTI_Line5;
    	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    	EXTI_Init(&EXTI_InitStructure);
    	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
     
    }
    
    void encoder_init(void){
    	encoder_rcc_init();
    	encoder_pin_init();
    	encoder_irq_init();
    	encoder_tim_init();
    }
    // 机械复位信号
    void EXTI9_5_IRQHandler(void){
    
    	if(EXTI_GetITStatus(EXTI_Line5) == SET){ 
    		
    	}
    	EXTI_ClearITPendingBit(EXTI_Line5);
    }
    
    MOTO_DIR encoder_get_motor_dir(void)
    {
    	if((TIM3->CR1 & 0x0010) == 0x0010){
    		return FORWARD;
    	}else{
    		return BACK;
    	}
    }
    
    int32_t encoder_get_signal_cnt(void){
    	int32_t cnt = 0;
    	if(TIM3->CNT > ENCODER_ZERO_VAL){
    		EncCnt = cnt = TIM3->CNT - ENCODER_ZERO_VAL;	
    	}else{
    		EncCnt = cnt = ENCODER_ZERO_VAL - TIM3->CNT;	
    	}
    	TIM_SetCounter(TIM3,ENCODER_ZERO_VAL);
    	return cnt;
    }
    
    /******************************************************************************/
    /*            STM32F10x Peripherals Interrupt Handlers                        */
    /******************************************************************************/
    /**
      * @brief  This function handles TIM3 global interrupt request.
      * @param  None
      * @retval None
      */
    void TIM3_IRQHandler(void)
    { 
    	uint16_t flag = 0x0001 << 4;
    	if(TIM3->SR&(TIM_FLAG_Update)){		
    		//down mode
    		if((TIM3->CR1 & flag) == flag){
    			N--;
    		}else{
    			//up mode
    			N++;
    		}
    	}	
    	TIM3->SR&=~(TIM_FLAG_Update);		
    }
    
    TIM3 global interrupt request.
      * @param  None
      * @retval None
      */
    void TIM3_IRQHandler(void)
    { 
    	uint16_t flag = 0x0001 << 4;
    	if(TIM3->SR&(TIM_FLAG_Update)){		
    		//down mode
    		if((TIM3->CR1 & flag) == flag){
    			N--;
    		}else{
    			//up mode
    			N++;
    		}
    	}	
    	TIM3->SR&=~(TIM_FLAG_Update);		
    }
    
    

    总结

    本文实现了STM32编码器接口模式的配置以及编码器的M法测速,如果配合机械复位信号,可以通过编码器的脉冲数得到位置信息,转过多少度,但当前并未实现。

    展开全文
  • 编码器接口模式 选择编码器接口模式的方法是: 如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的 SMS=001; 如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则...
     
     
    
    编码器接口模式
    选择编码器接口模式的方法是:
    如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的 SMS=001
    如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011
    通过设置TIMx_CCER寄存器中的CC1P和CC2P位,可以选择TI1和TI2极性;如果需要,还可以 对输入滤波器编程。
    两个输入TI1和 TI2 被用来作为增量编码器的接口。参看表73
    假定计数器已经启动 (TIMx_CR1 寄存器中的CEN=1) ,则计数器由每次在 TI1FP1 TI2FP2 上的有效跳变驱动。 TI1FP1 TI2FP2 是TI1 TI2 在通过输入滤波器和极性控制后的信号;如果没有滤波和变相,则 TI1FP1=TI1 , TI2FP2=TI2。根据两个输入信号的跳变顺序,产生了计数脉冲和方向信号。依据两个输入信号 的跳变顺序,计数器向上或向下计数,同时硬件对TIMx_CR1 寄存器的 DIR 位进行相应的设置。
    不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数,在任一输入端(TI1或者 TI2)的跳变都会重新计算DIR位。 编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到 TIMx_ARR寄存器的自动装载值之间连续计数(根据方向,或是0到ARR计数,或是ARR到0计 数)。
    所以在开始计数之前必须配置 TIMx_ARR ;同样,捕获器、比较器、预分频器、重复计数 器、触发输出特性等仍工作如常。编码器模式和外部时钟模式2 不兼容,因此不能同时操作。 在这个模式下,计数器依照增量编码器的速度和方向被自动的修改,因此计数器的内容始终指 示着编码器的位置。计数方向与相连的传感器旋转的方向对应。下表列出了所有可能的组合,
    假设 TI1 TI2 不同时变换。
    73 计数方向与编码器信号的关系
     
    一个外部的增量编码器可以直接与 MCU 连接而不需要外部接口逻辑。但是,一般会使用比较器
    将编码器的差动输出转换到数字信号,这大大增加了抗噪声干扰能力。编码器输出的第三个信
    号表示机械零点,可以把它连接到一个外部中断输入并触发一个计数器复位。
    下图是一个计数器操作的实例,显示了计数信号的产生和方向控制。它还显示了当选择了双边
    沿时,输入抖动是如何被抑制的;抖动可能会在传感器的位置靠近一个转换点时产生。在这个
    例子中,我们假定配置如下:
    CC1S=’01’ (TIMx_CCMR1 寄存器, IC1FP1 映射到 TI1)
    CC2S=’01’ (TIMx_CCMR2 寄存器, IC2FP2 映射到 TI2)
    CC1P=’0’ (TIMx_CCER 寄存器, IC1FP1 不反相, IC1FP1=TI1)
    CC2P=’0’ (TIMx_CCER 寄存器, IC2FP2 不反相, IC2FP2=TI2)
    SMS=’011’ (TIMx_SMCR 寄存器,所有的输入均在上升沿和下降沿有效 ).
    CEN=’1’ (TIMx_CR1 寄存器,计数器使能 )
     
    (1)、stm32f407中定时器1、2、3、4、5、8提供编码器接口模式 
    (2)、可以对输入信号TI1,TI2进行滤波处理,数字滤波器由事件器组成,每N个事件才视为一个有效边沿,可以在TIMx_CCMR1、TIMx_CCMR2中的IC1F位域设置 
    (3)、stm32提供了单项计数(只能测速度)和双项计数模式(可测速度&方向),双项模式可以更好地消除毛刺干扰,一般使用双项模式
     
     
    	TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);

    函数原型

    
    /**
      * @brief  Configures the TIMx Encoder Interface.
      * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
      * @param  TIM_EncoderMode: specifies the TIMx Encoder Mode.
      *   This parameter can be one of the following values:
      *     @arg TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level.
      *     @arg TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending on TI1FP1 level.
      *     @arg TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and TI2FP2 edges depending
      *                                on the level of the other input.
      * @param  TIM_IC1Polarity: specifies the IC1 Polarity
      *   This parameter can be one of the following values:
      *     @arg TIM_ICPolarity_Falling: IC Falling edge.
      *     @arg TIM_ICPolarity_Rising: IC Rising edge.
      * @param  TIM_IC2Polarity: specifies the IC2 Polarity
      *   This parameter can be one of the following values:
      *     @arg TIM_ICPolarity_Falling: IC Falling edge.
      *     @arg TIM_ICPolarity_Rising: IC Rising edge.
      * @retval None
      */
    void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                    uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
    {
      uint16_t tmpsmcr = 0;
      uint16_t tmpccmr1 = 0;
      uint16_t tmpccer = 0;
        
      /* Check the parameters */
      assert_param(IS_TIM_LIST5_PERIPH(TIMx));
      assert_param(IS_TIM_ENCODER_MODE(TIM_EncoderMode));
      assert_param(IS_TIM_IC_POLARITY(TIM_IC1Polarity));
      assert_param(IS_TIM_IC_POLARITY(TIM_IC2Polarity));
    
      /* Get the TIMx SMCR register value */
      tmpsmcr = TIMx->SMCR;
      
      /* Get the TIMx CCMR1 register value */
      tmpccmr1 = TIMx->CCMR1;
      
      /* Get the TIMx CCER register value */
      tmpccer = TIMx->CCER;
      
      /* Set the encoder Mode */
      tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
      tmpsmcr |= TIM_EncoderMode;
      
      /* Select the Capture Compare 1 and the Capture Compare 2 as input */
      tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S)));
      tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
      
      /* Set the TI1 and the TI2 Polarities */
      tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P)));
      tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4));
      
      /* Write to TIMx SMCR */
      TIMx->SMCR = tmpsmcr;
      /* Write to TIMx CCMR1 */
      TIMx->CCMR1 = tmpccmr1;
      /* Write to TIMx CCER */
      TIMx->CCER = tmpccer;
    }
    
    /**
      * @brief  Forces the TIMx output 1 waveform to active or inactive level.
      * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the TIM peripheral.
      * @param  TIM_ForcedAction: specifies the forced Action to be set to the output waveform.
      *   This parameter can be one of the following values:
      *     @arg TIM_ForcedAction_Active: Force active level on OC1REF
      *     @arg TIM_ForcedAction_InActive: Force inactive level on OC1REF.
      * @retval None
      */

     

     
     
     
     
    91
    编码器模式下的计数器操作实例
     
    下图为当 IC1FP1 极性反相时计数器的操作实例 (CC1P=’1’ ,其他配置与上例相同 )
    92
    IC1FP1 反相的编码器接口模式实例
     
     
    定时器时钟图
     
     

    由此可看  无论是通用定时器还是高级定时器都可以  使用正交编码模式 只是 需要注意的是使用 定时器的通道1和通道2 

     

    本实验采用的增量式编码器

    配置为下拉输入  PA0 PA1要加上拉电阻

     
     
    #include "encoder.h"
    
    /*************************定时器TIM2初始化****************************/
    void left_encoder_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;	//定义一个GPIO结构体变量
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定义一个定时器结构体变量
    	TIM_ICInitTypeDef TIM_ICInitStructure;	//定义一个定时器编码器结构体变量
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;		//配置PA0->TIM2_CH1,PA1->TIM2_CH2
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//设置50MHz时钟
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;		//设置为下拉输入模式
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	TIM_TimeBaseStructure.TIM_Period = 360*4;	//计数器最大值	编码器的脉冲数
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;	//时钟不分频
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0;	// 使用的采样频率之间的分频比例
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);	//初始化定时器2
    
    	TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    	TIM_ICStructInit(&TIM_ICInitStructure);
    	TIM_ICInitStructure.TIM_ICFilter = 6;//滤波器值
    	TIM_ICInit(TIM2, &TIM_ICInitStructure);
    
    	TIM_SetCounter(TIM2, 0x7fff);
    
    	//  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);		//清除定时器2中断标志位
    	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    
    	//	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);		//打开定时器2中断
    	TIM_Cmd(TIM2, ENABLE);  //计数器使能,开始计数
    }
    
    
    /*************************定时器TIM3初始化****************************/
    void right_encoder_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;	//定义一个GPIO结构体变量
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定义一个定时器结构体变量
    	TIM_ICInitTypeDef TIM_ICInitStructure;	//定义一个定时器编码器结构体变量
    
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;		//配置PA6->TIM3_CH1,PA7->TIM3_CH2
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//设置50MHz时钟
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;		//设置为下拉输入模式
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	TIM_TimeBaseStructure.TIM_Period = 0xffff;	//计数器最大值	
    	TIM_TimeBaseStructure.TIM_Prescaler = 0;	//时钟不分频
    	TIM_TimeBaseStructure.TIM_ClockDivision = 0;	// 使用的采样频率之间的分频比例
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);	//初始化定时器2
    
    	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    	TIM_ICStructInit(&TIM_ICInitStructure);
    	TIM_ICInitStructure.TIM_ICFilter = 6;
    	TIM_ICInit(TIM3, &TIM_ICInitStructure);
    
    	TIM_SetCounter(TIM3, 0x7fff);
    
    	//  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);		//清除定时器2中断标志位
    	TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    
    	//	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);		//打开定时器3中断
    	TIM_Cmd(TIM3, ENABLE);  //计数器使能,开始计数
    }
    void encoder_init(void)
    {
    	left_encoder_init();	//初始化定时器2
    	right_encoder_init();	//初始化定时器3	
    }
    void get_encoder_count(int *_leftEncoderCount,int *_RightEncoderCount)
    {
    	*_leftEncoderCount=TIM_GetCounter(TIM2)-0x7fff;
    	*_RightEncoderCount=TIM_GetCounter(TIM3)-0x7fff;		//读取编码器寄存器计数值,并减去中间值,得到速度矢量
    	TIM_SetCounter(TIM2, 0x7fff);
    	TIM_SetCounter(TIM3, 0x7fff);						//重置编码器计数值	
    }
    
    
    

    主函数 将获取的编码器的角度数据 送到数组中  通过串口发送和显示到oled上

    #include "stm32f10x.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "stdio.h"
    #include "string.h"
    #include "moto.h"
    #include "timer.h"
    #include "sys.h"
    #include "pwm.h"
    #include "guangdiankey.h"
    #include "exti.h"
    #include "key.h"
    #include "wdg.h"
    #include "oled.h"
    #include "encoder.h"
    
    //电机测试
    #if 0
    void test()
    {
    //拉低使能端
    	GPIO_ResetBits(	D1_EN,D1_GPIO_EN);
    //顺时针旋转180	
     motor(D1_STEP,D1_DIR,D1_GPIO_STEP,D1_GPIO_DIR,0,100);
    
    }
    #endif
    
    int main(void)
     {	
    	 int leftEncoderCount=0,RightEncoderCount=0;
    	#if 0
    	int flag=0;	 
    	int flag1=10;	 
     	u8 t=0;
    	u16 jiaodu[8];	
    	u16 SPEED_COUNT;
    	#endif
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级	
    	delay_init();	    	 //延时函数初始化
    	LED_Init();LED0=0;;//led初始化
    	moto_Init();//电机初始化
    	KEY_Init();	 //回零点的开关检测
    	OLED_Init();//屏幕显示
    	USART1_Configuration(115200);	 //串口初始化为115200
    	EXTIX_Init();//外部中断初始化
    	TIM1_Int_Init(1099,7200); //5hz 的计数频率,计数到 999 为 100ms
    	TIM8_Int_Init(999,7200);	 //定时器8初始化  定时LED闪烁
    	 left_encoder_init();
    #if 0
    	TIM2_PWM_Init(399,109);    //电机脉冲频率1.11630k
    	TIM3_PWM_Init(399,109);    //	电机脉冲频率	 
    	TIM4_PWM_Init(399,109);    //	电机脉冲频率 
    	TIM5_PWM_Init(399,109);    //	电机脉冲频率 
    	TIM2_PWM_Init(599,99);    //电机脉冲频率1.11630k
    	TIM3_PWM_Init(599,99);    //	电机脉冲频率	 
    	TIM4_PWM_Init(599,99);    //	电机脉冲频率 
    	TIM5_PWM_Init(599,99);    //	电机脉冲频率 
    	kaijidouhua();//开机屏幕显示
    	#endif
    	IWDG_Init(4,625);    //4*2^4与分频数为64,重载值为625,溢出时间为1s	
    	    TIM2->CNT = 0;//每次遇到相对零(Z信号)就将计数归0
        TIM_Cmd(TIM2, ENABLE);
      while(1)
    	{	
    //	get_encoder_count(&leftEncoderCount,&RightEncoderCount);
    //	crc16_data1[0]=leftEncoderCount;		
    		bianmaqi();//显示编码器的数据
    		
    
    	//	crc16_data1[0]=TIM_GetCounter(TIM2);//-0x7fff;
    crc16_data1[0]=TIM2->CNT/4;
    		
    
    		
    /*******************看门狗复位******************************/	
    		IWDG_ReloadCounter();//喂狗
    	 }	
     } 
    
    	
    	
    	
    
    
    
    

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    展开全文
  • STM32——编码器测速原理及STM32编码器模式

    千次阅读 多人点赞 2021-01-19 22:12:53
    本问讲解了编码器测速原理及STM32编码器模式,文末有STM32编码器模式例程。

    1. 编码器概述在这里插入图片描述

    编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感 器,我们可以通过编码器测量到底位移或者速度信息。编码器从输出数据类型上 分,可以分为增量式编码器和绝对式编码器。

    从编码器检测原理上来分,还可以分为光学式、磁式、感应式、电容式。常 见的是光电编码器(光学式)和霍尔编码器(磁式)。

    2. 编码器原理

    光电编码器是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。光电编码器是由光码盘和光电检测装置组成。光码盘是在一 定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,检测装置检测输出若干脉冲信号,为判断转向,一般输出两组存在一 定相位差的方波信号。

    霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。霍尔编码器是由霍尔码盘和霍尔元件组成。霍尔码盘是在一 定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号。

    可以看到两种原理的编码器目的都是获取 AB 相输出的方波信号,其使用方法也是一样,下面是一个简单的示意图。
    在这里插入图片描述

    3. 编码器接线说明

    具体到我们的编码器电机,我们可以看看电机编码器的实物。
    在这里插入图片描述
    在这里插入图片描述

    4. 编码器软件四倍频技术

    下面我们说一下编码器倍频的原理。为了提高大家下面学习的兴趣,我们先明确,这是一项实用的技术,可以真正地把编码器的精度提升 4 倍。作用可类比 于单反相机的光学变焦,而并非牺牲清晰度来放大图像的数码变焦。OK,先看看下面编码器输出的波形图。在这里插入图片描述
    这里,我们是通过软件的方法实现四倍频。首先可以看到上图编码器输出的AB 相波形,正常情况下我们使用 M 法测速的时候,会通过测量单位时间内 A 相输出的脉冲数来得到速度信息。常规的方法,我们只测量 A 相(或 B 相)的上升 沿或者下降沿,也就是上图中对应的数字 1234 中的某一个,这样就只能计数 3次。而四倍频的方法是测量 A 相和 B 相编码器的上升沿和下降沿。这样在同样的 时间内,可以计数 12 次(3 个 1234 的循环)。这就是软件四倍频的原理。

    5. STM32编码器模式

    在STM32中,编码器使用的是定时器接口,通过数据手册可知,定时器1,2,3,4,5和8有编码器的功能,而其他没有。编码器输入信号TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
    在这里插入图片描述
    STM32编码器有三种工作模式,其中模式三即为上文中提到的四倍频模式。
    在这里插入图片描述
    在使用编码器模式时需要注意以下几点:

    • 编码器有个转速上限,超过这个上限是不能正常工作的,这个是硬件的限制,原则上线数越多转速就越低,这点在选型时要注意。
    • 定时器初始化好以后,任何时候CNT寄存器的值就是编码器的位置信息,正转他会加反转他会减这部分是不需要软件干预的,初始化时给的TIM_Period 值应该是码盘整圈的刻度值,在减溢出会自动修正为这个数.加超过此数值就回0.
    • 计数值偶尔也会有出错误的情况,一圈多计一个或少计一个数都是很正常的特别是转速比较高的时候尤其明显,有个绝对位置信号做修正是很有必要的.绝对位置信号不需要一定在零位置点,收到这个信号就将CNT修正为一个固定的数值即可.

    6. STM32编码器模式例程

    此例程用于初始化定时器2和定时器3为编码器模式,得到小车底盘上两个直流电机的运转速度。

    #.c文件
    #include "encoder.h"
    
    /**************************************************************************
    *  函数功能:把TIM2初始化为编码器接口模式
    *
    *  入口参数:无
    *
    *  返 回 值:无
    **************************************************************************/
    void Encoder_Init_TIM2(void)
    {
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
    	TIM_ICInitTypeDef TIM_ICInitStructure;  
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);//使能PA PB端口时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;	//端口配置 PA15
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    	GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOA
      
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;	//端口配置 PB3
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    	GPIO_Init(GPIOB, &GPIO_InitStructure);					      //根据设定参数初始化GPIOB
    	
    	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    	TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 
    	TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  //初始化定时器2
    	
    	TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
    	
    	TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
    	TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度
    	TIM_ICInit(TIM2, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设	TIMx
     
    	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
    	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能定时器中断
    	
    	TIM_SetCounter(TIM2,0);
    	TIM_Cmd(TIM2, ENABLE); //使能定时器2
    }
    
    /**************************************************************************
    函数功能:把TIM3初始化为编码器接口模式
    入口参数:无
    返回  值:无
    **************************************************************************/
    void Encoder_Init_TIM3(void)
    {
      	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
      	TIM_ICInitTypeDef TIM_ICInitStructure;  
      	GPIO_InitTypeDef GPIO_InitStructure;
    	
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3的时钟
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
      	
     	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//端口配置 PA6 PA7
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
      	GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOA
      	
      	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
      	TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 
     	TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
      	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
      	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 
      	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  //初始化定时器3
    	
      	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3(TIM_ICPolarity_Rising或者TIM_ICPolarity_Falling效果相同,都是4倍频)
    	
      	TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
      	TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度
      	TIM_ICInit(TIM3, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设	TIMx
     
      	TIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位
      	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能定时器中断
      	TIM_SetCounter(TIM3,0);
      	TIM_Cmd(TIM3, ENABLE); //使能定时器
    }
    
    /**************************************************************************
    函数功能:单位时间读取编码器A计数
    入口参数:无
    返回  值:计数值
    **************************************************************************/
    float Read_EncoderA(void)
    {
    	int Encoder_TIM = 0;  
    	float Speed = 0.0;  
    	Encoder_TIM= (short)TIM2 -> CNT;   
    	TIM2 -> CNT=0;
    	return -Encoder_TIM;
    }
    /**************************************************************************
    函数功能:单位时间读取编码器B计数
    入口参数:无
    返回  值:计数值
    **************************************************************************/
    float Read_EncoderB(void)
    {
    	int Encoder_TIM = 0;  
    	float Speed = 0.0;  
    	Encoder_TIM= (short)TIM3 -> CNT;   
    	TIM3 -> CNT=0;
    	return Encoder_TIM;
    }
    
    /**************************************************************************
    *  函数功能:TIM2中断服务函数
    *
    *  入口参数:无
    *
    *  返 回 值:无
    **************************************************************************/
    void TIM2_IRQHandler(void)
    { 		    		  			    
    	if(TIM2->SR&0X0001)//溢出中断
    	{    				   				     	    	
    	}				   
    	TIM2->SR&=~(1<<0);//清除中断标志位 	    
    }
    
    
    /**************************************************************************
    *  函数功能:TIM3中断服务函数
    *
    *  入口参数:无
    *
    *  返 回 值:无
    **************************************************************************/
    void TIM3_IRQHandler(void)
    { 		    		  			    
    	if(TIM3->SR&0X0001)//溢出中断
    	{    				   				     	    	
    	}				   
    	TIM3->SR&=~(1<<0);//清除中断标志位 	    
    }
    
    
    #.h文件
    #define __ENCODER_H
    #include <sys.h>	 
    #include "init.h" //include了所有需要的头文件
    #define ENCODER_TIM_PERIOD (u16)(65535)   //不可大于65535 因为F103的定时器是16位的。
    
    void Encoder_Init_TIM2(void);
    void Encoder_Init_TIM3(void);
    	
    float Read_EncoderA(void);
    float Read_EncoderB(void);
    
    void TIM2_IRQHandler(void);
    void TIM3_IRQHandler(void);
    
    #endif
    
    展开全文
  • STM32电机测速(正交或者霍尔编码器

    万次阅读 多人点赞 2020-08-19 22:41:41
    2.2 STM32电机测速(正交或者霍尔编码器) 我们这里提供左右电机测速代码,在公众号:小白学移动机器人,发送:电机测速,即可获得源码工程下载链接。 2.2.1 实现工具 STM32单片机、带编码器的直流减速电机、Keil5、...

    2.2 STM32电机测速(正交或者霍尔编码器)

    我们这里提供左右电机测速代码,在公众号:小白学移动机器人,发送:电机测速,即可获得源码工程下载链接。

    2.2.1 实现工具

    STM32单片机、带编码器的直流减速电机、Keil5、(蓝牙、串口助手)调试用

    2.2.2 编码器原理

    (1)编码器是什么?

    编码器是一种将角位移或者角速度转换成一串电数字脉冲的旋转式传感器。编码器又分为光电编码器和霍尔编码器。

    (2)编码器工作原理是什么?

    霍尔编码器是有霍尔马盘和霍尔元件组成。霍尔马盘是在一定直径的圆板上等分的布置有不同的磁极。霍尔马盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号。示意图如下:

    img

    (3)带霍尔编码器的直流减速电机接线图

    展开全文
  • 编码器源码

    2021-01-06 12:55:24
    decoder.c ...uint16_t con_speed_period=20;//20ms采集一次数据,根据实际修改 float Decoder_GetSpeed(void) { static int16_t tmp; static float re_dat=0; tmp=(int16_t)Decoder_GetCnt(); if(tmp>2
  • STM32 Cubemax(五) —— STM32利用定时器编码器模式处理带编码器直流电机 文章目录 系列文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 电赛延期了,趁有时间再...
  • 上一个博文介绍了编码器实现测试,这也是编码器最普遍的应用,我们需要操作的东西并不多,通常来说记录脉冲数。 STM32操作增量式编码器(一)----使用外部中断实现测速 1.增量式编码器实现定位思路 对于增量式...
  • stm32f4编码器模式

    万次阅读 多人点赞 2018-09-03 02:42:56
    stm32f4编码器模式 花费一下午时间研究编码器的使用,简单总结如下 E6B2-CWZ1X编码器 stm32f407 定时器编码器模式 一、编码器简介 1、分类 编码器可按以下方式来分类。 (1)增量型: 每转过单位的角度就...
  • STM32f4日记5之AB相编码器测速实验(TIM定时器的编码器模式使用) 板子:stm32f407zgt6正点原子迷你版 电机参数:减速比 1:90 线数:1170(1390)* // 鉴于目前网上的教学形态各异,很多带有迷惑、误导性质,所以写...
  • 编码器类型主要有增量型
  • STM32f103c8t6编码器.zip

    2019-09-19 19:18:47
    1.适用于STM32f103c8t6读取正交编码器角度 2.PB6->A相 PB7->B相 PA1->Z相 3.记得ABZ相输出上拉 4.我使用的是2500p/r的编码器。如果想得出360度,但是你不是这个规格的,记得调整两个地方 main.c的 count = TIM4->CNT...
  • 编码器从输出数据类型上分,可以分为增量式编码器和绝对式编码器。   从编码器检测原理上来分,还可以分为光学式、磁式、感应式、电容式。常见的是光电编码器(光学式)和霍尔编码器(磁式)。 2.编码器原理
  • STM32编码器的学习笔记 顺时针旋转就是一个递增的计数器 逆时针旋转就是一个递减的计数器 编码器的使用: 设置从模式寄存器的SMCR(SMS) 工作模式:编码器模式1,编码器模式2,编码器模式3;...
  • STM32控制编码器

    万次阅读 多人点赞 2017-07-14 02:25:41
    stm32 编码器 的控制 直流电机+PWM
  • 音频编码器

    2017-07-28 15:29:00
    16 音频编码器 介绍当前可用的音频编码器 aac AAC(Advanced Audio Coding )编码器 当前原生(内置)编码器还处于实验阶段,而且只能支持AAC-LC(低复杂度AAC)。要使用这个编码器,必须选择 ‘experimental’或者'...
  • 读取编码器数值实现电机测速电机系列二、读取编码器数值实现电机测速2 、配置编码器;encoder.hencoder.cmain.c3、测速; 电机系列 二、读取编码器数值实现电机测速 2 、配置编码器; encoder.h #ifndef __ENCODER_H...
  • STM32—TIMx实现编码器四倍频

    千次阅读 2020-02-22 12:34:07
    储备知识二.TIMx的编码器模式介绍1.计数边沿设置2.选择极性和使能3.使能4.计数方向三.代码部分 一.储备知识 通过STM32的定时器编码器接口模式对编码器进行四倍频,并使用M法测速得到小车电机的速度信息。 编码器的...
  • STM32编码器

    千次阅读 2019-12-10 23:09:05
    最近在做毕业设计,需要计算小车的行驶距离,需要用到编码器计算具体走了多远,就了解学习了一下编码器。 一、编码器简介 编码器(encoder)是将信号 如比特流或数据进行编制、转换为可用以通讯、传输和存储的信号...
  • 编码器又有增量式编码器、绝对式编码器、混合绝对式编码器等,具体的大家可以百度了解。 本文主要讲解常用的AB相编码器,一般是霍尔或者光电增量式编码器,starrobot底层开发板、12V 5200ma锂电池、GB37-520减速...
  • STM32定时器---正交编码器模式详解

    万次阅读 多人点赞 2016-01-25 17:11:09
    1.编码器简介编码器分类: 按工作原理:光电式、磁电式和触点电刷式 按码盘的刻孔方式:增量式和绝对式两类 由于博主接触面还不是很广,一共就用过两个种类的编码器,都是属于光电的 差分编码器:一般由8根线连接...
  • 【STM32】 定时器---正交解码编码器模式详解

    万次阅读 多人点赞 2019-08-07 20:53:24
    增量式编码器也成为正交编码器,是通过两个信号线的脉冲输出来进行数据处理,一个输出脉冲信号就对应于一个增量位移,编码器每转动固定的位移,就会产生一个脉冲信号 通过读取单位时间脉冲信号的数量,便可以达到...
  • 增量式编码器详解

    千次阅读 2020-12-09 18:11:50
    光电编码器由三个部分组成:发光二极管,码盘以及码盘背面的光传感器。 这个码盘安装在旋转轴上,上面均匀地排列着透光和不透光的扇形区域。当码盘转动时,不透光的部分能够挡住光线,而透光区则允许光线透过,那么...
  • 还好单片机的通用定时器具有专门的正交编码器接口,只需配置相应的寄存器,就可实现编码器输入的上下沿自动捕获与计数,非常便于编码器的测速。 下面就来介绍下定时器的编码器模式的使用: 1 正反转计数原理示例 ...
  • STM32实战九 编码器

    2019-07-05 21:43:12
    这一章编写编码器程序,通过定时器连接编码器,原理和细器节这里不多说,参考代码段中的网页,有两个注意事项,一是所有网上的参考代码都没有设置第二个通道,默认没有滤波,虽然能用,但是通道2抗干扰能力差,容易...
  • 平衡车编码器

    2020-06-24 21:41:25
    平衡车编码器 最近在开始研究平衡小车但在编码器的使用上就遇到了许多的麻烦,后来在网上查阅了众多资料和大佬的讲解,终于有一点明白。 首先,我使用得是电机自带的编码器。 这里介绍下编码器的原理。编码器的...
  • STM32正交编码器接口

    万次阅读 2017-12-18 11:45:08
    STM32四路正交编码器接口 芯片型号、使用引脚及初始化程序源码 TIM2端口重映射问题 与JTAG接口冲突时的现象及解决方法
  • STM32学习笔记——基于正点原子例程编码器模式小结 本文作者为小白,漏洞较多,大家见谅。 最近一段时间学习了,STM32f4的编码器功能,经过自己探索和他人的热心帮助,对于编码器模式有了一定了解。STM32f4单片机...
  • ESP32 读取正交编码器

    千次阅读 2019-03-20 15:42:45
    ESP32 IDF库中包含了多种的代码示例,其中的 examples/perihperals/pcnt 文件夹下已经提供了能够读取计数器的demo,本文在此demo的基础上修改并实现了ESP32读取正交编码器的功能。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,855
精华内容 4,342
关键字:

编码器period