错误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
上一篇:stm32中编码器模式读出“负数”的问题
下一篇:STM32F103之实验2控制1个电机并采用编码器读取电机转速
推荐阅读最新更新时间:2024-03-16 16:14
设计资源 培训 开发板 精华推荐
- 安全的革新,全新的验证方式 下载富士通 《频谱验证解决方案 》白皮书 好礼送!
- 阅1SP0350V SCALE-2单通道即插即用型门极驱动器,参与PI答题享好礼!
- TI 图形化界面助力快速开发,这就是您想要的MSP430™通用MCU!
- TI直播:精讲“双向CLLLC谐振、双有源电桥(DAB)参考设计”
- 下载有礼|精华课件汇编:泰克半导体器件的表征及可靠性研究交流会暨吉时利测试测量年度研讨会
- TI 有奖直播|业界超精确3D霍尔效应位置传感器
- 参加MSP430F5529培训,长知识、免费送、超低团、抢楼得!
- 【免费租用】Xilinx Spartan-6 FPGA 嵌入式套件!
- 夏末狂欢,观看TI 课程有好礼!