TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430F6438的ADC12采样不准,采样结果不随输入信号的改变而变化,怎么办?

程序内容:用6438的ADC12采样0.5+0.5sin(2pi*50t),计算这个信号的真有效值。采样频率fs=256*50=12800Hz,我用到了ADC12、串口usci_a1的UART模式、定时器TA0三个模块。 时钟方面设置了ACLK=XT1=32768Hz,MCLK=SMCLK=(74 + 1) * 32768 = 2457600Hz。定时器TA0采用增计数模式,每隔1/fs产生中断,然后在TA0的中断里打开ADC12的A0通道开始采样,从而保证采样频率为fs,初始值TA0CCR0 =2457600/256/50-1=191。当采样256个点时,在main中计算有效值,通过串口调试助手显示有效值。现在问题是:

1)每次结果都是1.3左右的数,信号幅值变为1、0.7等时,结果还是1.3;把信号去掉,A0通道没有信号时,输出数据还是1.3。这就奇葩了。

2)怀疑A0通道不行,我就使能A1通道,信号加到A1通道上,结果没有数据,在register中看到ADC12MEM1没有数据,ADC12MEM0中竟然有数据。

3)整个程序的功能我转移到449上,发现449上输出结果就对(虽然有误差,但整体趋势是对的啊),所以程序应该没问题。

4)所有模块的初始化,我都是按照TI例程初始化的。

5)怀疑是ADC12通道干扰,我用A0时,就把A1-A7通道接地,但是结果还是和上面的问题一样啊。

6)ROM和RAM都没超出。

所以问题到底出现在哪里?我好急啊,求解答@TI员工。完整的程序如下:

#include <msp430.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M 256
#define uchar unsigned char
#define uint unsigned int
char buffer[100];
uint adc_flag=0;
uint count=0;
float ad_temp=0;
float ad=0;
int i,j;

void delay(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<1000;j++)
{}
}
}

int main(void)

{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
//时钟初始化
P1DIR |= BIT0; // ACLK set out to pin P1SEL |= BIT0;
P3DIR |= BIT4; // SMCLK set out to pins

P3SEL |= BIT4;
while(BAKCTL & LOCKBAK) // Unlock XT1 pins for operation BAKCTL &= ~(LOCKBAK); UCSCTL6 &= ~(XT1OFF); // XT1 On
UCSCTL6 |= XCAP_3; // Internal load cap // Loop until XT1 fault flag is cleared do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
// Initialize DCO to 2.45MHz

__bis_SR_register(SCG0); // Disable the FLL control loop

UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx

UCSCTL1 = DCORSEL_3; // Set RSELx for DCO = 4.9 MHz
UCSCTL2 = FLLD_1 + 74; // Set DCO Multiplier for 2.45MHz
// (N + 1) * FLLRef = Fdco
// (74 + 1) * 32768 = 2457600Hz
// Set FLL Div = fDCOCLK/2
__bic_SR_register(SCG0); // Enable the FLL control loop

__delay_cycles(76563);
// Loop until XT1,XT2 & DCO fault flag is cleared

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 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive strength
UCSCTL4 |= SELA_0; // ACLK = LFTX1 (by default)

//usci_a1初始化
P8SEL |= (BIT2+BIT3); //p8.2,p8.3=usci_a1TXD,RXD (F6438) P8DIR |= BIT2; P8DIR &=~BIT3; // 选择引脚方向
UCA1CTL1 |= UCSWRST; // 状态机复位
UCA1CTL1 |= UCSSEL_1; // 选择时钟源CLK = ACLK

UCA1BR0 = 0x03; //波特率分频 32768/9600=3.41
UCA1BR1 = 0x00; // Modulation UCBRSx=3, UCBRFx=0
UCA1MCTL = UCBRS_3+UCBRF_0; UCA1CTL1 &=~UCSWRST; // 启动状态机,即启用串口功能
UCA1IE |= UCRXIE; // 允许接收中断

//初始化ADC12
P6SEL |= 0x01; // Enable A/D channel A0
REFCTL0 &= ~REFMSTR; // Reset REFMSTR to hand over control to ADC12_A ref control registers
ADC12CTL0 = ADC12ON+ADC12SHT02+ADC12REFON+ADC12REF2_5V;
// Turn on ADC12, Sampling timeOn Reference Generator and set to2.5V //a single conversion on channel A0.
ADC12CTL1 = ADC12SHP; // Use sampling timer
ADC12MCTL0 = ADC12SREF_1; // Vr+=Vref+ and Vr-=AVss
ADC12IE = 0x01; // Enable interrupt A0
for ( i=0; i<0x30; i++); // Delay for reference start-up
ADC12CTL0 |= ADC12ENC; // Enable conversions
//初始化TA0 TA0CTL = TASSEL_2 + MC_1 + TACLR + TAIE; // SMCLK, upmode, clear TAR
TA0CCR0 = 191; //2457600/256/50=192

_EINT();
while(1)
{
while(adc_flag==1)
{
ad=ad+ad_temp*ad_temp;
count++;
if(count==M)
{
ad=ad/M;
ad=sqrt(ad); sprintf(buffer,"%.4f\n",ad);
while(!(UCA1IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
for(int k=0;k<sizeof(buffer);k++)
{
UCA1TXBUF=buffer[k];
delay(30);
}
ad=0;
count=0;
ad_temp=0;
}
adc_flag=0;
}
}
}
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
switch(__even_in_range(ADC12IV,34))

{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: // Vector 6: ADC12IFG
{
ad_temp=(ADC12MEM0*2.5/4095);
adc_flag=1;
} break;
case 8: break; // Vector 8: ADC12IFG1
case 10: break; // Vector 10: ADC12IFG2
case 12: break; // Vector 12: ADC12IFG3
case 14: break; // Vector 14: ADC12IFG4
case 16: break; // Vector 16: ADC12IFG5
case 18: break; // Vector 18: ADC12IFG6
case 20: break; // Vector 20: ADC12IFG7
case 22: break; // Vector 22: ADC12IFG8
case 24: break; // Vector 24: ADC12IFG9
case 26: break; // Vector 26: ADC12IFG10
case 28: break; // Vector 28: ADC12IFG11
case 30: break; // Vector 30: ADC12IFG12
case 32: break; // Vector 32: ADC12IFG13
case 34: break; // Vector 34: ADC12IFG14
default: break;
}
}

#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(__even_in_range(TA0IV,14))

{
case 0: break; // No interrupt
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 6: break; // reserved
case 8: break; // reserved
case 10: break; // reserved
case 12: break; // reserved
case 14: if(adc_flag==0) // overflow
{
ADC12CTL0 |=ADC12SC;
}break;
default: break;
}
}

baoshuai wang:

各路大神求解答啊

Jacky Xu:

1) 随便找一个我们的历程,例如连续单通道采样例程看ADC采样结果是否正常

2)在你的定时器中断里面和ADC中断里面分别翻一个IO做toggle,用示波器观察这两个引脚波形。是否如你所想的那样,以这样的频率在每次进timer去配置SC,以及随后是否进了ADC中断

HG:

回复 baoshuai wang:

这款芯片支持TIMER Trigger ADC的,不一定要在timer中断里开ADC,这样实时性也不是太好

baoshuai wang:

回复 HG:

HG

这款芯片支持TIMER Trigger ADC的,不一定要在timer中断里开ADC,这样实时性也不是太好

baoshuai wang:

回复 Jacky Xu:

Jacky Xu

1) 随便找一个我们的历程,例如连续单通道采样例程看ADC采样结果是否正常

2)在你的定时器中断里面和ADC中断里面分别翻一个IO做toggle,用示波器观察这两个引脚波形。是否如你所想的那样,以这样的频率在每次进timer去配置SC,以及随后是否进了ADC中断

HG:

回复 baoshuai wang:

亲,不是看ADC啊,你要看

HG:

回复 baoshuai wang:

你为啥要在Overflow的中断里去开ADC呢,就弄一个普通的中断,并且要重新给TIMER赋值

灰小子:

回复 Jacky Xu:

建议先运行下官网的例程,在例程的基础上修改和增加其他功能

baoshuai wang:

回复 HG:

HG

你为啥要在Overflow的中断里去开ADC呢,就弄一个普通的中断,并且要重新给TIMER赋值

赞(0)
未经允许不得转载:TI中文支持网 » MSP430F6438的ADC12采样不准,采样结果不随输入信号的改变而变化,怎么办?
分享到: 更多 (0)