关于STM32的编码器计数及溢出处理调试总结
错误1、
pc6 pc7被用作其他用途,GPIO模式配置错误。导致计数不准确;
错误2、引脚模式设置错误,应该设置为GPIO_Mode_IPD;//GPIO_Mode_IPU GPIO_Mode_IN_FLOATING 都可以;
错误3 引脚重映射没有开启AFIO时钟; 总结 关于编码器的溢出处理: 网上的检测数值突变的方法不可靠,会有漏检的情况。在滴答定时器中检测encoder的值突变
void SysTick_Handler(void) {// systick中断,1ms一次
static int encoder[2] = {0 , 0};// 两次编码器读值,用以计算溢出方向
static int N = 0;// 圈数
encoder[1] = TIM3->CNT;
if((encoder[1] - encoder[0] ) > 0x7FFF)
{ N--; }
else if( (encoder[0] - encoder[1] ) > 0x7FFF)
{ N++; }
EncCnt = N * 0xFFFF + encoder[1];
encoder[0] = encoder[1]; }
我采用了两种方法处理:一种是采用另一个定时器实时的检测溢出标志及方向标志,这种方法是可行的。即使速度很快的时候依然计数准确。但是出现了新的问题,用作定时器的时钟,当定时周期设置的很小的时候才可以计数准确,但是由于中断的优先级高,导致无法进入主循环程序。附上检测代码。这样的处理方法,在速度慢的时候可以检测正确。但是定时周期要设置足够小。CR1的bit4代表计数方向标志,1代表减二代表加;SR的bit0代表溢出中断标志,1代表溢出。该位是硬件置1软件清零。另一种是使用编码器溢出中断。中断的时候对编码器溢出方向进行判断,然后根据方向进行累加。
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )
{ TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
encoder= TIM3->CNT;
if((TIM3->CR1&0x10) == 0x10)//向下计数
{
if(TIM3->SR&0x01 == 0x01)//tim3计数溢出
{
TIM3->SR= TIM3->SR&0xFE;//sr的bit0清零
N--;
}
}
else if((TIM3->CR1&0x10) == 0x00)//向上计数
{
if(TIM3->SR&0x01 == 0x01)//tim3计数溢出
{
TIM3->SR= TIM3->SR&0xFE;//sr的bit0清零
N++;
}
}
EncCnt= N * 65536 + TIM3->CNT;
// encoder[0] = encoder[1];
}
复制代码
}
最后,我找到了更简单的检测编码器溢出中断并进行累计的方法。
其实当编码器的定时器溢出的时候,会导致进入中断。这样直接用编码器的中断函数即可。但是需要注意的是,需要在编码器的定时器配置的时候,配置中断。如果不配置,就会导致程序一运行就死机。一直停在DMA2_Channel4_5_IRQHandler这一句。
附上最终测试验证完成的代码
编码器初始化配置 ( 注意。如果不适用中断溢出的方法,无需配置
NVIC_InitStructure.NVIC_IRQChannel =TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
这部分。。。)
并且我适用的是tim3重定义到pc7 pc6的。也可以使用部分重映射和默认引脚。
void EncoderTimInit()
{
// 对TIM_ICInitStructure的配置和对TIM_EncoderInterfaceConfig函数的使用实际上是冲突的,两个语句中的极性的设置是重复的
//--------------1
GPIO_InitTypeDefGPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //AFIO时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); //TIM选择全复用功能使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;//PC6 PC7浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//GPIO_Mode_IPU GPIO_Mode_IN_FLOATING
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
TIM_DeInit(TIM3); //TIM3初始化
/* Timer configuration in Encoder mode */
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 不分频
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM3_PERIOD-1; //计数40000 定时 T = 1/72000000 *40000 S= 1/1.8ms
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_Rising, TIM_ICPolarity_Rising); //TIM_ICPolarity_Rising上升沿捕获
TIM_ICStructInit(&TIM_ICInitStructure); //输入捕获模式配置为硬件默认值
TIM_ICInitStructure.TIM_ICFilter = 0x06;//ICx_FILTER; //比较滤波器
TIM_ICInit(TIM3, &TIM_ICInitStructure);//调用库函数把配置信息填充进去
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// TIM_ARRPreloadConfig(TIM3,ENABLE);
// TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);
//Clear all pending interrupts
// TIM_SetAutoreload(TIM3,0xffff);
TIM_ClearFlag(TIM3,TIM_FLAG_Update);//清除TIM3的更新标志位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能中断
//Reset counter 计数初始值
TIM3->CNT = 0;
TIM_Cmd(TIM3, ENABLE);
}
编码器计数模块
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3 , TIM_FLAG_Update);
if((TIM3->CR1&0x10) == 0x10)//向下计数
{
N--;
}
else if((TIM3->CR1&0x10) == 0x00)//向上计数
{
N++;
}
EncCnt= N * 65536 + TIM3->CNT;
}
}
注: N 和EncCnt变量最好定义为volatile
- 点赞
- 收藏
- 关注作者
评论(0)