STM32编码器接口!

2019-07-20 14:39发布

[mw_shl_code=c,true] //Email:ykee@outlook.com #include "timer.h" #include "led.h" u32 count=0; //脉冲计数 u32 count_val=0; //计数值 //定时器3中断服务程序 void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001)//溢出中断 { SYS_LED=!SYS_LED; } TIM3->SR&=~(1<<0);//清除中断标志位 } void TIM4_Init(u16 arr, u16 psc ,u32 count) { RCC->APB1ENR |= 1<<2; //TIM4时钟使能 RCC->APB2ENR |= 1<<3; //使能PORTB时钟 GPIOB->CRL &= 0XF0FFFFFF;//PB6输出 GPIOB->CRL |= 0X0B000000;//复用功能输出 GPIOB->ODR |= 1<<6;//PB6上拉 TIM4->ARR = arr;//设定计数器自动重装值 TIM4->SC = psc;//预分频器不分频 TIM4->CCR1 = arr/2; //占空比为50% count_val=count-1; //脉冲输出个数 TIM4->CCMR1 |= 7<<4; //CH1 PWM2模式 TIM4->CCMR1 |= 1<<3; //CH1预装载使能 TIM4->CCER |= 1<<0; //TIM4 OC1 PB6 输出使能 TIM4->DIER|=1<<0; //允许更新中断 TIM4->DIER|=1<<6; //允许触发中断 TIM4->EGR |=1<<1; //允许产生比较捕获事件 MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//抢占1,子优先级3,组2 TIM4->CR1 |= 0x0080; //ARPE使能 TIM4->CR1 |= 0x0001; //使能定时器4 TIM4->CCMR1 |= 7<<4; //CH1 PWM2模式 TIM4->CCMR1 |= 1<<3; //CH1预装载使能 TIM4->CR1 |= 0x0080; //ARPE使能 TIM4->CR1 |= 0x0001; //使能定时器3 } void TIM4_IRQHandler(void) { if(TIM4->SR&0X0001)//产生更新中断 { count++; if(count==count_val) { TIM4->CR1&=~(0x01); //CEN=0,禁止定时器3 count=0; } } TIM4->SR&=~(1<<0);//清除中断标志位 } void Encoder_Init(void) { /* TIM3 clock source enable */ RCC->APB1ENR|=1<<1; //TIM3时钟使能 /* Enable GPIOA, clock */ RCC->APB2ENR|=1<<2; //使能PORTA时钟 /* Configure PA.06,07 as encoder input */ GPIOA->CRL&=0XF0FFFFFF;//PA6 GPIOA->CRL|=0X04000000;//浮空输入 GPIOA->CRL&=0X0FFFFFFF;//PA7 GPIOA->CRL|=0X40000000;//浮空输入 /* Enable the TIM3 Update Interrupt */ //这两个东东要同时设置才可以使用中断 TIM3->DIER|=1<<0; //允许更新中断 TIM3->DIER|=1<<6; //允许触发中断 MY_NVIC_Init(1,3,TIM3_IRQChannel,2); /* Timer configuration in Encoder mode */ TIM3->SC = 0x0;//预分频器 TIM3->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 TIM3->CR1 &=~(3<<8);// 选择时钟分频:不分频 TIM3->CR1 &=~(3<<5);// 选择计数模式:边沿对齐模式 TIM3->CCMR1 |= 1<<0; //CC1S='01' IC1FP1映射到TI1 TIM3->CCMR1 |= 1<<8; //CC2S='01' IC2FP2映射到TI2 TIM3->CCER &= ~(1<<1); //CC1P='0' IC1FP1不反相,IC1FP1=TI1 TIM3->CCER &= ~(1<<5); //CC2P='0' IC2FP2不反相,IC2FP2=TI2 TIM3->CCMR1 |= 3<<4; // IC1F='1000' 输入捕获1滤波器 TIM3->SMCR |= 3<<0; //SMS='011' 所有的输入均在上升沿和下降沿有效 TIM3->CNT = COUNTER_RESET; TIM3->CR1 |= 0x01; //CEN=1,使能定时器 } [/mw_shl_code] 这个程序中TIM3为何要中断啊,中断只是为了让灯亮灭吗?按理不是TIM3的计数值就是正交编码器的脉冲计数吗?为何要需要TIM4? TIM4这里又是干什么的 啊?求解啊!看得我一头雾水!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
49条回答
翱翔云端的鸟
2019-07-20 20:49
还需要一个外部中断,对Z信号敏感,以清0计数TIM->CNT = 0;附上中断配置代码和中断函数代码 [mw_shl_code=c,true]/*void PA_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; // Configure one bit for preemption priority NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //配置P[A|B|C|D|E]1为中断源 NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } */ /* * 函数名:NVIC_Configuration * 描述 :配置嵌套向量中断控制器NVIC * 输入 :无 * 输出 :无 * 调用 :内部调用 */ void EXTI_PA1_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /* config the extiline(PA1) clock and AFIO clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO,ENABLE); /* config the NVIC(PA1) */ NVIC_Configuration(1); /* EXTI line gpio config(PA1) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); /* EXTI line(PA1) mode config */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1); EXTI_InitStructure.EXTI_Line = EXTI_Line1; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }[/mw_shl_code]
NVIC(1)是因为我有多个中断,所以使用条件参数配置
[mw_shl_code=c,true]void USART1_NVIC_Config(NVIC_InitTypeDef NVIC_InitStructure4) { NVIC_InitStructure4.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure4.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure4.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure4.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure4); } void NVIC_Configuration(int Interrupt_flag) { NVIC_InitTypeDef NVIC_InitStructure; /* 配置中断使用组合2 抢占式2位,响应式2位*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); if(Interrupt_flag == 1) { /*外部中断1,Z相归零----优先级最高 0 0*/ PA_NVIC_Configuration(NVIC_InitStructure); } if(Interrupt_flag == 2) { /*TIM3中断,编码器解码----优先级 1 1*/ TIM3_NVIC_Config(NVIC_InitStructure); } if(Interrupt_flag == 3) { /*TIM2中断,数据帧接收完毕判断----优先级 2 2*/ TIM2_NVIC_Config(NVIC_InitStructure); } if(Interrupt_flag == 4) { /* USART1中断,数据接收----优先级 3 3*/ USART1_NVIC_Config(NVIC_InitStructure); } }[/mw_shl_code]
[mw_shl_code=c,true]void PA_NVIC_Configuration(NVIC_InitTypeDef NVIC_InitStructure1) { NVIC_InitStructure1.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure1.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure1.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure1); }[/mw_shl_code]
最后是中断处理函数,比较简单
[mw_shl_code=c,true]void EXTI1_IRQHandler(void) { GPIO_WriteBit(GPIOF, GPIO_Pin_8, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_8)))); TIM3->CNT = 0; EXTI_ClearITPendingBit(EXTI_Line1); }[/mw_shl_code]
至此,我的编码器模块就完成了。还是那句话花点时间总归是有点收获的!

一周热门 更多>