我在把相关的程序贴出来,这样方便……
参数: XT2 = 20M
SMCLK=XT2/2 =10M ,MCLK = XT2 =20M;
ADC12通道:循序通道A0~A4单次采样,通过定时器T0 控制ADC12进行采样转换;
20 ms 进行32点采样, Fs=1600Hz,每10ms进行一次计算。
测试源: 许继继保测试系统
测试数据见表。
结果说明:软件仿真时,前3次计算是对的,之后就乱了,软件复位后在进行仿真同样。
用Matlab将ADC12采样的数据进行计算后跟程序算的一样,就是说问题在采样数据这里,是ADC12驱动设置程序有问题还是别的?求指点
/*
****************************************************************************
* 功 能:UCS时钟初始化
* 参 数:XT2 = 20M
* 返回值:无
****************************************************************************
*/
void UCS_Init(void)
{
P5SEL |= 0x0C; // Port select XT2
UCSCTL6 &= ~ XT2OFF; // Set XT2 On
UCSCTL3 |= SELREF_2; // FLLref = REFO,DCODIV=1.045MHz,DCO 参考频率
UCSCTL4 |= SELA_2; // ACLK=REFO=32768Hz,SMCLK=DCO,MCLK=DCO,晶振先起振,无此步骤晶振无法工作
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
UCSCTL6 |= XT2DRIVE_2 ; // Decrease XT2 Drive according to
UCSCTL4 |= SELS_5 + SELM_5; // MCLK=SMCLK=DCO=XT2
UCSCTL5 |= DIVS_1; // ACLK=32.768 ,SMCLK=XT2/2,MCLK=XT2
}
/*
****************************************************************************
* 功 能:ADC12初始化
* 参 数:无
* 返回值:无
****************************************************************************
*/
void ADC12_Init(void)
{
P6SEL |= 0x1F; // Enable A/D channel inputs
ADC12CTL0 &=~ ADC12ENC; //初始化在ENC = 0下修改
ADC12CTL0 |= ADC12ON+ADC12MSC+ADC12SHT0_8; // Turn on ADC12, extend sampling time
// to avoid overflow of results
ADC12CTL1 |= ADC12SHP+ADC12CONSEQ_1; // Use sampling timer, repeated sequence
//ADC12CTL2 |= ADC12RES_2;
ADC12MCTL0 |= ADC12INCH_0 + ADC12SREF_2; // ref+=VeREF+, channel = A0 VeREF外部参考电压
ADC12MCTL1 |= ADC12INCH_1 + ADC12SREF_2; // ref+=VeREF+, channel = A1
ADC12MCTL2 |= ADC12INCH_2 + ADC12SREF_2; // ref+=VeREF+, channel = A2
ADC12MCTL3 |= ADC12INCH_3 + ADC12SREF_2; // ref+=AVcc, channel = A3
ADC12MCTL4 |= ADC12INCH_4 + ADC12SREF_2 + ADC12EOS; // ref+=AVcc, channel = A4, end seq.
ADC12IE |= 0x10; // Enable ADC12IFG.4
ADC12CTL0 |= ADC12ENC; // Enable conversions
//ADC12CTL0 |= ADC12SC; // Start convn - software trigger
//__bis_SR_register(GIE); //Enable Int16errupts
}
/*
****************************************************************************
* 功 能:Time0_A5 A0定时器初始化
* 参 数:无
* 备注:T = 10M/625/2/5=1600Hz,AD采样
****************************************************************************
*/
void Time_A0_Init(void)
{
TA0CCTL0 |= CCIE; // TACCR0 Int16errupt enabled
TA0CCR0 = 625; //1600Hz
TA0EX0 |= TAIDEX_4; //T/5
TA0CTL |= TASSEL_2 + TACLR + MC_1 + ID_1; //SMCLK,upmode, clear TAR, TA enable Int16errupt
}
void main(void)
{
WDTCTL = WDTPW+WDTHOLD; // WDT
GlobalInit();
__bis_SR_register(GIE); //Enable Int16errupts
while(1)
{
if (Calc_Flag == TRUE && FFT_Flag == TRUE)
{
Calc_Flag = FALSE;
SampPreProcess();
Calc(); //算法 结果在 ACVal 用仿真器在窗口看
__no_operation(); // SET BREAKPOINT HERE
}
}
}
//Timer0_A5 A0 Int16errupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void) //ADC12
{
ADC12CTL0 |= ADC12SC; // Start convn - software trigger
}
//每5ms巡检一次,20ms进行一次I,U计算
// Timer ADC12 Int16errupt service routine
#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
static uChar8 FFT_Cnt, T_5Ms;
AdSamp *ADBuf_WrPtr = NULL;
ADBuf[FFT_Cnt].DC = ADC12MEM0; // Move A0 results, IFG is cleared
ADBuf[FFT_Cnt].Ia = ADC12MEM1; // Move A1 results, IFG is cleared
ADBuf[FFT_Cnt].Ic = ADC12MEM2; // Move A2 results, IFG is cleared
ADBuf[FFT_Cnt].I0 = ADC12MEM3; // Move A3 results, IFG is cleared
ADBuf[FFT_Cnt].Uac = ADC12MEM4; // Move A4 results, IFG is cleared
FFT_Cnt++;
ADBuf_WrP++;
T_5Ms++;
if(ADBuf_WrP >= ADBufEndP)
{
ADBuf_WrP = ADBuf; // 如果到了末尾,到前面
FFT_Flag = TRUE; //64点后才进行
}
if (T_5Ms >= 16) //每半个周期换一次新值
{
T_5Ms = 0;
ADBuf_WrPtr = ADBuf_WrP;
CopyADBufToCalcBuf(ADBuf_WrPtr);
Calc_Flag = TRUE;
}
if (FFT_Cnt >= FFT_N*2)
{
FFT_Cnt = 0;
}
}