SPI配置高精度采集8通道24位ADS1256(卷一---datasheet阅读总结篇)

0、引言

断断续续又隔了一个月,看datasheet总共加起来应该有10遍吧,第一遍十分慢的读,第二遍慢读,第三遍快读。。。直到第10遍略读标记重点。看得滚瓜烂熟了,现在终于开始打算写代码了,虽然datasheet有的模拟电路的地方,我也看不太明白,但是把对应的寄存器看明白了,大概功能能用了,也就差不多可以写代码了。本篇文章先总结一下24位的8通道24bit高精度采集的24位ADS1256,本篇文章不是纯粹的datasheet的抄袭,而是datasheet的总结,高度概括,以及对我们编程有用的思路,我大概看了一下网上流传的版本,大多数都是STM32,另外有一份是verilog不知道是谁写的,各个网都有,它是多通道采集,仅仅使用了一种模式,而且让人看起来费解,更改起来也不方便,我追求高质量的代码,也就是只用更改parameter参数,就可以立马改变功能。本文将关于AD9361的知网论文资料、标记重点以及自己注释了的芯片手册、以及官网原版datasheet以及网上流传的付费下载的AD1256的代码,我都打包放在文章最后了,物超所值。

1、芯片介绍ADS1256

  • 24位速率和PGA改变

  • 高达23位的无噪声分辨率

  • 数据率达30KSPS。

  • 快速的通道切换。(这里需要了解一下AD的有效位effective Bits)

  • 一个触发转换(单通道时候)

  • 灵活可配备传感器检测的输入通道选择(4个差分 or 8个单通道)

  • 达80欧的输入buffer(提高输入阻抗)

  • 低噪声的PGA设置

  • 自校正和系统校正

  • 低功耗:

     	1、38mW(正常模式)
     	2、0.4mW(待机模式)
    

1.1 描述

在这里插入图片描述
从上图中,我们可以看到在模拟输入端,包括了输入通道选择的寄存器、buffer、PGA。
在可编程数数字滤波器可以设置SPS(采样速率达30KSPS)
在通用数字口可以配置将D0端口设置为输出或者关闭。用于别的ADS1256的时钟(‘晶振’)

1.2 管脚

在这里插入图片描述
我们需要关注的是管脚CS_n 、DIN、DOUT、SCLK、DRDY_n。这几个,我们这里要说明的是DRDY_n这个管脚。其它三个,对于知道SPI协议的都非常熟悉了,不熟悉的可以去了解基础知识再说。对于DRDY_n,官方给出的解释是,只要DRDY_n为低,表示数据有效,可以被读取了,也就是说采样后已经被量化了。在高电平的时候,是不能读取的。

在这里插入图片描述
上图是官方给出的管脚解释,非常简单。

1.3 串行接口时序

在这里插入图片描述在这里插入图片描述
以上其它的我们都不用多说,重点我们说一下fCLKIN的时钟是7.68MHz,也就是晶振是7.68MHz,这个是这款芯片推荐的AD时钟主频。
另外说一下DIN和DOUT的写入和读取,官方的意思是在下降沿将数据移出来到DOUT线上,读取的话当然要是在下降沿。写入,当然是要在上升沿送入到DIN线上,然后AD1256读取,是在下降沿读取的。所以对于FPGA来说,DIN是在上升沿,DOUT是在下降沿,对于ADS1256来说,读取DIN是在下降沿,输出到DOUT是在上升沿。而我们设计的是FPGA,所以我们需要符合DIN是在上升沿,DOUT是在下降沿。
最后,我们还要说的是t6和t11这两个时间点。t6是在输入命令用于将数据移出到DOUT上面的延时,这些命令包括了RDATA、RDATAC、RREG这三个命令,都会让数据移出去到DOUT线上,而让这些数据移到DOUT需要一定的延时时间,这段延时时间的就是t6.
最后的t11时间点,这个等会儿,我再来说,这个有点迷糊。
在这里插入图片描述

1.4 复位方式

复位的方式,可以用SCLK满足一定的时序来复位,也可以直接用RESET管脚复位。
在这里插入图片描述
下图是采用复位信号输入,保持reset的t16时间,就可以复位
在这里插入图片描述
以上的 t 时序这里就不再赘述,看芯片手册的表格即可。
这里要复位直接采用reset_n更为方便,我们决定采用RESET_N来复位,而不采用SCLK来复位。

1.5 DRDY_n 时序

在这里插入图片描述
以上图片我们可以知道在t17阶段,数据是不能被读取的。另外最小是16个τCLKIN,具体是多少这个跟你配置的DATA_rate的设置有关系。

1.6 同步SYNC的时序

在这里插入图片描述
要同步SYNC,要么采用管脚SYNC,要么发出SYNC的命令。这里我们打算采用的是发出SYNC命令。

2、分立部件

2.1 INPUT MULTIPLEXER输入通道选择器

同一时刻,只能有一个通道输入,所以输入通道的选择控制由 MULTIPLEXER 寄存器控制。AINp是正,如果采用单端输
入,那么AINN则接地。
提醒:
在这里插入图片描述

2.2 OPEN/SHORT SENSOR DETECTION 开路/短路的传感器检测

传感器检测电流源(SDCS)提供了一种方法来验证连接到ADS1255/6的外部传感器的完整性。(说实话,我没看懂,尴尬)
没关系,我们采用关闭这个传感器检测。我个人猜的话,可能就是用于判断是否给模拟输入端输入了信号,是否是开路还是短路状态。
当SDCS使能的时候,ADS1256将会自动的打开模拟输入端的buffer,无视buffer的bit位设置。这样做可以防止输入信号从SDCS中加载信号。
总而言之,模拟的部分,我没看太懂,但是我们可以知道的是开了SDCS的话,就可以防止在开路短路的时候测量。

2.3 PGA(可编程的增益放大器)

在这里插入图片描述
上述表格的意义就很有意思了,PGA的设置也不是随便设置的,当要测量特别小的信号时候,PGA就非常有用了,这一点要根据满量程最大的输入电压选择合适的PGA。PGA的设置在ADCON寄存器中。
重要:
在这里插入图片描述
在改变PGA的设置后,需要重新校准A/D转换器

2.4 DIGITAL FILTER(数字滤波器)

可以权衡数据速率(采样率)和分辨率。
数据速率的配置在DRATE里面设置。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是幅频响应
在这里插入图片描述
在这里插入图片描述

3 模式

首先要说一下在AD1256这款芯片里面,有SETTLING TIME这个概念。
The settling time指的是从模拟输入端到数字滤波器的传播延时,对于不同的数据速率,The SETTLING TIME对应不同。使用不同的模式,会产生不同的setting time。
在这里插入图片描述
这个都没关系DRDY_n作为输入信号,ADS1256会发出低电平指示我们可以开始读取数据了。

以下都是基于buffer、PGA、datarate的初始化设置完毕后。采取的模式选择。

3.1 单通道同步模式

在这里插入图片描述
在初始化完毕后,发送同步命令、或者通过SYNC/PWND的管脚发出的同步命令后,进入setting time (t18)。
然后在DRDY_n在低电平的时候后发出RDATA命令,接着读取即可。
这种模式也是十分简单的。

3.2 使用输入选择器切换通道

最有效的切换(cycle through)改变输入通道的方式就是使用WREG 命令给MUX寄存器,在DRDY_n变低后,发出WREG命令,然后改变通道,通过发出SYNC和WAKEUP的命令重新启动转换,并且以RDATA发出命令后读取数据。并且这里我们要注意了,当输入通道切换时,我们完全没有必要丢弃数据,因为ADS1256在DRDY_n走低前,就可以完全获得稳定的数据指示读取数据已经准备好了。不过读取数据,是读取的上一个通道的数据。当DRDY_n再次走低的时候吧,通过更新多通道寄存器重复循环。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 使用单触发模式(节能模式)

使用STANDBY 命令可以让功耗大量的减小,通过发出wakeup命令可以从待机模式到单触发转换。使用这种模式,会有一个额外的延时需要用于ADC的调制器的启动和稳定。
在这里插入图片描述
在这里插入图片描述

3.4 连续转换模式(RDATAC)

这种模式的意思就是说,转换只需要一RDATAC,而不需要发送一个rdata,读取一个DOUT。
使用这种连续转换的读取方式,是在同步、输入寄存器改变后,或者从待机模式下唤醒后,都可以使用这种连续读取的方式。这种方式其他都一样,只不过读取不再是使用发送一个rdata,然后读取数据。而是只需要发送一次rdatac后,以后就在drdy_n的低电平,直接读取数据,即可。不过这个取决于DRDY_n的周期个数。下图是不同的SPS对应的DRDY_n的周期。如果不按照周期读取,那么可能读到旧数据和新数据的混合物。
所以,这种连续读取的模式,我不太建议,这里我们不做实现。就算实现,我觉得也只能在单通道的采集的情况下实现好点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、校准

OFC校准:offset calibration
FSC校准: full-scale calibration
在这里插入图片描述
在这里插入图片描述
DRDY_n goes high when calibration begins and remains so until settled data is ready afterwards.
DRDY_n会一直走高,当校准开始时,直到数据准备完毕。
下面这段话就很关键了,在reset复位后、上电后、buffer改变、数据率改变、PGA改变后都要执行自校验。
在这里插入图片描述
以下是在不同数据率下理想的OFC和FSC,但是这点都不重要,我们交给系统自动校验即可,不用专门通过寄存器的方式写入。
在这里插入图片描述

4.1自校准 self-calibration

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上官方建议,强烈推荐上电后使用SELFCAL命令。虽然配置了自动自校验。

使用SELFOCAL、SELFGCAL、SELFCAL这三个命令

4.2 系统校准 system-calibration

系统校准使用命令SYSOCAL 和SYSGCAL命令
在这里插入图片描述
在这里插入图片描述

4.3 自动校验

在这里插入图片描述

系统校验,是平时不用的,这里我们可以忽略掉。

我们这里推荐自动校验。自动校验可以自动初始化自校验,在使用WREG命令完成数据速率、PGA设置、或者Buffer状态的设置后自动发起自校验。
在这里插入图片描述
这里我们推荐,使用自动校验。然后在上电后,额外发送一个SELFCAL命令。

5、寄存器

在这里插入图片描述

6、命令

在这里插入图片描述

7、编程思路

对其余三种模式,均做实现,对于连续读取模式不做实现。
上电后,初始化,发送额外的自校验命令,接着发送配置寄存器的信息,最后开始进行模式选择,不同的模式,可以根据1、2、3,选择三种不同的模式,来读取数据。

8、ADS1256的所有资料福利链接

包含了:官方datasheet一份、CSDN付费下载的ADS1256 verilog一份、划重点注释后的ADS1256 datasheet一份、ADS1256的相关知网论文。
福利链接:https://download.csdn.net/download/ciscomonkey/11123767

  • 79
    点赞
  • 455
    收藏
    觉得还不错? 一键收藏
  • 41
    评论
STM32单片机(STM32F429)读写(8通道带PGA的24ADC)ADS1256软件例程源码,可以做为你的学习设计参考。 int main(void) { uint8_t i; bsp_Init(); PrintfLogo(); /* 打印例程Logo到串口1 */ bsp_DelayMS(100); /* 等待上电稳定,等基准电压电路稳定, bsp_InitADS1256() 内部会进行自校准 */ bsp_InitADS1256(); /* 初始化配置ADS1256. PGA=1, DRATE=30KSPS, BUFEN=1, 输入正负5V */ /* 打印芯片ID (通过读ID可以判断硬件接口是否正常) , 正常时状态寄存器的高4bit = 3 */ #if 0 { uint8_t id; id = ADS1256_ReadChipID(); if (id != 3) { printf("Error, ASD1256 Chip ID = 0x%X\r\n", id); } else { printf("Ok, ASD1256 Chip ID = 0x%X\r\n", id); } } #endif ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_30SPS); /* 配置ADC参数: 增益1:1, 数据输出速率 1KHz */ ADS1256_StartScan(); /* 启动中断扫描模式, 轮流采集8个通道的ADC数据. 通过 ADS1256_GetAdc() 函数来读取这些数据 */ while (1) { bsp_Idle(); /* 空闲时执行的函数,比如喂狗. 在bsp.c中 */ /* 打印采集数据 */ for (i = 0; i < 8; i++) { int32_t iTemp; iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; /* 计算实际电压值(近似估算的),如需准确,请进行校准 */ if (iTemp < 0) { iTemp = -iTemp; printf("%d=%6d,(-%d.%03d %03d V) ", i, g_tADS1256.AdcNow[i], iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000); } else { printf("%d=%6d,( %d.%03d %03d V) ", i, g_tADS1256.AdcNow[i], iTemp/1000000, (iTemp%1000000)/1000, iTemp%1000); } } printf("\r\n"); bsp_DelayMS(500); /* 每隔500ms 输出一次数据 */ } }
很抱歉,我无法提供完整的程序代码。但是,我可以提供一些关于如何编写这样一个程序的提示和指导。 首先,你需要配置STM32的SPI2端口,并且将SPI2端口配置为DMA传输模式。下面是一个简单的SPI2配置代码的示例: ```c void SPI2_Init(void) { // Enable the clock for SPI2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // Configure the SPI2 pins GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); // Connect SPI2 pins to Alternate Function GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // Configure the SPI2 peripheral SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); // Enable SPI2 SPI_Cmd(SPI2, ENABLE); } ``` 接下来,你需要配置ADS1256驱动器。这个过程可能会有些复杂,因为ADS1256配置需要一些特殊的寄存器设置。这里提供一个示例代码来配置ADS1256: ```c void ADS1256_Init(void) { // Reset ADS1256 ADS1256_Reset(); // Set the input multiplexer to AIN0 and AIN1 ADS1256_WriteRegister(REG_MUX, (0 << 4) | (1 << 0)); // Set the gain to 1 and the data rate to 15SPS ADS1256_WriteRegister(REG_ADCON, (0 << 0) | (7 << 3)); // Perform a self-calibration ADS1256_SelfCalibrate(); } ``` 接下来,你需要使用DMA传输模式来实现SPI2端口的数据采集。这可以通过使用STM32的DMA控制器来实现。下面是一个简单的DMA配置代码的示例: ```c void DMA_Init(void) { // Enable the clock for DMA RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Configure the DMA channel for SPI2 RX DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 25000; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); // Enable the DMA channel for SPI2 RX DMA_Cmd(DMA1_Channel4, ENABLE); } ``` 最后,你需要编写一个主函数来控制ADS1256和DMA传输,并将采集到的数据存储到一个缓冲区中。下面是一个简单的主函数示例: ```c uint8_t buffer[25000]; int main(void) { // Initialize the system clock SystemInit(); // Initialize SPI2 SPI2_Init(); // Initialize ADS1256 ADS1256_Init(); // Initialize DMA DMA_Init(); // Start ADC conversions ADS1256_Start(); // Wait for DMA transfer to complete while (DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET); // Disable DMA channel for SPI2 RX DMA_Cmd(DMA1_Channel4, DISABLE); // Process the data in the buffer ProcessData(buffer, 25000); // Infinite loop while(1); } ``` 上述示例代码中的ProcessData函数是用来处理采集到的数据的自定义函数。 需要注意的是,以上代码示例只是作为参考,实际的程序代码需要根据具体的需求进行修改和调整。在编写程序时,请务必参考STM32的官方文档和ADS1256的数据手册。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值