打印
[STM32F4]

STM32F407光栅尺测速

[复制链接]
859|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2021-9-6 15:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F407光栅尺测速

//TIM5初始化为编码器接口模式,读取光栅尺数值
//分频psc=0;自动重装载值arr根据定时器位数定

void TIM5_Config(u32 arr,u32 psc)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);          //TIM5时钟使能   
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTF时钟       
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //光栅尺
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出
        GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_UP; //上拉
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        //速度100MHz
        GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PD
       
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //复用为TIM5
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM5); //复用为TIM5
       
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  
        TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
        TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值16位 0xFFFF 65535; 32位0xFFFFFFF
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;         //时钟分频
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);  //初始化TIM5
       
  //编码器模式1 – 根据TI1FP1的电平,计数器在TI2FP2的边沿向上/下计数。
        TIM_EncoderInterfaceConfig(TIM5,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);  //编码器接口模式配置
        TIM_ICStructInit(&TIM_ICInitStructure);  //默认值赋值
        TIM_ICInitStructure.TIM_ICFilter =0x2;   //滤波 0x0~0xF  
        TIM_ICInit(TIM5, &TIM_ICInitStructure);  //初始化

        TIM_ClearFlag(TIM5, TIM_FLAG_Update);//清除标志位
        TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE); //更新中断

        TIM_SetCounter(TIM5,0);  //计数器清零
        TIM_Cmd(TIM5, ENABLE);
}


使用特权

评论回复
沙发
tpgf|  楼主 | 2021-9-6 15:35 | 只看该作者
//基本定时器6中断初始化
//TIM6时钟为84M
//arr:自动重装值。例5000-1,计数器从0数到4999,即5000次为一个定时器周期
//psc:时钟预分频数。例8400-1,若时钟为84M,则分频后为84M/8400=10KHz 即0.1ms
//定时器溢出时间计算方法:Tout=((arr+1)(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//例(100-1,840-1) T=1000.01ms=1ms

void TIM6_Int_Init(u16 arr,u16 psc)
{       
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);  ///使能TIM6时钟
       
  TIM_TimeBaseInitStructure.TIM_Period = arr;         //自动重装载值
        TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStructure);
       
        TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE); //允许定时器6更新中断
        TIM_Cmd(TIM6,ENABLE); //使能定时器6
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM6_DAC_IRQn;  
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先级2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);                                                                          
}



//定时器6中断服务程序
//每20ms采集一次脉冲值,并计算出当前位置和速度,结果通过串口打印

void TIM6_DAC_IRQHandler(void) //1ms中断一次   定时向伺服发送读取指令
{                                             
        static vu16 t=0;
        static int32_t encoderDataLast=0;  //脉冲数
        static int32_t encoderDataNow=0;   //脉冲数
       
        if(TIM_GetITStatus(TIM6,TIM_IT_Update)==SET) //溢出中断
        {
                t++; //每1ms加一
                if(t==20) //第20ms
                {
                                t=0;
                                encoderDataNow=TIM5->CNT;   //读取编码器脉冲数
                                encoderData=GetENCODECounter(encoderDataNow);  //脉冲值反方向值处理
                                CurrentPos = GetCurrentPosition(encoderData);  //计算当前位置
       
                                CurrentSpeer = EncoderSpeer(encoderDataNow,encoderDataLast,20); //计算速度 20ms
                                encoderDataLast=encoderDataNow;   //
                       
                          printf("当前位置: %.2fmm; 速度:%.2f mm/s\r\n",CurrentPos,CurrentSpeer); //程序用时3.43ms
                }
        }                                  
        TIM_ClearITPendingBit(TIM6,TIM_IT_Update);  //清除中断标志位   
}


使用特权

评论回复
板凳
tpgf|  楼主 | 2021-9-6 15:35 | 只看该作者
encoder.c文件 算法

#include "encoder.h"                  // Device header
#include "stdlib.h"

u32 encoderData; //编码器脉冲数
float  CurrentPos; //当前位置
float  CurrentSpeer;//当前速度
       
//编码器反方向转换
//输入:count脉冲数
//输出0xX0000000  正方向X=0  反方向X=8
//局限性:正向运动输入的脉冲数永远不会超过0X80000000
u32 GetENCODECounter(u32 count)  //编码器反方向数值转换
{
        if(count>0X80000000)     //负方向
        {
                count=0XFFFFFFFF-count;  //
                count=count | 0X80000000 ;                       
        }
        return count;
}

//计算当前位置
//输入:count脉冲数   EncoderResolution编码器分辨率:一个脉冲距离/mm
//输出:float当前位置,单位:mm
float GetCurrentPosition(u32 count)  //计算当前位置
{
        int32_t  data;
       
        if(count<0X80000000)          data=count;   //正向
        if(count>0X80000000)          data=0X80000000-count;   //反向
       
        return data * EncoderResolution;  //编码器分辨率 mm
}
       
//计算当前速度
//输入:encoderDataNow encoderDataLast脉冲数  time间隔时间/ms
//abs() 求绝对值;   EncoderResolution编码器分辨率
//输出:float当前速度,单位:mm/s
float EncoderSpeer(u32 encoderDataNow,u32 encoderDataLast,u8 time) //计算速度
{
        return (abs(encoderDataNow-encoderDataLast))* EncoderResolution*1000/((float)time);   // mm/s
}



encoder.h文件

#ifndef _ENCODER_H
#define _ENCODER_H
#include "sys.h"

#define  EncoderResolution  0.0001     //编码器分辨率

extern         u32 encoderData; //编码器脉冲数
extern float  CurrentPos; //当前位置
extern float  CurrentSpeer;//当前速度
       
u32 GetENCODECounter(u32 count);  //编码器反方向数值转换
float GetCurrentPosition(u32 count);  //当前位置
float EncoderSpeer(u32 encoderDataNow,u32 encoderDataLast,u8 time); //计算速度

#endif


使用特权

评论回复
地板
tpgf|  楼主 | 2021-9-6 15:41 | 只看该作者
main.c

int main(void)
{
        u16 times=0;

        //设置系统中断优先级分组2  主优先级0~3 子优先级0~3
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
        delay_init(168);   //初始化延时函数
       
        uart_init(115200);        //初始化串口波特率为115200 上位机通信         中断级别中:主1子3

        LED_Init();        //初始化LED
          buzzer_Init();        //蜂鸣器初始化LED        
         
        //100*(84M/840)=100*0.01ms=1ms        
        TIM6_Int_Init(100-1,840-1); //初始化基本定时器 定时读取伺服状态   中断级别低:主2子3
        //1000*(84M/8400)=1000*0.1ms=100ms        
        TIM7_Int_Init(1000-1,8400-1); //初始化基本定时器 控制灯闪烁       中断级别低:主3子3
       
        /*编码器*/
        TIM5_Config(0XFFFFFFFF,0); //光栅尺
       
        printf("控制板开机启动\r\n");           
        delay_ms(100); //等待伺服上电准备

        while(1)
        {
                        times++;
                  LED0=!LED0; //闪烁LED,提示系统正在运行
//                  if(times%2==0)  {LED0=!LED0;}//闪烁LED,提示系统正在运行 2*200ms=400ms
               
               
                        delay_ms(200);  
        }   
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝