F429的,通过HAL函数配置编码器,使用编码器模式,准确判断圈数(正负)。通过串口打印。

2019-07-20 00:40发布

最近在调编码器,网上的大多没有F429 的HAL例程,并且没有圈数的准确计算。此例程在其他的基础上进行编码器圈数的准确计算。圈数通过串口打印小数形式。
欢迎大家讨论!
附件上传不了???
主要是main和timer 。我贴出来吧!


#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "timer.h"
/************************************************
ALIENTEK 阿波罗STM32F429开发板实验7
定时器中断实验-HAL库函数版
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司  
作者:正点原子 @ALIENTEK
************************************************/
/************************************************
A、B 相的接PD12 和PD13 ,由于编码器能正反转,具体的接法看实际需求
这里只是一个编码器例程,其他需要只需要在配置几个定时器和引脚即可使用
************************************************/

int main(void)
{
        HAL_Init();                     //初始化HAL库
        Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
        delay_init(180);                //初始化延时函数
        uart_init(9600);              //初始化USART
        LED_Init();                     //初始化LED
        KEY_Init();                     //初始化按键
        TIM4_Init(2000,3);       //定时器3初始化,定时器时钟为60M
        Interupt_Num=0 ;
        Pulse_Num =0 ;
        Circle_NUm =0;
        while(1)
        {
                Circle_Print();
                delay_ms(100);
                LED0 = !LED0;
        }
}



/////////////////////////////////////////timer.h///////////////////////////////////////////////////////////////////////////////
#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//定时器驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////        
extern TIM_HandleTypeDef TIM3_Handler;      //定时器句柄
extern TIM_Encoder_InitTypeDef Code_Config;
extern TIM_MasterConfigTypeDef Master_Config;

extern long Interupt_Num ;         //因为编码器配置的定时器数值溢出进入中断次数
extern long Pulse_Num ;                 //计算得到的所有的脉冲数
extern float Circle_NUm ;          //计算得到的所有圈数,有正负之分

void TIM4_Init(u16 arr,u16 psc);
void Circle_Print();
#endif


/////////////////////////////////////////timer.c///////////////////////////////////////////////////////////////////////////////
#include "timer.h"
#include "led.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//定时器中断驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////        

TIM_HandleTypeDef TIM4_Handler;      //定时器句柄
TIM_Encoder_InitTypeDef TIM4_Encoder_Handler;

//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!(定时器3挂在APB1上,时钟为HCLK/2)

long Interupt_Num=0 ;
long Pulse_Num =0 ;
float Circle_NUm =0;  

void TIM4_Init(u16 arr,u16 psc)
{  
        TIM4_Handler.Instance=TIM4;
        TIM4_Handler.Init.Prescaler=psc;                     //分频系数
        TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器
        TIM4_Handler.Init.Period=arr;                        //自动装载值
        TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频银子
       
        //HAL_TIM_Base_Init(&TIM4_Handler);        //HAL_TIM_OC_Init(&TIM4_Handler);
        //不要用这句话,他是基本定时器的设置,这里使用了编码器模式,没必要配置
       
        TIM4_Encoder_Handler.EncoderMode=TIM_ENCODERMODE_TI12;
        TIM4_Encoder_Handler.IC1Filter=0;
        TIM4_Encoder_Handler.IC1Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC1Prescaler=TIM_ICPSC_DIV1;
        TIM4_Encoder_Handler.IC1Selection=TIM_ICSELECTION_DIRECTTI;
               
        TIM4_Encoder_Handler.IC2Filter=0;
        TIM4_Encoder_Handler.IC2Polarity=TIM_ICPOLARITY_RISING;
        TIM4_Encoder_Handler.IC2Selection=TIM_ICSELECTION_DIRECTTI;
        TIM4_Encoder_Handler.IC2Prescaler=TIM_ICPSC_DIV1;
        HAL_TIM_Encoder_Init(&TIM4_Handler,&TIM4_Encoder_Handler);
       
        HAL_TIM_Encoder_Start(&TIM4_Handler,TIM_CHANNEL_ALL);
        HAL_TIM_Encoder_Start_IT(&TIM4_Handler,TIM_CHANNEL_ALL);//开启中断
        TIM4->CNT=1000;
    __HAL_TIM_ENABLE_IT(&TIM4_Handler,TIM_IT_UPDATE);   //使能更新中断
    __HAL_TIM_ENABLE(&TIM4_Handler);

}

void TIM4_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM4_Handler);
}

void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
{   
        GPIO_InitTypeDef GPIO_Initure;
        if(htim->Instance==TIM4)
  {
    __HAL_RCC_TIM4_CLK_ENABLE();            //使能TIM4时钟
        HAL_NVIC_SetPriority(TIM4_IRQn,1,3);    //设置中断优先级,抢占优先级1,子优先级3
        HAL_NVIC_EnableIRQ(TIM4_IRQn);          //开启ITM4中断   
        HAL_TIM_Base_Start_IT(&TIM4_Handler); //使能定时器4和定时器4更新中断:TIM_IT_UPDATE   

    __HAL_RCC_GPIOD_CLK_ENABLE();                        //开启GPIOD时钟          
    GPIO_Initure.Pin=GPIO_PIN_12|GPIO_PIN_13;         
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;      //输入
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Alternate=GPIO_AF2_TIM4;   
    HAL_GPIO_Init(GPIOD,&GPIO_Initure);
        }       
}

//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

        if(htim==(&TIM4_Handler))
        {
                LED1 = !LED1 ;
                if ( (TIM4->CR1&0x0010) == 0 )  //向上计数溢出
                {
                        Interupt_Num++ ;
                }
                else //向下计数溢出
                {
                        Interupt_Num-- ;
                }               
        }
}

void Circle_Print()
{
        if (Interupt_Num ==0 )                        //CNT从1000开始,刚开始的时候计算脉冲的方法
                Pulse_Num = TIM4->CNT-1000 ;
        else
        {  
                Pulse_Num = 1000 + (Interupt_Num - 1) *2000 +TIM4->CNT ; //在第一圈完成之后,计算脉冲数多的方法
        }
        Circle_NUm =  Pulse_Num/1000.0f                ;                 //所有人脉冲除以细分数就可以得到转的圈数(正负之分)
        printf("Interupt_Num的值是:%ld--捕获到的总数是%ld*****转过的圈数是%f " , Interupt_Num, Pulse_Num , Circle_NUm );
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。