AD7124芯片,是属于AD公司的较新产品,高达24位的精度,确实让人眼馋,究竟如何呢。
寄存器配置顺序
1、AD上电后,先关闭SPI片选
2、使能开启单片机的 SPI
3、复位设备及所有内部寄存器,发送64位的1,也就是8个0xFF
4、读Status Register寄存器,用于清除上电复位标志,否则对AD7124_ADC_Control的配置不起作用,AD7124-8似乎没有这个问题。非常重要!!
5、做好从 AD7124_ADC_Control 到 AD7124_Filter_7寄存器的配置清单、通道配置、滤波配置等。(在实际应用中,可以一次调零校准和满量程校准后,将该通道的失调寄存器的值和增益寄存器的值直接保存起来,下次上电后再直接写进去,就不用反复校准了,如果需要将失调寄存器和增益寄存器写入的话,记得把Control寄存器配置为低功耗或中功耗模式!!!我这里是直接将Control寄存器设置为低功耗、空闲模式,然后开始校准,所以没有写入失调寄存器和增益寄存器)
6、将从 AD7124_ADC_Control 到 AD7124_Filter_7ADC所有寄存器写入AD芯片,写入过程中,建议写一个寄存器,就延时20-30ms,另外,需要修改的才写,不需要修改的寄存器就不用写,浪费时间。
7、内部满量程校准,再写Control寄存器,设置内部满量程校准。
8、等待一下,确保校准完成。
9、读Status Register寄存器,用于清除该寄存器中上电复位标志。由于校准后会自动进入空闲模式,我在调试过程中,居然有出现上电复位标志被置位了,所以读一下为好,这个上电复位标志为1的话,功能都运行不了。。。
10、内部零电平校准,再写Control寄存器,设置内部零电平校准。
11、等待一下,确保校准完成。
12、读Status Register寄存器,用于清除该寄存器中上电复位标志。由于校准后会自动进入空闲模式,我在调试过程中,居然有出现上电复位标志被置位了,所以读一下为好,这个上电复位标志为1的话,功能都运行不了。。。
13、现在可以将Control寄存器设置为全功率、连续运行模式等等了。我是设置为 全功率、单次运行模式。
单次运行模式被设置后,AD进行一次转换,然后自动进入空闲模式,Status寄存器的RDY位为0,表示数据转换完成。读取数据后,再设置Control寄存器全功率、单次运行模式,等Status寄存器的RDY位为0了,就读写,依次循环…
下面上部分代码
int32_t AD7124_Setup(ad7124_device *device)
{
int32_t ret;
enum ad7124_registers regNr;
if(!device)
return INVALID_VAL;
SPI1_CS_SET; //关闭片选
__HAL_SPI_ENABLE(&hspi1); // 使能SPI1,开启
AD7124_Reset(); // 复位设备及所有内部寄存器
device->check_ready = 1; // 使能检查设备准备好,使用开机/重置设置更新设备结构
ret = AD7124_ReadRegister( device, &device->regs[AD7124_ID] ); //读ID寄存器
if (ret < 0)
return ret;
//读Status Register寄存器,用于清除上电复位标志,否则对AD7124_ADC_Control的配置不起作用,AD7124-8似乎没有这个问题。非常重要!!
ret = AD7124_ReadRegister( device, &device->regs[AD7124_Status] );
if (ret < 0)
return ret;
// ADC所有寄存器初始化,从 AD7124_ADC_Control 到 AD7124_Offset_0
for( regNr = AD7124_ADC_Control; (regNr <= AD7124_Offset_0); regNr++ )
{
HAL_Delay(30);
if ( device->regs[regNr].rw == AD7124_RW )
{
ret = AD7124_WriteRegister( device, &device->regs[regNr] );
printf("AD-write-%X---%X\n",regNr,device->regs[regNr].value); //写入AD数据
if (ret < 0)
break;
}
// 获取CRC状态和设备SPI接口设置,
// 根据初始化的寄存器数组ad7124_st_reg ad7124_regs[],确定是否需要CRC、检查设备准备好,并更新设置
if (regNr == AD7124_Error_En)
{
AD7124_UpdateCRCSetting(device);
AD7124_UpdateDevSpiSettings(device);
}
if ( regNr == AD7124_ADC_Control )
{ //如果控制寄存器开启了DATA_STATUS位(读数据寄存器后将,将跟随一个字节的指示那个通道的值,再加CRC,即3+1+CRC)
//那么读AD7124_Data字节数量将增加1个
if ( device->regs[AD7124_ADC_Control].value & AD7124_ADC_CTRL_REG_DATA_STATUS )
{
(device->regs[AD7124_Data].size)++;
}
}
}
if (ret < 0)
return ret;
//
// 内部满量程校准
device->regs[AD7124_ADC_Control].value =
/* 控制寄存器 ADC_Control Register bits */
// AD7124_ADC_CTRL_REG_DOUT_RDY_DEL // (1 << 12),
// | AD7124_ADC_CTRL_REG_CONT_READ // (1 << 11)
AD7124_ADC_CTRL_REG_DATA_STATUS // (1 << 10),开启数据寄存器后跟随通道显示
// | AD7124_ADC_CTRL_REG_CS_EN // (1 << 9)
| AD7124_ADC_CTRL_REG_REF_EN // (1 << 8),内部基准电压使能,1=内部使能,0=外部使能
| AD7124_ADC_CTRL_REG_POWER_MODE(0) // (((x) & 0x3) << 6),电源模式,0-1-2-3,低、中、全、全功耗
| AD7124_ADC_CTRL_REG_MODE(6) // (((x) & 0xF) << 2),ADC工作模式,5=内部调零,6=内部满量程,7=系统零电平校准,8=系统满量程
| AD7124_ADC_CTRL_REG_CLK_SEL(0) // (((x) & 0x3) << 0),ADC时钟源选择
;
printf("nbmlc->W_Control=%0x \n",(device->regs[AD7124_ADC_Control].value));
ret = AD7124_WriteRegister(device, &device->regs[AD7124_ADC_Control]); //写入值,AD将会进入中功率,满量程校准模式,
if (ret < 0) //校准完成后,自动进入空闲模式
return ret;
HAL_Delay(5000);
ret = AD7124_WaitForConvReady(device, 10000);
if (ret < 0)
return ret;
//读Status Register寄存器,用于清除上电复位标志,否则对AD7124_ADC_Control的配置不起作用,AD7124-8似乎没有这个问题。非常重要!!
ret = AD7124_ReadRegister( device, &device->regs[AD7124_Status] );
if (ret < 0)
return ret;
//
// 内部零电平校准
device->regs[AD7124_ADC_Control].value =
/* 控制寄存器 ADC_Control Register bits */
// AD7124_ADC_CTRL_REG_DOUT_RDY_DEL // (1 << 12),
// | AD7124_ADC_CTRL_REG_CONT_READ // (1 << 11)
AD7124_ADC_CTRL_REG_DATA_STATUS // (1 << 10),开启数据寄存器后跟随通道显示
// | AD7124_ADC_CTRL_REG_CS_EN // (1 << 9)
| AD7124_ADC_CTRL_REG_REF_EN // (1 << 8),内部基准电压使能,1=内部使能,0=外部使能
| AD7124_ADC_CTRL_REG_POWER_MODE(0) // (((x) & 0x3) << 6),电源模式,0-1-2-3,低、中、全、全功耗
| AD7124_ADC_CTRL_REG_MODE(5) // (((x) & 0xF) << 2),ADC工作模式,5=内部调零,6=内部满量程,7=系统零电平校准,8=系统满量程
| AD7124_ADC_CTRL_REG_CLK_SEL(0) // (((x) & 0x3) << 0),ADC时钟源选择
;
printf("nbtl->W_Control=%0x \n",(device->regs[AD7124_ADC_Control].value));
ret = AD7124_WriteRegister(device, &device->regs[AD7124_ADC_Control]);
if (ret < 0)
return ret;
HAL_Delay(5000);
ret = AD7124_WaitForConvReady(device, 10000);
if (ret < 0)
return ret;
//读Status Register寄存器,用于清除上电复位标志,否则对AD7124_ADC_Control的配置不起作用,AD7124-8似乎没有这个问题。非常重要!!
ret = AD7124_ReadRegister( device, &device->regs[AD7124_Status] );
if (ret < 0)
return ret;
printf("\n----AD AD7124_Setup(0=normal)= %d----\n",ret);
return ret;
}
下面来说说精度问题
我是使用了内部基准2.5V,AI1 和 AI2 引脚直接接信号发生器,由于只是测试,没有接任何电容电阻等其他元件,AI输入配置为缓冲,基准不缓冲,PGA放大16倍。
第一列数据:AD转换码, 第二列:转换为电压值(单位mV,图片中单位错误,见谅), 第三列:上次AD转换码与本次之差。
总体感觉,这个芯片的精度是还行的,但是抗干扰能力并不好。
我是用这个芯片测RTD电阻,用芯片本身的恒电流源,测试出来的AD数据,时好时不好,或者有时用手碰下RTD测量回路,都会芯片死机,重启或复位又好了,有时感觉就是外部干扰(甚至空气中干扰),都会影响AD数据跳动,然后我把板子装在机壳里面,用了很久,又很稳定。总体来讲,就是抗干扰能力不强。
但是,如果使用外部基准源(或内部基准源)2.5V,似乎抗干扰能力就强很多了,手摸测量回路,AD数据跳动都比较小,并能很快恢复数据,基本也不死机。
说明就是,基准的端子一定要稳!!