野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10287|回复: 9

求助

[复制链接]
发表于 2017-6-4 19:13:47 | 显示全部楼层 |阅读模式
最近在做一个项目,就是遇到读取编码器脉冲数值的问题,做法是用基本定时器6定时每100ms读取一次采集的脉冲数,使用通用定时器4的编码器模式进行脉冲的捕捉,编码器是1000线的,但是转速很慢,目前我在测试代码。并没有使用编码器来测试而是使用单片机输出PWM波来进行测试,具体是使用定时器3输出PWM,利用信号线将PWM连接到PB6引脚,PWM的周期是1ms,我使用定时器6定时100ms,而100ms内定时器4只能捕捉到100次脉冲,我再定时器6的中断函数中读取定时器4的计数器的值,原理上每次读取的值应该为100,但是每次读取到的值都不对,不知道错误在哪。恳请大神指点

#include "TimerConfig.h"


static void TIM6_NVIC_Configuration(void)
{
       
        NVIC_InitTypeDef NVIC_InitStructure;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                                                                                         
        NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;          
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;       
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
       
        NVIC_Init(&NVIC_InitStructure);
       
}
void TIM6_Mode_Config(void)
{

        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;


        //RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
       
        TIM_TimeBaseStructure.TIM_Period = 9999;
        TIM_TimeBaseStructure.TIM_Prescaler = 7199;
        //TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
        //TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
        TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
       
       
        TIM6_NVIC_Configuration();
        TIM_ClearFlag(TIM6, TIM_FLAG_Update);
        //TIM_UpdateRequestConfig(TIM6,TIM_UpdateSource_Regular);
  TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
        TIM_Cmd(TIM6,ENABLE);       
}


        void TIM4_Mode_Config()      
{
        GPIO_InitTypeDef     GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef      TIM_ICInitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,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_ResetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);

        GPIO_Init(GPIOB,&GPIO_InitStructure);
       
        TIM_DeInit(TIM4);
        TIM_TimeBaseStructure.TIM_Period = 9999 ;
        TIM_TimeBaseStructure.TIM_Prescaler = 71;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
       
        //ÅäÖñàÂëÆ÷Ä£ê½′¥·¢Ô′oí¼«DÔ
        TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
        TIM_ICStructInit(&TIM_ICInitStructure);
        //TIM_ICInitStructure.TIM_Channel     = TIM_Channel_1;              
        //TIM_ICInitStructure.TIM_ICPolarity  = TIM_ICPolarity_Rising;       
        //TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
        //TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;                   
        TIM_ClearFlag(TIM4, TIM_FLAG_Update);
        TIM_ICInitStructure.TIM_ICFilter = 6;
        TIM_ICInit(TIM4,&TIM_ICInitStructure);
       
        //TIMx_NVIC_Configuration();
       
  TIM_ITConfig(TIM4,  TIM_IT_Update |TIM_IT_CC1, ENABLE);
        TIM4->CNT = 0;
        TIM_Cmd(TIM4,ENABLE);  
}



        void TIM6_IRQHandler(void)
{
        if ( TIM_GetITStatus ( TIM6, TIM_IT_Update) != RESET )            
        {       
                  Value = TIM_GetCounter(TIM4);
            
                        printf("\r\n The current value = 0x%04X \r\n", Value);
                         
                  TIM_SetCounter(TIM4,0);
                  
                  TIM_ClearITPendingBit ( TIM6, TIM_FLAG_Update );
        }
               
}


回复

使用道具 举报

 楼主| 发表于 2017-6-4 20:21:52 | 显示全部楼层
大神们顶起来
回复 支持 反对

使用道具 举报

发表于 2017-6-5 08:53:07 | 显示全部楼层
本帖最后由 尤艾斯比 于 2017-6-5 09:28 编辑

看了下我之前用输入捕获做的, 这里好像有点不同。
        /* IC1捕获:上升沿触发 TI1FP1 */
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;     //捕获通道1
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  //上升沿
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  //TI1FP1
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入分频
  TIM_ICInitStructure.TIM_ICFilter = 0x0;    //滤波设置
  TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

  TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);                 // 选择定时器输入触发: TI1FP1
  TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);  // 选择从模式: 复位模式
  TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
  TIM_Cmd(TIM3, ENABLE); //使能控制定时器
  TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);  // 使能捕获/比较2中断请求



it.c
void TIM3_IRQHandler (void)
{
  /* 清除定时器捕获/比较1中断 */
  TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);  //IC1Value = 0
       
  /* 获取输入捕获值 */
  IC1Value = TIM_GetCapture1(TIM3);

printf(" IC1Value = %d  \r\n ",IC1Value);
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 09:27:21 | 显示全部楼层
尤艾斯比 发表于 2017-6-5 08:53
基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO,不能实现输入捕获 ...

我这代码里面是用定时器6来做基本的定时的,定时时间是100ms,同时开启通用定时器4做输入捕获并配置为编码器模式,定时器4我设置的触发值是1000,也就是每输入1000个脉冲就会中断,但是脉冲源的周期是1ms,同时我在定时器6的中断函数中将定时器4的计数器清0,也就是定时器4不会进入中断,原理上是定时器4每计满100次,就会被清0,同时通过串口输出显示,但是得到的捕获值不正确,而且差的太大,所以请教大神
回复 支持 反对

使用道具 举报

发表于 2017-6-5 09:38:10 | 显示全部楼层
本帖最后由 尤艾斯比 于 2017-6-5 09:49 编辑
wbjust 发表于 2017-6-5 09:27
我这代码里面是用定时器6来做基本的定时的,定时时间是100ms,同时开启通用定时器4做输入捕获并配置为编 ...

输入捕获的值就是在TIM3中断函数里获取的 。 (TIM3和TIM4都是通用)    /* 获取输入捕获值 */ IC1Value = TIM_GetCapture1(TIM3);
如果按你说 TIM3不进中断的话,你开启的TIM3中断标志(TIM_ITConfig(TIM4,  TIM_IT_Update |TIM_IT_CC1, ENABLE); )没有清除, 怎么得到捕获值。




回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 09:40:29 | 显示全部楼层
尤艾斯比 发表于 2017-6-5 08:53
看了下我之前用输入捕获做的, 这里好像有点不同。
        /* IC1捕获:上升沿触发 TI1FP1 */
  TIM_ICInitStru ...

你的代码我看了,你把定时器3配置成PWM输入模式,但是我使用的是编码器接口模式,手册上说这种接口模式是专门用来做编码器的脉冲捕捉的,我不知道用PWM模式行不行,我想知道PWM模式和编码器接口模式究竟有什么区别,请大神不吝赐教
回复 支持 反对

使用道具 举报

发表于 2017-6-5 09:45:47 | 显示全部楼层
wbjust 发表于 2017-6-5 09:40
你的代码我看了,你把定时器3配置成PWM输入模式,但是我使用的是编码器接口模式,手册上说这种接口模式是 ...

搞不清白。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 09:47:04 | 显示全部楼层
尤艾斯比 发表于 2017-6-5 09:38
输入捕获的值就是在TIM3中断函数里获取的 。 (TIM3和TIM4都是通用)    /* 获取输入捕获值 */ IC1Value  ...

哦哦,这样啊,但是有一个问题就是一旦定时器被用作输入捕捉,那么它就相当于一个计数器,也就没有了定时的功能,那么我怎样来实现一个固定的定时周期内读取脉冲的计数值
回复 支持 反对

使用道具 举报

发表于 2017-6-5 09:57:02 | 显示全部楼层
本帖最后由 尤艾斯比 于 2017-6-5 09:58 编辑
wbjust 发表于 2017-6-5 09:47
哦哦,这样啊,但是有一个问题就是一旦定时器被用作输入捕捉,那么它就相当于一个计数器,也就没有了定时 ...

我是参照野火的那个滴答定时器设置为1ms中断一次,i--,当i =500减到 i =0时 读取一次 这样就是每隔500ms就会进入读取函数
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 10:15:15 | 显示全部楼层
尤艾斯比 发表于 2017-6-5 09:57
我是参照野火的那个滴答定时器设置为1ms中断一次,i--,当i =500减到 i =0时 读取一次 这样就是每隔500ms ...

你说的这个我知道的,就是有一个问题一旦捕获脉冲计数到设置的的触发值的时候,计数器就会被清0,所以这样计数就会不准确,所以要解决再固定的定时周期内读取捕捉到的脉冲值,你没有相关的代码可以实现这个功能
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-25 14:35 , Processed in 0.028869 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表