打算做一个增量式编码器位移量读取电路,
想用STM32外部中断来对脉冲进行计数.
选择了PB12,PB13,PB14这三个IO口,分别对应编码器的A,B,Z相.
PB12和PB13需要在上升沿和下降沿都对脉冲计数,就是四倍频计数.PB14需要在上升沿时对脉冲数量进行修正.
我用的是300线的编码器,正常情况下四倍频以后编码器转一圈应该是1200个脉冲数量,实际仿真的时候这个脉冲数量远远不对.
后来我把中断服务函数里只留下PB12.也就是只对A相这一个外部中断进行计数,仿真结果编码器转一圈脉冲计数的数量是对的,300线2倍频,600个脉冲.
经过反复测试发现,无论是中断服务函数里单独留下A或B相进行计数,脉冲数量都是对的,如果两相同时参与计数,那么脉冲数量就远远的不对了.
还有就是使用A或B相单独进行脉冲计数时,加入Z相中断判断(只做判断,然后清中断标志位,不做其它事情),也会影响计数的准确性.
以下是部分功能代码
void EXTI_Configuration(void)//配置外部中断
{
EXTI_InitTypeDef EXTI_InitStructure;//EXTI初始化结构定义
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用时钟
EXTI_ClearITPendingBit(EXTI_Line12);//清除中断标志
EXTI_ClearITPendingBit(EXTI_Line13);
EXTI_ClearITPendingBit(EXTI_Line14);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);//选择GPIO管脚用作外部中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource13);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
EXTI_InitStructure.EXTI_Line=EXTI_Line12 | EXTI_Line13;//外部中断线路选择
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //触发方式 中断触发
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising_Falling;//上升沿下降沿都触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能
EXTI_Init(&EXTI_InitStructure);//初始化
EXTI_InitStructure.EXTI_Line=EXTI_Line14;//外部中断线路选择
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //触发方式 中断触发
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能
EXTI_Init(&EXTI_InitStructure);//初始化
}
void EXTI15_10_IRQHandler(void)//中断服务程序
{
if(EXTI_GetITStatus(EXTI_Line12)==SET)//A相产生中断
{
dat = GPIOB->IDR & 0x3000;
switch(dat)//读取AB状态
{
case 0x3000://A=1 B=1 理论反
case 0x0000://A=0 B=0
jishu += 1;
break;
case 0x1000://A=1 B=0 理论正
case 0x2000://A=0 B=1
jishu -= 1;
break;
}
EXTI_ClearFlag(EXTI_Line12);
EXTI_ClearITPendingBit(EXTI_Line12);//清除中断请求标志
}
// else if(EXTI_GetITStatus(EXTI_Line13)==SET)//B相产生中断
// {
//
// dat = GPIOB->IDR & 0x3000;
// switch(dat)//读取AB状态
// {
// case 0x3000://B=1 A=1 理论正
// case 0x0000://B=0 A=0
// jishu -= 1;
//
// break;
// case 0x1000://B=0 A=1 理论反
// case 0x2000://B=1 A=0
// jishu += 1;
//
// break;
// }
// EXTI_ClearFlag(EXTI_Line13);
// EXTI_ClearITPendingBit(EXTI_Line13);//清除中断请求标志
// }
以下是仿真时外设的配置情况
求帮助...感激不尽...
|