我最近有一个项目要利用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,谢谢了!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
/*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的库
一周热门 更多>