STM32的硬件SPI驱动AD7124的方法

STM32的硬件SPI驱动AD7124的方法

  • 一、芯片介绍
  • 二、引脚排布
  • 三、时序图与驱动程序
    • 1. 芯片初始化
    • 2. SPI读写函数
    • 3. AD7124复位
    • AD7124读取ID
    • AD7124写入配置
    • 读取数据
  • 资料链接

一、芯片介绍

AD7124是一款适合高精度测量应用的低功耗、低噪声、完整模拟前端。该器件内置一个低噪声24位Σ-Δ型模数转换器(ADC),可配置来提供8个差分输入或15个单端或伪差分输入。片内低噪声级确保ADC中可直接输入小信号。可用于温度测量、压力测量、工业过程控制、仪器仪表和只能发射器。

二、引脚排布

STM32的硬件SPI驱动AD7124的方法_第1张图片
AD7124的接口属于标准4线SPI,DOUT是从设备输出至主设备的,连接单片机SPI模块的MISO(主输入从输出);DIN是主设备数据输出至从设备的,连接单片机SPI模块的MOSI(主输出从输入)。SYNC和CLK悬空。
本项目我们使用SPI2模块。

三、时序图与驱动程序

调试数字设备,我们需要一边查看技术手册的时序图写代码,一边挂上逻辑分析仪。

1. 芯片初始化

我们打开AD7124的DataSheet,对其时序图进行分析,如下:
下图为AD7124的单次和连续转换时序图,由图可知,SCLK在空闲状态下是高电平。
STM32的硬件SPI驱动AD7124的方法_第2张图片
下图是AD7124的读&写时序图,无论是读时序还是写时序,均在第二个时钟沿进行数据转换。
STM32的硬件SPI驱动AD7124的方法_第3张图片
所以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
}

2. SPI读写函数

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接收从机数据
}

3. AD7124复位

芯片上电初始化前,必须复位才能使用。
STM32的硬件SPI驱动AD7124的方法_第4张图片
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提前拉高,造成复位失败。在读写操作中,同样加入了延时处理。
逻辑分析仪采集到的波形如下:
在这里插入图片描述

AD7124读取ID

复位完成后需要读取芯片的ID号,不同封装的ID号也不同,AD7124-4通常为0x14,而AD7124-8是0x12或0x04。SPI写入命令0x40为读寄存器,读ID为0x05,故写入0x45就可以读出ID。
STM32的硬件SPI驱动AD7124的方法_第5张图片
0x40是发送读取ID指令返回的字节,0x14是ID号。

AD7124写入配置

写入配置需要根据写时序图编写,读时序如下
STM32的硬件SPI驱动AD7124的方法_第6张图片
我们复位后先对ADC_CTRL进行操作,以开启ADC控制寄存器,AD7124_ADC_CTRL_REG地址是0X01,如下图DIN的第一个Byte,之后再把2字节的配置信息依次写入,这个根据用户需求配置,不在赘述。
通道和内置滤波器配置方法相同。
STM32的硬件SPI驱动AD7124的方法_第7张图片

读取数据

本次实验我们采用单次读取模式。在读取数据之前先要写入命令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。
STM32的硬件SPI驱动AD7124的方法_第8张图片

STM32的硬件SPI驱动AD7124的方法_第9张图片

为了验证数据是否正确,我们查看此次串口读取到的值:
STM32的硬件SPI驱动AD7124的方法_第10张图片

原16进制数据读取正确,万用表实际测量11.0mV,实际读取值为11.180mV,误差在±100~200uV。因为信号发生器的线过长,影响了此次的精度。在PCB Layout时,尽可能将ADC输入的线路缩短,且圆弧布线,可以有效降低误差。

资料链接

代码可以在此处下载:

链接: https://download.csdn.net/download/m0_46369352/85612772

你可能感兴趣的:(C语言,模拟电路,元器件使用,stm32,单片机,arm)