打印
[STM32F1]

SOS 关于测频率和占空比

[复制链接]
2995|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jsbjzy|  楼主 | 2014-8-14 15:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
os, TI, ST, TE, ic
本帖最后由 jsbjzy 于 2014-8-14 15:28 编辑

求教高手,我用STM32F103R8T6做了个项目,测试方波的占空比和频率,用示波器测的占空比为50%左右的方波,但通过程序测得的却在35%上下,频率也不对,示波器上看的时候,是3kHZ左右,但通过程序用仿真器看的结果却是39kHZ左右。程序如下:

//---------------------------------------------------------------//
        #define        RCC_Duty_test_NPNA                    RCC_APB2Periph_GPIOA
        #define        Duty_test_NPNA_PORT                  GPIOA
        #define        Duty_test_NPNA_Pin                      GPIO_Pin_8
        
        #define        RCC_Duty_test_NPNA_TIMER      RCC_APB2Periph_TIM1
        #define        Duty_test_NPNA_TIMER              TIM1        
        #define        Duty_test_NPNA_TIM_channel     TIM_Channel_1
        #define        Duty_test_NPNA_IRQ_channel    TIM1_CC_IRQn
//---------------------------------------------------------------//

vu16    Num_T_high_NPNA;
vu16    Num_T_all_NPNA;
vu16    DutyCycle_NPNA;
vu32    Frequency_NPNA;

//--------------------------------------------------//
void    Duty_test_NPNA_GPIO_configuration(void)
        {        
                GPIO_InitTypeDef GPIO_InitStructure;   
               
                RCC_APB2PeriphClockCmd(RCC_Duty_test_NPNA, ENABLE);
                GPIO_InitStructure.GPIO_Pin = Duty_test_NPNA_Pin;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                GPIO_Init(Duty_test_NPNA_PORT, &GPIO_InitStructure);
        }        
//--------------------------------------------------//

//--------------------------------------------------//
void        Duty_test_NPNA_TIMER_Configuration(void)
        {
                TIM_ICInitTypeDef    TIM_ICInitStructure;       // 库函数定义的时钟结构体
                TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
               
                RCC_APB2PeriphClockCmd(RCC_Encoder1_Periph, ENABLE);
                TIM_InternalClockConfig(Duty_test_NPNA_TIMER);

                TIM_DeInit(Duty_test_NPNA_TIMER);
                TIM_TimeBaseStructure.TIM_Period =0xffff;         //自动重装载寄存器的值
                TIM_TimeBaseStructure.TIM_Prescaler =0;             //TIM2时钟频率除数的预分频值
                TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;           //采样分频
                TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    //向上计数模式
                TIM_TimeBaseInit(Duty_test_NPNA_TIMER, &TIM_TimeBaseStructure);   

                TIM_ICInitStructure.TIM_Channel = Duty_test_NPNA_TIM_channel; //选择通道
                TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  //输入上升沿捕获  
                TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 通道方向选择   
                TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;    //每次检测到捕获输入就触发一次捕获
                TIM_ICInitStructure.TIM_ICFilter = 0x00;//选择输入比较滤波器,滤波设置,经历几个周期跳变认定波形稳定0x0~0xF
                TIM_ICInit(Duty_test_NPNA_TIMER, &TIM_ICInitStructure);

                TIM_PWMIConfig(Duty_test_NPNA_TIMER, &TIM_ICInitStructure);

                TIM_SelectInputTrigger(Duty_test_NPNA_TIMER, TIM_TS_TI2FP2);
                TIM_SelectSlaveMode(Duty_test_NPNA_TIMER, TIM_SlaveMode_Reset);
                TIM_SelectMasterSlaveMode(Duty_test_NPNA_TIMER, TIM_MasterSlaveMode_Enable);                                                                                                                        
                TIM_ITConfig(Duty_test_NPNA_TIMER,TIM_IT_CC2,ENABLE);
                TIM_Cmd(Duty_test_NPNA_TIMER, ENABLE);       //开启时钟               
                TIM_ITConfig(Duty_test_NPNA_TIMER, TIM_IT_CC2, ENABLE);     
        }
//--------------------------------------------------//
        
//--------------------------------------------------//
void        Duty_test_NPNA_NVIC_Configuration(void)
        {
                NVIC_InitTypeDef NVIC_InitStructure;

                //- Set the Vector Table base address at 0x08000000 -//
                NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);

                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 //选择中断分组2
                NVIC_InitStructure.NVIC_IRQChannel = Duty_test_NPNA_IRQ_channel;             //选择中断通道10
                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;               //抢占式中断优先级设置为0
                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                      //响应式中断优先级设置为0
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //使能中断
                NVIC_Init(&NVIC_InitStructure);
        }
//--------------------------------------------------//
        
void TIM1_CC_IRQHandler(void)
        {
                if(TIM_GetITStatus(Duty_test_NPNA_TIMER, TIM_IT_CC2) == SET)
                {
                        TIM_ClearITPendingBit(Duty_test_NPNA_TIMER, TIM_IT_CC2);
                        
                                TIM_SetCompare1(Duty_test_NPNA_TIMER,0);
                                TIM_SetCompare2(Duty_test_NPNA_TIMER,0);
                        Num_T_all_NPNA = TIM_GetCapture2(Duty_test_NPNA_TIMER);
                        Num_T_high_NPNA = TIM_GetCapture1(Duty_test_NPNA_TIMER);
                        if (Num_T_all_NPNA != 0)
                        {
                                DutyCycle_NPNA = (Num_T_high_NPNA * 100) / Num_T_all_NPNA;
                                Frequency_NPNA = 72000000 / Num_T_all_NPNA;
                        }
                        else
                        {
                                DutyCycle_NPNA = 0;
                                Frequency_NPNA = 0;
                        }
                }
        }
沙发
jsbjzy|  楼主 | 2014-8-14 15:29 | 只看该作者
自己先顶起来,哪位高手指点下

使用特权

评论回复
板凳
shdjdq| | 2014-8-14 15:33 | 只看该作者
频率也差太多了吧,测占空比,有一个简单的办法,RC滤波,测电压。当然中断也行,计数也行,看你的要求和指标。

使用特权

评论回复
地板
jsbjzy|  楼主 | 2014-8-14 15:35 | 只看该作者
不知道程序是不是有什么问题,亟待解决中……

使用特权

评论回复
5
jsbjzy|  楼主 | 2014-8-14 16:01 | 只看该作者
感谢3楼,我希望通过我发的程序,能准确测方波的占空比和频率,精度1%就够了,占空比范围30%~70%,频率10kHz以下,频率我换了好几种,3k的、1k的,还有几百hz的,测的结果跟示波器显示的占空比还是老样子,示波器显示50%左右,但程序测得的总是35%上下

使用特权

评论回复
6
mmuuss586| | 2014-8-14 19:03 | 只看该作者
TIM_ICInit(Duty_test_NPNA_TIMER, &TIM_ICInitStructure);
这句先去掉;

STM32测量占空比和频率还是比较准的,你这误差大太多了
1、找下规律;
   看下实际输入频率和实测值的关系,是比例关系的话,可能时钟源不对,不是72M;
2、你测量频率这么低,可以加分频;
   TIM_TimeBaseStructure.TIM_Prescaler = 71;
   我一般72分频;

使用特权

评论回复
7
jsbjzy|  楼主 | 2014-8-15 09:58 | 只看该作者
mmuuss586 发表于 2014-8-14 19:03
TIM_ICInit(Duty_test_NPNA_TIMER, &TIM_ICInitStructure);
这句先去掉;

感谢版主的建议。
我去掉了那句,同时分频我也分了,有72分频、9分频的我都试了,占空比还是原样子,35%左右,频率我看了下,基本是10倍的关系。
占空比应该和频率没关系吧,但占空比还是不对啊。
时钟我用的是内部时钟:

//--------------------------------------------------//
void        System_RCC_configuration(void)
        {
                RCC_HSICmd(ENABLE);
                RCC_HCLKConfig(RCC_SYSCLK_Div1);               
                RCC_PCLK2Config(RCC_HCLK_Div1);
                RCC_PCLK1Config(RCC_HCLK_Div1);
               
                RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_4);//72/6=12MHz  PLLCLK = 12MHz * 6 = 72MHz

                RCC_ADCCLKConfig(RCC_PCLK2_Div2);
        }       
//--------------------------------------------------//
       

使用特权

评论回复
8
mmuuss586| | 2014-8-15 12:19 | 只看该作者
本帖最后由 mmuuss586 于 2014-8-15 12:21 编辑
jsbjzy 发表于 2014-8-15 09:58
感谢版主的建议。
我去掉了那句,同时分频我也分了,有72分频、9分频的我都试了,占空比还是原样子,35% ...


void TIM3_IRQHandler(void)
{
  /* Clear TIM3 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM3);

  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;

    /* Frequency computation */
    Frequency = SystemCoreClock / IC2Value;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}
中断,先用官方程序先调通吧;
时钟初始化程序,也用官方的,先试验;

如还有问题,把程序打包发上来;

使用特权

评论回复
9
jsbjzy|  楼主 | 2014-8-15 16:53 | 只看该作者
mmuuss586 发表于 2014-8-15 12:19
void TIM3_IRQHandler(void)
{
  /* Clear TIM3 Capture compare interrupt pending bit */

我用TIM4也试了,结果是一样的,示波器显示50%占空比的方波,软件测出的任然是35%左右。我用J_LINK仿真器观察0x40012c34和0x40012c38的值的时候,发现是捕获的数据不对,中断计算结果是没有问题的。
还有,我在中断处理函数里面通过设置断点单步运行的时候,0x40012c34和0x40012c38的值怎么会有变动?在处理的时候,按道理捕获事件应该不会发生的啊。
虽然没有解决问题,我还是把悬赏分送给你

使用特权

评论回复
10
mmuuss586| | 2014-8-15 17:35 | 只看该作者
jsbjzy 发表于 2014-8-15 16:53
我用TIM4也试了,结果是一样的,示波器显示50%占空比的方波,软件测出的任然是35%左右。我用J_LINK仿真器 ...

:dizzy:
我昨天还调过这个呢,你可以把程序发上来;

使用特权

评论回复
11
jsbjzy|  楼主 | 2014-8-18 09:49 | 只看该作者
mmuuss586 发表于 2014-8-15 17:35
我昨天还调过这个呢,你可以把程序发上来;

程序就是我前面贴上来的那些,其他的都没关系了。要不把你那边相关的程序段发给我看看呢,我比较下你写的程序和我的到底有什么不同?

使用特权

评论回复
12
mmuuss586| | 2014-8-18 12:08 | 只看该作者
jsbjzy 发表于 2014-8-18 09:49
程序就是我前面贴上来的那些,其他的都没关系了。要不把你那边相关的程序段发给我看看呢,我比较下你写的 ...

可以;
这是我的IO和中断配置:
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* TIM2 clock enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3|RCC_APB1Periph_TIM4, ENABLE);
  
  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB, ENABLE);
  
  /* TIM2 chennel2 configuration : PA.01 */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0|GPIO_Pin_6|GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  /* Enable the TIM2 global Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

使用特权

评论回复
13
mmuuss586| | 2014-8-18 12:09 | 只看该作者
jsbjzy 发表于 2014-8-18 09:49
程序就是我前面贴上来的那些,其他的都没关系了。要不把你那边相关的程序段发给我看看呢,我比较下你写的 ...

这是我的定时器初始化部分, 共用了4路:
static void TIM_PWM_Config(void)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
               
        TIM_TimeBaseStructure.TIM_Period = 50000;   
  TIM_TimeBaseStructure.TIM_Prescaler = 71;                                                                          //71+1=72·ÖƵ,F=1M   
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
       
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  /* ---------------------------------------------------------------------------
    TIM2 configuration: PWM Input mode
     The external signal is connected to TIM2 CH2 pin (PA.01)
     TIM2 CCR2 is used to compute the frequency value
     TIM2 CCR1 is used to compute the duty cycle value

    In this example TIM2 input clock (TIM2CLK) is set to 2*APB1 clock, since
    APB1 prescaler is set to 2.
      TIM2CLK = 2*PCLK1 = HCLK = SystemCoreClock

    External Signal Frequency = SystemCoreClock / TIM2_CCR2 in Hz.
    External Signal DutyCycle = (TIM2_CCR1*100)/(TIM2_CCR2) in %.
  Note:
  SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f1xx.c file.
  Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
  function to update SystemCoreClock variable value. Otherwise, any configuration
  based on this variable will be incorrect.
  --------------------------------------------------------------------------- */  
  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_ICInitStructure.TIM_ICFilter = 0x0;

        TIM_PWMIConfig(TIM1, &TIM_ICInitStructure);
  TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
        TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
  TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);

  /* Select the TIM1 Input Trigger: TI2FP2 */
        TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1);
        /* Select the slave Mode: Reset Mode */
        TIM_SelectSlaveMode(TIM1, TIM_SlaveMode_Reset);
        TIM_SelectMasterSlaveMode(TIM1,TIM_MasterSlaveMode_Enable);
        /* TIM enable counter */
        TIM_Cmd(TIM1, ENABLE);
        /* Enable the CC2 Interrupt Request */
        TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);       
       
          /* Select the TIM2 Input Trigger: TI2FP2 */
        TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1);
        /* Select the slave Mode: Reset Mode */
        TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
        TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
        /* TIM enable counter */
        TIM_Cmd(TIM2, ENABLE);
        /* Enable the CC2 Interrupt Request */
        TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);       
       
          /* Select the TIM2 Input Trigger: TI2FP2 */
        TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
        /* Select the slave Mode: Reset Mode */
        TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
        TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
        /* TIM enable counter */
        TIM_Cmd(TIM3, ENABLE);
        /* Enable the CC2 Interrupt Request */
        TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);       
       
        /* Select the TIM2 Input Trigger: TI2FP2 */
        TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
        /* Select the slave Mode: Reset Mode */
        TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
        TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);
        /* TIM enable counter */
        TIM_Cmd(TIM4, ENABLE);
        /* Enable the CC2 Interrupt Request */
        TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);       

}

使用特权

评论回复
14
mmuuss586| | 2014-8-18 12:11 | 只看该作者
jsbjzy 发表于 2014-8-18 09:49
程序就是我前面贴上来的那些,其他的都没关系了。要不把你那边相关的程序段发给我看看呢,我比较下你写的 ...


这是其中1路中断程序,程序只写了测试占空比部分(我产品中不需要测频率):
typedef struct
{
uint16_t PulseData ;
uint16_t PulseWidth ;
}PWMDATA;
PWMDATA CSB_DATA1;
PWMDATA CSB_DATA2;
PWMDATA CSB_DATA3;
PWMDATA CSB_DATA4;
PWMDATA CSB_DATA5;

void TIM1_CC_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET)
        {
                /* Clear TIM2 Capture compare interrupt pending bit */
                TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);

                /* Get the Input Capture value */
                CSB_DATA1.PulseWidth = TIM_GetCapture1(TIM1);                                                        //PWMÖÜÆÚÖµ

                if (CSB_DATA1.PulseWidth != 0)
                {
                        CSB_DATA1.PulseData=TIM_GetCapture2(TIM1);                                                //PWM IC1¼Ä´æÆ÷µÄÖµ
                }
                else
                {
                        CSB_DATA1.PulseData=0;
                }
        }
        else;
}

使用特权

评论回复
15
jsbjzy|  楼主 | 2014-8-18 15:13 | 只看该作者
mmuuss586 发表于 2014-8-18 12:11
这是其中1路中断程序,程序只写了测试占空比部分(我产品中不需要测频率):
typedef struct
{

原来你用是cc1,而我用的是cc2捕获,我也改成cc1捕获后,完全正确了,非常感谢!!!:lol

使用特权

评论回复
16
jsbjzy|  楼主 | 2014-8-18 15:14 | 只看该作者
mmuuss586 发表于 2014-8-18 12:11
这是其中1路中断程序,程序只写了测试占空比部分(我产品中不需要测频率):
typedef struct
{

就是不知道为什么cc2不行

使用特权

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

本版积分规则

3

主题

12

帖子

0

粉丝