|
发表于 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[4],PWM_End[4],PWM_dt[4];//上升沿捕获值,下降沿捕获值,PWM脉宽存放数组
unsigned int flag[4],flag_tov[4]; //定时器溢出标志,如果在溢出之前捕获到上升沿
//在溢出之后捕获到下降沿,标志为0xff,否则为0
int Frequency_CH[4];
//"--------------"
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[0]=1000000/(PWM_dt[0]*2);
Display_buf_CH0[7]=(char)(Frequency_CH[0]/10000)+0x30;
Display_buf_CH0[8]=(char)(Frequency_CH[0]%10000/1000)+0x30;
Display_buf_CH0[9]=(char)(Frequency_CH[0]%1000/100)+0x30;
Display_buf_CH0[10]=(char)(Frequency_CH[0]%100/10)+0x30;
Display_buf_CH0[11]=(char)(Frequency_CH[0]%10)+0x30;
LCD_WriteString(0,0,Display_buf_CH0);
Frequency_CH[1]=1000000/(PWM_dt[1]*2);
Display_buf_CH1[7]=(char)(Frequency_CH[1]/10000)+0x30;
Display_buf_CH1[8]=(char)(Frequency_CH[1]%10000/1000)+0x30;
Display_buf_CH1[9]=(char)(Frequency_CH[1]%1000/100)+0x30;
Display_buf_CH1[10]=(char)(Frequency_CH[1]%100/10)+0x30;
Display_buf_CH1[11]=(char)(Frequency_CH[1]%10)+0x30;
LCD_WriteString(0,1,Display_buf_CH1);
Frequency_CH[2]=1000000/(PWM_dt[2]*2);
Display_buf_CH2[7]=(char)(Frequency_CH[2]/10000)+0x30;
Display_buf_CH2[8]=(char)(Frequency_CH[2]%10000/1000)+0x30;
Display_buf_CH2[9]=(char)(Frequency_CH[2]%1000/100)+0x30;
Display_buf_CH2[10]=(char)(Frequency_CH[2]%100/10)+0x30;
Display_buf_CH2[11]=(char)(Frequency_CH[2]%10)+0x30;
LCD_WriteString(0,2,Display_buf_CH2);
Frequency_CH[3]=1000000/(PWM_dt[3]*2);
Display_buf_CH3[7]=(char)(Frequency_CH[3]/10000)+0x30;
Display_buf_CH3[8]=(char)(Frequency_CH[3]%10000/1000)+0x30;
Display_buf_CH3[9]=(char)(Frequency_CH[3]%1000/100)+0x30;
Display_buf_CH3[10]=(char)(Frequency_CH[3]%100/10)+0x30;
Display_buf_CH3[11]=(char)(Frequency_CH[3]%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[channel]=*tbccrx;
flag[channel]=0;
}
else //否则就是下降沿
{
if(flag[channel]==0xFFFF)//如果捕获跨越了定时器溢出边沿
{
flag[channel]=0;
PWM_dt[channel]=TimerB_Length-PWM_Start[channel]+*tbccrx+1;
}
else
PWM_dt[channel]=*tbccrx-PWM_Start[channel]+1;
}
}
//每次定时器溢出检查是否有通道断开,每个定时器周期中至少PWM更新一次,否则认为断路
void brkChk(unsigned char channel)
{
flag[channel]=0xFFFF;
if(flag_tov[channel]==0)
PWM_dt[channel]=0;
flag_tov[channel]=0;
}
// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B(void)
{
switch(TBIV)
{
case 2://捕获器1
flag_tov[0]++;
CalPWM(0);
break;
case 4://捕获器2
flag_tov[1]++;
CalPWM(1);
break;
case 6://捕获器3
flag_tov[2]++;
CalPWM(2);
break;
case 8://捕获器4
flag_tov[3]++;
CalPWM(3);
break;
case 14 ://TBIFG
brkChk(0);brkChk(1);brkChk(2);brkChk(3);
break;
}
} |
|