STM32学习笔记——基于正点原子例程编码器模式小结

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/secretboys/article/details/102726207

STM32学习笔记——基于正点原子例程编码器模式小结

最近一段时间学习了,STM32f4的编码器功能,经过自己探索和他人的热心帮助,对于编码器模式有了一定了解。STM32f4单片机提供编码器模式,以便用户可以直接使用编码器模式读出编码器所传输的位置信息,供单片机进行下一步操作。
本文章所使用的编码器为直流电机尾部自带的编码器。
学习STM32编码器模式,首先应该知道其模式返回的值所代表的含义是什么,正交编码器模式在对应的定时器数据寄存器TIMX->CNT中的值反映的是编码器所处的“位置”,或者所是角度(个人理解就是其所记录的脉冲次数),正负号代表编码器是正转还是反转。开始编程之前,首先应该知道自己所用的编码器的线数(所谓线数,个人理解就是电机转一圈,所使用的编码器单独一相所产生的脉冲数是多少),常见的有130、260、390、780。如果实在不知道自己所用的编码器的线数,可以在编编好程序后,手动把电机转一圈,使用串口读出此时定时器数据寄存器TIMX->CNT中的值然后除以自己所设置的是几倍频,对照编码器常用的线数规格,取接近值。

STM32f4正交编码器设置步骤

本设置以16位通用定时器TIM4为例

步骤一:设置初始化结构体变量

    GPIO_InitTypeDef GPIO_InitStructure;//定时器4对应IO端口初始化变量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定时器4初始化变量
    TIM_ICInitTypeDef TIM_ICInitStructure;//定时器4输入捕获参数

步骤二:时钟设置

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//GPIO时钟设置
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//TIM4时钟设置

步骤三:GPIO口设置

    GPIO_StructInit(&GPIO_InitStructure); //端口复位,避免干扰
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;//初始化TIM4ch1和ch2通道端口,D12、D13        
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF;//端口复用模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//时钟频率100MHZ
    GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD 端口                         

    GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//GPIOD12、D13复用为TIM4_CH1,CH2

步骤四:TIM4定时器模式设置

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//结构体参数设置设为默认值
    TIM_TimeBaseStructure.TIM_Period = 520-1;//自动重装载值为520,这里我采用二倍频技术,编码器线数为260  
    TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频系数为1
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//对TIM4初始化

步骤五:TIM4输入捕获模式参数设置

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising);//正交编码器模式,A,B两相都记录上升沿跳变,二倍频技术 
    TIM_ICStructInit(&TIM_ICInitStructure); //结构体参数设置设为默认值
    TIM_ICInitStructure.TIM_ICFilter = 0;  //滤波次数为1
    TIM_ICInit(TIM4, &TIM_ICInitStructure);//输入捕获初始化
    TIM_ClearFlag(TIM4, TIM_FLAG_Update); //TIM4更新中断标志清零

步骤六:其余参数设置

    TIM_SetCounter(TIM4,0);//TIM4数据寄存器清零
    TIM_Cmd(TIM4, ENABLE); //使能TIM4 

步骤七:读取函数

//定时器5中断服务函数
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //是否产生更新(溢出)中断
	{
  printf("\\n编码器值为:%d\n",TIM4->CNT);
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清空TIM5中断标志位
}

整体代码

    GPIO_InitTypeDef GPIO_InitStructure;//定时器4对应IO端口初始化变量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定时器4初始化变量
    TIM_ICInitTypeDef TIM_ICInitStructure;//定时器4输入捕获参数
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//GPIO时钟设置
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//TIM4时钟设置

    GPIO_StructInit(&GPIO_InitStructure); //端口复位,避免干扰
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;//初始化TIM4ch1和ch2通道端口,D12、D13        
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF;//端口复用模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//时钟频率100MHZ
    GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD 端口                         

    GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//GPIOD12、D13复用为TIM4_CH1,CH2

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//结构体参数设置设为默认值
    TIM_TimeBaseStructure.TIM_Period = 520-1;//自动重装载值为520,这里我采用二倍频技术,编码器线数为260  
    TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频系数为1
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//对TIM4初始化

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising);//正交编码器模式,A,B两相都记录上升沿跳变,二倍频技术 
    TIM_ICStructInit(&TIM_ICInitStructure); //结构体参数设置设为默认值
    TIM_ICInitStructure.TIM_ICFilter = 0;  //滤波次数为1
    TIM_ICInit(TIM4, &TIM_ICInitStructure);//输入捕获初始化
    TIM_ClearFlag(TIM4, TIM_FLAG_Update); //TIM4更新中断标志清零

    TIM_SetCounter(TIM4,0);//TIM4数据寄存器清零
    TIM_Cmd(TIM4, ENABLE); //使能TIM4

//定时器5中断服务函数
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //是否产生更新(溢出)中断
	{
  printf("\\n编码器值为:%d\n",TIM4->CNT);
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清空TIM5中断标志位
}

本文之前采用四倍频设置,但问过小伙伴后,小伙伴说官网的四倍频程序有问题,建议我我采用二倍频设置,自己也经过实验验,发现当正交编码器模式设置四倍频时,电机转一圈所得的脉冲数是二倍频模式的一半,二倍频为精度最高的模式,所以设置为二倍频设置

猜你喜欢

转载自blog.csdn.net/secretboys/article/details/102726207