大家好。
我用模拟SPI调试ADS1246,测试数据偏差较大,所以想到采用校准。但是没有弄清楚ADS1246校准方面的问题。下面是我的校准程序代码
:
void ADS1246_Calibrate(void)
{
u8 Cmd[2];
DIN_1246 = 0;
Cmd[0] = ADC_CMD_WREG | ADC_REG_MUX;
Cmd[1]=0x00;
ADS1246_WriteByte(Cmd,2); //恢复正常模式
ADS1246_SendCmd(ADC_CMD_SELFOCAL); //系统偏移自校准
ADS1246_WaitBusy(); //等待校准完成
DIN_1246 = 1;
Cmd[0] = ADC_CMD_WREG | ADC_REG_MUX;
Cmd[1]=0x01;
ADS1246_WriteByte(Cmd,2); //恢复正常模式
ADS1246_SendCmd(ADC_CMD_SYSOCAL); //系统偏移自校准
ADS1246_WaitBusy();
Cmd[0] = ADC_CMD_WREG | ADC_REG_MUX;
Cmd[1]=0x02;
ADS1246_WriteByte(Cmd,2); //恢复正常模式
ADS1246_SendCmd(ADC_CMD_SYSGCAL); //系统偏移自校准
ADS1246_WaitBusy();
}
请问问题出在哪里?
再有我启动AD(ADS1246_Start(ADC_MODE_SINGLECOV);)后,采用单次(ADS1246_SendCmd(ADC_CMD_RDATA);//设置器件转换模式 单次转换模式)读取AD值。能够读出AD值,但是偏差较大。
然后我考虑连续读取20ms做平均来较少误差,但是在设置连续转换模式时候出现问题。请问ADS1246在设置成连续转换模式时候应该注意些什么?
贴上我的代码。谢谢!
float ADS1246_GetValue(void)
{
u8 i;
float AD = 0;
u32 TempValue = 0;
u32 CountValue = 0;
CS1_1246 = 0; //拉低片选,使能ADS1246。
ADS1246_Start(ADC_MODE_SINGLECOV);//启动 单次AD转换
/*
ADS1246_Start(ADC_MODE_SINGLECOV);
ADC_MODE_SINGLECOV单次转换是START_1246 产生一个下降沿脉冲。
ADC_MODE_CONTINUOUS连续转换是直接拉高 START_1246信号。
*/
while(DRDY_1246 == 1); //等待AD转换完毕
ADS1246_SendCmd(ADC_CMD_RDATA);//设置元件转换模式 单次转换模式
DIN_1246 = 1;//拉高元件输入信号
for(i = 0; i < 24; i++)//24位AD 循环24次依次读取24位值
{
//产生时钟下降沿 元件AD值在时钟的下降沿送出
CLK_1246 = 1;
delay1246(10);
CLK_1246 = 0;
TempValue <<= 1; //数据位移动
if(DOUT1_1246) //读取数据
TempValue |= 0x01;
}
CLK_1246 = 0;
CS1_1246 = 1; //拉高片选
//将AD值转换成电压值
if(TempValue > 0x7FFFFF)//基准电压2.5V判断 电压值的转换范围则是-2.5V——+2.5V
{
AD = (float)(((~(TempValue)) & 0x7FFFFF) * (-5000.0)) / 16777216;
}
else
{
AD = (float)(((TempValue) & (0X7FFFFF)) * 5000.0) / 16777216;
}
return AD;
}
上面的单次读取函数能够读取到转换电压,但是噪声比较大,故想起校准和连续读取20ms做平均的方法(亦能较少外部感应干扰)。
下面采用连续转换和连续读取时候出现问题。请帮忙看看下面的函数实现问题出现在哪里?
float ADS1246_GetValue_C(void)//连续读取20ms
{
u8 i,j;
float AD = 0;
u32 TempValue = 0;
u32 CountValue = 0;
CS1_1246 = 0; //拉低片选,使能ADS1246。
ADS1246_Start(ADC_MODE_CONTINUOUS);//启动 连续AD转换
/*
ADS1246_Start(ADC_MODE_SINGLECOV);
ADC_MODE_SINGLECOV单次转换是START_1246 产生一个下降沿脉冲。
ADC_MODE_CONTINUOUS连续转换是直接拉高 START_1246信号。
*/
for(j=0; j<65; j++)//经过测算大概连续采集65次为20ms
{
while(DRDY_1246 == 1); //等待AD转换完毕
ADS1246_SendCmd(ADC_CMD_RDATAC);//设置元件转换模式 连续转换模式
DIN_1246 = 1;//拉高元件输入信号
for(i = 0; i < 24; i++)//24位AD 循环24次依次读取24位值
{
//产生时钟下降沿 元件AD值在时钟的下降沿送出
CLK_1246 = 1;
delay1246(10);
CLK_1246 = 0;
TempValue <<= 1; //数据位移动
if(DOUT1_1246) //读取数据
TempValue |= 0x01;
}
CountValue += TempValue;
TempValue = 0;
}
ADS1246_SendCmd(ADC_CMD_SDATAC);
CLK_1246 = 0;
CS1_1246 = 1; //拉高片选 关闭使能
TempValue = CountValue/65;
//将AD值转换成电压值
if(TempValue > 0x7FFFFF)//基准电压2.5V判断 电压值的转换范围则是-2.5V——+2.5V
{
AD = (float)(((~(TempValue)) & 0x7FFFFF) * (-5000.0)) / 16777216;
}
else
{
AD = (float)(((TempValue) & (0X7FFFFF)) * 5000.0) / 16777216;
}
return AD;
}
user151383853:
从解决问题的角度来看, 校准是解决偏差的有效途径.
而 AD 类的芯片, 都有个校准的手段, 现代的 AD 芯片基本都包含了这个校准的功能. 配置寄存器发个命令就完成了校准工作.
不过现实条件下, 还是有很多的偏差不能被消除, 这就需要你进一步分析这些偏差出现的原因. 来寻求更为合理的解决办法.
richard lee1:
回复 user151383853:
这是校准问题,但是实际情况中我还尝试了另一种方式,就是连续采集20ms做平均来减少误差。
请问能不能帮忙看下我的1246连续读取20ms程序中存在的问题。
我这边的现象是单次转换和读取时间大概是200us。然后我设置成连续转换和读取,多循环一次竟然需要200ms。
应该是我软件的设置问题,不知到能否帮忙看下问题出在哪里!谢谢!