OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...
查看: 73797|回复: 240

STM32编码器接口模式--寄存器版

  [复制链接]

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
发表于 2012-9-11 16:59:12 | 显示全部楼层 |阅读模式
STM32编码器接口模式--寄存器版
已测试通过,如果不能使用,那可能就是编码器信号干扰比较大。

void Encoder_Init(void)
{
/* TIM3 clock source enable */ 
RCC->APB1ENR|=1<<1;       //TIM3时钟使能
/* Enable GPIOA, clock */
RCC->APB2ENR|=1<<2;    //使能PORTA时钟

/* Configure PA.06,07 as encoder input */
GPIOA->CRL&=0XF0FFFFFF;//PA6
GPIOA->CRL|=0X04000000;//浮空输入
GPIOA->CRL&=0X0FFFFFFF;//PA7
GPIOA->CRL|=0X40000000;//浮空输入

/* Enable the TIM3 Update Interrupt */
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0;   //允许更新中断
TIM3->DIER|=1<<6;   //允许触发中断
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);

/* Timer configuration in Encoder mode */ 
TIM3->SC = 0x0;//预分频器
TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频
TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式
TIM3->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1
TIM3->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2
TIM3->CCER &= ~(1<<1); //CC1P='0' IC1FP1不反相,IC1FP1=TI1
TIM3->CCER &= ~(1<<5); //CC2P='0' IC2FP2不反相,IC2FP2=TI2
TIM3->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器
TIM3->SMCR |= 3<<0; //SMS='011' 所有的输入均在上升沿和下降沿有效
TIM3->CNT = COUNTER_RESET;
TIM3->CR1 |= 0x01;    //CEN=1,使能定时器
}

STM32正交编码器程序.zip

950.75 KB, 下载次数: 7590

永远保持一颗学习的心态。
回复

使用道具 举报

  离线 

0

主题

14

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2015-5-22
在线时间
0 小时
发表于 2015-5-22 21:11:33 | 显示全部楼层
请你帮我看下哪里有问题,我用的是stm32f10x的战舰开发板加光电编码器,要实现编码器测量电机转速。程序文件是根据你的改的,TIM4作为pwm信号输出控制电机转动,TIM3控制编码器。毕业设计

STM32正交编码器程序改.rar

821.44 KB, 下载次数: 1479

回复 支持 1 反对 0

使用道具 举报

  离线 

511

主题

9万

帖子

31

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
133718
金钱
133718
注册时间
2010-12-1
在线时间
1278 小时
发表于 2012-9-11 23:38:25 | 显示全部楼层
楼主又出精品了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

  离线 

63

主题

223

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2012-6-28
在线时间
0 小时
发表于 2012-9-12 09:26:52 | 显示全部楼层
那我也要顶个
http://www.y-ec.com/
http://y-ec.taobao.com/
QQ?940436962
回复 支持 反对

使用道具 举报

  离线 

18

主题

158

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
400
金钱
400
注册时间
2011-11-23
在线时间
0 小时
发表于 2012-9-12 15:26:45 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
狂顶~
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2012-9-12 15:28:19 | 显示全部楼层
回复【2楼】正点原子:

---------------------------------
谈不上精品~ 呵呵~~
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

头像被屏蔽

  离线 

82

主题

191

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
465
金钱
465
注册时间
2011-11-14
在线时间
33 小时
发表于 2012-9-17 01:58:12 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
问下楼主:
(1)TI1 TI2信号同时计数输出的脉冲不是输入的编码脉器冲个数吧,我感觉是单个信号的计数脉冲是输入脉冲,同时TI1 TI2计数应该是编码脉冲*2的脉冲。
(2)还有就是如果计数溢出了还没有达到我记得数值怎么办,溢出后的数值怎么计数,溢出后可以在一个中断内加1如果此时编码开关反转不就错了么?
(3)我怎样判断向上溢出还是向下溢出,
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2012-9-20 19:59:22 | 显示全部楼层

回复【6楼】 tianheyun :

---------------------------------
(1)  嗯,计数器的值并不是编码器脉冲的个数;因为是A相、B相的上升沿和下降沿都计数,所以计数器的值是编码器脉冲的4倍;
(2) 关于溢出我还没有做,附件是网友的算法。
(3) 可以通过计数器的计数方向寄存器DIR判断。

stm32正交编码器学习.docx

20.38 KB, 下载次数: 3569

永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

11

主题

78

帖子

0

精华

初级会员

Rank: 2

积分
142
金钱
142
注册时间
2012-8-21
在线时间
0 小时
发表于 2013-1-15 22:46:55 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
你好,我修改了下你的定时器,然后编码器计数值一直都是1;不知道是怎么回事。你的TIMER4我用我的TIMER2代替;TIMER3都一样。不知道是怎么回事?
#include "timer.h"
#include "motor.h"
#include "sys.h"

u32 count=0;       //脉冲计数
u32 count_val=0;   //计数值

void TIM2_IRQHandler(void)
{              
if(TIM2->SR&0X0001)//产生更新中断
{
count++;
if(count==count_val)
{
TIM2->CR1&=~(0x01);    //CEN=0,禁止定时器2
count=0;
}                    
}    
TIM2->SR&=~(1<<0);//清除中断标志位      
}

void Encoder_Init(void)
{
RCC->APB1ENR|=1<<2; //timer3
RCC->APB2ENR|=1<<4; //GPIOB

GPIOB->CRL&=0XFFFFFFF4; //PB0悬空输入模式
GPIOB->IDR|=1<<0; //PB0
GPIOB->CRL&=0XFFFFFF4F; //PB1悬空输入模式
GPIOB->IDR|=1<<1; //PB1

  /* Enable the TIM3 Update Interrupt */
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0;   //允许更新中断
TIM3->DIER|=1<<6;   //允许触发中断
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);

/* Timer configuration in Encoder mode */ 
TIM3->SC = 0x0;//预分频器
TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频
TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式

TIM3->CCMR2 |= 1<<0; //CC3S='01' IC1FP1映射到TI1
TIM3->CCMR2 |= 1<<8; //CC4S='01' IC2FP2映射到TI2
TIM3->CCER &= ~(1<<9);  //CC3P='0'  IC1FP1不反相,IC1FP1=TI1
TIM3->CCER &= ~(1<<13);  //CC4P='0'  IC2FP2不反相,IC2FP2=TI2
TIM3->CCMR2 |= 3<<4; // IC3F='1000' 输入捕获1滤波器
TIM3->SMCR |= 3<<0;  //SMS='011' 所有的输入均在上升沿和下降沿有效
TIM3->CNT = COUNTER_RESET;
TIM3->CR1 |= 0x01;    //CEN=1,使能定时器
}

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void WM_Init(u16 arr,u16 psc,u32 count)
{    
//此部分需手动修改IO口设置
RCC->APB1ENR|=1<<0;       //TIM2时钟使能    
  
GPIOA->CRL&=0XFFFFFF0F;//PA1输出
GPIOA->CRL|=0X000000B0;//复用功能输出    
GPIOA->ODR|=1<<1;//PA1上拉

TIM2->ARR=arr;//设定计数器自动重装值 
TIM2->SC=psc;//预分频器不分频

count_val=count-1;   //脉冲输出个数

TIM2->DIER|=1<<0;   //允许更新中断
TIM2->DIER|=1<<6;   //允许触发中断
TIM2->EGR |=1<<1;  //允许产生比较捕获事件
MY_NVIC_Init(1,3,TIM2_IRQChannel,2);//抢占1,子优先级3,组2

TIM2->CCMR1|=6<<12;  //CH2 WM2模式  
TIM2->CCMR1|=1<<11; //CH2预装载使能    

TIM2->CCER|=1<<4;   //OC2 输出使能    

TIM2->CR1=0x8000;   //ARPE使能 
TIM2->CR1|=0x01;    //使能定时器2    
}
回复 支持 反对

使用道具 举报

  离线 

11

主题

78

帖子

0

精华

初级会员

Rank: 2

积分
142
金钱
142
注册时间
2012-8-21
在线时间
0 小时
发表于 2013-1-15 22:47:40 | 显示全部楼层
回复【8楼】xuelu0602:
---------------------------------
用的是TIMER3_CH3喝CH4;注释有些没改
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-1-16 14:18:28 | 显示全部楼层
回复【8楼】xuelu0602:

回复【楼主位】科科1987:
---------------------------------
你好,我修改了下你的定时器,然后编码器计数值一直都是1;不知道是怎么回事。你的TIMER4我用我的TIMER2代替;TIMER3都一样。不知道是怎么回事?
#include "timer.h"
#include "motor.h"
#include "sys.h"
u32 count=0;       //脉冲计数
u32 count_val=0;   //计数值
void TIM2_IRQHandler(void)
{              
if(TIM2->SR&0X0001)//产生更新中断
{
count++;
if(count==count_val)
{
TIM2->CR1&=~(0x01);  
......
---------------------------------
TIM2与编码器计数没有关系吧,你只需读TIM3->CNT 就可以了。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

1

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2012-6-25
在线时间
10 小时
发表于 2013-1-20 23:43:47 | 显示全部楼层
谢谢,学习了。
回复 支持 反对

使用道具 举报

  离线 

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1777
金钱
1777
注册时间
2011-3-29
在线时间
111 小时
发表于 2013-1-21 15:18:51 | 显示全部楼层
中断有什么用?我准备用查询算了。
业余程序玩家。
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-1-22 22:44:36 | 显示全部楼层
回复【12楼】ofourme:
---------------------------------
也可以
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

8

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2011-5-31
在线时间
2 小时
发表于 2013-1-31 20:26:32 | 显示全部楼层
//-----------------------------------------------------------------
void EXTI9_5_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line6)!= RESET)
  {
   if(IN2==1)
   {
    if(IN1==0)
    {     
     Key_dir1=1;
     Key_val1++;
    }
    else
    if(IN1==1)
    {
     Key_dir1=0;
     Key_val1++;
     }
    }
     EXTI_ClearITPendingBit(EXTI_Line6);
 }
//----------------------------------------------------- 
 if(EXTI_GetITStatus(EXTI_Line8)!= RESET)
  {
   if(IN4==1)
   {
    if(IN3==0)
    {     
     Key_dir2=1;
     Key_val2++;
    }
    else
    if(IN3==1)
    {
     Key_dir2=0;
     Key_val2++;
     }
    }
   EXTI_ClearITPendingBit(EXTI_Line8);
 }
}
电子爱好者
回复 支持 反对

使用道具 举报

  离线 

31

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
202
金钱
202
注册时间
2013-3-29
在线时间
0 小时
发表于 2013-4-24 14:11:21 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
请问一下你这个程序里面TIM4是用来干什么的,和编码器这块有关系吗?
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-4-25 09:34:06 | 显示全部楼层
回复【15楼】murongyiruo:

回复【楼主位】科科1987:
---------------------------------
请问一下你这个程序里面TIM4是用来干什么的,和编码器这块有关系吗?

---------------------------------
没有关系,只看:
void Encoder_Init(void)
{
/* TIM3 clock source enable */ 
RCC->APB1ENR|=1<<1;       //TIM3时钟使能
/* Enable GPIOA, clock */
RCC->APB2ENR|=1<<2;    //使能PORTA时钟

/* Configure A.06,07 as encoder input */
GPIOA->CRL&=0XF0FFFFFF;//PA6
GPIOA->CRL|=0X04000000;//浮空输入
GPIOA->CRL&=0X0FFFFFFF;//PA7
GPIOA->CRL|=0X40000000;//浮空输入

/* Enable the TIM3 Update Interrupt */
//这两个东东要同时设置才可以使用中断
TIM3->DIER|=1<<0;   //允许更新中断
TIM3->DIER|=1<<6;   //允许触发中断
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);

/* Timer configuration in Encoder mode */ 
TIM3->SC = 0x0;//预分频器
TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频
TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式

TIM3->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1
TIM3->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2
TIM3->CCER &= ~(1<<1);  //CC1P='0'  IC1FP1不反相,IC1FP1=TI1
TIM3->CCER &= ~(1<<5);  //CC2P='0'  IC2FP2不反相,IC2FP2=TI2
TIM3->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器
TIM3->SMCR |= 3<<0;  //SMS='011' 所有的输入均在上升沿和下降沿有效
TIM3->CNT = COUNTER_RESET;
TIM3->CR1 |= 0x01;    //CEN=1,使能定时器
}
请忽略其他部分。。。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

31

主题

58

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
202
金钱
202
注册时间
2013-3-29
在线时间
0 小时
发表于 2013-4-27 10:49:28 | 显示全部楼层
回复【16楼】科科1987:
---------------------------------
void Encoder_Init(void)
{
/* TIM4 clock source enable */ 
RCC->APB1ENR|=1<<2;       //TIM4时钟使能
/* Enable GPIOA, clock */
RCC->APB2ENR|=1<<3;    //使能PORTB时钟

/* Configure B.06,07 as encoder input */
GPIOB->CRL&=0XF0FFFFFF;//PB6
GPIOB->CRL|=0X04000000;//浮空输入
GPIOB->CRL&=0X0FFFFFFF;//PB7
GPIOB->CRL|=0X40000000;//浮空输入

/* Enable the TIM3 Update Interrupt */
//这两个东东要同时设置才可以使用中断
TIM4->DIER|=1<<0;   //允许更新中断
TIM4->DIER|=1<<6;   //允许触发中断
MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//组2,抢占优先级1,次优先级3

/* Timer configuration in Encoder mode */ 
TIM4->SC = 0x0;//预分频器
TIM4->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
TIM4->CR1 &=~(3<<8);// 选择时钟分频:不分频
TIM4->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式

TIM4->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1
TIM4->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2
TIM4->CCER &= ~(1<<1);  //CC1P='0'  IC1FP1不反相,IC1FP1=TI1
TIM4->CCER &= ~(1<<5);  //CC2P='0'  IC2FP2不反相,IC2FP2=TI2
TIM4->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器
TIM4->SMCR |= 3<<0;  //SMS='011' 所有的输入均在上升沿和下降沿有效
TIM4->CNT = COUNTER_RESET;
TIM4->CR1 |= 0x01;    //CEN=1,使能定时器
}

currentCount = TIM4 -> CNT;

楼主,我把改到定时器4上,为什么转动电机轴计数值一直是1呢?
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-5-6 14:21:41 | 显示全部楼层
回复【17楼】murongyiruo:
---------------------------------
计数信号为A,B两相,它们之间相差90度,你看看编码器信号是否正确。。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

75

主题

349

帖子

0

精华

高级会员

Rank: 4

积分
649
金钱
649
注册时间
2012-9-19
在线时间
1 小时
发表于 2013-6-4 14:49:00 | 显示全部楼层
回复【18楼】科科1987:
---------------------------------
使用CH3和 CH4,难道不行吗? 看大家都是使用CH1 CH2
具有资深STM32点灯技术,
回复 支持 反对

使用道具 举报

  离线 

108

主题

1438

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2217
金钱
2217
注册时间
2012-4-30
在线时间
5 小时
发表于 2013-6-4 17:06:55 | 显示全部楼层
回复【19楼】敌害:
---------------------------------
就像是在问:使用TIM3难道不行吗,为啥楼主非要用TIM4,,~~~呵呵~~~
回复 支持 反对

使用道具 举报

  离线 

75

主题

349

帖子

0

精华

高级会员

Rank: 4

积分
649
金钱
649
注册时间
2012-9-19
在线时间
1 小时
发表于 2013-6-8 14:42:50 | 显示全部楼层
回复【20楼】lsj9383:
---------------------------------
哎。。。。呵呵
具有资深STM32点灯技术,
回复 支持 反对

使用道具 举报

头像被屏蔽

  离线 

6168

主题

7041

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19700
金钱
19700
注册时间
2012-12-27
在线时间
23 小时
发表于 2013-6-9 10:30:05 | 显示全部楼层
潜力贴留名,Opera插图补丁,颜色补丁,字数补丁,哦类类,哦啦啦,886,我闪~~
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-6-10 19:50:42 | 显示全部楼层
回复【19楼】敌害:

回复【18楼】科科1987:
---------------------------------
使用CH3和 CH4,难道不行吗? 看大家都是使用CH1 CH2

---------------------------------
可以的,修改一下这段代码:
TIM4->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1 
TIM4->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

26

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2013-5-2
在线时间
4 小时
发表于 2013-8-8 18:36:32 | 显示全部楼层
回复【17楼】murongyiruo:
------------------------------
请问这位仁兄的这个问题解决了么?我现在也是遇到这个问题,读出的currentCount一直是1.
回复 支持 反对

使用道具 举报

  离线 

26

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2013-5-2
在线时间
4 小时
发表于 2013-8-9 10:26:30 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
LZ你好,我按着你的程序去设置,然后读出的currentCount一直是1,这是怎么回事?我用示波器看了AB相,是没问题的,相差90度。这是程序:

void encoder_Init(u16 ENCODER_TIM_PERIOD,u16 COUNTER_RESET)
{
RCC->APB1ENR|=1<<1;//TIM3时钟使能 

RCC->APB2ENR|=1<<2;    //使能PORTA时钟
GPIOA->CRL&=0XF00FFFFF;
GPIOA->CRL|=0X0440000;//PA6,7浮空输入 

TIM3->DIER|=1<<0;   //允许更新中断
TIM3->DIER|=1<<6;   //允许触发中断
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);

/* Timer configuration in Encoder mode */ 
TIM3->SC = 0x0;//预分频器
TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频
TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式

TIM3->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1
TIM3->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2
TIM3->CCER &= ~(1<<1);  //CC1P='0'  IC1FP1不反相,IC1FP1=TI1
TIM3->CCER &= ~(1<<5);  //CC2P='0'  IC2FP2不反相,IC2FP2=TI2
TIM3->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器
TIM3->SMCR |= 3<<0;  //SMS='011' 所有的输入均在上升沿和下降沿有效
TIM3->CNT = COUNTER_RESET; //计数器初始值
TIM3->CR1 |= 0x01;    //CEN=1,使能定时器
}

主程序里:encoder_Init(200,1);
               delay_ms(1000);
       currentCount=TIM3->CNT;
               printf("编码器计数值为:%d \n",currentCount+1);
请问哪里有问题么?
回复 支持 反对

使用道具 举报

  离线 

26

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
291
金钱
291
注册时间
2013-5-2
在线时间
4 小时
发表于 2013-8-9 17:51:13 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
LZ你好,我用你的程序可以读出数据了,可是有个问题,就是读出来的currentCount= ENCODER_TIM_PERIOD-1;这是什么一个情况?要么读出来是0,要么就是ENCODER_TIM_PERIOD-1,这个数应该不正常吧?请LZ指教啊!还有就是读出数据后计算位置的程序该怎么写啊?
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-8-9 21:19:00 | 显示全部楼层
回复【26楼】648342243:

回复【楼主位】科科1987:
---------------------------------
LZ你好,我用你的程序可以读出数据了,可是有个问题,就是读出来的currentCount= ENCODER_TIM_PERIOD-1;这是什么一个情况?要么读出来是0,要么就是ENCODER_TIM_PERIOD-1,这个数应该不正常吧?请LZ指教啊!还有就是读出数据后计算位置的程序该怎么写啊?

---------------------------------
请问你的电路是怎么接的?
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-8-9 21:19:53 | 显示全部楼层
回复【25楼】648342243:

回复【楼主位】科科1987:
---------------------------------
LZ你好,我按着你的程序去设置,然后读出的currentCount一直是1,这是怎么回事?我用示波器看了AB相,是没问题的,相差90度。这是程序:
void encoder_Init(u16 ENCODER_TIM_PERIOD,u16 COUNTER_RESET)
{
RCC->APB1ENR|=1<<1;//TIM3时钟使能 
RCC->APB2ENR|=1<<2;    //使能PORTA时钟
GPIOA->CRL&=0XF00FFFFF;
GPIOA->CRL|=0X0440000;//PA6,7浮空输入 
TIM3->DIER|=1<<0;   //允许更新中断
TI
......
---------------------------------
请问的电机转一转需要多长时间?
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2013-8-18
在线时间
0 小时
发表于 2013-8-18 10:12:20 | 显示全部楼层
请问楼主,定时器3的中断会触发吗?你那个中断服务函数式干嘛用的?
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-8-19 20:35:14 | 显示全部楼层
是更新中断,可以触发的, 在我的例程里没有什么用处,但是你可以根据实际情况添加服务代码。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

225

主题

828

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1355
金钱
1355
注册时间
2011-10-9
在线时间
100 小时
发表于 2013-8-30 14:36:19 | 显示全部楼层
请问楼主

我现在的编码器只有1相 我也只需检测他走没走 无需检测正反

请问我只接入1相 能工作么
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-8-30 21:17:26 | 显示全部楼层
--
回复【31楼】 simms01 :
---------------------------------
只接入1相应该不可以。但你可以用示波器看看,如果没有示波器的话,用定时器输入捕获看看。


永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

50

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
490
金钱
490
注册时间
2013-2-2
在线时间
0 小时
发表于 2013-9-5 10:56:07 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
A相和B相接什么口呢
回复 支持 反对

使用道具 举报

  离线 

50

主题

270

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
490
金钱
490
注册时间
2013-2-2
在线时间
0 小时
发表于 2013-9-5 18:57:28 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
哥们,你这个正转计数器加1,反转计数器减1,是怎么确定的?
回复 支持 反对

使用道具 举报

  离线 

47

主题

146

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2013-8-8
在线时间
0 小时
发表于 2013-9-6 09:14:31 | 显示全部楼层
为什么读出的读出的currentCount一直是1啊 啊啊
___诺现在就觉得失望无力,未来那么远该怎么扛。
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-9-9 20:40:13 | 显示全部楼层
回复【34楼】 qq382663074 :
---------------------------------
看看这两张图片:




永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-9-9 22:21:57 | 显示全部楼层
回复【33楼】qq382663074:

回复【楼主位】科科1987:
---------------------------------
A相和B相接什么口呢

---------------------------------
PA6,PA7
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

5

主题

154

帖子

0

精华

初级会员

Rank: 2

积分
198
金钱
198
注册时间
2013-6-8
在线时间
1 小时
发表于 2013-9-11 09:50:25 | 显示全部楼层
这样也能精品啊
即使爬到最高的山上,一次也只能脚踏实地地迈一步。
回复 支持 反对

使用道具 举报

  离线 

511

主题

9万

帖子

31

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
133718
金钱
133718
注册时间
2010-12-1
在线时间
1278 小时
发表于 2013-9-11 10:18:15 | 显示全部楼层
回复【38楼】倒拔萝卜:
---------------------------------
你可以发个更好的,或者类似的,我也可以给你的帖子置精品。
只要原创,且论坛之前没有人发过的,都可以申请作为精品。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

  离线 

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2013-10-19
在线时间
0 小时
发表于 2013-10-19 01:05:54 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
楼主你好,我最近在用STM32正交编码器接口测试摆的角度,但是一直读的脉冲是0或是1,A相 B相用示波器检查是正常的(幅值为5V),但是当接入PA6 A7(浮空输入)时用示波器检测就没有信号了,很困惑。能否留下QQ,方便以后请教,谢谢
回复 支持 反对

使用道具 举报

  离线 

0

主题

91

帖子

0

精华

初级会员

Rank: 2

积分
134
金钱
134
注册时间
2013-8-25
在线时间
11 小时
发表于 2013-10-19 08:38:40 | 显示全部楼层
顶下
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2013-10-19 23:14:04 | 显示全部楼层
回复【40楼】kkingkeen:

回复【楼主位】科科1987:
---------------------------------
楼主你好,我最近在用STM32正交编码器接口测试摆的角度,但是一直读的脉冲是0或是1,A相 B相用示波器检查是正常的(幅值为5V),但是当接入PA6 A7(浮空输入)时用示波器检测就没有信号了,很困惑。能否留下QQ,方便以后请教,谢谢

---------------------------------
A相 B相在示波器里看是相差90度吗,有可能是硬件问题,可能存在干扰,PA6 A7口加个滤波电容试试。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

0

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2014-2-28
在线时间
0 小时
发表于 2014-3-1 12:11:37 | 显示全部楼层
我有一个问题,STM32编码器模式最高输入频率是多少??望解释!!!!!!!!
最近自己要用STM32的编码器功能,A、B相输入,感觉单相输入最小完整周期都不到2ms,
我用STM32的TIM5的两个通道(TIM5_CH1、TIM5_CH2)翻转输出相差90°的两个脉冲模拟A、B相,TIM4做编码器输入,TIM4计数中断后关闭TIM5(即关闭TIM5_CH1、TIM5_CH2的输出),但发现TIM5输出频率太高(T5<2ms)时,用逻辑分析仪测得的TIM5_CH1、TIM5_CH2输出脉冲数不对,增大时计数才是对的(但每次都多一个脉冲)
一下是我的源代码:
//TIM4 编码器输入,TIM4_CH1作A相,TIM4_CH2作B相
//period_tim4: TIM4周期计数值
//period_tim5:TIM5 PWM输出周期
//duty_tim5_CH1:TIM5 CH1反转输出点,A相
//duty_tim5_CH2:TIM5 CH2反转输出点,B相
void TIM4_ENCODER_PB6_PB7_TIM5_CH1_PA0_CH2_PA1(uint16_t period_tim4,
uint16_t period_tim5, uint16_t duty_tim5_CH1, uint16_t duty_tim5_CH2)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 | RCC_APB1Periph_TIM5, ENABLE);

//TIM4 PB6 A相 PB7 B相  58/59脚
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);

//TIM5 PA0 CH1 PA1 CH2 14/15脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);

// Enable the TIM4 Update Interrupt
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//初始化TIM4
TIM_TimeBaseStructure.TIM_Period = period_tim4; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = 0; //设置用来作为TIMx时钟频率除数的预分频值,72MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
//初始化TIM5
TIM_TimeBaseStructure.TIM_Period = period_tim5; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = (9 - 1); //设置用来作为TIMx时钟频率除数的预分频值,72MHz/(9 - 1 + 1)=8MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

/* Output Compare Toggle Mode configuration: Channel1/2  */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //管脚输出模式:翻转
TIM_OCInitStructure.TIM_Pulse = duty_tim5_CH1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能TIM5_CH1通道
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出为负逻辑
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //管脚输出模式:翻转
TIM_OCInitStructure.TIM_Pulse = duty_tim5_CH2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM5, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable);

// Clear all pending interrupts
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM4, 0);
TIM_Cmd(TIM4, ENABLE);

TIM_ARRPreloadConfig(TIM5, ENABLE);
TIM_SetCounter(TIM5, 0);

TIM_Cmd(TIM5, ENABLE);
}
TIM4_ENCODER_PB6_PB7_TIM5_CH1_PA0_CH2_PA1(20, 48*200, 12*200, 36*200);
实际效果:
period_tim5 = 48 * 170时逻辑分析仪监测:






回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2014-3-5 22:45:17 | 显示全部楼层
回复【43楼】Joshour:
---------------------------------
占空比公式:TIM_Pulse/(TIM_Period+1)。
比如:TIM4_ENCODER_PB6_PB7_TIM5_CH1_PA0_CH2_PA1(20, 48*200, 12*200, 36*200);占空比分别为12*200/(48*200+1)和36*200/(48*200+1),计算结果不是整数,如果TIM5输出频率太高,也就是TIM_Period比较小,那么TIM_Period+1之后对于占空比影响更甚。
还有,你贴出的代码中TIM5的两个通道输出的极性怎么是相同的。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

15

主题

78

帖子

0

精华

初级会员

Rank: 2

积分
159
金钱
159
注册时间
2014-3-14
在线时间
0 小时
发表于 2014-3-31 10:55:47 | 显示全部楼层
回复【32楼】科科1987:
---------------------------------
我只是用编码器测速度,不需要测正反转,直接入一相,不可以吗?如果两相都接入的话,可不可以只在T1或者T2计数?因为我不需要倍频的。
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2014-4-7 15:41:37 | 显示全部楼层
回复【45楼】STM32学徒:
---------------------------------
1、编码器模式需要两相输入的。
2、看看参考手册。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

24

主题

95

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
211
金钱
211
注册时间
2014-3-15
在线时间
0 小时
发表于 2014-4-19 20:17:03 | 显示全部楼层
回复【楼主位】科科1987:
---------------------------------
请问楼主,这个正交编码器的计数率可不可以是单倍的计数率,而不是两倍和四倍的计数率?如果可以,该怎么设置?谢谢!
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2014-4-20 09:20:26 | 显示全部楼层


配置有效计数边沿,TI1,TI2输入极性,应该可以实现单倍计数的。
建议仔细看看附件文档。

STM32_正交编码.pdf

323.4 KB, 下载次数: 2426

永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

  离线 

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-4-20
在线时间
0 小时
发表于 2014-4-20 10:51:00 | 显示全部楼层
回复【楼主位】科科1987:
STM32编码器接口模式--寄存器版
已测试通过,如果不能使用,那可能就是编码器信号干扰比较大。
void Encoder_Init(void)
{

......
---------------------------------
请问下lz那个printf("编码器计数值为:%d \n",currentCount+1);    怎么观察呢?
回复 支持 反对

使用道具 举报

  离线 

38

主题

523

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1389
金钱
1389
注册时间
2011-11-27
在线时间
117 小时
 楼主| 发表于 2014-4-20 13:26:11 | 显示全部楼层
回复【49楼】papermx:
回复【楼主位】科科1987:
STM32编码器接口模式--寄存器版
已测试通过,如果不能使用,那可能就是编码器信号干扰比较大。
void Encoder_Init(void)
{
......
---------------------------------
请问下lz那个printf("编码器计数值为:%d \n",currentCount+1);    怎么观察呢?
---------------------------------
使用串口调试助手。
永远保持一颗学习的心态。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




关闭

报名原子哥新品发布会&粉丝见面会上一条 /1 下一条

正点原子公众号

QQ|联系我们|手机版|官方淘宝店|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-10-18 08:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */