
ADS8688评估板(开源)
简介
本项目制作了一个8通道的ADS8688芯片评估板,用户可以使用带有SPI通信接口的开发板配合ADS8688评估板即可学习ADS8688采集外界电压寄存器配置过程。
简介:本项目制作了一个8通道的ADS8688芯片评估板,用户可以使用带有SPI通信接口的开发板配合ADS8688评估板即可学习ADS8688采集外界电压寄存器配置过程。开源协议
:GPL 3.0
描述
1 项目简介
本项目制作了一个8通道的ADS8688芯片评估板,用户可以使用带有SPI通信接口的开发板配合ADS8688评估板即可学习ADS8688采集外界电压寄存器配置过程,笔者在ZYNQ开发板上学习ADS8688笔者最后放出ZYNQ7020平台下的ADS8688驱动代码,用户可根据自身情况进行移植。
2 项目声明
该项目仅限学习交流使用。
3 原理图讲解
3.1 电源
电源部分由三部分组成,TPS61040DBVRG4芯片产生6.3V电压,SPX3819M5-5.0芯片产生5V电压给ADS8688芯片供电,ADR444BRZ芯片产生ADS8688外部4.096V基准带电压(当然ADS8688也支持内部参考电压,通过REFSEL引脚选择基准电压来源)。
3.2 ADS8688电路
ADS8688 REFSEL引脚可以通过J1和J2跳线帽选择外部或者内部基准电压,SPI接口通过2X8PIN插针引出供通信板使用。
4 PCB实物
ADS8688正面照和背面照如下所示,笔者PCB布线水平有限,经过实际电压采样评估板个别通道之间电压存在10MV区别,板子使用需要用户根据实际电压和测量误差进行计算各通道特性值校准后才能精确测量外部电压。
5 芯片介绍
ADS8688是德州仪器(TI)推出的一款16位、500kSPS、8通道单电源供电的逐次逼近型(SAR)模数转换器(ADC)。其集成了模拟前端(AFE)电路,支持双极性和单极性输入范围,适用于高精度多通道数据采集系统。
上述状态转移图中除了PROG其余大致关注命令寄存器操作,芯片上电从RESET状态开始运行,左边的状态转移图描述芯片下电、读写程序寄存器、等待模式功能,右边状态转移图介绍了芯片处于电压采集模式。
6 驱动开发(程序寄存器读写模式)
6.1 读取与写入program寄存器时序(3字节模式)
官方手册程序寄存器的读写时序官方推荐的是3字节长度通信模式,读取模式和写入模式的区别在于MOSI的BYTE1最低位是0时为读取模式,否则为写入模式。
6.2 读取PROG AUTO_SEQ_EN 0X01
读取PROG AUTO_SEQ_EN 0X01的MISO时序为03 00 00,可见波形返回了00 00 FF其中FF为读取模式下从寄存器中读取的有效数据,这里FF也是PROG AUTO_SEQ_EN的默认值(初次上电)。
发送数据 02 00 00
接收数据 00 00 FF
6.3 读取Channel Power Down 0X02
读取Channel Power Down 0X02的MISO时序为04 00 00,可见波形返回了00 00 00其中FF为读取模式下从寄存器中读取的有效数据,这里MISO的BYTE3 00也是Channel Power Down的默认值(初次上电)。
发送数据 04 00 00
接收数据 00 00 00
6.4 写入Device Features Selection Control Register 0X03
Device Features Selection Control Register关系到指定设备在菊花链模式中的ID身份,和SPI通信模式中MISO输出长度(这个设置和命令模式读取ADC数据有关)。
此处我们将MISO的数据设置为07 03 00,表示在0X11寄存器中写入0000 0011表示设置当前设备的菊花链身份证为00,MISO的输出长度为16+25bit长度,其中24-9为ADC通道转换出的原始ADC数据,有的用户则不关心BIT8-0的信息,可以从模型上看MISO最后BYTE输出了0X03表示数据写入成功。
发送数据 07 03 00
接收数据 00 00 03
6.5 读取Device Features Selection Control Register 0X03
发送数据 06 03 00
接收数据 00 00 03
在没有其他操作破坏的情况下。
6.6 其余程序寄存器读写模式(3字节模式)
根据上述程序寄存器的读取和写入时序用户可根据自己需求自行读写相应的程序寄存器并抓取相应的波形验证芯片工作状态。
7 驱动开发(命令寄存器读写模式)
7.1 手动获取通道0数据(6字节模式)
在芯片默认工作模式下所有通道都打开(Auto-Scan Sequence Enable Register),所有通道都设置No Power Down(Channel Power Down Register),并且所有通道输入电压量程范围默认正负2.5*Vref(Channel Power Down Register )。
命令寄存器读写模式下获取通道0的ADC采样值,MISO的通信数据为C4 00 00 00 00 00表示要读取通道0数据,MOSI返回的数据则是00 00 9B D7 10 00,从这张图中虚线部分就表示SDO输出模式可以通过Device Features Selection Control Register进行长度配置。
发送数据 C4 00 00 00 00 00
接收数据 00 00 9B D7 10 00
这样做的目的是为零读取SDO在25bit模式下读取数据,prog寄存器读写模式下SDO在特定时间后进入高阻态不受SDO输出格式影响,9B D7为ADS8688芯片16bit原生ADC采样数据,8-5bit显示现在是第一通道,4-3显示现在是菊花链模式设备地址00表示标号0设备,2-0表示ADC通道选择的输入采样电压范围是2.5xVref。
当然用户也可以使用4字节模式进行通信,只用拿取原始ADC16bit数据,随着下一次的SPI复位,重新一帧SPI通信又开始了,那么BIT8到BIT0的数据则可以不用关心了。
7.2 NO OPERATION(6字节模式)
NO OPERATION模式命令在6字节通信模式中MSB的前16Bit命令为0000h,其余部分和其他命令寄存器操作则一致。NO OPERATION一般用在电压采样模式和空操作等待中。
发送数据 00 00 00 00 00 00
接收数据 00 00 9B B4 10 00
7.3 STANDBY MODE(6字节模式)
发送数据 82 00 00 00 00 00
接收数据 00 00 FF FF FF 80
7.4 Auto Channel Enable with Reset(6字节模式)
发送数据 A0 00 00 00 00 00
接收数据 00 00 FF FF FF 80
7.4.1 第1个NO OPREATION
自动读取第一通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B A8 00 00
7.4.2 第2个NO OPREATION
自动读取第二通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B B4 10 00
7.4.3 第3个NO OPREATION
自动读取第三通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B E1 20 00
7.4.4 第4个NO OPREATION
自动读取第四通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B A6 30 00
7.4.5 第5个NO OPREATION
自动读取第五通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B D1 40 00
7.4.6 第6个NO OPREATION
自动读取第六通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B E9 50 00
7.4.7 第7个NO OPREATION
自动读取第七通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B A5 60 00
7.4.8 第8个NO OPREATION
自动读取第八通道的电压数据
发送数据 00 00 00 00 00 00
接收数据 00 00 9B CB 70 00
7.5 Power-Down Mode(PWR_DN)(6字节模式)
发送数据 83 00 00 00 00 00
接收数据 00 00 FF FF FF 80
假设后续有手动获取ADC数据或者自动获取ADC数据等操作会将掉电通道重新进行唤醒。
8 电压换算
经过以下代码初始化,ADS8688被配置成所有通道开启不下电,并且所有通道处量程处于正负10.24V,并且MISO的在命令操作模式下的SDO数据长度被配置为25bit,所以需要6字节长度才能读取完整信息,以7.4.1 第1个NO OPREATION操作读取到的就是第一通道的数据XX XX 9B A8 00 00,其中9B A8才是ADC电压数据,00 00为通道状态信息,9B A8经过(0X98A8-0X8000)(2.54.096*2)/0XFFFF=0.986265V, 用户可根据自身情况进行验证。
int8_t ADS8688_Init_Mult(XSpiPs *XSpiPs_Instance)
{
int8_t ads8688_status;
ADS8688RST_PD_H;
ADS8688DAISY_IN_L;
ads8688_reset_program_register(XSpiPs_Instance); //software reset
ads8688_program_register_write(XSpiPs_Instance, 0X01, 0XFF); //Auto-Scan Sequence Enable Register, open 8 channles
ads8688_program_register_write(XSpiPs_Instance, 0X02, 0X00); //Channel Power Down Register, power up 8 channles
ads8688_program_register_write(XSpiPs_Instance, 0X03, 0X03); //Device Features Selection Control Register, device 0 is in daisy mode, sdo mode is 25bit
ads8688_write_reg_range(XSpiPs_Instance, 1, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 2, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 3, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 4, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 5, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 6, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, 7, 0X00);
sleep(1);
ads8688_status = ads8688_auto_channel_enable_with_reset(XSpiPs_Instance); //Open channel loop to acquire voltage mode.
return ads8688_status;
}
9 驱动开发(ADS8688驱动文件)
9.1 头文件
#ifndef __ADS8688_H_
#define __ADS8688_H_
#include "sleep.h"
#include "xgpiops.h"
#include "xspips.h"
#include "COMMON.h"
#define ADS8688RST_PD_PIN_NUMBER 54 //V10
#define ADS8688DAISY_PIN_NUMBER 55 //V12
#define ADS8688_PIN_OUTPUT_MODE 0
#define ADS8688_PIN_INPUT_MODE 1
#define ADS8688DAISY_IN_H XGpioPs_WritePin(&GpioPs, ADS8688DAISY_PIN_NUMBER, 1);
#define ADS8688DAISY_IN_L XGpioPs_WritePin(&GpioPs, ADS8688DAISY_PIN_NUMBER, 0);
#define ADS8688RST_PD_H XGpioPs_WritePin(&GpioPs, ADS8688RST_PD_PIN_NUMBER, 1);
#define ADS8688RST_PD_L XGpioPs_WritePin(&GpioPs, ADS8688RST_PD_PIN_NUMBER, 0);
//Command Register
#define ADS8688_CMD_REG_NOOP 0x00
#define ADS8688_CMD_REG_STDBY 0x82
#define ADS8688_CMD_REG_PWRDN 0x83
#define ADS8688_CMD_REG_RST 0x85
#define ADS8688_CMD_REG_AUTORST 0xA0
#define ADS8688_CMD_REG_MANAUX 0xE0
#define ADS8688_CMD_REG(x) (x << 8)
#define ADS8688_CMD_REG_MAN_CH(chan) (0xC0 | (4 * chan))
#define ADS8688_CMD_DONT_CARE_BITS 16
//Program Register
#define ADS8688_PROG_REG_AUTOSEQEN 0x01
#define ADS8688_PROG_REG_CPD 0x02
#define ADS8688_PROG_REG_FS 0x03
#define ADS8688_PROG_REG(x) (x << 9)
#define ADS8688_PROG_REG_RANGE_CH(chan) (0x05 + chan)
#define ADS8688_PROG_REG_ALARMFROVERTF 0x10
#define ADS8688_PROG_REG_ALARMFRCH0_3TF 0x11
#define ADS8688_PROG_REG_ALARMFRCH0_3AF 0x12
#define ADS8688_PROG_REG_ALARMFRCH4_7TF 0x13
#define ADS8688_PROG_REG_ALARMFRCH4_7AF 0x14
#define ADS8688_PROG_REG_ALARMTRCHNHYS(chan) (0x15 + chan)
#define ADS8688_PROG_REG_ALARMTRCHNHTM(chan) (0x16 + chan)
#define ADS8688_PROG_REG_ALARMTRCHNHTL(chan) (0x17 + chan)
#define ADS8688_PROG_REG_ALARMTRCHNLTM(chan) (0x18 + chan)
#define ADS8688_PROG_REG_ALARMTRCHNLTL(chan) (0x19 + chan)
#define ADS8688_PROG_REG_CRB 0x3F
#define BIT(nr) (1UL << (nr))
#define ADS8688_PROG_WR_BIT BIT(8)
#define ADS8688_PROG_DONT_CARE_BITS 8
#define ADS8688_REG_PLUSMINUS25VREF 0
#define ADS8688_REG_PLUSMINUS125VREF 1
#define ADS8688_REG_PLUSMINUS0625VREF 2
#define ADS8688_REG_PLUS25VREF 5
#define ADS8688_REG_PLUS125VREF 6
#define ADS8688_VREF_MV 4096
#define ADS8688_REALBITS 16
#define ADS8688_MAX_CHANNELS 8
typedef struct {
/* SPI */
XSpiPs *XSpiPs_Instance;
uint16_t csPin;
} ADS8688_t;
/*
* enum ads8688_range - ADS8688 reference voltage range
* @ADS8688_PLUSMINUS25VREF: Device is configured for input range 卤2.5 * VREF
* @ADS8688_PLUSMINUS125VREF: Device is configured for input range 卤1.25 * VREF
* @ADS8688_PLUSMINUS0625VREF: Device is configured for input range 卤0.625 * VREF
* @ADS8688_PLUS25VREF: Device is configured for input range 0 - 2.5 * VREF
* @ADS8688_PLUS125VREF: Device is configured for input range 0 - 1.25 * VREF
*/
enum ads8688_range {
ADS8688_PLUSMINUS25VREF,
ADS8688_PLUSMINUS125VREF,
ADS8688_PLUSMINUS0625VREF,
ADS8688_PLUS25VREF,
ADS8688_PLUS125VREF,
};
/********************************************************initialize the ADS8688 hardware****************************************************/
int8_t ads8688_hardware_init(void);
int8_t ads8688_init(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
/********************************************************Write/Read ads8688 cmd/prog data with spi interface********************************/
uint8_t ads8688_program_register_write(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr, uint32_t val);
uint8_t ads8688_program_register_read(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr);
uint16_t ads8688_command_register_wr(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr, uint32_t val);
/********************************************************Set ads8688 mode(cmd register)*****************************************************/
uint16_t ads8688_no_operation(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
uint16_t ads8688_standby(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
uint16_t ads8688_power_down(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
uint16_t ads8688_reset_program_register(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
uint32_t ads8688_auto_channel_enable_with_reset(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
uint32_t ads8688_manual_channeln_read(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t chan);
uint16_t ads8688_manual_aux_select(XSpiPs *XSpiPs_Instance, uint8_t cs_number);
/********************************************************make ads8688 function**************************************************************/
int8_t ads8688_write_reg_range(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t chan, uint8_t range);
int8_t ADS8688_Init_Single(XSpiPs *XSpiPs_Instance, uint8_t cs_number); //The input voltage single mode
int8_t ADS8688_Init_Mult(XSpiPs *XSpiPs_Instance, uint8_t cs_number); //The input voltage differential mode
#endif
9.2 源文件
#include "ADS8688.h"
#include "COMMON.h"
/********************************************************initialize the ADS8688 hardware****************************************************/
int8_t ads8688_hardware_init(void)
{
PS_GPIO_SetMode(ADS8688RST_PD_PIN_NUMBER, ADS8688_PIN_OUTPUT_MODE, 1);
ADS8688RST_PD_L;
usleep(1000);
ADS8688RST_PD_H;
return 0;
}
int8_t ads8688_init(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
return 0;
}
/********************************************************Give ads8688 cmd/prog data with spi interface********************************/
uint8_t ads8688_program_register_write(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr, uint32_t val)
{
uint8_t spi_data_tx[3] = {0, 0, 0};
uint8_t spi_data_rx[3] = {0, 0, 0};
uint8_t write_val;
uint32_t temp_data = ADS8688_PROG_REG(addr) | ADS8688_PROG_WR_BIT | val;
temp_data = temp_data << ADS8688_PROG_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 16) & 0xFF;
spi_data_tx[1] = (temp_data >> 8) & 0xFF;
spi_data_tx[2] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 3);
write_val = spi_data_rx[2];
return write_val;
}
/********************************************************Read ads8688 prog data with spi interface********************************/
uint8_t ads8688_program_register_read(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr)
{
uint8_t spi_data_tx[3] = {0, 0, 0};
uint8_t spi_data_rx[3] = {0, 0, 0};
uint8_t ads8688_prog_read_data;
uint32_t temp_data = ADS8688_PROG_REG(addr);
temp_data = temp_data << ADS8688_PROG_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 16) & 0xFF;
spi_data_tx[1] = (temp_data >> 8) & 0xFF;
spi_data_tx[2] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 3);
ads8688_prog_read_data = spi_data_rx[2];
return ads8688_prog_read_data;
}
/********************************************************Write/Read ads8688 command data with spi interface********************************/
uint16_t ads8688_command_register_wr(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t addr, uint32_t val)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
uint16_t ads8688_read_data;
uint32_t temp_data = ADS8688_CMD_REG(addr);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
ads8688_read_data = (spi_data_rx[2] << 8) | (spi_data_rx[3]);
return ads8688_read_data;
}
/********************************************************Set ads8688 mode*******************************************************************/
uint16_t ads8688_no_operation(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
uint16_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_NOOP);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
channeln_data = spi_data_rx[2] << 8;
channeln_data = channeln_data | spi_data_rx[3];
return channeln_data;
}
uint16_t ads8688_standby(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
uint16_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_STDBY);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
channeln_data = spi_data_rx[2] << 8;
channeln_data = channeln_data | spi_data_rx[3];
return channeln_data;
}
uint16_t ads8688_power_down(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
uint16_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_PWRDN);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
channeln_data = spi_data_rx[2] << 8;
channeln_data = channeln_data | spi_data_rx[3];
return channeln_data;
}
uint16_t ads8688_reset_program_register(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
uint16_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_RST);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
channeln_data = spi_data_rx[2] << 8;
channeln_data = channeln_data | spi_data_rx[3];
return channeln_data;
}
uint32_t ads8688_auto_channel_enable_with_reset(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[6] = {0, 0, 0, 0, 0, 0};
uint8_t spi_data_rx[6] = {0, 0, 0, 0, 0, 0};
uint32_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_AUTORST);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
spi_data_tx[4] = 0;
spi_data_tx[5] = 0;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 6);//get 25bit sample sdo data with 6bytes mode, you can change it as you like.
channeln_data = (spi_data_rx[2] << 24) | (spi_data_rx[3] << 16) | (spi_data_rx[4] << 8) | (spi_data_rx[5]);
return channeln_data;
}
uint32_t ads8688_manual_channeln_read(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t chan)
{
uint8_t spi_data_tx[6] = {0, 0, 0, 0, 0, 0};
uint8_t spi_data_rx[6] = {0, 0, 0, 0, 0, 0};
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_MAN_CH(chan));
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
uint32_t channeln_data = 0;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
spi_data_tx[4] = 0;
spi_data_tx[5] = 0;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 6);//get 25bit sample sdo data with 6byte mode, you can change 16bit sample data withe 4byte mode as you like.
channeln_data = (spi_data_rx[2] << 24) | (spi_data_rx[3] << 16) | (spi_data_rx[4] << 8) | (spi_data_rx[5]);
return channeln_data;
}
uint16_t ads8688_manual_aux_select(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
uint8_t spi_data_tx[4] = {0, 0, 0, 0};
uint8_t spi_data_rx[4] = {0, 0, 0, 0};
int8_t channeln_data;
uint32_t temp_data = ADS8688_CMD_REG(ADS8688_CMD_REG_MANAUX);
temp_data = temp_data << ADS8688_CMD_DONT_CARE_BITS;
spi_data_tx[0] = (temp_data >> 24) & 0xFF;
spi_data_tx[1] = (temp_data >> 16) & 0xFF;
spi_data_tx[2] = (temp_data >> 8) & 0xFF;
spi_data_tx[3] = temp_data & 0xFF;
PS_SPI_Transfer(XSpiPs_Instance, cs_number, spi_data_tx, spi_data_rx, 4);
channeln_data = spi_data_rx[2] << 8;
channeln_data = channeln_data | spi_data_rx[3];
return channeln_data;
}
int8_t ads8688_write_reg_range(XSpiPs *XSpiPs_Instance, uint8_t cs_number, uint32_t chan, uint8_t range)
{
uint32_t temp_data = ADS8688_PROG_REG_RANGE_CH(chan);
return ads8688_program_register_write(XSpiPs_Instance, cs_number, temp_data, range);
}
int8_t ADS8688_Init_Single(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
return 0;
}
int8_t ADS8688_Init_Mult(XSpiPs *XSpiPs_Instance, uint8_t cs_number)
{
int8_t ads8688_status;
ADS8688RST_PD_H;
ADS8688DAISY_IN_L;
ads8688_reset_program_register(XSpiPs_Instance, cs_number); //software reset
ads8688_program_register_write(XSpiPs_Instance, cs_number, 0X01, 0XFF); //Auto-Scan Sequence Enable Register, open 8 channles
ads8688_program_register_write(XSpiPs_Instance, cs_number, 0X02, 0X00); //Channel Power Down Register, power up 8 channles
ads8688_program_register_write(XSpiPs_Instance, cs_number, 0X03, 0X03); //Device Features Selection Control Register, device 0 is in daisy mode, sdo mode is 25bit
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 1, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 2, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 3, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 4, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 5, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 6, 0X00);
ads8688_write_reg_range(XSpiPs_Instance, cs_number, 7, 0X00);
sleep(1);
ads8688_status = ads8688_auto_channel_enable_with_reset(XSpiPs_Instance, cs_number); //Open channel loop to acquire voltage mode.
return ads8688_status;
}
void PS_SPI_Transfer(XSpiPs *SpiInstPtr, uint32_t Sel_Num, uint8_t *WriteBuffer, uint8_t *ReadBuffer, uint32_t BUFFER_SIZE)
{
//选择片选设备,一共3位
XSpiPs_SetSlaveSelect(SpiInstPtr, Sel_Num);
//与从机进行数据传输,每发送一个字节就接受一个字节,发送的数据为WriteBuffer里的内容,接收的数据存在ReadBuffer里
XSpiPs_PolledTransfer(SpiInstPtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);
}
设计图

BOM


评论