提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 1.AD7190概述
- 2.硬件设计分析
- 3.时序图解说
- 4.核心源码
- 5.测试结果
- 6.总结
- STM32驱动AD7190
- ad7190官方驱动
原文链接:https://blog.csdn/tanbohong004/article/details/73824988/
1.AD7190概述
AD7190是一款适合高精密测量应用的低噪声完整模拟前端。它集成一个低噪声、24位Σ-Δ型模数转换(ADC)。片内低噪声增益级意味着可直接输入小信号。
这款器件可配置为两路差分输入或四路伪差分输入。片内通道序列器可以使能多个通道,AD7190按顺序在各使能通道上执行转换,这可以简化与器件的通信。片内4.92 MHz时钟可以用作ADC的时钟源;或者,也可以使用外部时钟或晶振。该器件的输出数据速率可在4.7 Hz至4.8 kHz的范围内变化。
这款器件提供两种数字滤波器选项。滤波器的选择会影响以编程输出数据速率工作时的均方根噪声和无噪声分辨率、建立时间以及50 Hz/60 Hz抑制。针对要求所有转换均需建立的应用,AD7190具有零延迟特性。该器件采用5 V模拟电源和2.7 V至5.25 V的数字电源供电,功耗为6mA,提供24引脚TSSOP封装。
AD7190性价比很高,出货量大,用量也很大,供货很稳定,非常适用于中低速高精度的测试,如电子秤、应变计、气体分析、仪器仪表、压力传感器、血液分析、工业过程控制、医疗科学仪器等应用。本人对AD7190做了一次比较测试,分享下测试的结果
2.硬件设计分析
从结构图可以看出来,AD7190是模拟区域与数字区域完全独立的ADC,即AVDD给模拟区域供电,DVDD给数字区域供电,在原理图设计方面按照官方指导文档,需要对两个区域做独立的布线与隔离处理,才能让信噪比最佳。另可靠的基准电压是高精度ADC命根,本次试验选择TI公司推出的REF5025作基准参考,REF5025可低于3µVpp/V 噪声、3ppm/°C 漂移,性能是十分出色的。
由于经常做高频类项目,十分讨厌杜邦线/飞线测试方式,在高精度的领域,24位ADC梯度值2的2416777216,如果接入基准电压是2.5v,理论分辨率可达到0.149μV,做过高频的工程师深知杜邦线的罪恶,根据上面的技术分析,哪怕线路被引入1μV的干扰,也可以让精度打上一定折扣。为了让AD7190性能得以充分体现,特意做了一个测试载板,载板的设计也是很关键,分割模拟数字区域同时,连接地方大量使用钽电容做旁路电路,以把波纹抑制到最小,合理的布局与布线也很重要,敷铜区域也需要模数分离,以磁珠或者0-5R/电感隔开。
3.时序图解说
由时序图看出来,AD7190读写是简单的3线串行读数方式,属于Microwire串行接口,STM32的SPI接口可以完美的与之匹配,当然也可以采用软仿SPI替代STM32的硬件SPI,这样的程序更具移植性。SPI时序实现也相对简单,AD7190的CS线仅仅只是做片选使用(上图所示),而不用过多管理,保持低电平即可。特别需要注意的是在空闲时候,SCLK时钟信号需要保持高电平,在SCLK半个周期当DIN接收到0x58后转换的数据才传入到DOUT总线,这时候才能读取数据。从时序图上看,与AD7799十分类似的,只是延时上要稍做一些处理。
4.核心源码
//寄存器列表
#define ComState_register (0)<<3
#define Mode_register (1)<<3
#define Config_register (2)<<3
#define Data_register (3)<<3
#define ID_register (4)<<3
#define GPOCON_register (5)<<3
#define Disorders_register (6)<<3
#define FullScale_register (7)<<3
//模式寄存器
#define MODE_ADC_OneByOne (0)<<21
#define MODE_ADC_OnlyOne (1)<<21
#define MODE_ADC_Free (2)<<21
#define MODE_ADC_SavePower (3)<<21
#define MODE_ADC_AdjustZero (4)<<21
#define MODE_ADC_AdjustFull (5)<<21
#define MODE_ADC_SysAdjustZero (6)<<21
#define MODE_ADC_SysAdjustFull (7)<<21
#define MODE_MCLK_OUTosc (0)<<18
#define MODE_MCLK_OUTclo (1)<<18
#define MODE_MCLK_IN (2)<<18
#define MODE_MCLK_INcloOut (3)<<18
#define MODE_SINC3 (1)<<15
#define MODE_ENPAR (1)<<13
#define MODE_Single (1)<<11
#define MODE_REJ60 (1)<<10
//#define MODE_Filter_Speed 0
//配置寄存器
#define Config_Chop_EN (1)<<23
#define Config_REFSEL_IO (1)<<20
#define Config_Burn_EN (1)<<7
#define Config_REFDET_EN (1)<<6
#define Config_BUF_EN (1)<<4
#define Config_UB_EN (1)<<3
#define Config_Ch0_A1A2 (1)<<8
#define Config_Ch1_A3A4 (1)<<9
#define Config_Ch2_temp (1)<<10
#define Config_Ch3_A2A2 (1)<<11
#define Config_Ch4_A1AC (1)<<12
#define Config_Ch5_A2AC (1)<<13
#define Config_Ch6_A3AC (1)<<14
#define Config_Ch7_A4AC (1)<<15
#define Config_ADC_Gain_1 0
#define Config_ADC_Gain_8 3
#define Config_ADC_Gain_16 4
#define Config_ADC_Gain_32 5
#define Config_ADC_Gain_64 6
#define Config_ADC_Gain_128 7
typedef struct {
u32 ADC_Mode;
u32 Return_state;
u32 ADC_SCLK;
u32 SINC3_EN;
u32 ENPAR;
u32 Single_EN;
u32 REJ60_EN;
u32 Filter;
}AD7190_MODE_SET;
typedef struct {
u32 Config_Channel;
u32 Config_ADC_Gain;
u32 Config_Chop; //斩波使能
u32 Config_REFSEL;
u32 Config_Burn;
u32 Config_REFDET;
u32 Config_BUF;
u32 Config_UB;
}AD7190_Config_SET;
//基本配置
void AD7190_config(void)
{
AD7190_MODE_SET Mode;
AD7190_Config_SET Config;
Config.Config_Channel = Config_Ch1_A3A4;
Config.Config_ADC_Gain = Config_ADC_Gain_1;
Config.Config_Chop = 1;
Config.Config_REFSEL = 0;
Config.Config_Burn = 0;
Config.Config_REFDET = 1;
Config.Config_BUF = 0;
Config.Config_UB = 1;
Mode.ADC_Mode = MODE_ADC_AdjustZero;
Mode.Return_state = 0;
Mode.ADC_SCLK = MODE_MCLK_IN;
Mode.SINC3_EN = 0;
Mode.ENPAR = 0;
Mode.Single_EN = 0;
Mode.REJ60_EN = 0;
Mode.Filter = 1;
}
//读取转换值
void ReadAD7190(unsigned char count, unsigned char *buf)
{
unsigned char i = 0;
unsigned char j = 0;
unsigned char RotateData = 0;
SET_SCL();
delay_us(1);
SET_CS();
delay_us(1);
CLR_CS();
delay_us(1);
for(j=count; j>0; j--)
{
for(i=0; i<8; i++)
{
CLR_SCL();
RotateData <<= 1;
delay_us(1);
RotateData |= GP0DAT;
SET_SCL();
delay_us(1);
}
*(buf + j - 1)= RotateData;
RotateData=0;
}
SET_CS();
}
//初始化:
void AD7799_INIT(void)
{
unsigned long command;
command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
command &= ~AD7799_CONF_GAIN(0xFF);
command |= AD7799_CONF_GAIN(1);
AD7799_SetRegisterValue(AD7799_REG_CONF,command,2);
AD7799_SetReference();
command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
command &= ~AD7799_CONF_CHAN(0xFF);
command |= AD7799_CONF_CHAN(2);
AD7799_SetRegisterValue(AD7799_REG_CONF,command,2);
command = AD7799_GetRegisterValue(AD7799_REG_MODE,2);
command &= ~AD7799_MODE_SEL(0xFF);
command |= AD7799_MODE_SEL(0);// 连续转换模式
AD7799_SetRegisterValue(AD7799_REG_MODE,command,2);
}
//读数程序:
while (1)
{
adcbuf=ADC_Num();
if(ADC_Channel==1)//see datasheet AIN3 AIN4
{
adcA3A4[i++]=adcbuf;
if(i>Num)
{
i=0;
adcA3A4value=GetAverage(adcA3A4,Num);
AD7190_DataFormatting(adcA3A4value , 2.5 ,1);
DataLCD(AD7190_DataFormatting(adcA3A4value , 2.5 ,1));
}
}
}
5.测试结果
测试源是1.25v基准输出电压值,实际加入电压是:1.25000000v(8位半表实测),通过误差曲线的分析,摆幅稳定在2-8µV,效果还是很理想的。官方测试条件Gain=128,VREF=5V,下图是手册提供噪音图(Y轴单位LSB),在4.7Hz采样时候只有12个LSB的波动,但是在4.8kHz采样时候有将近450个LSB的波动,频率采集快了,会有一定失真,这是所有AD转换芯片的通病, 当然阻抗匹配也有一定的原因。因此在使用前零度和满度校准是十分必要的。
6.总结
作为一款中低速高精度的ADC,AD7190有着4.8kHz的转换频率,两路差分输入或四路伪差分输入,是个不错的选择,相比于AD7799虽然价格略高一些,但是他比AD7799的性能提高不少,特别是采样速率,测试看来,超高的性价比和出色的性能让它在同级别的ADC中也有很强的竞争能力。
============================================
STM32驱动AD7190
============================================
原文链接: https://blog.csdn/shaynerain/article/details/102970032
针对STM32,并且使用的时HAL库,改成其他库也很容易,只需要把相关通讯部分改了就行。
时序图中已经包含了很多信息,所以SPI配置如下,其中时钟最高为5M,在数据手册中看到的t3有最小时间限制:
CS引脚可以一直为低的状态,表示一直选中,如果要多片通讯,可以设置为其他,先把驱动程序放出来。
#include "ad7190.h"
//#define CS_H HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET)
//#define CS_L HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET)
static AD7190_REG_T ad7190_obj;
void init_AD7190_reg_cmds(AD7190_REG_Ptr ad7190_reg_ptr);
unsigned char SPIDEV1_single_transfer(unsigned char data_byte)
{
uint8_t data=0;
//CS_L;
//HAL_Delay(1);
HAL_SPI_TransmitReceive(&hspi4, &data_byte, &data, 1, 1000);
//HAL_Delay(1);
//CS_H;
return 0;
}
int SPIDEV1_transfer(unsigned char *send, unsigned char *receive, unsigned char bytes_num)
{
//uint8_t i=0;
//CS_L;
//HAL_Delay(1);
HAL_SPI_TransmitReceive(&hspi4, send, receive, bytes_num, 5000);
//HAL_Delay(1);
//CS_H;
return 0;
}
/****************************************************************
* Function Name : init_AD7190_reg_cmds
* Description : API to initialize the AD7190 commands structure
* for communication
* Returns : None
* Params @ad7190_reg_ptr: Pointer to commands structure
****************************************************************/
void init_AD7190_reg_cmds(AD7190_REG_Ptr ad7190_reg_ptr)
{
ad7190_reg_ptr->cmd_rd_ID_reg = COM_READ_ID_REG_CMD;
ad7190_reg_ptr->cmd_rd_config_reg = COM_READ_CONFIG_REG_CMD;
ad7190_reg_ptr->cmd_rd_data_reg = COM_READ_DATA_REG_CMD;
ad7190_reg_ptr->cmd_rd_full_scale_reg = COM_READ_FULL_SCALE_REG_CMD;
ad7190_reg_ptr->cmd_rd_gpocon_reg = COM_READ_GPCON_REG_CMD;
ad7190_reg_ptr->cmd_rd_mode_reg = COM_READ_MODE_REG_CMD;
ad7190_reg_ptr->cmd_rd_offset_reg = COM_READ_OFFSET_REG_CMD;
ad7190_reg_ptr->cmd_rd_status_reg = COM_READ_STATUS_REG_CMD;
ad7190_reg_ptr->cmd_wr_gpocon_reg = COM_WRITE_GPCON_RED_CMD;
ad7190_reg_ptr->cmd_wr_config_reg = COM_WRITE_CONFIG_REG_CMD;
ad7190_reg_ptr->cmd_wr_mode_reg = COM_WRITE_MODE_REG_CMD;
}
/****************************************************************
* Function Name : init_AD7190_cmds
* Description : Initialize the AD7190 commands structure
* for communication
* Returns : None
* Params : None
****************************************************************/
void init_AD7190_cmds()
{
init_AD7190_reg_cmds(&ad7190_obj);
}
/****************************************************************
* Function Name : AD7190_configure
* Description : Configure/Write to the configuration register
* for communication
* Returns : (-1) typecast for error, 0 for success
* Params @cbyte_2: Data to write to Most Significant Byte
* @cbyte_1: Data to write to Middle Byte
* @cbyte_0: Data to write to Least Significant Byte
****************************************************************/
char AD7190_configure(unsigned char cbyte_2, unsigned char cbyte_1, unsigned char cbyte_0)
{
char check_ret = 0x00;
unsigned char ad7190_id = 0x00;
ad7190_id = AD7190_get_ID();
//printf("Initializing AD7190 ADC Device ID = 0x%x\r\n", ad7190_id);
/* Go to write to configuration register */
check_ret = SPIDEV1_single_transfer(ad7190_obj.cmd_wr_config_reg);
/* Write to Most Significant Byte */
check_ret = SPIDEV1_single_transfer(cbyte_2);
/* Write to Mid Byte */
check_ret = SPIDEV1_single_transfer(cbyte_1);
/* Write to Least Significant Byte */
check_ret = SPIDEV1_single_transfer(cbyte_0);
return (check_ret);
}
/****************************************************************
* Function Name : AD7190_mode
* Description : Configure/Write to the mode register
* for communication
* Returns : (-1) typecast for error, 0 for success
* Params @mbyte_2: Data to write to Most Significant Byte
* @mbyte_1: Data to write to Middle Byte
* @mbyte_fs: Data to write to Least Significant Byte
****************************************************************/
char AD7190_mode(unsigned char mbyte_2, unsigned char mbyte_1, unsigned char mbyte_fs)
{
char check_ret = 0x00;
/* Go to write to configuration register */
check_ret = SPIDEV1_single_transfer(ad7190_obj.cmd_wr_mode_reg);
/* Write to Most Significant Byte */
check_ret = SPIDEV1_single_transfer(mbyte_2);
/* Write to Mid Byte */
check_ret = SPIDEV1_single_transfer(mbyte_1);
/* Write to Least Significant Byte */
check_ret = SPIDEV1_single_transfer(mbyte_fs);
//add new gpocon 打开switch
check_ret = SPIDEV1_single_transfer(ad7190_obj.cmd_wr_gpocon_reg);
check_ret = SPIDEV1_single_transfer(0x40);
return (check_ret);
}
/****************************************************************
* Function Name : AD7190_read_status_reg
* Description : Read the status register
* Returns : Contents of the status register
* Params : None
****************************************************************/
unsigned char AD7190_read_status_reg()
{
unsigned char status_reg = 0x00;
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_status_reg);
status_reg = SPIDEV1_single_transfer(0x00);
return (status_reg);
}
/****************************************************************
* Function Name : AD7190_get_ID
* Description : Read the ID register
* Returns : Contents of the ID register
* Params : None
****************************************************************/
unsigned char AD7190_get_ID()
{
unsigned char ad7190_ID = 0x00;
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_gpocon_reg);
ad7190_ID = SPIDEV1_single_transfer(0x00);
return (ad7190_ID);
}
/****************************************************************
* Function Name : AD7190_reset
* Description : Resets the AD7190
* Returns : None
* Params : None
****************************************************************/
void AD7190_reset()
{
char cnt;
for(cnt = 0 ; cnt < 55; cnt++)
SPIDEV1_single_transfer(0xFF);
}
/****************************************************************
* Function Name : AD7190_read_data
* Description : Read the data register
* Returns : Contents of the data register
* Params : None
****************************************************************/
int AD7190_read_data(void)
{
unsigned char Tx_bytes[]={0xff,0xff,0xff}, Rx_bytes[3] = {0,0,0}, reg_status = 0, drdy_bit;
int adc_data = 0x00;
//memset(Tx_bytes, 0xFF, sizeof(Tx_bytes));
//memset(Rx_bytes, 0, sizeof(Rx_bytes));
drdy_bit = 1;
reg_status = AD7190_read_status_reg();
drdy_bit = reg_status & 0x80;
if (drdy_bit == 0x00)
{
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_data_reg);
if (SPIDEV1_transfer(Tx_bytes, Rx_bytes, 3) == 0)
{
adc_data = (adc_data | Rx_bytes[0]) << 8;
adc_data = (adc_data | Rx_bytes[1]) << 8;
adc_data = adc_data | Rx_bytes[2];
//printf("%lu\r\n",adc_data);
}
else
{
//printf("(AD7190_read_test)Transaction Failed\r\n");
adc_data = 0xffffffff;
}
}
else
{
adc_data = 0xffffffff;
}
return (adc_data);
}
/****************************************************************
* Function Name : AD7190_dump_regs
* Description : Dump the contents of the registers
* Returns : None
* Params @regs_to_dump: Registers to dump
****************************************************************/
void AD7190_dump_regs(REG_DumpT regs_to_dump)
{
unsigned char Tx_bytes[3]={0xff,0xff,0xff}, Rx_bytes[3] = {0,0,0}, reg_status_id = 0;
unsigned long read_config_mode = 0x00;
//memset(Tx_bytes, 0xFF, sizeof(Tx_bytes));
//memset(Rx_bytes, 0, sizeof(Rx_bytes));
switch(regs_to_dump)
{
case DUMP_CONFIG_REG_CONTENTS:
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_config_reg);
if (SPIDEV1_transfer(Tx_bytes, Rx_bytes, 3) == 0)
{
read_config_mode = (read_config_mode | Rx_bytes[0]) << 8;
read_config_mode = (read_config_mode | Rx_bytes[1]) << 8;
read_config_mode = read_config_mode | Rx_bytes[2];
//printf("Dump - Configuration Register = 0X%x\r\n",read_config_mode);
}
else
{
//printf("(AD7190_dump_regs)Transaction Failed\r\n");
}
break;
case DUMP_MODE_REG_CONTENTS:
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_mode_reg);
if (SPIDEV1_transfer(Tx_bytes, Rx_bytes, 3) == 0)
{
read_config_mode = (read_config_mode | Rx_bytes[0]) << 8;
read_config_mode = (read_config_mode | Rx_bytes[1]) << 8;
read_config_mode = read_config_mode | Rx_bytes[2];
//printf("Dump - Mode Register = 0X%x\r\n",read_config_mode);
}
else
{
//printf("(AD7190_dump_regs)Transaction Failed\r\n");
}
break;
case DUMP_STATUS_REG_CONTENTS:
reg_status_id = AD7190_read_status_reg();
//printf("Dump - Status Register = 0X%x\r\n",reg_status_id);
break;
case DUMP_ID_REG_CONTENTS:
reg_status_id = AD7190_get_ID();
//printf("Dump - ID Register = 0X%x\r\n",reg_status_id);
break;
case DUMP_CONFIG_AND_MODE_REG_CONTENTS:
default:
//SPIDEV1_single_transfer(ad7190_obj.cmd_rd_config_reg);
//if (SPIDEV1_transfer(Tx_bytes, Rx_bytes, 3) == 0)
//{
// read_config_mode = (read_config_mode | Rx_bytes[0]) << 8;
// read_config_mode = (read_config_mode | Rx_bytes[1]) << 8;
// read_config_mode = read_config_mode | Rx_bytes[2];
// //printf("Dump - Configuration Register = 0X%x\r\n",read_config_mode);
//}
//else
//{
// //printf("(AD7190_dump_regs)Transaction Failed\r\n");
//}
//
memset(Rx_bytes, 0, sizeof(Rx_bytes));
//read_config_mode = 0x00;
SPIDEV1_single_transfer(ad7190_obj.cmd_rd_mode_reg);
if (SPIDEV1_transfer(Tx_bytes, Rx_bytes, 3) == 0)
{
read_config_mode = (read_config_mode | Rx_bytes[0]) << 8;
read_config_mode = (read_config_mode | Rx_bytes[1]) << 8;
read_config_mode = read_config_mode | Rx_bytes[2];
//printf("Dump - Mode Register = 0X%x\r\n",read_config_mode);
}
else
{
//printf("(AD7190_dump_regs)Transaction Failed\r\n");
}
break;
}
}
下面是ad7190.h文件
#include "stm32h7xx_hal.h"
#include "main.h"
#ifndef AD7190_H_
#define AD7190_H_
/* Commands to write to specific registers */
#define COM_WRITE_CONFIG_REG_CMD 0x10
#define COM_WRITE_MODE_REG_CMD 0x08
#define COM_WRITE_GPCON_RED_CMD 0x28
/* Commands to read from specific registers */
#define COM_READ_CONFIG_REG_CMD 0x50
#define COM_READ_STATUS_REG_CMD 0x40
#define COM_READ_MODE_REG_CMD 0x48
#define COM_READ_DATA_REG_CMD 0x58
#define COM_READ_GPCON_REG_CMD 0x68
#define COM_READ_ID_REG_CMD 0x60
#define COM_READ_OFFSET_REG_CMD 0x70
#define COM_READ_FULL_SCALE_REG_CMD 0x78
/* Sampling Rates */
#define FS_60_HZ 0x50
#define FS_300_HZ 0x10
#define FS_960_HZ 0x05
#define FS_2400_HZ 0x02
#define FS_4800_HZ 0x01
/* Register settings commands for Configuration Register */
#define CONFIG_REG_CMD_MSB 0x00
#define CONFIG_REG_CMD_MID 0x01
/*May have to change Gain depending on input signal voltage
See Table 19 in AD7190 datasheet for more information*/
#define CONFIG_REG_CMD_LSB 0x01//0x1F
/* Register settings commands for Mode Register */
#define MODE_REG_CMD_MSB 0x08
#define MODE_REG_CMD_MID 0x00
#define MODE_REG_CMD_LSB FS_4800_HZ
/* Read the data register continously and place the data on DOUT */
//#define COMM_REG_CREAD 0x5C
/* Structure Map of AD7190 internal registers
* for read and write operations
*/
typedef struct{
unsigned char cmd_rd_status_reg;
unsigned char cmd_wr_mode_reg;
unsigned char cmd_rd_mode_reg;
unsigned char cmd_wr_config_reg;
unsigned char cmd_rd_config_reg;
unsigned char cmd_rd_data_reg;
unsigned char cmd_rd_ID_reg;
unsigned char cmd_rd_gpocon_reg;
unsigned char cmd_wr_gpocon_reg;
unsigned char cmd_rd_offset_reg;
unsigned char cmd_rd_full_scale_reg;
}AD7190_REG_T, *AD7190_REG_Ptr;
/* Enum commands to dump register contents */
typedef enum{
DUMP_CONFIG_REG_CONTENTS,
DUMP_MODE_REG_CONTENTS,
DUMP_STATUS_REG_CONTENTS,
DUMP_ID_REG_CONTENTS,
DUMP_CONFIG_AND_MODE_REG_CONTENTS
}REG_DumpT;
/* AD7190 API's */
void init_AD7190_reg_cmds(AD7190_REG_Ptr ad7190_reg_ptr);
void init_AD7190_cmds(void);
char AD7190_configure(unsigned char cbyte_2, unsigned char cbyte_1, unsigned char cbyte_0);
char AD7190_mode(unsigned char mbyte_2, unsigned char mbyte_1, unsigned char mbyte_fs);
unsigned char AD7190_read_status_reg(void);
unsigned char AD7190_get_ID(void);
void AD7190_reset(void);
int AD7190_read_data(void);
void AD7190_dump_regs(REG_DumpT regs_to_dump);
#endif /* AD7190_H_ */
最后初始化
init_AD7190_cmds();
AD7190_reset();
HAL_Delay(20);
AD7190_configure(CONFIG_REG_CMD_MSB, CONFIG_REG_CMD_MID, CONFIG_REG_CMD_LSB);
AD7190_mode(MODE_REG_CMD_MSB, MODE_REG_CMD_MID, MODE_REG_CMD_LSB);
程序最后解读关键部分
首先芯片的读写是都要先发送要操作的寄存器,然后才是读或者写,这个程序参照了github上面的,做了改进,在AD7190_mode中打开了基准电压AGND的开关,
//add new gpocon 打开switch
check_ret = SPIDEV1_single_transfer(ad7190_obj.cmd_wr_gpocon_reg);
check_ret = SPIDEV1_single_transfer(0x40);
内部原理图如下,必须要打开开关才能正常使用。
========================================
ad7190官方驱动
========================================
ad7190.h
/***************************************************************************//**
* @file AD7190.h
* @brief Header file of AD7190 Driver.
* @author DNechita (Dan.Nechita@analog)
********************************************************************************
* Copyright 2012(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************
* SVN Revision: 903
*******************************************************************************/
#ifndef __AD7190_H__
#define __AD7190_H__
/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include "Communication.h"
/******************************************************************************/
/******************************** AD7190 **************************************/
/******************************************************************************/
/* SPI slave device ID */
#define AD7190_SLAVE_ID 1
/* AD7190 GPIO */
#define AD7190_RDY_STATE GPIO1_STATE
/* AD7190 Register Map */
#define AD7190_REG_COMM 0 // Communications Register (WO, 8-bit)
#define AD7190_REG_STAT 0 // Status Register (RO, 8-bit)
#define AD7190_REG_MODE 1 // Mode Register (RW, 24-bit
#define AD7190_REG_CONF 2 // Configuration Register (RW, 24-bit)
#define AD7190_REG_DATA 3 // Data Register (RO, 24/32-bit)
#define AD7190_REG_ID 4 // ID Register (RO, 8-bit)
#define AD7190_REG_GPOCON 5 // GPOCON Register (RW, 8-bit)
#define AD7190_REG_OFFSET 6 // Offset Register (RW, 24-bit
#define AD7190_REG_FULLSCALE 7 // Full-Scale Register (RW, 24-bit)
/* Communications Register Bit Designations (AD7190_REG_COMM) */
#define AD7190_COMM_WEN (1 << 7) // Write Enable.
#define AD7190_COMM_WRITE (0 << 6) // Write Operation.
#define AD7190_COMM_READ (1 << 6) // Read Operation.
#define AD7190_COMM_ADDR(x) (((x) & 0x7) << 3) // Register Address.
#define AD7190_COMM_CREAD (1 << 2) // Continuous Read of Data Register.
/* Status Register Bit Designations (AD7190_REG_STAT) */
#define AD7190_STAT_RDY (1 << 7) // Ready.
#define AD7190_STAT_ERR (1 << 6) // ADC error bit.
#define AD7190_STAT_NOREF (1 << 5) // Error no external reference.
#define AD7190_STAT_PARITY (1 << 4) // Parity check of the data register.
#define AD7190_STAT_CH2 (1 << 2) // Channel 2.
#define AD7190_STAT_CH1 (1 << 1) // Channel 1.
#define AD7190_STAT_CH0 (1 << 0) // Channel 0.
/* Mode Register Bit Designations (AD7190_REG_MODE) */
#define AD7190_MODE_SEL(x) (((x) & 0x7) << 21) // Operation Mode Select.
#define AD7190_MODE_DAT_STA (1 << 20) // Status Register transmission.
#define AD7190_MODE_CLKSRC(x) ((x) & 0x3) << 18) // Clock Source Select.
#define AD7190_MODE_SINC3 (1 << 15) // SINC3 Filter Select.
#define AD7190_MODE_ENPAR (1 << 13) // Parity Enable.
#define AD7190_MODE_SCYCLE (1 << 11) // Single cycle conversion.
#define AD7190_MODE_REJ60 (1 << 10) // 50/60Hz notch filter.
#define AD7190_MODE_RATE(x) ((x) & 0x3FF) // Filter Update Rate Select.
/* Mode Register: AD7190_MODE_SEL(x) options */
#define AD7190_MODE_CONT 0 // Continuous Conversion Mode.
#define AD7190_MODE_SINGLE 1 // Single Conversion Mode.
#define AD7190_MODE_IDLE 2 // Idle Mode.
#define AD7190_MODE_PWRDN 3 // Power-Down Mode.
#define AD7190_MODE_CAL_INT_ZERO 4 // Internal Zero-Scale Calibration.
#define AD7190_MODE_CAL_INT_FULL 5 // Internal Full-Scale Calibration.
#define AD7190_MODE_CAL_SYS_ZERO 6 // System Zero-Scale Calibration.
#define AD7190_MODE_CAL_SYS_FULL 7 // System Full-Scale Calibration.
/* Mode Register: AD7190_MODE_CLKSRC(x) options */
#define AD7190_CLK_EXT_MCLK1_2 0 // External crystal. The external crystal
// is connected from MCLK1 to MCLK2.
#define AD7190_CLK_EXT_MCLK2 1 // External Clock applied to MCLK2
#define AD7190_CLK_INT 2 // Internal 4.92 MHz clock.
// Pin MCLK2 is tristated.
#define AD7190_CLK_INT_CO 3 // Internal 4.92 MHz clock. The internal
// clock is available on MCLK2.
/* Configuration Register Bit Designations (AD7190_REG_CONF) */
#define AD7190_CONF_CHOP (1 << 23) // CHOP enable.
#define AD7190_CONF_REFSEL (1 << 20) // REFIN1/REFIN2 Reference Select.
#define AD7190_CONF_CHAN(x) (((x) & 0xFF) << 8) // Channel select.
#define AD7190_CONF_BURN (1 << 7) // Burnout current enable.
#define AD7190_CONF_REFDET (1 << 6) // Reference detect enable.
#define AD7190_CONF_BUF (1 << 4) // Buffered Mode Enable.
#define AD7190_CONF_UNIPOLAR (1 << 3) // Unipolar/Bipolar Enable.
#define AD7190_CONF_GAIN(x) ((x) & 0x7) // Gain Select.
/* Configuration Register: AD7190_CONF_CHAN(x) options */
#define AD7190_CH_AIN1P_AIN2M 0 // AIN1(+) - AIN2(-)
#define AD7190_CH_AIN3P_AIN4M 1 // AIN3(+) - AIN4(-)
#define AD7190_CH_TEMP_SENSOR 2 // Temperature sensor
#define AD7190_CH_AIN2P_AIN2M 3 // AIN2(+) - AIN2(-)
#define AD7190_CH_AIN1P_AINCOM 4 // AIN1(+) - AINCOM
#define AD7190_CH_AIN2P_AINCOM 5 // AIN2(+) - AINCOM
#define AD7190_CH_AIN3P_AINCOM 6 // AIN3(+) - AINCOM
#define AD7190_CH_AIN4P_AINCOM 7 // AIN4(+) - AINCOM
/* Configuration Register: AD7190_CONF_GAIN(x) options */
// ADC Input Range (5 V Reference)
#define AD7190_CONF_GAIN_1 0 // Gain 1 +-5 V
#define AD7190_CONF_GAIN_8 3 // Gain 8 +-625 mV
#define AD7190_CONF_GAIN_16 4 // Gain 16 +-312.5 mV
#define AD7190_CONF_GAIN_32 5 // Gain 32 +-156.2 mV
#define AD7190_CONF_GAIN_64 6 // Gain 64 +-78.125 mV
#define AD7190_CONF_GAIN_128 7 // Gain 128 +-39.06 mV
/* ID Register Bit Designations (AD7190_REG_ID) */
#define ID_AD7190 0x4
#define AD7190_ID_MASK 0x0F
/* GPOCON Register Bit Designations (AD7190_REG_GPOCON) */
#define AD7190_GPOCON_BPDSW (1 << 6) // Bridge power-down switch enable
#define AD7190_GPOCON_GP32EN (1 << 5) // Digital Output P3 and P2 enable
#define AD7190_GPOCON_GP10EN (1 << 4) // Digital Output P1 and P0 enable
#define AD7190_GPOCON_P3DAT (1 << 3) // P3 state
#define AD7190_GPOCON_P2DAT (1 << 2) // P2 state
#define AD7190_GPOCON_P1DAT (1 << 1) // P1 state
#define AD7190_GPOCON_P0DAT (1 << 0) // P0 state
/******************************************************************************/
/*********************** Functions Declarations *******************************/
/******************************************************************************/
/*! Writes data into a register. */
void AD7190_SetRegisterValue(unsigned char registerAddress,
unsigned long registerValue,
unsigned char bytesNumber,
unsigned char modifyCS);
/*! Reads the value of a register. */
unsigned long AD7190_GetRegisterValue(unsigned char registerAddress,
unsigned char bytesNumber,
unsigned char modifyCS);
/*! Checks if the AD7139 part is present. */
unsigned char AD7190_Init(void);
/*! Resets the device. */
void AD7190_Reset(void);
/*! Set device to idle or power-down. */
void AD7190_SetPower(unsigned char pwrMode);
/*! Waits for RDY pin to go low. */
void AD7190_WaitRdyGoLow(void);
/*! Selects the channel to be enabled. */
void AD7190_ChannelSelect(unsigned short channel);
/*! Performs the given calibration to the specified channel. */
void AD7190_Calibrate(unsigned char mode, unsigned char channel);
/*! Selects the polarity of the conversion and the ADC input range. */
void AD7190_RangeSetup(unsigned char polarity, unsigned char range);
/*! Returns the result of a single conversion. */
unsigned long AD7190_SingleConversion(void);
/*! Returns the average of several conversion results. */
unsigned long AD7190_ContinuousReadAvg(unsigned char sampleNumber);
/*! Read data from temperature sensor and converts it to Celsius degrees. */
unsigned long AD7190_TemperatureRead(void);
#endif /* __AD7190_H__ */
ad7190.c
/***************************************************************************//**
* @file AD7190.c
* @brief Implementation of AD7190 Driver.
* @author DNechita (Dan.Nechita@analog)
********************************************************************************
* Copyright 2012(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
********************************************************************************
* SVN Revision: 903
*******************************************************************************/
/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include "AD7190.h" // AD7190 definitions.
#include "TIME.h" // TIME definitions.
/***************************************************************************//**
* @brief Writes data into a register.
*
* @param registerAddress - Address of the register.
* @param registerValue - Data value to write.
* @param bytesNumber - Number of bytes to be written.
* @param modifyCS - Allows Chip Select to be modified.
*
* @return none.
*******************************************************************************/
void AD7190_SetRegisterValue(unsigned char registerAddress,
unsigned long registerValue,
unsigned char bytesNumber,
unsigned char modifyCS)
{
unsigned char writeCommand[5] = {0, 0, 0, 0, 0};
unsigned char* dataPointer = (unsigned char*)®isterValue;
unsigned char bytesNr = bytesNumber;
writeCommand[0] = AD7190_COMM_WRITE |
AD7190_COMM_ADDR(registerAddress);
while(bytesNr > 0)
{
writeCommand[bytesNr] = *dataPointer;
dataPointer ++;
bytesNr --;
}
SPI_Write(AD7190_SLAVE_ID * modifyCS, writeCommand, bytesNumber + 1);
}
/***************************************************************************//**
* @brief Reads the value of a register.
*
* @param registerAddress - Address of the register.
* @param bytesNumber - Number of bytes that will be read.
* @param modifyCS - Allows Chip Select to be modified.
*
* @return buffer - Value of the register.
*******************************************************************************/
unsigned long AD7190_GetRegisterValue(unsigned char registerAddress,
unsigned char bytesNumber,
unsigned char modifyCS)
{
unsigned char registerWord[5] = {0, 0, 0, 0, 0};
unsigned long buffer = 0x0;
unsigned char i = 0;
registerWord[0] = AD7190_COMM_READ |
AD7190_COMM_ADDR(registerAddress);
SPI_Read(AD7190_SLAVE_ID * modifyCS, registerWord, bytesNumber + 1);
for(i = 1; i < bytesNumber + 1; i++)
{
buffer = (buffer << 8) + registerWord[i];
}
return buffer;
}
/***************************************************************************//**
* @brief Checks if the AD7190 part is present.
*
* @return status - Indicates if the part is present or not.
*******************************************************************************/
unsigned char AD7190_Init(void)
{
unsigned char status = 1;
unsigned char regVal = 0;
SPI_Init(0, 1000000, 1, 0);
AD7190_Reset();
/* Allow at least 500 us before accessing any of the on-chip registers. */
TIME_DelayMs(1);
regVal = AD7190_GetRegisterValue(AD7190_REG_ID, 1, 1);
if( (regVal & AD7190_ID_MASK) != ID_AD7190)
{
status = 0;
}
return status ;
}
/***************************************************************************//**
* @brief Resets the device.
*
* @return none.
*******************************************************************************/
void AD7190_Reset(void)
{
unsigned char registerWord[7];
registerWord[0] = 0x01;
registerWord[1] = 0xFF;
registerWord[2] = 0xFF;
registerWord[3] = 0xFF;
registerWord[4] = 0xFF;
registerWord[5] = 0xFF;
registerWord[6] = 0xFF;
SPI_Write(AD7190_SLAVE_ID, registerWord, 7);
}
/***************************************************************************//**
* @brief Set device to idle or power-down.
*
* @param pwrMode - Selects idle mode or power-down mode.
* Example: 0 - power-down
* 1 - idle
*
* @return none.
*******************************************************************************/
void AD7190_SetPower(unsigned char pwrMode)
{
unsigned long oldPwrMode = 0x0;
unsigned long newPwrMode = 0x0;
oldPwrMode = AD7190_GetRegisterValue(AD7190_REG_MODE, 3, 1);
oldPwrMode &= ~(AD7190_MODE_SEL(0x7));
newPwrMode = oldPwrMode |
AD7190_MODE_SEL((pwrMode * (AD7190_MODE_IDLE)) |
(!pwrMode * (AD7190_MODE_PWRDN)));
AD7190_SetRegisterValue(AD7190_REG_MODE, newPwrMode, 3, 1);
}
/***************************************************************************//**
* @brief Waits for RDY pin to go low.
*
* @return none.
*******************************************************************************/
void AD7190_WaitRdyGoLow(void)
{
unsigned long timeOutCnt = 0xFFFFF;
while(AD7190_RDY_STATE && timeOutCnt--)
{
;
}
}
/***************************************************************************//**
* @brief Selects the channel to be enabled.
*
* @param channel - Selects a channel.
*
* @return none.
*******************************************************************************/
void AD7190_ChannelSelect(unsigned short channel)
{
unsigned long oldRegValue = 0x0;
unsigned long newRegValue = 0x0;
oldRegValue = AD7190_GetRegisterValue(AD7190_REG_CONF, 3, 1);
oldRegValue &= ~(AD7190_CONF_CHAN(0xFF));
newRegValue = oldRegValue | AD7190_CONF_CHAN(1 << channel);
AD7190_SetRegisterValue(AD7190_REG_CONF, newRegValue, 3, 1);
}
/***************************************************************************//**
* @brief Performs the given calibration to the specified channel.
*
* @param mode - Calibration type.
* @param channel - Channel to be calibrated.
*
* @return none.
*******************************************************************************/
void AD7190_Calibrate(unsigned char mode, unsigned char channel)
{
unsigned long oldRegValue = 0x0;
unsigned long newRegValue = 0x0;
AD7190_ChannelSelect(channel);
oldRegValue = AD7190_GetRegisterValue(AD7190_REG_MODE, 3, 1);
oldRegValue &= ~AD7190_MODE_SEL(0x7);
newRegValue = oldRegValue | AD7190_MODE_SEL(mode);
ADI_PART_CS_LOW;
AD7190_SetRegisterValue(AD7190_REG_MODE, newRegValue, 3, 0); // CS is not modified.
AD7190_WaitRdyGoLow();
ADI_PART_CS_HIGH;
}
/***************************************************************************//**
* @brief Selects the polarity of the conversion and the ADC input range.
*
* @param polarity - Polarity select bit.
Example: 0 - bipolar operation is selected.
1 - unipolar operation is selected.
* @param range - Gain select bits. These bits are written by the user to select
the ADC input range.
*
* @return none.
*******************************************************************************/
void AD7190_RangeSetup(unsigned char polarity, unsigned char range)
{
unsigned long oldRegValue = 0x0;
unsigned long newRegValue = 0x0;
oldRegValue = AD7190_GetRegisterValue(AD7190_REG_CONF,3, 1);
oldRegValue &= ~(AD7190_CONF_UNIPOLAR |
AD7190_CONF_GAIN(0x7));
newRegValue = oldRegValue |
(polarity * AD7190_CONF_UNIPOLAR) |
AD7190_CONF_GAIN(range);
AD7190_SetRegisterValue(AD7190_REG_CONF, newRegValue, 3, 1);
}
/***************************************************************************//**
* @brief Returns the result of a single conversion.
*
* @return regData - Result of a single analog-to-digital conversion.
*******************************************************************************/
unsigned long AD7190_SingleConversion(void)
{
unsigned long command = 0x0;
unsigned long regData = 0x0;
command = AD7190_MODE_SEL(AD7190_MODE_SINGLE) |
AD7190_MODE_CLKSRC(AD7190_CLK_INT) |
AD7190_MODE_RATE(0x060);
ADI_PART_CS_LOW;
AD7190_SetRegisterValue(AD7190_REG_MODE, command, 3, 0); // CS is not modified.
AD7190_WaitRdyGoLow();
regData = AD7190_GetRegisterValue(AD7190_REG_DATA, 3, 0);
ADI_PART_CS_HIGH;
return regData;
}
/***************************************************************************//**
* @brief Returns the average of several conversion results.
*
* @return samplesAverage - The average of the conversion results.
*******************************************************************************/
unsigned long AD7190_ContinuousReadAvg(unsigned char sampleNumber)
{
unsigned long samplesAverage = 0x0;
unsigned char count = 0x0;
unsigned long command = 0x0;
command = AD7190_MODE_SEL(AD7190_MODE_CONT) |
AD7190_MODE_CLKSRC(AD7190_CLK_INT) |
AD7190_MODE_RATE(0x060);
ADI_PART_CS_LOW;
AD7190_SetRegisterValue(AD7190_REG_MODE, command, 3, 0); // CS is not modified.
for(count = 0;count < sampleNumber;count ++)
{
AD7190_WaitRdyGoLow();
samplesAverage += AD7190_GetRegisterValue(AD7190_REG_DATA, 3, 0); // CS is not modified.
}
ADI_PART_CS_HIGH;
samplesAverage = samplesAverage / sampleNumber;
return samplesAverage ;
}
/***************************************************************************//**
* @brief Read data from temperature sensor and converts it to Celsius degrees.
*
* @return temperature - Celsius degrees.
*******************************************************************************/
unsigned long AD7190_TemperatureRead(void)
{
unsigned char temperature = 0x0;
unsigned long dataReg = 0x0;
AD7190_RangeSetup(0, AD7190_CONF_GAIN_1);
AD7190_ChannelSelect(AD7190_CH_TEMP_SENSOR);
dataReg = AD7190_SingleConversion();
dataReg -= 0x800000;
dataReg /= 2815; // Kelvin Temperature
dataReg -= 273; //Celsius Temperature
temperature = (unsigned long) dataReg;
return temperature;
}
更多推荐
AD7190之STM32程序
发布评论