AD7124是一款适合高精度测量应用的低功耗、低噪声、完整模拟前端。该器件内置一个低噪声24位Σ-Δ型模数转换器(ADC),可配置来提供8个差分输入或15个单端或伪差分输入。片内低噪声级确保ADC中可直接输入小信号。可用于温度测量、压力测量、工业过程控制、仪器仪表和只能发射器。
AD7124的接口属于标准4线SPI,DOUT是从设备输出至主设备的,连接单片机SPI模块的MISO(主输入从输出);DIN是主设备数据输出至从设备的,连接单片机SPI模块的MOSI(主输出从输入)。SYNC和CLK悬空。
本项目我们使用SPI2模块。
调试数字设备,我们需要一边查看技术手册的时序图写代码,一边挂上逻辑分析仪。
我们打开AD7124的DataSheet,对其时序图进行分析,如下:
下图为AD7124的单次和连续转换时序图,由图可知,SCLK在空闲状态下是高电平。
下图是AD7124的读&写时序图,无论是读时序还是写时序,均在第二个时钟沿进行数据转换。
所以AD7124初始化时,需要将SPI模式设置为时钟悬空高、数据捕获于第2个时钟沿
void AD7124_SPI_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主机
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第2个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 0; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI2, ENABLE);
AD7124_CS_H; //片选拉高,失能AD7124
}
SPI读写是驱动SPI设备的基础。SPI的原理为
第一步:通过硬件或软件NSS拉低从设备片选(CS),使能从设备。
第二步:通过MOSI引脚,发送8个时钟周期,每个周期发送1个bit的数据;通过写入不同的地址,来决定对从设备的读操作/写操作。
第三步:8个倍数的时钟周期发送完毕后,拉高片选,结束“发送/接收数据”。
这里我们把读和写都放在一个函数里面,因为SPI如果只读取,都需要发送8个时钟周期和指令0XFF。
/**
* @brief AD7124的读写SPI操作
* @param Data : 需要传输的数据
* @retval SPI读到的数据
*/
uint8_t AD7124_SPI_ReadWrite(uint8_t Data)
{
uint16_t retry=0;
//超时等待
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI2, Data); //MOSI主机发送给从机
retry=0;
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI2); //MISO接收从机数据
}
芯片上电初始化前,必须复位才能使用。
CS = 0 和 DIN = 1 的 64 个 SCLK。这会复位 ADC 和所有寄存器内容。也就是说,只要在AD7124 CS拉低的期间,在64个时钟周期内MOSI不断输出高电平,即可复位。代码如下:
void AD7124_Reset(void)
{
AD7124_CS_L;
//提供大于64个写操作,复位AD7124
for(uint8_t a=0; a<9; a++)
{
AD7124_SPI_ReadWrite(0XFF); //MOSI拉高
}
delay_us(60);
AD7124_CS_H;
}
加入延时delay_us()的目的是,防止在硬件SPI还未发送完最后几个时钟周期,CS提前拉高,造成复位失败。在读写操作中,同样加入了延时处理。
逻辑分析仪采集到的波形如下:
复位完成后需要读取芯片的ID号,不同封装的ID号也不同,AD7124-4通常为0x14,而AD7124-8是0x12或0x04。SPI写入命令0x40为读寄存器,读ID为0x05,故写入0x45就可以读出ID。
0x40是发送读取ID指令返回的字节,0x14是ID号。
写入配置需要根据写时序图编写,读时序如下
我们复位后先对ADC_CTRL进行操作,以开启ADC控制寄存器,AD7124_ADC_CTRL_REG地址是0X01,如下图DIN的第一个Byte,之后再把2字节的配置信息依次写入,这个根据用户需求配置,不在赘述。
通道和内置滤波器配置方法相同。
本次实验我们采用单次读取模式。在读取数据之前先要写入命令0x42,之后需要读取多少个Byte的字节,就修改形式参数byte的数量即可。读取一次单次采集到的数据,需要3次SPI读写(24个时钟周期),DIN输出全高即可读取。
uint32_t DATA=0;
uint32_t Rd_Ary[3];
uint32_t AD7124_Read_Data(uint8_t byte)
{
for(uint8_t i=0; i<byte; i++)
{
Rd_Ary[i] = AD7124_SPI_ReadWrite(0xFF);
}
DATA = (Rd_Ary[0]<<16) + (Rd_Ary[1]<<8) + Rd_Ary[2];
return DATA;
}
主函数读取代码如下:
while(1)
{
AD7124_CS_L;
AD7124_SPI_ReadWrite(0x42); //读操作
Data = AD7124_Read_Data(3); //Data采集结果
AD7124_CS_H;
data_temp = Data;
data_last1 = (float)Vref/AD_Gain * (float)data_temp/(2*0X800000); //单极性模式电压转换公式,单位mV
// data_last1 = (float)Vref/AD_Gain * ((float)data_temp/0X800000-1); //双极性模式电压转换公式,单位mV
data_last1 = data_last1 * 1000.0f; //转换为uV
printf("%X\r\n", Data); //打印原始16进制数据
printf("%2f uV\r\n", data_last1); //打印微伏
delay_ms(100);
}
让我们采集11mV的直流信号,下图分别为实际测量和逻辑分析仪读取到的数据,为0x928D11。
原16进制数据读取正确,万用表实际测量11.0mV,实际读取值为11.180mV,误差在±100~200uV。因为信号发生器的线过长,影响了此次的精度。在PCB Layout时,尽可能将ADC输入的线路缩短,且圆弧布线,可以有效降低误差。
代码可以在此处下载:
链接: https://download.csdn.net/download/m0_46369352/85612772