我的单通道多次转换AD,已经有软件的平滑滤波,但是检测大于1V的信号是显示低于1V接近1V 检测200mV的信号显示0.956~0.542之间不断波动,总之是与实际值相差较大,检测2V以上信号时候还会相差200mV这样,求解为什么会是这样,怎解决。代码已经粘贴,无错的。
#include "msp430g2553.h"
#define uint unsigned int
#define uchar unsigned char
uint Results[32]; //存放ADC的转换结果
float Average=0;
uint ad_value=0;
//在此设置输入端口*************************************************************/
#define LCD_SID1 P2OUT|=BIT4
#define LCD_SID0 P2OUT&=~BIT4 //WR 做数据传输使用sid
#define LCD_SCLK1 P2OUT|=BIT3
#define LCD_SCLK0 P2OUT&=~BIT3 //EN 当做串行时钟使用sclk
#define LCD_SID_READ P2IN&0X10
#define CPU_F ((double)8000000)//cpu frequency8000000
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/2000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/2000.0))
#define com 0
#define dat 1
unsigned char s1[] ={"电压(V): "};
unsigned char s2[] ={"TI杯电子设计大赛"};
/*********************写命令或数据************************/
void wr_lcd(uchar dat_com,uchar data)
{
uchar a,i,j;
delay_us(50);
a = data;
LCD_SID1; //WR=0;
LCD_SCLK0; //EN=0;
for(i=0;i<5;i++) //时序
{
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0; //wr=0
LCD_SCLK1; //en=1
LCD_SCLK0; //en=0
if(dat_com) LCD_SID1;
else LCD_SID0;
LCD_SCLK1;
LCD_SCLK0;
LCD_SID0;
LCD_SCLK1;
LCD_SCLK0;
for(j=0;j<2;j++) //8次循环写写一字节数据
{
for(i=0;i<4;i++)
{
if(a&0x80)
LCD_SID1;
else
LCD_SID0;
a=a<<1;
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0;
for(i=0;i<4;i++) //时钟
{
LCD_SCLK1;
LCD_SCLK0;
}
}
}
/*******************初始化***********************************/
void init_lcd(void)
{
wr_lcd(com,0x30);//基本指令集操作
wr_lcd(com,0x01);//清楚显示
delay_ms(2);
wr_lcd(com,0x30);//基本指令集操作
wr_lcd(com,0x01);//清楚显示
delay_ms(2);
wr_lcd(com,0x06);//光标右移,AC自动加1,整体显示不移动
wr_lcd(com,0x0c);//整体显示ON,光标显示OFF,光标位置不反白闪烁
}
/**********************写字符串,x0取值0-3,x取值0-7****************************/
void wr_string(uchar x,uchar x0,uchar *p)
{
uchar pos=0;//初始化
uchar cnt=0;//传递过来的是指针 ,cnt为偏移量,然后一个字符一个字符的写入。
switch(x0)
{
case 0: pos=0x80+x;break;
case 1: pos=0x90+x;break;
case 2: pos=0x88+x;break;
case 3: pos=0x98+x;break;
default: break;
}
wr_lcd(com,pos);//写地址
while(*(p+cnt)!='\0')
{
wr_lcd(dat,*(p+cnt));//写数据
cnt++;
}
}
/********************************浮点型数据显示*******************************/
void wr_float(uchar x,uchar x0,float NUM)
{
uchar a_SHOW[7];
long int t;
t=(long int)(NUM*1000);
a_SHOW[0]=(t/10000)%10+'0';//shi
a_SHOW[1]=(t/1000)%10+'0' ;//ge
a_SHOW[2]='.'; //
a_SHOW[3]=(t/100)%10+'0';//shi fen
a_SHOW[4]=(t/10)%10+'0'; //bai fen
a_SHOW[5]=t%10+'0'; //qian fen
a_SHOW[6]='\0';
wr_string(x,x0,a_SHOW);
}
/****************main***********************************/
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P2DIR |= BIT3+BIT4;
init_lcd();
wr_string(0,3,s1);
wr_string(0,0,s2);
P1DIR&=~BIT0;
ADC10AE0=BIT0; //把普通引脚功能关掉,使能ADC10AEx
P1DIR|=BIT6;
//P1OUT|=BIT6;
//P1SEL|=BIT1;
ADC10CTL0|=ADC10ON+MSC+ADC10SHT_3+ADC10IE;
ADC10CTL1|=CONSEQ_2+INCH_0;
ADC10CTL0|=ENC+ADC10SC;
while(1)
{
_BIS_SR(LPM0_bits + GIE);
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10IN(void)
{
static uchar index = 0;
Results[index++] = ADC10MEM; // Move results, IFG is cleared
if(index == 31)
{
uchar i;
Average = 0;
for(i = 0; i < 32; i++)
Average += Results;
Average = Average/32; //除以32求平均值
Average=(Average*3.5)/1023;
if (Average>30) //给的电压过高,LED6亮
P1OUT|=BIT6;
else P1OUT&=~BIT6;
wr_float(4,3,Average);
index = 0;
_BIC_SR_IRQ(LPM0_bits); // Clear LPM0
}
} |