精华内容
下载资源
问答
  • Quartus 完整的工程,verilog HDL语言编写,输入编码器A与B正交信号,通过硬件4倍频后,输出脉冲,编码器正转时输出加脉冲,编码器反转时输出减脉冲,可以自行跟据加减脉冲信号修改并增加内部计数器后输出
  • stm32正交编码器例程

    热门讨论 2016-01-25 17:18:14
    STM32的正交编码器例程,5线编码器A B Z GND和VCC,OC门输出记得接上拉
  • STM32F407使用定时器TIM3获取正交编码器的值,然后在主函数里通过串口打印输出
  • 可串口显示脉冲数 LCD显示转速 基于stm32f103ze 正交编码器读取
  • 正交编码器

    2012-03-16 15:41:56
    正交编码器原理、应用、接口配置及控制方法
  • 自己编写的正交编码器测速程序,硬件为STM32f103ZET6, 编译器为keil4,自己测试可以正常使用
  • STM32F4的正交编码器

    2018-08-03 15:22:42
    RCC->APB1ENR|=1; //TIM5 ʱÖÓʹÄÜ RCC->AHB1ENR|=1; //ʹÄÜPORTAʱÖÓ GPIO_Set(GPIOA,PIN0|PIN1,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//¸´Óù¦ÄÜ,ÏÂÀ­ ...
  • STM32正交编码器例程

    2020-02-06 10:30:27
    STM32的每个TIMER都有正交编码器输入接口,TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数。
  • 正交编码器定位程序(使用全向轮),使用can总线传输
  • 基于STM32F429IG HAL库配置编码器,定时器,pwm输出控制电机pid的程序。
  • 提出了一种不用查询表的正弦正交编码器细分方法,利用控制系统临界稳定原理生成一个高频数字正弦载波与采样得到的正弦编码信号实时比较来获取相位信息曰与传统查询表细分方法相比,节省了大量的存储空间,而且整个细分...
  • 编码器编码器正交编码信号中计数脉冲,这些信号通常可从旋钮,电机或轴传感器以及其他位置传感器获得。
  • 基于STM32的读取正交编码器的例程。
  • 编码器及其应用概述  编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。 编码器把角位移或直线位移转换成电信号,前者成为码盘,后者称码尺。按照读出方式...
  • LS7366 一个用于连接LS7366正交编码器计数器的Arduino库。
  • 由于最近干活遇到需要获取正交编码的功能,所以返回来研究一下STM32CubeMX的编码器功能,之前也更新过STM32的定时器功能,但是因为之前搞平衡车的正交编码器没有搞清楚原理,就直接用了脉冲输入功能草草了事,现在也...

    由于最近干活遇到需要获取正交编码的功能,所以返回来研究一下STM32CubeMX的编码器功能,之前也更新过STM32的定时器功能,但是因为之前搞平衡车的正交编码器没有搞清楚原理,就直接用了脉冲输入功能草草了事,现在也算是为之前的年轻买单了,不过看到现有的Encoder说明都比较简单,所以就当是为开发者做贡献了,我研究清楚之后来一篇博客。
    书归正传,正交编码器通常是安装在电机上的,与电机转子的主轴同轴,有一些是通过主轴连接减速或加速齿轮组再接入编码器的,编码器一般有光栅编码器和磁极编码器两种,正转反转输出的脉冲都是下图这个样子
    正交编码器脉冲输出
    STM32本身带有处理正交脉冲的功能,也就是定时器中的Encoder模式
    具体操作:

    STM32CubeMX配置

    1.打开STM32CubeMX,选择自己使用的芯片,此处我以STM32F429IGT6为例进行;

    2.设置系统、时钟基本操作

    SYS
    SYS系统设置
    RCCRCC时钟设置CC

    3.定时器设置

    此处我选用的是TIM3,TIM3位通用定时器,一般芯片通用定时器比较多
    Combined Channels采用Encoder Mode(编码器模式)
    选用此模式后TIM3的CH1和CH2就变为编码器接口了,记住对应的两个接口,之后要把编码器信号接到这两个口上,我的是PA6和PA7
    在这里插入图片描述
    下方参数设定根据需求进行设定,由于我需要记录编码器的上升沿和下降沿,所以此处选择的是Encoder Mode TI1 and TI2,这个模式将AB两组脉冲的上升下降沿都计数了,就是计数4次,不需要那么精确的同学可以把预分频系数(Prescaler)修改为4-1,那么脉冲检测到4个脉冲就会计数1次了,滤波器看个人,我用杜邦线直连的,距离10cm不到所以我设的是0,具体怎么选可以看STM32中文参考手册,懒人看下面的图
    在这里插入图片描述
    在这里插入图片描述

    4.串口设置

    为了方便观察,需要通过串口发送对应的旋转方向,旋转计数值到串口调试助手。
    由于芯片只用于发送数据,就不搞中断了,直接选择异步串口即可
    在这里插入图片描述

    5.最后配置时钟树

    这个大家自行处理,每块芯片都不同,最终让中间HCLK(MHz)为72即可
    在这里插入图片描述

    6.项目配置

    我用的开发环境是Keil5,所以在Toolchain/IDE中选择了MDK-ARM

    在这里插入图片描述
    代码生成的时候把Generated files中的第一项选中,不然h文件和c文件混着,看着都难受
    在这里插入图片描述

    7.点击右上角GENERATE CODE生成代码即可

    代码修改

    1.串口代码修改

    为了方便,用printf函数输出信息,所以需要在串口的/* USER CODE BEGIN 0 */后添加串口重定向函数,如下所示:

    /* USER CODE BEGIN 0 */
    #include <stdio.h>
    struct __FILE 
    { 
    	int handle; 
    }; 
    FILE __stdout;       
    void _sys_exit(int x) 
    { 
    	x = x; 
    } 
    int fputc(int ch, FILE *f)
    { 	
    	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    	USART1->DR=(uint8_t)ch;      
    	return ch;
    }
    
    /* USER CODE END 0 */
    

    2.main.c修改

    首先要添加stdio.h的包含,方便后面用printf输出
    在main.c的/* USER CODE BEGIN Includes */后添加如下代码:

    /* USER CODE BEGIN Includes */
    #include <stdio.h>
    /* USER CODE END Includes */
    

    之后需要几个变量,分别为

    变量名变量用途
    Direction编码器转动方向
    counter主函数计数,用于printf函数的定时段发送
    enc1编码器计数(0~65535)
    enc1_old上一次的编码器计数值(0~65535)
    enc2enc1的进位
    enc最终的编码器计数值

    定义变量,在/* USER CODE BEGIN 1 */后添加如下代码

    /* USER CODE BEGIN 1 */
      uint8_t Direction;
      uint16_t counter;
      uint16_t enc1 = 0,enc1_old = 0;
      int16_t enc2 = 0;
      int32_t enc;
      /* USER CODE END 1 */
    

    启动编码器解释,在/* USER CODE BEGIN 2 */后添加编码器启动函数

    /* USER CODE BEGIN 2 */
      HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
    /* USER CODE END 2 */
    

    在循环中,也就是/* USER CODE BEGIN 3 */后添加读取编码器数值函数以及进位处理函数和打印输出函数:

    /* USER CODE BEGIN 3 */
    	Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);  
        enc1 = (uint32_t)(__HAL_TIM_GET_COUNTER(&htim3));	//获取定时器的值
    	if((Direction == 0) &(enc1 < enc1_old))				//正向旋转数值变小,说明进位
    	{
    		enc2++;
    	}
    	if((Direction == 1) &(enc1 > enc1_old))				//反向旋转数值变小,说明借位
    	{
    		enc2--;
    	}
    	enc1_old = enc1;									//更新enc1_old,便于下次计算
    	enc = enc2<<16 | enc1;								//计算当前计数总值,带+-号
    	counter++;											//主函数计数
    	if(counter>1000)									//主函数每次运行约1ms,此处用于每1000ms发送一次数
    	{
    		counter = 0;									//计数值清零
    		printf("Dir %d,	Enc2 %d, Enc1 %d, ENC %d\r\n",Direction,enc2,enc1,enc);//打印相关计数数据
    	}
    	HAL_Delay(1);
      }
      /* USER CODE END 3 */
    

    此时代码已经完全修改完成,编译下载到芯片内,等待接线测试

    接线测试

    我用的编码器是5v供电的一款磁极编码器,但最终接口都应该是VCC、GND、A、B四个接口,此时按如下方式连接

    编码器STM32
    ATIM3_CH1
    BTIM3_CH2
    VCC5V电平
    GND与STM32共地

    接好之后就可以上电,打开串口调试助手,连接上串口1
    就会收到如下数据,此时转动编码器就可以看到数值的改变
    在这里插入图片描述
    至此,编码器功能已完成。

    		  Good Game!!!!!!
    
    接下来会推出一系列的关于串口使用的分享,有需要的猿们敬请关注!!!!!
    

    以上内容欢迎大家转载引用,标明出处即可!!!!!

    展开全文
  • 正交编码器输出

    2019-02-17 20:00:39
    stm32f1定时器编码器模型正交输入,通过单片机编码器接口实现单片机对电机编码器的读取
  • 正交编码器的码盘测速。
  • 在没有正交编码器计数器接口的电路中,对于速度不高的编码器,可以用软件的方式来实现 原理过程参考此文档:编码器四倍频电路的单片机高速算法设计 - 百度文库 (baidu.com) 正交编码器鉴相表 前一个AB相电平...

    在没有正交编码器计数器接口的电路中,对于速度不高的编码器,可以用软件的方式来实现

    原理过程参考此文档:编码器四倍频电路的单片机高速算法设计 - 百度文库 (baidu.com)

    正交编码器鉴相表

    前一个AB相电平状态(ab)

    后一个AB相电平状态(AB)

    拼接成的状态码(二/十六进制)

    对应处理动作

    输出值

    00

    00

    0000

    0x00

    状态无变化,不处理

    0

    00

    01

    0001

    0x01

    输出转脉冲Cnt-

    -1

    00

    10

    0010

    0x02

    输出转脉冲Cnt+

    +1

    00

    11

    0011

    0x03

    异常变化,不处理

    0

    01

    00

    0100

    0x04

    输出转脉冲Cnt+

    +1

    01

    01

    0101

    0x05

    状态无变化,不处理

    0

    01

    10

    0110

    0x06

    异常变化,不处理

    0

    01

    11

    0111

    0x07

    输出转脉冲Cnt-

    -1

    10

    00

    1000

    0x08

    输出转脉冲Cnt-

    -1

    10

    01

    1001

    0x09

    异常变化,不处理

    0

    10

    10

    1010

    0x0A

    状态无变化,不处理

    0

    10

    11

    1011

    0x0B

    输出转脉冲Cnt+

    +1

    11

    00

    1100

    0x0C

    异常变化,不处理

    0

    11

    01

    1101

    0x0D

    输出转脉冲Cnt+

    +1

    11

    10

    1110

    0x0E

    输出转脉冲Cnt-

    -1

    11

    11

    1111

    0x0F

    状态无变化,不处理

    0

     

    unsigned char const EncoderAction[16]={0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};	// 每个 a b A B对应的编码动作
    
    int EncCnt=0;	//编码器计数值
    unsigned char Enc_abAB=0;	//编码器相位信号
    
    void DoEncoder2(void)
    {
    	unsigned char AB=0;
    	
    	Enc_abAB<<=1;	//移位操作准备接入新的编码器信号
    	if(EncA) Enc_abAB|=0x01;		// EncA 为编码器接口的A脚电平
    	Enc_abAB<<=1;
    	if(EncB) Enc_abAB|=0x01;		// EncB 为编码器接口的B脚电平
    	Enc_abAB&=0x0F;
    	EncCnt+=EncoderAction[Enc_abAB];	//直接准对状态码做运算
    }
    
    
    void DoEncoder3(void)    //另外一种
    {
    	unsigned char AB=0;
    	
    	Enc_abAB<<=2;	//移位操作准备接入新的编码器信号
    	if(EncA) Enc_abAB|=0x02;		// EncA 为编码器接口的A脚电平 若方向反了 此处可调整
    	if(EncB) Enc_abAB|=0x01;		// EncB 为编码器接口的B脚电平
    	Enc_abAB&=0x0F;
    	EncCnt+=EncoderAction[Enc_abAB];	//直接准对状态码做运算
    }

    将上面的函数放入定时中断中运行,以高于编码器实际动作的频率运行,应该就不会丢失动作。

    正在测试中。。。

    展开全文
  • STM32正交编码器接口

    万次阅读 2017-12-18 11:45:08
    STM32四路正交编码器接口 芯片型号、使用引脚及初始化程序源码 TIM2端口重映射问题 与JTAG接口冲突时的现象及解决方法

    STM32四路正交编码器接口

    一、主要内容

    1. 芯片型号、使用引脚及初始化程序源码
    2. TIM2端口重映射问题
    3. 与JTAG接口冲突时的现象及解决方法

    二、芯片型号、使用引脚及初始化程序源码

    芯片型号:STM32F103RET6
    使用定时器:TIM2、TIM3、TIM4、TIM5
    使用引脚:
         TIM2—PA15、PB3(remap)
         TIM3—PA6、PA7
         TIM4—PB6、PB7
         TIM5—PA0、PA1
    初始化程序源码:
    (其中TIM2的配置有特殊需要注意的地方,其他配置相同,调试时遇到的问题和解决方法见下文)

    #include "stm32f10x.h"
    #include "encoder.h"
    
    
    void TIM2_Mode_Config(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;      
    
        //PA15 ch1, PB3 ch2 
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
    
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);        // 关闭JTAG功能
        GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);            // 重映射TIM2的CH1、CH2到PA15和PB3
        GPIO_StructInit(&GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;         
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);                           
        GPIO_StructInit(&GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;         
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);                           
    
        TIM_DeInit(TIM2);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_TimeBaseStructure.TIM_Period = 50000;
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);              
    
        TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM2, &TIM_ICInitStructure);
    
        TIM_ClearFlag(TIM2, TIM_FLAG_Update);
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM2->CNT = 0;
    
        TIM_Cmd(TIM2, ENABLE);
    }
    
    
    void TIM3_Mode_Config(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;      
    
        //PA6 ch1, PA7 ch2 
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
        GPIO_StructInit(&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);                           
    
        TIM_DeInit(TIM3);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_TimeBaseStructure.TIM_Period = 50000;
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);              
    
        TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM3, &TIM_ICInitStructure);
    
        TIM_ClearFlag(TIM3, TIM_FLAG_Update);
        TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM3->CNT = 0;
    
        TIM_Cmd(TIM3, ENABLE);
    }
    
    
    void TIM4_Mode_Config(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;      
    
        //PB6 ch1, PB7 ch2 
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
        GPIO_StructInit(&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(GPIOB, &GPIO_InitStructure);                           
    
        TIM_DeInit(TIM4);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_TimeBaseStructure.TIM_Period = 50000;
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);              
    
        TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM4, &TIM_ICInitStructure);
    
        TIM_ClearFlag(TIM4, TIM_FLAG_Update);
        TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM4->CNT = 0;
    
        TIM_Cmd(TIM4, ENABLE);
    }
    
    
    void TIM5_Mode_Config(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;      
    
        //PA0 ch1 A,PA1 ch2 
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
        GPIO_StructInit(&GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;         
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);                           
    
        TIM_DeInit(TIM5);
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
        TIM_TimeBaseStructure.TIM_Period = 50000;
        TIM_TimeBaseStructure.TIM_Prescaler = 0;
        TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);              
    
        TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_BothEdge ,TIM_ICPolarity_BothEdge);
        TIM_ICStructInit(&TIM_ICInitStructure);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM5, &TIM_ICInitStructure);
    
        TIM_ClearFlag(TIM5, TIM_FLAG_Update);
        TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
        //Reset counter
        TIM5->CNT = 0;
    
        TIM_Cmd(TIM5, ENABLE);
    }
    

    在使用时,读取TIMx->CNT寄存器中的数据即可。

    三、 TIM2端口重映射问题

    问题描述

    在一开始调试的时候,TIM2的初始化程序和其他定时器的相同,这时旋转TIM2连接的编码器,计数没有变化,旋转TIM5连接的编码器时,TIM2和TIM5的计数同时变化并且数值相同。

    解决方法

    引脚定义
    引脚定义
    引脚定义

    从手册中可以看出PA15和PB3的TIM2功能需要进行重映射,否则在PA0和PA1上编码器信号既进入TIM2,又进入TIM5,因此会导致TIM2和TIM5的计数相同。

    在PA15和PB3作为TIM2编码器信号输入引脚时,需要进行IO重映射:

    GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);            // 重映射TIM2的CH1、CH2到PA15和PB3

    四、与JTAG接口冲突时的现象及解决方法

    问题描述

    在TIM2进行IO重映射后,仍不能正常使用,无论如何旋转编码器,计数器的值只有0、1、MAX三个值(在0上+1或-1)

    解决方法

    编码器模式中计数器样例
    从手册中编码器模式下的计数器变化过程中可以看出,当两相编码器的一个信号不变,另一个信号变化时,计数器计数值会在某个数值上下波动,和上述问题情况类似,因此猜测是因为编码器其中一相的信号没有捕获到。
    引脚定义
    引脚定义
    再次查阅手册发现PA15和PB3引脚的默认功能为JTAG功能,需要关闭后才能正确使用,否则JTDO为输出引脚,无法捕获到编码器信号,所以会出现计数值只有0,1,MAX三个值的现象。这里仅关闭JTAG功能,保留SWD以便调试使用:

        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);        // 关闭JTAG功能
    

    五、参考链接

    http://blog.csdn.net/wang328452854/article/details/50579832
    http://www.openedv.com/posts/list/54017.htm
    http://www.openedv.com/posts/list/0/57077.htm

    展开全文
  • STM32正交编码器测速

    千次阅读 2020-01-11 21:24:43
    一、正交编码解码原理 参考链接:https://blog.csdn.net/as480133937/article/details/98750922 二、解码思路 (1)方法一:使用定时器的输入捕获功能,配置好TIM_ICInitTypeDef即可获取一定时间内的脉冲个数,并可...

    一、正交编码解码原理
    参考链接:https://blog.csdn.net/as480133937/article/details/98750922

    二、解码思路
    (1)方法一:使用定时器的输入捕获功能,配置好TIM_ICInitTypeDef即可获取一定时间内的脉冲个数,并可根据B相上升沿时A相所处的电平判断电机正转还是反转。中断类型配置为更新事件和上升沿触发,更新事件的时间由定时器配置的参数计算出,在更新事件中断中计算速度;在上升沿中断中计脉冲数。

    void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
    

    配置示例代码:(后续添加注释)

    #include "dcmotor.h"		
    struct dc_motor DC_information;
    char temp[10];
    
    void dcmotor_Init(u16 per,u16 psc){ 
    	TIM_ICInitTypeDef TIM_icinitStruct; 
    	TIM_TimeBaseInitTypeDef TIM_InitStructure;
     	NVIC_InitTypeDef NVIC_InitStructure;
     	GPIO_InitTypeDef GPIO_InitStructure; 
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    	TIM_icinitStruct.TIM_Channel = TIM_Channel_1;
    	TIM_icinitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    	TIM_icinitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; 
    	TIM_icinitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
    	TIM_icinitStruct.TIM_ICFilter = 0x00; 
    	TIM_ICInit(TIM3,&TIM_icinitStruct);
    
    	TIM_InitStructure.TIM_Period = per;
    	TIM_InitStructure.TIM_Prescaler = psc;
    	TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    	TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    	TIM_TimeBaseInit(TIM3,&TIM_InitStructure);
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    
    	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    	TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);
    	TIM_Cmd(TIM3,ENABLE);
    
    	 DC_information.dc_angle = 0;
    	 DC_information.dc_speed = 0;
    }
    
    void TIM3_IRQHandler(){
    	if(TIM_GetITStatus(TIM3,TIM_IT_Update)){
    		DC_information.dc_speed = DC_information.dc_angle*PI/256/64;
    		DC_information.dc_angle = 0;
    		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    	}
    
    	if(TIM_GetITStatus(TIM3,TIM_IT_CC1)){
    		if(DC_information.dc_angle<99999&&DC_A == 1){
    			DC_information.dc_angle ++;
    		}else if(DC_information.dc_angle>=99999){
    			DC_information.dc_angle = 0;
    		}
    		TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
    	}	
    }
    	
    

    (2)方法二:使用定时器的编码器模式

     TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);	//编码器模式
    

    编码器模式下,中断事件的产生条件为计数达到,TIM_InitStructure.TIM_Period的值。需要注意的是,若计数模式选为,TIM_EncoderMode_TI12,则对正交编码器的A相和B相的上升和下降沿都会计数,实际脉冲数应为TIM_InitStructure.TIM_Period的值除以4;而其他的两种模式只对单相的上升和下降沿计数,实际脉冲数应为TIM_InitStructure.TIM_Period的值除以2。

    编码器模式下未解决问题:暂时不知道中断的周期如何确定,尝试过再开一个定时器,设定中断周期,在这个定时器的中断事件中计算速度,编码器模式的定时器负责计脉冲,但是效果很差。(求解)
    问题未解决,暂无代码。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,011
精华内容 4,404
关键字:

正交编码器