OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 19988|回复: 7

stm32编码器模式

[复制链接]

18

主题

158

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
400
金钱
400
注册时间
2011-11-23
在线时间
0 小时
发表于 2012-8-31 19:17:01 | 显示全部楼层 |阅读模式
我最近有一个项目要利用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_TIMER时钟初始化
  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_PRIORITY;
  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_Rising, TIM_ICPolarity_Rising); //编码器接口初始化
  //TIM_ICPolarity_Rising:  TIM输入捕获上升沿
  TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER; // TIM_ICFilter选择输入比较滤波器。该参数取值在0x0和0xF之间
  TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
  
 // Clear all pending interrupts
  TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);// 清除TIMx的待处理标志位
  TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);  //使能或者失能指定的TIM中断
  //Reset counter
  TIM2->CNT = COUNTER_RESET;
  

  
  TIM_Cmd(ENCODER_TIMER, ENABLE);  //  使能或者失能TIMx外设
}
//****************************************************************************************************
// 计算马达转子相对于初始位置的角度  -180至+180
//****************************************************************************************************
void ENC_Get_Electrical_Angle(uint16_t *degree)
{
int32_t temp;
int16_t tim_count;  
tim_count=TIM_GetCounter(ENCODER_TIMER);   //获取ENCODER_TIMER的值
if(tim_count>=400) //如果超过180度,角度为负数
{
degree[0]='-';
degree[1]=(800-tim_count)*180/(4*ENCODER_PPR/2); //整数部分
temp = (int32_t)(800-tim_count) * (int32_t)(1000000/(4*ENCODER_PPR/2))*360-degree[1]*1000000; 
  degree[2]=(unsigned char)temp; //小数部分
}
else //如果未超过180度,角度为正数
{
degree[0]='+';
degree[1]=tim_count*180/(4*ENCODER_PPR/2); //整数部分
temp = (int32_t)tim_count * (int32_t)(1000000/(4*ENCODER_PPR/2))*180-degree[1]*1000000; 
  degree[2]=(unsigned char)temp;   //小数部分
}
}
//****************************************************************************************************
//TIm2_IRQ 计算编码器每秒钟产生的脉冲数
//**************************************************************************************************
void Tim2_IRQ(void)
{  
unsigned int temp;
if(Count[0]==0)
{
Count[0]++; //以便下次读取并计算
Count[2]=Count[1];
Encoder_TIM_Count[0]=TIM_GetCounter(ENCODER_TIMER); //第一次读取ENCODER_TIMER的值
}
else  
{
temp=Count[1]-Count[2]; //ENCODER_TIMER溢出次数
Encoder_TIM_Count[1]=TIM_GetCounter(ENCODER_TIMER); //第二次读取ENCODER_TIMER的值
Count[0]=0;
Count[1]=0;
if(temp==0) //如果ENCODER_TIMER溢出次数为0
{
if(Encoder_TIM_Count[1]>=Encoder_TIM_Count[0])
{
Speed[1]=(Encoder_TIM_Count[1]-Encoder_TIM_Count[0])*8;  //每秒的脉冲数等于两次计数器差的绝对值*4
}
else
{
Speed[1]=(Encoder_TIM_Count[0]-Encoder_TIM_Count[1])*8;
}
}
else //如果ENCODER_TIMER溢出次数不为0
{
if(Speed[0]=='+') //如果ENCODER_TIMER正向溢出 
{
if(Encoder_TIM_Count[1]>=Encoder_TIM_Count[0])
{
Speed[1]=(Encoder_TIM_Count[1]-Encoder_TIM_Count[0]+(4*ENCODER_PPR)*temp)*8;
}
else  
{
Speed[1]=(800-Encoder_TIM_Count[0]+Encoder_TIM_Count[1]+(4*ENCODER_PPR)*(temp-1))*8;
}
else //如果ENCODER_TIMER逆向溢出
{
Speed[1]=(800-Encoder_TIM_Count[1]+Encoder_TIM_Count[0]+(4*ENCODER_PPR)*(temp-1))*8;
}
}
}

}
//****************************************************************************************************
//TIm4_IRQ   获得溢出此数count[1]和旋转方向speed
//****************************************************************************************************
void Tim4_IRQ(void)
{
unsigned int temp;
Count[1]++;

 /* Clear the interrupt pending flag */
TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);

temp=TIM_GetCounter(ENCODER_TIMER);
if(temp==0)  //如果计数器的值为0,则正向旋转
Speed[0]='+';
else if(temp==799)   //如果计数器的值为0,则逆向旋转
Speed[0]='-';
 
}
库函数版本的编码器很多例子,可是原子大哥配置的寄存器模式,不知道哪位大哥、大神可曾经调试过,或者有什么经验,可以交流一下,我的qq号是505021476,谢谢了!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-8-31 20:00:31 | 显示全部楼层
STM32驱动编码器我也没搞过哇...
你这个库函数的可用么?
可用的话,对照着改,不难的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

18

主题

158

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
400
金钱
400
注册时间
2011-11-23
在线时间
0 小时
 楼主| 发表于 2012-8-31 20:00:47 | 显示全部楼层
回复【楼主位】shuilian007:
---------------------------------
有大神吗?我们用的都是原子哥的寄存器配置,在网上更多的都是库函数版本~
回复 支持 反对

使用道具 举报

11

主题

78

帖子

0

精华

初级会员

Rank: 2

积分
142
金钱
142
注册时间
2012-8-21
在线时间
0 小时
发表于 2013-1-15 15:40:12 | 显示全部楼层
回复【3楼】shuilian007:
---------------------------------
你的编码器模式能够起作用了没?
回复 支持 反对

使用道具 举报

5

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2013-6-18
在线时间
0 小时
发表于 2013-7-16 13:41:34 | 显示全部楼层
/*Configure TIM2 TIM3 TIM4 TIM5 as Encoder Interfaces input*/
/*TIM base Configuration*/
    TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 65535;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;

/*预分频=1,向上计数,不分频,自动重装载=65535,软件产生一次更新事件(UG)*/
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);

/*编码器模式3,通道1、2为输入,映射到TI1、2上;        IC1输入捕获在上升沿;      IC2输入捕获在上升沿*/
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); 
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

    /* TIM2 3 4 enable counter */
    TIM_Cmd(TIM2, ENABLE);
    TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE); 
TIM_Cmd(TIM5, ENABLE); 

我用过这段代码,使用TIM2345作为伺服电机的闭环反馈,对码盘反馈脉冲周期计数从而测得实际速度。
使用时注意TIMx的通道引脚映射;以上函数为V3.50的库
回复 支持 反对

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2013-7-26
在线时间
2 小时
发表于 2013-9-6 21:17:11 | 显示全部楼层
用IC是不是的上啦一个电阻啊?检测不到脉冲
回复 支持 反对

使用道具 举报

17

主题

54

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
310
金钱
310
注册时间
2016-7-1
在线时间
94 小时
发表于 2016-11-17 08:32:14 | 显示全部楼层
我擦,看到这层,突然断了,可是我还没找到我想要的答案。。最近也遇到用编码器模式测电机的转速和方向。。。挥汗如雨,,
回复 支持 反对

使用道具 举报

SUPERXUE 该用户已被删除
发表于 2016-12-2 12:47:59 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 19:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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