打印

pwm输入捕获频率

[复制链接]
1822|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
斯诺|  楼主 | 2014-4-2 09:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在做MSP430输入捕获实验,用的是msp430G2452单片机。捕获实验是成功了。但是捕获的频率一高,捕获数据就出错。求大神指教:
1、8M主频,最大能捕获多高频率,单片机运行正常,怎么计算?

2、要捕获40K赫兹的方波,单片机的主频最少是多少?怎么计算?

思维有点乱,还请大侠不吝赐教,在此先行谢过.不胜感激~

相关帖子

沙发
斯诺|  楼主 | 2014-4-2 12:27 | 只看该作者
人工置顶.......

使用特权

评论回复
板凳
dirtwillfly| | 2014-4-2 22:54 | 只看该作者

1、8M主频,最大能捕获能做很高的,远大于40kHz,前提是你的中断服务程序里代码别影响太多时间。最高多高梅测试过。
2、 也和你的其他程序代码有关

使用特权

评论回复
地板
斯诺|  楼主 | 2014-4-3 08:37 | 只看该作者
可能是我程序的思路和方案不对吧。我再使劲想想

使用特权

评论回复
5
dirtwillfly| | 2014-4-4 08:25 | 只看该作者
斯诺 发表于 2014-4-3 08:37
可能是我程序的思路和方案不对吧。我再使劲想想

要不你把代码传上来,我帮你看看

使用特权

评论回复
6
斯诺|  楼主 | 2014-4-8 09:48 | 只看该作者
本帖最后由 斯诺 于 2014-4-8 10:00 编辑

#pragma vector=TIMER0_A0_VECTOR
1.进中断记录第一次上升沿CCR0的值,中断次数加一;
2.中断一次上升沿次数加一记录定时器溢出中断前的最后一次CCR0的值;

#pragma vector=TIMER0_A1_VECTOR  
1、计算中断的次数,计算周期次数
2、计算周期时间
3、根据周期数和时间计算方波频率

使用特权

评论回复
7
斯诺|  楼主 | 2014-4-8 09:50 | 只看该作者
本帖最后由 斯诺 于 2014-4-8 10:06 编辑

#include "msp430g2452.h"
//==========================================================================//
//=============================Wdt_reset====================================//
void wdt_reset(void)
{
        WDTCTL = WDTPW + WDTCNTCL ;
}
//==========================================================================//
//===========================Init_Capture===================================//
void Init_Capture(void)
{
  P1DIR&=~BIT1;
  P1SEL|=BIT1;
  BCSCTL2 |= SELM0;                          
  BCSCTL2 |= DIVS_0;                        
  TACTL |=TASSEL_2+TAIE+TACLR;            
  CCTL0 |=CM_1+SCS+CAP+CCIS_0+CCIE;       //上升沿捕获+同步捕获+开捕获+timerA为捕获+打开捕获中断
  TACTL |=MC_2;                             //连续模式
}
//==========================================================================//
//===============================adc_init===================================//
  void adc_init(void)
  {
      ADC10CTL1 = INCH_10 + ADC10DIV_3;         // Temp Sensor ADC10CLK/4
      ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON+ ADC10IE;

  }

//==========================================================================//
//=============================定义全局变量=================================//
  typedef struct
  {
        float    time;
        float    duty;
        unsigned int Cap_Tar;
        unsigned long Cap_First;
        unsigned long Cap_Next;
        unsigned long Cap_Last;
        unsigned long temp;
        unsigned char IntDegF;
        unsigned char IntDegC;
}user_t;
extern user_t user;
  void adc_proc(void)
  {
    ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
    // oF = ((A10/1024)*1500mV)-923mV)*1/1.97mV = A10*761/1024 - 468
    user.temp = ADC10MEM;
    user.IntDegF = ((user.temp - 630) * 761) / 1024;
    // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
    user.temp = ADC10MEM;
    user.IntDegC = ((user.temp - 673) * 423) / 1024;
    __no_operation();  
  }

//==========================================================================//
//===============================主程序=====================================//
void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;// Stop WDT
    _DINT();//关中断
   if (CALBC1_8MHZ==0xFF)                    // If calibration constants erased
  {                                                                                       
    while(1);                               // do not load, trap CPU!!        
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_8MHZ;                    // Set range
  DCOCTL = CALDCO_8MHZ;                     // Set DCO step + modulation */
    Init_Capture();
    adc_init();
    _EINT();//开中断
    while(1)
    {
      adc_proc();
      wdt_reset();
    }
}
//===========================================================================//
//============================TIMER0_VECTOR==================================//
user_t user;
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void timer_A(void)
{
     if((user.Cap_Tar==0)&&( CCTL0 &=~CM_1))
    {
      CCTL0 |=CM_2;
      user.Cap_First = TACCR0; //第一个上升沿时间
      user.Cap_Tar++;
    }
    else if((user.Cap_Tar==1)&&( CCTL0 &=~CM_2))
    {
      CCTL0 |=CM_1;
      user.Cap_Next = TACCR0;//第一个下降沿时间
      user.Cap_Tar++;
    }
    else if((user.Cap_Tar==2)&&( CCTL0 &=~CM_1))
    {
      CCTL0 |=CM_2;
      user.Cap_Last = TACCR0;//第二个上升沿时间
      user.Cap_Tar++;
    }
    else if((user.Cap_Tar==3)&&( CCTL0 &=~CM_2))  
    {
      user.duty=(user.Cap_Next-user.Cap_First)*100.00/(user.Cap_Last-user.Cap_First);
      user.time=7900000.0/(user.Cap_Last-user.Cap_First);
      TACTL |=TACLR;
      CCTL0 |=CM_1;
      user.Cap_Tar=0;
    }
}

使用特权

评论回复
8
斯诺|  楼主 | 2014-4-8 09:51 | 只看该作者
能捕获到100K左右了 。问题基本上解决只是,数据值和示波器的值误差有点大,精确度也不高

使用特权

评论回复
9
斯诺|  楼主 | 2014-4-9 16:05 | 只看该作者
dirtwillfly 发表于 2014-4-4 08:25
要不你把代码传上来,我帮你看看

版主大大,有木有精度高些的PWM输入捕获的方案啊??

使用特权

评论回复
10
dirtwillfly| | 2014-4-9 17:30 | 只看该作者
斯诺 发表于 2014-4-8 09:51
能捕获到100K左右了 。问题基本上解决只是,数据值和示波器的值误差有点大,精确度也不高 ...

自己做的系统没经过校准,肯定误差大。
要想精度高,要注意晶振的精度,中断服务程序的执行时间,另外,后期要进行校准。
计量器具出厂前一般都要校准的,在误差范围内才能出厂。

使用特权

评论回复
11
斯诺|  楼主 | 2014-4-10 15:52 | 只看该作者
dirtwillfly 发表于 2014-4-9 17:30
自己做的系统没经过校准,肯定误差大。
要想精度高,要注意晶振的精度,中断服务程序的执行时间,另外, ...

谢谢版主大大

使用特权

评论回复
12
dirtwillfly| | 2014-4-12 20:21 | 只看该作者
斯诺 发表于 2014-4-10 15:52
谢谢版主大大

:L晕死,谢我也不给点分

使用特权

评论回复
13
斯诺|  楼主 | 2014-4-14 10:09 | 只看该作者
dirtwillfly 发表于 2014-4-12 20:21
晕死,谢我也不给点分

想给分来着,特么系统说分配不照什么的

使用特权

评论回复
14
dirtwillfly| | 2014-4-14 10:29 | 只看该作者
斯诺 发表于 2014-4-14 10:09
想给分来着,特么系统说分配不照什么的

结贴教程:https://bbs.21ic.com/icview-442857-1-1.html

使用特权

评论回复
15
零度888| | 2014-5-4 17:49 | 只看该作者

使用特权

评论回复
16
arto| | 2014-5-5 11:25 | 只看该作者
捕获频率,很难做到测出的频率精度稳定,必须用DMA

使用特权

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

本版积分规则

3

主题

23

帖子

0

粉丝