基于STM32F103平台的ADS79xx系列ADC(TI公司)应用方案

第一章 ADS79xx系列芯片特性简介

基本特性
12/10/8 位分辨率产品系列
• 零等待时间
• 20MHz 串行接口
• 模拟电源范围:2.7V 至 5.25V
• I/O 电源范围:1.7V 至 5.25V
• 两个软件可选择单极,输入范围:0 到 VREF 和 0 到 2 x VREF
• 针对通道选择的自动和手动模式
• 4 通道、8 通道器件和 12 通道、16 通道器件大小相同
• 每通道两个可编程警报级别
• TSSOP 封装中四个可独立配置的 GPIO:VQFN 封装中一个 GPIO
• 典型功率耗散值:1MSPS下为14.5 mW (+VA = 5 V, +VBD = 3 V, 相当于工作电流约为2~4mA)
• 断电电流(1μA, 允许低功耗运行)
• 输入带宽(3db时为47MHz需要在输入前端进行抗混叠设计
• 38 引脚、30 引脚 TSSOP 和 32 引脚、24 引脚VQFN 封装

第二章 芯片内部结构简介

在这里插入图片描述
从中可以看出,Ch0~Chn为芯片的模拟输入通道端,由模数转换器控制哪个通道与输出接口MXO连接。AINP为芯片内部单ADC的输入端;REF为ADC的参考源输入端,转换的结果由SDO被输出至主机。此外,SDI,SCK,CS与SDO共同构成了该芯片的通信接口。该芯片推荐在MXO与AINP中间接入一个高输入阻抗的PGA(可编程增益放大器),用于提高输入阻抗。而GPIO1-GPIO3可用于控制增益PGA的增益系数。此外,GPIO0可用于对输入电压的高低进行报警。

第三章 封装介绍

以ADS7952/ADS7956/ADS7960为例,说明封装的各个引脚定义
以ADS7952 QFN32为例介绍芯片封装

引脚号引脚功能
1AGND连接至模拟地
2MXO连接到芯片内部多路复用器Muxplexier的输出端
3AINP内部单ADC的输入正端
4AINM内部单ADC的输入负端
5NC连接至模拟地
6NC连接至模拟地
7~18CH输入通道
19NC连接至模拟地
20NC连接至模拟地
21+VA模拟电压输入,一般为5V,决定了所能检测的电压范围
22AGND连接至模拟地
23CS’连接至模拟地
24SCLKSPI协议的SCLK线
25SDISPI协议的SDI线(MOSI)
26SDOSPI协议的SDO线(MISO)
27BDGND连接到数字地
28+VBD数字电压输入,一般为3.3V,决定了逻辑电平
29GPIO芯片通用端口,用于报警
30REFMADC参考源的地
31REFPADC参考源的正输入端,一般接2.5V
32+VA模拟电压输入,一般为5V,决定了所能检测的电压范围
33

第四章 硬件布线设计

在这里插入图片描述
在设计时,采用单5V供电的方式来整个系统系统供电,并利用REF2925作为2.5V的参考电压源;XC6206-3.3被用于将5V电平转换为3.3V电平,为逻辑部分供电。注意,电路中区分了模拟地与参考地,二者在ADC附近通过0Ω电阻相连。MXO与AINP由于成本限制,选择了直接相连的方式。在输入端,利用33Ω电阻与150pF电容进行抗混叠滤波,低通截止频率为32MHz(这里是参考了小信号带宽47MHz)。最终设计的3D仿真图如下图所示:
在这里插入图片描述

第五章 基于STM32F103平台的Keil编程

在这里插入图片描述
由数据手册可知,该芯片由SPI协议驱动,故在Keil内使能SPI外设。通过查阅STM32F103的数据手册可知,该主控芯片有2个SPI外设。由于平台选用的是mcudev的STM32F103C8T6平台,如上图所示,其SPI2口上接了24C04,若直接将ADS79XX的SPI接至此处,会产生误码而导致无法通信。故选用SPI1接口,包括PA5~PA7。经过测试,将SPI协议配置如下:

void CS_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				 //CS2-->PA8 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOA,&GPIO_InitStructure);					 //根据设定参数初始化GPIOB0
	GPIO_SetBits(GPIOA,GPIO_Pin_8);							 //PA8 输出高
	
}
void ADS7960_Init(void)
{ 
	SPI_InitTypeDef SPI_InitStructure; //SPI结构体
	SPI_I2S_DeInit(SPI2);  //清空SPI2的所有设置
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//使能SPI2时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//GPIOB时钟
	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //禁用JTAG
	
	//PA5~PA7使能复用功能,SCK->PA5 MISO->PA6 MOSI->PA7
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //STM32F103为SPI的主机
	SPI_InitStructure.SPI_DataSize=SPI_DataSize_16b; //16位数据
	SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; //SCK引脚在空闲时为低电平
	SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge; //SCK时钟的第一个边沿进行数据位的采样,数据在第一个时钟边沿被锁存。
	SPI_InitStructure.SPI_NSS=SPI_NSS_Soft; //软件控制CS
	SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4; //4分频 9MHz
	SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; //数据高位在前
	SPI_InitStructure.SPI_CRCPolynomial=7;
	SPI_Init(SPI2,&SPI_InitStructure); //SPI2初始化

	SPI_Cmd(SPI2,ENABLE); //SPI2使能
	CS_Init();
	ADS7960_CS2=1;
}
u16 SPI1_ReadWriteByte(u16 TxData)
{		 			 
 
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空  
	
	SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个byte数据
		
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte  
 
	return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx上一时刻接收的数据	

}

以上便完成了STM32F103平台上的SPI初始化,接下来查阅数据手册,明确通过MOSI往ADC芯片内写入数据的含义。
在这里插入图片描述
选择自动模式auto-2(用于轮扫所有的通道)。可以看到:
DI15-DI12用于选择模式,将其置为0x3;
DI11用于使得DI10~DI0的设置有效,选为1;
DI10则用于控制通道,显然第一次调用时应当将其归1,从CH0开始,而后将其至1,每次通道加1;
DI09-DI07不关心,任意设置即可;
DI06选择转换范围,是2×VREF还是1×VREF,这里我们选用2倍参考输入,即5V输入范围;
DI05用于选择低功耗,这里我们不需要低功耗运行,故选择为1;
DI04为配置DO15-DO12的内容,这里我们不适用GPIO,故选择为0,这是DO15-DO12为通道代码,如CH0就为0x0,CH15就为0xF;
DI03-DI00用于配置GPIO,我们未用到,故将其置0.

此外,auto-2模式写入的设置在2次使能芯片后方才有效。也就是说,这时通过MOSI写入的指令在两次使能后才从MISO中输出。故读取指令编写如下:

void ADS7960_ReadSR2(u8* data)   
{  
	
	u16 byte[13]={0};
	ADS7960_CS2=0;                              //使能器件
	SPI2_ReadWriteByte(0x3C40);    //发送读取状态寄存器命令
	ADS7960_CS2=1;                              //取消片选
	delay_us(1);
	
	ADS7960_CS2=0;                              //使能器件
	byte[0]=SPI2_ReadWriteByte(0x3840);    //发送读取状态寄存器命令
	ADS7960_CS2=1;                              //取消片选
	delay_us(1);
	
	ADS7960_CS2=0;                              //使能器件
	byte[1]=SPI2_ReadWriteByte(0x3840);    
	data[0]=(byte[1]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	delay_us(1);
	
	ADS7960_CS2=0;                              //使能器件
	byte[2]=SPI2_ReadWriteByte(0x3840);    
	data[1]=(byte[2]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选

	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[3]=SPI2_ReadWriteByte(0x3840);    
	data[2]=(byte[3]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[4]=SPI2_ReadWriteByte(0x3840);    
	data[3]=(byte[4]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	//以下为ADS7960
	ADS7960_CS2=0;                              //取消片选
	byte[5]=SPI2_ReadWriteByte(0x3840);    
	data[4]=(byte[5]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[6]=SPI2_ReadWriteByte(0x3840);   
	data[5]=(byte[6]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[7]=SPI2_ReadWriteByte(0x3840);    
	data[6]=(byte[7]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[8]=SPI2_ReadWriteByte(0x3840);    
	data[7]=(byte[8]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[9]=SPI2_ReadWriteByte(0x3840);    
	data[8]=(byte[9]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[10]=SPI2_ReadWriteByte(0x3840);    
	data[9]=(byte[10]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	ADS7960_CS2=0;                              //取消片选
	byte[11]=SPI2_ReadWriteByte(0x3840);    
	data[10]=(byte[11]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
	
	ADS7960_CS2=0;                              //取消片选
	byte[12]=SPI2_ReadWriteByte(0x3840);    
	data[11]=(byte[12]&0x0FFF)>>4;
	ADS7960_CS2=1;                              //取消片选
	
	delay_us(1);
}

而后,通过USART1串口输出采样数值

u8 data[12]={0};
ADS7960_ReadSR2(data);
	for(i=0;i<=11;i++)
	{
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);  //线连不需要
	USART_SendData(USART1,data[i]);
	}

至此完成了ADS79XX模数转换器的配置与数据读取。
在这里插入图片描述
如有需要购买上图中的模块(价格为¥100,包顺丰),请私信我。程序相关代码在https://download.csdn.net/download/qq_43657314/12515311给出

参考文献

[1] TI ADS7952数据表, available at https://www.ti.com.cn/product/cn/ADS7952
[2] STM STM32F103C8T6数据表, available at https://www.stmcu.org.cn/document/list/index/category-154


版权声明:本文为qq_43657314原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。