makerpace 发表于 2010-10-18 10:51:11

初学者请教msp430的capture模式怎么测量信号的频率?谢谢!

看了一下datasheet没怎么看懂,但是我想原理是这样的:先测量信号第一个边沿(假设为rising edge)发生的时间T1,

在测量第二个边沿(还是rising edge)发生的时间T2, 这样信号的频率: f = 1 / (T2 - T1), 但是msp430中具体怎么操作没看懂,望指教!

wanpujame 发表于 2010-10-18 15:16:58

回复【楼主位】makerpace
-----------------------------------------------------------------------

你使用的是哪款430单片机?
TI针对每款MSP430单片机的所有外设都提供了示例应用程序,可以去官网下载。
以下是我使用MSP430F169捕获模式测4通道频率的程序,你可以参考一下。
/*
P4.1<--------PWM input0
P4.2<--------PWM input1
P4.3<--------PWM input2
P4.4<--------PWM input3
*/
#include<msp430x16x.h>
#include"nokia5110.h"

#define TimerB_Length 0xFFFF

int PWM_Start,PWM_End,PWM_dt;//上升沿捕获值,下降沿捕获值,PWM脉宽存放数组

unsigned int flag,flag_tov;   //定时器溢出标志,如果在溢出之前捕获到上升沿
                                    //在溢出之后捕获到下降沿,标志为0xff,否则为0

int Frequency_CH;
                      //"--------------"
char Display_buf_CH0[]={"FreCH0:XXXXXHz"};
char Display_buf_CH1[]={"FreCH1:XXXXXHz"};
char Display_buf_CH2[]={"FreCH2:XXXXXHz"};
char Display_buf_CH3[]={"FreCH3:XXXXXHz"};

void CalPWM(unsigned char channel);//中断中的捕获值处理子程序声明

//初始化系统时钟
void InitFreq(void)
{
    //使用外部8M高速晶振
    char Crystal;
    BCSCTL1&=~XT2OFF;//Enable XT2
    do
    {
      IFG1&=~OFIFG;//Clear OFIFG
      for(Crystal=0xff;Crystal>0;Crystal--);//set a delay
    }
    while(IFG1&OFIFG);//weck-up the OFIFG
    BCSCTL2 |= (SELM1 + SELS);   //MCLK = XT2,SMCLK = XT2
}

void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;//关闭MSP430看门狗
    InitFreq();//启动外部8MHz高速晶振
   
    LCD_Init();//初始化NOKIA5110液晶   
    LCD_Clear();//清屏

    P4SEL|=0x1E;//设置P4.0-P4.3作为捕获输入引脚

    //捕获模式+上升沿和下降沿都捕获+捕获CCIxB+中断使能
    TBCCTL1 =CAP+CM_3+CCIS_1+SCS+CCIE;               
    TBCCTL2 =CAP+CM_3+CCIS_1+SCS+CCIE;               
    TBCCTL3 =CAP+CM_3+CCIS_1+SCS+CCIE;               
    TBCCTL4 =CAP+CM_3+CCIS_1+SCS+CCIE;   
            
    //时钟源SMCLK+连续计数模式(0-0xFFFF)+计数时钟8分频+计数器长度16Bit+中断使能
    TBCTL = TBSSEL_2 + MC_2+ID_3+CNTL_0+TBIE ;      
    _EINT();//开启总中断
   
    while(1)
    {
      Frequency_CH=1000000/(PWM_dt*2);
      Display_buf_CH0=(char)(Frequency_CH/10000)+0x30;
      Display_buf_CH0=(char)(Frequency_CH%10000/1000)+0x30;
      Display_buf_CH0=(char)(Frequency_CH%1000/100)+0x30;
      Display_buf_CH0=(char)(Frequency_CH%100/10)+0x30;
      Display_buf_CH0=(char)(Frequency_CH%10)+0x30;
      LCD_WriteString(0,0,Display_buf_CH0);
      
      Frequency_CH=1000000/(PWM_dt*2);
      Display_buf_CH1=(char)(Frequency_CH/10000)+0x30;
      Display_buf_CH1=(char)(Frequency_CH%10000/1000)+0x30;
      Display_buf_CH1=(char)(Frequency_CH%1000/100)+0x30;
      Display_buf_CH1=(char)(Frequency_CH%100/10)+0x30;
      Display_buf_CH1=(char)(Frequency_CH%10)+0x30;
      LCD_WriteString(0,1,Display_buf_CH1);
      
      Frequency_CH=1000000/(PWM_dt*2);
      Display_buf_CH2=(char)(Frequency_CH/10000)+0x30;
      Display_buf_CH2=(char)(Frequency_CH%10000/1000)+0x30;
      Display_buf_CH2=(char)(Frequency_CH%1000/100)+0x30;
      Display_buf_CH2=(char)(Frequency_CH%100/10)+0x30;
      Display_buf_CH2=(char)(Frequency_CH%10)+0x30;
      LCD_WriteString(0,2,Display_buf_CH2);
      
      Frequency_CH=1000000/(PWM_dt*2);
      Display_buf_CH3=(char)(Frequency_CH/10000)+0x30;
      Display_buf_CH3=(char)(Frequency_CH%10000/1000)+0x30;
      Display_buf_CH3=(char)(Frequency_CH%1000/100)+0x30;
      Display_buf_CH3=(char)(Frequency_CH%100/10)+0x30;
      Display_buf_CH3=(char)(Frequency_CH%10)+0x30;
      LCD_WriteString(0,3,Display_buf_CH3);
    }
}
//捕获值处理子程序,channel为通道值,范围0-3,对应存放的数组的序号
void CalPWM(unsigned char channel)
{
    unsigned volatile short *tbcctlx,*tbccrx;
    tbcctlx=&TBCCTL1+channel;
    tbccrx=&TBCCR1+channel;

    if(*tbcctlx & CCI)//上升沿判断
    {
      PWM_Start=*tbccrx;
      flag=0;
      
    }
    else      //否则就是下降沿
    {
      if(flag==0xFFFF)//如果捕获跨越了定时器溢出边沿
      {
            flag=0;               
            PWM_dt=TimerB_Length-PWM_Start+*tbccrx+1;
      }
      else         
      PWM_dt=*tbccrx-PWM_Start+1;      
    }
}

//每次定时器溢出检查是否有通道断开,每个定时器周期中至少PWM更新一次,否则认为断路
void brkChk(unsigned char channel)
{
    flag=0xFFFF;
    if(flag_tov==0)
      PWM_dt=0;
    flag_tov=0;
}

// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B(void)
{
    switch(TBIV)
    {
      case 2://捕获器1
            flag_tov++;
            CalPWM(0);
            break;
      case 4://捕获器2
            flag_tov++;
            CalPWM(1);
            break;
      case 6://捕获器3
            flag_tov++;
            CalPWM(2);
            break;
      case 8://捕获器4
            flag_tov++;
            CalPWM(3);
            break;
      case 14 ://TBIFG
            brkChk(0);brkChk(1);brkChk(2);brkChk(3);
            break;
}
}

makerpace 发表于 2010-10-18 21:52:41

谢谢楼上这位大哥,我用的器件是MSP430x4618。回去参考参考你的程序。

不知你的nokia5110液晶屏哪里弄的?效果怎么样?

wanpujame 发表于 2010-10-19 14:53:14

回复【2楼】makerpace
-----------------------------------------------------------------------

淘宝上买的,效果还不错,功耗低,接口简单。

makerpace 发表于 2010-10-19 16:43:23

回复【3楼】wanpujame
-----------------------------------------------------------------------
不错,有时间我也弄一个玩玩。

zhouting928 发表于 2010-10-19 17:07:13

mark

deweyled 发表于 2011-3-20 12:55:29

mk

fengyuehaoran 发表于 2011-4-3 16:19:18

mark

568581185 发表于 2011-8-29 20:36:27

回复【1楼】wanpujame
-----------------------------------------------------------------------

请问 MSP430F149有PWM输入口么???
是哪几个引脚?

jlhgold 发表于 2011-9-3 14:55:30

mark
页: [1]
查看完整版本: 初学者请教msp430的capture模式怎么测量信号的频率?谢谢!