小弟刚接触430,下面是一个g2553的AD的重复序列转换程序。
有点小问题,上电后有时候A0通道测的值会比实际的大2.354,复位后就可以测出正确值,
不知道是怎么回事,恳请请大家指点。
/**********************************
重复序列通道转换,每个通道转换32次,
A0,A1输入,转换先从A1开始,然后到A0
数据存放在data[64],每路AD采样32次后
中断,data[奇数]为A0的数据,data[偶数]
为A1的数据。
P2作为数据口,
P1^0作为RS
P1^1作为RW
P1^2作为E
********************************/
#include"msp430g2553.h"
#define uint unsigned int
#define uchar unsigned char
uchar a1[]={"A0:"};
uchar a2[]={"A1:"};
uint d[6];
uchar number[] = {"0123456789."};
void delaynms(int a )
{
uint i,j;
while(a)
{
for(i=10;i>0;i--)
for(j=33;j>0;j--);
a--;
}
}
void write_order(uchar order) //写指令函数,
{
delaynms(2);
//while(busy_test==1); //所有读写之前都要进行忙检测
P1OUT &= ~(BIT2 + BIT3 + BIT4);
;
P2OUT = order;
delaynms(5);
P1OUT |= BIT4;
;
delaynms(5);
P1OUT &= ~BIT4;
}
void write_address(uchar address) //写入数据的地址
{
write_order(0x80+address); //也可以用或|来代替+
}
void write_data(uchar Data) //写数据
{
delaynms(2);
//while(busy_test==1); //所有读写之前都要进行忙检测
P1OUT |= BIT2;
P1OUT &= ~(BIT3 + BIT4);
;
P2OUT =Data;
delaynms(5);
P1OUT |= BIT4;
;
delaynms(5);
P1OUT &= ~BIT4;
}
void init_lcd() //初始化lcd
{
uchar i=0;
delaynms(15);
write_order(0x38); //16*2,5*7点阵,8位数据
delaynms(5);
write_order(0x38); //至少要写三次,否则显示可能不正常
delaynms(5);
write_order(0x38);
delaynms(5);
write_order(0x0e); //开显示,光标闪烁
delaynms(5);
write_order(0x06); //读写一个字符光标后移,整屏不移动
delaynms(5);
write_order(0x01); //*清显示:清屏幕指令
write_address(0x00); //显示地址
while(a1
!= '\0') //没遇到结束符不停止
{
write_data(a1);
delaynms(10);
i++;
}
i=0;
write_address(0x40); //显示地址
while(a2 != '\0') //没遇到结束符不停止
{
write_data(a2);
delaynms(10);
i++;
}
}
void init_430()
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= BIT2 + BIT3 + BIT4; //LCD控制位
P2DIR |= 0XFF; //八位数据输出
P2SEL =0X00; //******P2.6,P2.7默认作为晶振接入,要做IO口,必须加上这句!!!!
//P1DIR &= ~(BIT0 + BIT1); //A1,A0作为输入端
ADC10CTL0 |= MSC + ADC10ON + ADC10IE; //复用模式
ADC10CTL1 |= INCH_1 + CONSEQ_3; //* Repeat sequence of channels */
ADC10DTC1 = 0x40; //进行64次转换后中断一次
ADC10AE0 |= BIT0 + BIT1; //使能输入端选择
}
uint data[64]; //定义一个大小为64的数组存放转换结果
void main()
{
init_430();
init_lcd();
while(1)
{
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & BUSY); //检测AD是否忙碌!!!
ADC10SA = (int)data; //转换数据存放首地址!!!
ADC10CTL0 |= ENC + ADC10SC; //开始采样转换。
_EINT();
LPM0;
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR()
{
ADC10CTL0 &= ~(ADC10IE + ENC + ADC10SC); //转换完一次就停止 等下次循环
uint data0,data1,data2;
uchar i=0;
for(i=0;i<32;i++)
{
data1 += data[i*2]; //取到了每组32个数据的总和
data2 += data[i*2+1];
}
data0 = data1;
data0 = data0>>5; //用data1/32也行!
data0 = (data0*3.5/1024)*1000; //此处是除以1024而不是1023!!!!!
d[0] = data0/1000; //此种算法和下面的算法均可得到准确的数值。
d[1] = 10;
d[2] = (data0 - d[0]*1000)/100;
d[3] = (data0 - d[0]*1000 - d[2]*100)/10;
d[4] = data0 - d[0]*1000 - d[2]*100 - d[3]*10;
write_address(0x44);
for(i=0;i<5;i++) //没遇到结束符不停止
{
write_data(number[d]);
delaynms(5);
}
data0 = data2;
data0 = data0/32;
data0 = (data0*3.5/1024)*1000;
d[0] = data0/1000;
d[1] = 10;
d[2] = (data0 - d[0]*1000)/100;
d[3] = (data0 - d[0]*1000 - d[2]*100)/10;
d[4] = data0 - d[0]*1000 - d[2]*100 - d[3]*10;
write_address(0x04);
for(i=0;i<5;i++) //没遇到结束符不停止
{
write_data(number[d]);
delaynms(5);
}
ADC10CTL0 |= ADC10IE + ENC + ADC10SC; //重新开始采样转换
LPM0_EXIT; //退出低功耗
}