电机转速测量求助,希望有人能帮忙看一下,自己看了好久也不行,小白求助

2019-08-22 14:24发布

毕设的东西,目前在测量电机转速,用的驱动模块是L298N,电机的测速传感器用的光电码盘,开发板为战舰,想实现的功能是:输出PWM波控制电机转速,光电编码器会输出方波脉冲,用中断对脉冲计数,遇到高电平就进入外部中断,中断函数计数加一,主函数中计算转速,通过串口输出,显示到电脑上。代码如下。现在的问题是进入中断出现问题,只有在PWM波输出线插拔的一瞬间才能进入中断,而且转速输出一直是0,求助[mw_shl_code=cpp,true]#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "timer.h"
#include "usart.h"
#include "exti.h"

float rot;
int count=0;


void GPIO_Configuration(void);
void TIM3_Configuration(void);
void EXTI_Configuration(void);
void USART_Configuration(void);

  GPIO_Configuration();
        EXTI_Configuration();
        TIM3_Configuration();
        USART_Configuration();

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

        uart_init(115200);
        delay_init();

        while(1)
        {
                EXTI_ClearITPendingBit(EXTI_Line6);
                delay_ms(500);
                printf(" 转速为%d ",count);
//    rot=(float)count*60/0.5/448;
                count=0;
//    printf(" 转速为(r/min):%f ",rot);
               
        }
        while(1)
        {
                EXTI_ClearITPendingBit(EXTI_Line6);
                delay_ms(500);
                printf(" 计数为%d ",count);
//    rot=(float)count*60/0.5/448;
                count=0;
//    printf(" 转速为(r/min):%f ",rot);
               
        }

void EXTI4_IRQnHandler(void)
{

         if(EXTI_GetITStatus(EXTI_Line4)!=RESET)
         {
                 count++;
                 printf(" 01010101010101 ");

         }         
           EXTI_ClearITPendingBit(EXTI_Line4);
}



void GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;       
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//½óêÕ
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//·¢Ëí
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);


}       


void EXTI_Configuration(void)
{
        EXTI_InitTypeDef EXTI_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ê1ÄüAFIOê±Öó

        GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);//ÖD¶ÏÏßÅäÖÃ



        EXTI_InitStructure.EXTI_Line=EXTI_Line6;
        EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
        EXTI_InitStructure.EXTI_LineCmd=ENABLE;
        EXTI_Init(&EXTI_InitStructure);
       
        NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0X02;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0X02;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}


void TIM3_Configuration(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_OCInitTypeDef TIM_OCInitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

       
        u16 CCR1_Val=700;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);



       
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseInitStructure.TIM_Period=999;
        TIM_TimeBaseInitStructure.TIM_Prescaler=3599;
        TIM_TimeBaseInitStructure.TIM_ClockDivision=0;
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
       
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCPolarity_High;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;       
        TIM_OCInitStructure.TIM_Pulse=CCR1_Val;
  TIM_OC1Init(TIM3,&TIM_OCInitStructure);
       
       
        TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);

        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

        TIM_Cmd(TIM3,ENABLE);

}


void USART_Configuration(void)
{
        USART_InitTypeDef USART_InitStruction;


        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
       
        USART_InitStruction.USART_BaudRate=115200;
        USART_InitStruction.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
        USART_InitStruction.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
        USART_InitStruction.USART_Parity=USART_Parity_No;
        USART_InitStruction.USART_StopBits=USART_StopBits_1;
        USART_InitStruction.USART_WordLength=USART_WordLength_8b;
        USART_Init(USART1,&USART_InitStruction);
       
        USART_Cmd(USART1,ENABLE);


}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
_daisy
1楼-- · 2019-08-22 16:53
已经解决了,中断函数那里多写了一个n,是可以进去中断的,而且换了一个电机,原来的电机光电码盘坏了,不能输出方波,在这里提醒一下做同样程序的人,如果脉冲计数出来很小但是稳定,那估计是PWM波周期太大,计数个数太少,在下的一点经验,现在已经调出来了
正点原子
2楼-- · 2019-08-22 16:55
帮顶
likunxue
3楼-- · 2019-08-22 18:29
本帖最后由 likunxue 于 2016-5-19 02:27 编辑

兄弟, 作两个定时器来完成,  比如定时器3设成编码器模式, 用于计数 另一个定时器设成10MS中断一次, 每次中断读取 定时器3的计数值, 从计数值中算出电机当前速度就行了


速度 =  (中断频率 * 60 * 脉冲个数 ) / 编码器的线数  ;
如果编码器模式设成4倍频, 哪就要用线数*4      
你这个电机好像是 448线的, 4倍频后 是 1792
#define ENCODER_PERIOD          (u16)40000      //编码器溢出重装值
#define COUNTER_RESET           0u              //编码器初值
#define CONSTER_BYTE            (s32)(CONSTER_DAT + TIM3->CNT) //当前转子机械坐标


typedef struct                     
{
vs32 OLD_Byte;                     //采样前编码器的值                 
vu16 SuDu;                         //当前速度
vu16 JIASUDU;                      //加速度
vu16 LeiJiaQi;                     //累加器     
vu16 Buf[10];                      //速度滤波队列数据缓存区
vu8 front;                         //速度滤波处理队列指针
}DIANJISUDU;
DIANJISUDU SUDU;
/*******************************************************************************************
函 数 名: 定时器3编码器模式初始化函数
调    用: TIM3_BMQMS_Init(u8 remap)
参    数: reamap 复用功能重映像 00,01,11 如果参数错误,则采用00参数
反 回 值: 无
说    明: 初始化编码器的AB信号接于 CH1,CH2上 四倍频输出
********************************************************************************************/  
void TIM3_BMQMS_Init(u8 remap)
     {            
     switch(remap)//IO接器重映像处理
           {
           case 2: { //TM3_REMAP[1,0] = 10
                   RCC->APB2ENR |= 1<< 0;       //开启辅助功能时钟
                   BIT_ADM(AFIO->MAPR,11) = 1;  //高电平   
                   BIT_ADM(AFIO->MAPR,10) = 0;  //高电平  
                   RCC->APB2ENR |= 1<<3;        //使能PORTB时钟     
                   GPIOB->CRL &= 0xFF00FFFF;    //PB4,PB5
                   GPIOB->CRL |= 0x00440000;    //浮空输入                     
                   }break;
           case 3: {//TM3_REMAP[1,0] = 11
                   RCC->APB2ENR |= 1<< 0;       //开启辅助功能时钟
                   BIT_ADM(AFIO->MAPR,11) = 1;  //高电平   
                   BIT_ADM(AFIO->MAPR,10) = 1;  //高电平
                   RCC->APB2ENR |= 1<<4;        //使能PORTC时钟     
                   GPIOC->CRL &= 0x00FFFFFF;    //PC6,PC7
                   GPIOC->CRL |= 0x44000000;    //浮空输入  
                   }break;
           default:{////TM3_REMAP[1,0] = 00
                   RCC->APB2ENR |= 1<<2;        //使能PORTA时钟     
                   GPIOA->CRL &= 0x00FFFFFF;    //PA6,PA7
                   GPIOA->CRL |= 0x44000000;    //浮空输入  
                   }break;           
           }
     BIT_ADM(RCC->APB1ENR,1)  = 1; //TIM3时钟使能         
     BIT_ADM(RCC->APB1RSTR,1) = 1; //复位TIM3定时器,使之进入初始状态
     BIT_ADM(RCC->APB1RSTR,1) = 0; //结束复位      
     TIM3->ARR = ENCODER_PERIOD-1; //设定计数器自动重装值                                 
     TIM3->PSC = 0;                //预分频器,不分频
     BIT_ADM(TIM3->CR1,7) = 1;     //定时器ARPE充许         
     BIT_ADM(TIM3->CR1,  8) = 0;   //选择时钟分频:不分频(在输入捕获中止参数无效)
     BIT_ADM(TIM3->CR1,  9) = 0;        
     BIT_ADM(TIM3->CR1,  5) = 0;   //选择计数模式:边沿对齐模式  
     BIT_ADM(TIM3->CR1,  6) = 0;      
     BIT_ADM(TIM3->CR1,  4) = 0;   //计数器向上计数      
     BIT_ADM(TIM3->CCMR1,8) = 1;   //CC2S='01' IC2FP2映射到TI2
     BIT_ADM(TIM3->CCMR1,9) = 0;
     BIT_ADM(TIM3->CCMR1,0) = 1;   //CC1S='01' IC1FP1映射到TI1
     BIT_ADM(TIM3->CCMR1,1) = 0;   
     BIT_ADM(TIM3->CCER ,1) = 0;   //CC1P='0'IC1FP1不反相,IC1FP1=TI1   
     BIT_ADM(TIM3->CCER ,5) = 0;   //CC2P='0'IC2FP2不反相,IC2FP2=TI2
     //输入捕获1滤波器     
     BIT_ADM(TIM3->CCMR1,4) = 0;   //IC1F='1000'(可能影响采集响应速度)
     BIT_ADM(TIM3->CCMR1,5) = 1;
     BIT_ADM(TIM3->CCMR1,6) = 0;
     BIT_ADM(TIM3->CCMR1,7) = 0;
     //编码器模式3 (四倍频的输出)
     BIT_ADM(TIM3->SMCR, 0) = 1;    //SMS='011' 所有的输入均在上升沿和下降沿有效
     BIT_ADM(TIM3->SMCR, 1) = 1;
     BIT_ADM(TIM3->SMCR, 2) = 0;
     SHURUMAICHONG = COUNTER_RESET; //清外部输入脉冲计数器为零  
     TIM3->CNT = COUNTER_RESET;     //计数器的初值
     CONSTER_DAT = COUNTER_RESET;   //清零中断计数累加器的值为初始值
     BIT_ADM(TIM3->DIER, 0) = 1;    //允许定时器更新中断   
     MY_NVIC_Init(0,0,TIM3_IRQn,4); //抢占0,子优先级0,组4 设定时器3更新中断为最高级别中断
     BIT_ADM(TIM3->CR1,0) = 1;      //开编码器
     }   
/*******************************************************************************************
函 数 名: 定时器3中断函数
调    用: 无
参    数: 无
反 回 值: 无(这里在编码器模式中CPU唯于需要处理的函数)
*******************************************************************************************/  
void TIM3_IRQHandler(void)
     {         
     if(BIT_ADM(TIM3->SR,0) == 1) //溢出中断     
       {
       BIT_ADM(TIM3->SR,0) = 0;   //清除中断标志位   
       if(BIT_ADM(TIM3->CR1,4) == 1)CONSTER_DAT -= ENCODER_PERIOD;
       else{
           CONSTER_DAT += ENCODER_PERIOD;   
           }     
       }                                      
     }   

别一个定时器的中断处理函数内部代码如下!!  这里使用了滑动滤波与一阶滤波, 计算的速度值在 SUDU.SuDu 中


         s32 Dat;
         u16 Error,Byte;     
         u8 ptr = SUDU.front&0x07;                      //得到当前要处理队列位置指针      
         Dat = CONSTER_BYTE;                          //取当前编码器的值  
         Error = CDSK_ABS(Dat,SUDU.OLD_Byte);   //计算脉冲个数   
         SUDU.JIASUDU = (int)SUDU.SuDu - Error;   //加速度
         SUDU.OLD_Byte = Dat;                           //更新比较差值  
         Byte = SUDU.Buf[ptr];                            //旧数据出队
         SUDU.Buf[ptr] = Error;                           //新数据入队            
         SUDU.LeiJiaQi += Error;                         //累加新值                 
         SUDU.LeiJiaQi -= Byte;                          //减去出队数据            
         SUDU.front ++;                                   //指针加1      
         Byte = SUDU.LeiJiaQi>>3;                    //得到均值              
         if(Byte < SUDU.SuDu)                         //如果新采样值小于前次采样值
           {
           Error =  (((SUDU.SuDu - Byte)<<7)+128)>>8; //+128是为了四舍五入
           SUDU.SuDu -= Error;
           }
         else{
             if(Byte > SUDU.SuDu)                //如果新采样值大于前次采样值
               {
               Error =  (((Byte - SUDU.SuDu)<<7)+128)>>8;//+128是为了四舍五入
               SUDU.SuDu += Error;
               }
             }   
*******************************************************/
主函数中读取速度的方法 以上假若窗口读取定时器设为  10ms 中断一次, 10MS = 100HZ,
100 *60 = 6000;

TD = 6000*SUDU.SuDu/1792;     //每分钟多少转





猫先森
4楼-- · 2019-08-22 23:21
 精彩回答 2  元偷偷看……
_daisy
5楼-- · 2019-08-23 00:29
本帖最后由 _daisy 于 2016-5-19 10:26 编辑
likunxue 发表于 2016-5-19 02:12
兄弟, 作两个定时器来完成,  比如定时器3设成编码器模式, 用于计数 另一个定时器设成10MS中断一次, 每次中 ...

谢谢你的建议,不过我不太明白为什么要设置一个编码器模式呢?不用倍频可以吗?我才开始学,所以寄存器的不是太懂,请问有库函数版本的吗?
1376115749
6楼-- · 2019-08-23 02:24
本帖最后由 1376115749 于 2016-6-18 10:52 编辑
_daisy 发表于 2016-5-19 10:16
谢谢你的建议,不过我不太明白为什么要设置一个编码器模式呢?不用倍频可以吗?我才开始学,所以寄存器的 ...
我这个是库函数版的,不过用的是原子哥的mini板,代码如下

[mw_shl_code=c,true]
#define U8_MAX     ((u8)255)
#define S8_MAX     ((s8)127)
#define S8_MIN     ((s8)-128)
#define U16_MAX    ((u16)65535u)
#define S16_MAX    ((s16)32767)
#define S16_MIN    ((s16)-32768)
#define U32_MAX    ((u32)4294967295uL)
#define S32_MAX    ((s32)2147483647)
#define S32_MIN    ((s32)2147483648uL)

#define ENCODER_TIMER   TIM4  // Encoder unit connected to TIM3
#define ENCODER_PPR           (u16)(448)   // number of pulses per revolution
#define SPEED_BUFFER_SIZE 8

#define COUNTER_RESET    ((u16)0)
#define ICx_FILTER      (u8) 6 // 6<-> 670nsec
#define SPEED_SAMPLING_TIME  9     // (9+1)*500usec = 5msec
#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))

/* Private variables ---------------------------------------------------------*/
typedef enum
{
    FALSE = 0, TRUE = !FALSE
} bool;
static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE]={0}, hRot_Speed;
static u8 bSpeed_Buffer_Index = 0;
static volatile u16 hEncoder_Timer_Overflow;
static bool bIs_First_Measurement = TRUE;

//正交编码器初始化
void Encoder_Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);

    //编码器接口
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    TIM_TimeBaseInitStructure.TIM_Period = (4*ENCODER_PPR)-1;  
    TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(ENCODER_TIMER,&TIM_TimeBaseInitStructure);

    TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,
                               TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

    //输入滤波器的设置
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
    TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);

    TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
    TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);

    TIM_Cmd(ENCODER_TIMER, ENABLE);//开启计数器
}

/*******************************************************************************
* Function Name  : ENC_Calc_Rot_Speed
* Description    : Compute return latest speed measurement
* Input          : None
* Output         : s16
* Return         : Return the speed in 0.1 Hz resolution.                    
*******************************************************************************/
s16 ENC_Calc_Rot_Speed(void)
{   
    s8  i = 0;
    s32 wDelta_angle;
    u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
    u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
    signed long long temp;
    s16 haux;

    if (!bIs_First_Measurement)
    {
        // 1st reading of overflow counter   
        hEnc_Timer_Overflow_sample_one = hEncoder_Timer_Overflow;
        // 1st reading of encoder timer counter
        hCurrent_angle_sample_one = ENCODER_TIMER->CNT;
        // 2nd reading of overflow counter
        hEnc_Timer_Overflow_sample_two = hEncoder_Timer_Overflow;  
        // 2nd reading of encoder timer counter
        hCurrent_angle_sample_two = ENCODER_TIMER->CNT;      

        // Reset hEncoder_Timer_Overflow and read the counter value for the next
        // measurement
        hEncoder_Timer_Overflow = 0;
        haux = ENCODER_TIMER->CNT;   

        if (hEncoder_Timer_Overflow != 0)
        {
            haux = ENCODER_TIMER->CNT;
            hEncoder_Timer_Overflow = 0;            
        }

        if (hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
        { //Compare sample 1 & 2 and check if an overflow has been generated right
          //after the reading of encoder timer. If yes, copy sample 2 result in
          //sample 1 for next process
            hCurrent_angle_sample_one = hCurrent_angle_sample_two;
            hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
        }

        if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)
        {// encoder timer down-counting
            wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle -
                                 (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
        }
        else
        {//encoder timer up-counting
            wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle +
                                 (hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
        }

        // speed computation as delta angle * 1/(speed sempling time)
        temp = (signed long long)(wDelta_angle * SPEED_SAMPLING_FREQ);
        temp *= 10;  // 0.1 Hz resolution
        temp /= (4*ENCODER_PPR);

    } //is first measurement, discard it
    else
    {
        bIs_First_Measurement = FALSE;
        temp = 0;
        hEncoder_Timer_Overflow = 0;
        haux = ENCODER_TIMER->CNT;      
        // Check if Encoder_Timer_Overflow is still zero. In case an overflow IT
        // occured it resets overflow counter and wPWM_Counter_Angular_Velocity
        if (hEncoder_Timer_Overflow != 0)
        {
            haux = ENCODER_TIMER->CNT;
            hEncoder_Timer_Overflow = 0;            
        }
    }

    hPrevious_angle = haux;  

    return((s16) temp);
}

/*******************************************************************************
* Function Name  : ENC_Calc_Average_Speed
* Description    : Compute smoothed motor speed based on last SPEED_BUFFER_SIZE
                   informations and store it variable  
* Input          : None
* Output         : s16
* Return         : Return rotor speed in 0.1 Hz resolution. This routine
                   will return the average mechanical speed of the motor.
*******************************************************************************/
void ENC_Calc_Average_Speed(void)//滑动平均滤波
{   
    s32 wtemp;
    u32 i;

    wtemp = ENC_Calc_Rot_Speed();

/* Compute the average of the read speeds */  
    hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
    bSpeed_Buffer_Index++;

    if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)
    {
        bSpeed_Buffer_Index = 0;
    }

    wtemp=0;

    for (i=0;i<SPEED_BUFFER_SIZE;i++)
    {
        wtemp += hSpeed_Buffer;
    }
    wtemp /= SPEED_BUFFER_SIZE;

    hRot_Speed = ((s16)(wtemp));
}

void TIM4_IRQHandler(void)
{
    OSIntEnter();
    if (TIM_GetITStatus(ENCODER_TIMER, TIM_IT_Update) == SET)
    {
        if (hEncoder_Timer_Overflow != U16_MAX)
            hEncoder_Timer_Overflow++;

        TIM_ClearITPendingBit(ENCODER_TIMER,TIM_IT_Update);
    }
    OSIntExit();
}

void Encode_test(void)
{
    Debug("ENCODER_TIMER->CNT 的值是:%d, 电机的速度为%d ",ENCODER_TIMER->CNT, hRot_Speed);
}

[/mw_shl_code]

这个代码也是参照网上的代码,自己调试通的,[size=13.3333px]ENC_Calc_Average_Speed这个函数需要在另一个定时器里面500us调用一次,其他数值也行,就是需要自己修改下面两个数值[size=13.3333px]#define[size=13.3333px] SPEED_SAMPLING_TIME  [size=13.3333px]9[size=13.3333px]     [size=13.3333px]// (9+1)*500usec = 5msec#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))
还有在调试编码器的时候,TI跟T2的相应引脚千万不要有上拉电阻,要不然,计数值的数值在临近的两个数值来回跳变,其他问题我这边没有遇到过,希望对你有帮助,不过现在这个时间你的毕业设计已经完了吧,希望对其他人有帮助吧。




一周热门 更多>