|
发表于 2011-9-10 01:57:43
|
显示全部楼层
看了下楼主的程序,目前只看了ADC部分.感觉有些地方有问题.
楼主的m16adc.h内程序为:
***********************************************************
//多通道ADC采样 junsheng427@126.com 20110520
void init_adc() //---->ADC初始化
{
DDRA &=~0x1f;
PORTA &=~0x1f;
}
uint read_adc() //---->带返回值函数,返回ADC当前通道采样值
{
ADCSRA =0X86; //控制寄存器0x82,4分频,0x83,8分频,0x85,32分频,0x86,64分频;0x87,128分频
ADCSRA |=BIT(ADSC); //启动AD转换
while(!(ADCSRA &(BIT(ADIF)))); //判断AD转换是否结束
return ADC; //返回数据
}
#define N 11
uint filter() //---->滤波
{
uint value_buf[N],temp;
char count,i,j;
for (count=0;count<N;count++)
{
value_buf[count] = read_adc();
}
for (j=0;j<N-1;j++)
for (i=0;i<N-j;i++)
if (value_buf>value_buf[i+1]) //+1
{
temp = value_buf;
value_buf = value_buf[i+1]; //+1
value_buf[i+1] = temp;
}
return value_buf[(N-1)/2];
}
void adc_conversion(void) //---->读各通道转换值
{
uchar m;
for(m=0;m<6;m++)
{
ADMUX=0x40+m; //多工通道选择寄存器,(0x40)参考电压AVCC,结果右对齐
switch(m)
{
case 0:
adc0=filter();
break;
case 1:
adc1=filter();
break;
case 2:
adc2=filter();
break;
case 3:
adc3=filter();
break;
case 4:
adc4=filter();
break;
case 5:
adc5=filter();
break;
}
}
}
void adc_value(void) //---->ADC值
{
adc_conversion(); //读各通道转换值
adc0=2560*adc0;
adc0=adc0/1024;
adc1=2560*adc1;
adc1=adc1/1024;
adc2=2560*adc2;
adc2=adc2/1024;
if(adc2<=15)
adc2=adc2-15;
adc3=2560*adc3;
adc3=adc3/512;
}
********************************************************************
第一个问题:初始化ADC部分
void init_adc() //---->ADC初始化
{
DDRA &=~0x1f;
PORTA &=~0x1f;
}
楼主上面的说明PORTA初始化为DDRA=11100000,即只让5个通道的ADC设置为输入态了,而电路上明显是6个通道的ADC0,1,2,3,4,5.最后一个通道是测量热敏电阻的分压值的吧...这样初始化是不是少了这个采集实时温度的通道?
第二个问题:ADC精度问题
ADC第一次转换的数据按手册是不可用的,事实上确实第一个AD值是错误的.所以按上面的程序算出的结果应是错的.还好楼主有数字滤波,不过第一个参数的严重错误明显也会影响到整个电源的精度.
第三个问题:
ADC的第五通道从另一个文件来看是采集10K热敏的分压的,那为什么还要用一个很占CPU实时性资源的DS18B20呢(还很贵呢...)?没用DS18B20做功率报警等明显是因为其响应时间过慢.用这个仅是为了显示一个已无实时价值的温度值而已了.完全可以去除,省下FLASH空间可用于热敏电阻采样值在CPU内线性化得到较实时的电源温度值. |
|