Перейти к содержанию
    

С continues режимом не работал. Попробуйте запустить процесс в single-conv., на один канал.

При работе на полной (24) разрядности Вы должны по готовности получить 3 байта данных из АЦП.

формат вызова 

static unsigned char data8[4];

static unsigned long dat32;

data8[3] = 0;

CS0;

data8[2] = SPI_Read_8();

data8[1] = SPI_Read_8();

data8[0] = SPI_Read_8();

CS1;

dat32 = (unsigned long *) &data8[0];

(3 чтения регистра данных, один CS)

А где в Вашем коде приводится тип 3 считанных байт (24 бита) к типу long ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

unsigned long AD7799_GetRegisterValue(unsigned char CS,unsigned char regAddress, unsigned char size)
{
	unsigned char data[4] = {0x00, 0x00, 0x00, 0x00};
	unsigned long receivedData = 0x00;	
	data[0] = AD7799_COMM_READ |  AD7799_COMM_ADDR(regAddress);
	AD7799_CS_LOW(CS);  
	AD7799_SpiTransferByte(data[0]);
        for(char i=0;i<size;i++)
          data[i]=AD7799_SpiTransferByte(data[i]);
	AD7799_CS_HIGH(CS);
	if(size == 1)
	{
		receivedData += (data[0] << 0);
	}
	if(size == 2)
	{
		receivedData += (data[0] << 8);
		receivedData += (data[1] << 0);
	}
	if(size == 3)
	{
		receivedData += (data[0] << 16);
		receivedData += (data[1] << 8);
		receivedData += (data[2] << 0);
	}
    return receivedData;
  
}

вот здесь 3 итерации цикла проходит и потом все что считалось склеивается со сдвигом

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Reystlin said:

вот здесь 3 итерации цикла проходит и потом все что считалось склеивается со сдвигом

И что, у Вас сдвинутый влево data размерности char дает нормальное значение? 

И зачем сложение, если достаточно логического OR ?

 

Или вообще можно union объявить и работать, доступаясь или к отдельным байтам или сразу к 32-битной величине, без всяких сдвигов. Но тут внимательно нужно к упаковке подойти.

typedef union { uint8_t _u8[4]; uint32_t _u32; }u32_4u8;

u32_4u8 usedData;  // usedData._u8[0]...usedData._u8[3] для байтов, usedData._u32 для 32-битного значения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

этот кусок кода был позаимствован из библиотеки от АД

а почему нет? у нас 8 бит загружается в АЛУ, АЛУ сдвигает их влево и возвращает полученный результат регистры у STM32 32х разрядные...

з.ы. код из библиотеки от АД

взято отсюда https://wiki.analog.com/resources/tools-software/uc-drivers/renesas/ad7799

#ifndef __AD7799_H__
#define __AD7799_H__

/******************************************************************************/
/* AD7799                                                                   */
/******************************************************************************/

/*AD7799 Registers*/
#define AD7799_REG_COMM		0 /* Communications Register(WO, 8-bit) */
#define AD7799_REG_STAT	    0 /* Status Register	    (RO, 8-bit) */
#define AD7799_REG_MODE	    1 /* Mode Register	     	(RW, 16-bit */
#define AD7799_REG_CONF	    2 /* Configuration Register (RW, 16-bit)*/
#define AD7799_REG_DATA	    3 /* Data Register	     	(RO, 16-/24-bit) */
#define AD7799_REG_ID	    4 /* ID Register	     	(RO, 8-bit) */
#define AD7799_REG_IO	    5 /* IO Register	     	(RO, 8-bit) */
#define AD7799_REG_OFFSET   6 /* Offset Register	    (RW, 24-bit */
#define AD7799_REG_FULLSALE	7 /* Full-Scale Register	(RW, 24-bit */

/* Communications Register Bit Designations (AD7799_REG_COMM) */
#define AD7799_COMM_WEN		(1 << 7) 			/* Write Enable */
#define AD7799_COMM_WRITE	(0 << 6) 			/* Write Operation */
#define AD7799_COMM_READ    (1 << 6) 			/* Read Operation */
#define AD7799_COMM_ADDR(x)	(((x) & 0x7) << 3)	/* Register Address */
#define AD7799_COMM_CREAD	(1 << 2) 			/* Continuous Read of Data Register */

/* Status Register Bit Designations (AD7799_REG_STAT) */
#define AD7799_STAT_RDY		(1 << 7) /* Ready */
#define AD7799_STAT_ERR		(1 << 6) /* Error (Overrange, Underrange) */
#define AD7799_STAT_CH3		(1 << 2) /* Channel 3 */
#define AD7799_STAT_CH2		(1 << 1) /* Channel 2 */
#define AD7799_STAT_CH1		(1 << 0) /* Channel 1 */

/* Mode Register Bit Designations (AD7799_REG_MODE) */
#define AD7799_MODE_SEL(x)		(((x) & 0x7) << 13)	/* Operation Mode Select */
#define AD7799_MODE_PSW(x)		(1 << 12)			/* Power Switch Control Bit */	
#define AD7799_MODE_RATE(x)		((x) & 0xF) 		/* Filter Update Rate Select */

/* AD7799_MODE_SEL(x) options */
#define AD7799_MODE_CONT		 0 /* Continuous Conversion Mode */
#define AD7799_MODE_SINGLE		 1 /* Single Conversion Mode */
#define AD7799_MODE_IDLE		 2 /* Idle Mode */
#define AD7799_MODE_PWRDN		 3 /* Power-Down Mode */
#define AD7799_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */
#define AD7799_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */
#define AD7799_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */
#define AD7799_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */

/* Configuration Register Bit Designations (AD7799_REG_CONF) */
#define AD7799_CONF_BO_EN	  (1 << 13) 			/* Burnout Current Enable */
#define AD7799_CONF_UNIPOLAR  (1 << 12) 			/* Unipolar/Bipolar Enable */
#define AD7799_CONF_GAIN(x)	  (((x) & 0x7) << 8) 	/* Gain Select */
#define AD7799_CONF_REFDET(x) (((x) & 0x1) << 5) 	/* Reference detect function */
#define AD7799_CONF_BUF		  (1 << 4) 				/* Buffered Mode Enable */
#define AD7799_CONF_CHAN(x)	  ((x) & 0x7) 			/* Channel select */

/* AD7799_CONF_GAIN(x) options */
#define AD7799_GAIN_1       0
#define AD7799_GAIN_2       1
#define AD7799_GAIN_4       2
#define AD7799_GAIN_8       3
#define AD7799_GAIN_16      4
#define AD7799_GAIN_32      5
#define AD7799_GAIN_64      6
#define AD7799_GAIN_128     7

/* AD7799_CONF_REFDET(x) options */
#define AD7799_REFDET_ENA   1	
#define AD7799_REFDET_DIS   0

/* AD7799_CONF_CHAN(x) options */
#define AD7799_CH_AIN1P_AIN1M	0 /* AIN1(+) - AIN1(-) */
#define AD7799_CH_AIN2P_AIN2M	1 /* AIN2(+) - AIN2(-) */
#define AD7799_CH_AIN3P_AIN3M	2 /* AIN3(+) - AIN3(-) */
#define AD7799_CH_AIN1M_AIN1M	3 /* AIN1(-) - AIN1(-) */
#define AD7799_CH_AVDD_MONITOR	7 /* AVDD Monitor */

/* ID Register Bit Designations (AD7799_REG_ID) */
#define AD7799_ID			0x9
#define AD7799_ID_MASK		0xF

/* IO (Excitation Current Sources) Register Bit Designations (AD7799_REG_IO) */
#define AD7799_IOEN			(1 << 6)
#define AD7799_IO1(x)		(((x) & 0x1) << 4)
#define AD7799_IO2(x)		(((x) & 0x1) << 5)

/******************************************************************************/
/* Functions Prototypes                                                       */
/******************************************************************************/

/* Initialize AD7799 and check if the device is present*/
unsigned char AD7799_Init(void);
/* Sends 32 consecutive 1's on SPI in order to reset the part. */
void AD7799_Reset(void);
/* Reads the value of the selected register. */
unsigned long AD7799_GetRegisterValue(unsigned char regAddress, 
									  unsigned char size);
/* Writes a value to the register. */
void AD7799_SetRegisterValue(unsigned char regAddress,
							 unsigned long regValue, 
							 unsigned char size);
/* Sets the operating mode of AD7799. */
void AD7799_SetMode(unsigned long mode);
/* Reads /RDY bit of Status register. */
unsigned char AD7799_Ready(void);              
/* Selects the channel of AD7799. */
void AD7799_SetChannel(unsigned long channel);
/* Sets the gain of the In-Amp. */
void AD7799_SetGain(unsigned long gain);
/* Enables or disables the reference detect function. */
void AD7799_SetReference(unsigned char state);

#endif	// _AD7799_H_

/***************************************************************************//**
 * @brief Initializes the AD7799 and checks if the device is present.
 *
 * @param None.
 *
 * @return status - Result of the initialization procedure.
 *                  Example: 1 - if initialization was successful (ID is 0x0B).
 *                           0 - if initialization was unsuccessful.
*******************************************************************************/
unsigned char AD7799_Init(void)
{ 
	unsigned char status = 0x1;
	if((AD7799_GetRegisterValue(AD7799_REG_ID, 1) & 0x0F) != AD7799_ID)
	{
		status = 0x0;
	}
	
	return(status);
}

/***************************************************************************//**
 * @brief Sends 32 consecutive 1's on SPI in order to reset the part.
 *
 * @param None.
 *
 * @return  None.    
*******************************************************************************/
void AD7799_Reset(void)
{
	unsigned char dataToSend[5] = {0x03, 0xff, 0xff, 0xff, 0xff};
	AD7799_CS_LOW;	    
	SPI_Write(dataToSend,4);
	AD7799_CS_HIGH;	
}
/***************************************************************************//**
 * @brief Reads the value of the selected register
 *
 * @param regAddress - The address of the register to read.
 * @param size - The size of the register to read.
 *
 * @return data - The value of the selected register register.
*******************************************************************************/
unsigned long AD7799_GetRegisterValue(unsigned char regAddress, unsigned char size)
{
	unsigned char data[5] = {0x03, 0x00, 0x00, 0x00, 0x00};
	unsigned long receivedData = 0x00;	
	data[1] = AD7799_COMM_READ |  AD7799_COMM_ADDR(regAddress);
	AD7799_CS_LOW;  
	SPI_Write(data,1);
	SPI_Read(data,size);
	AD7799_CS_HIGH;
	if(size == 1)
	{
		receivedData += (data[0] << 0);
	}
	if(size == 2)
	{
		receivedData += (data[0] << 8);
		receivedData += (data[1] << 0);
	}
	if(size == 3)
	{
		receivedData += (data[0] << 16);
		receivedData += (data[1] << 8);
		receivedData += (data[2] << 0);
	}
    return receivedData;
}
/***************************************************************************//**
 * @brief Writes the value to the register
 *
 * @param -  regAddress - The address of the register to write to.
 * @param -  regValue - The value to write to the register.
 * @param -  size - The size of the register to write.
 *
 * @return  None.    
*******************************************************************************/
void AD7799_SetRegisterValue(unsigned char regAddress,
                             unsigned long regValue, 
                             unsigned char size)
{
	unsigned char data[5] = {0x03, 0x00, 0x00, 0x00, 0x00};	
	data[1] = AD7799_COMM_WRITE |  AD7799_COMM_ADDR(regAddress);
    if(size == 1)
    {
        data[2] = (unsigned char)regValue;
    }
    if(size == 2)
    {
		data[3] = (unsigned char)((regValue & 0x0000FF) >> 0);
        data[2] = (unsigned char)((regValue & 0x00FF00) >> 8);
    }
    if(size == 3)
    {
		data[4] = (unsigned char)((regValue & 0x0000FF) >> 0);
		data[3] = (unsigned char)((regValue & 0x00FF00) >> 8);
        data[2] = (unsigned char)((regValue & 0xFF0000) >> 16);
    }
	AD7799_CS_LOW;	    
	SPI_Write(data,(1 + size));
	AD7799_CS_HIGH;

}
/***************************************************************************//**
 * @brief Reads /RDY bit of status reg.
 *
 * @param None.
 *
 * @return rdy	- 0 if RDY is 1.
 *              - 1 if RDY is 0.
*******************************************************************************/
unsigned char AD7799_Ready(void)
{
    unsigned char rdy = 0;
    rdy = (AD7799_GetRegisterValue( AD7799_REG_STAT,1) & 0x80);   
	
	return(!rdy);
}

/***************************************************************************//**
 * @brief Sets the operating mode of AD7799.
 *
 * @param mode - Mode of operation.
 *
 * @return  None.    
*******************************************************************************/
void AD7799_SetMode(unsigned long mode)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_MODE,2);
    command &= ~AD7799_MODE_SEL(0xFF);
    command |= AD7799_MODE_SEL(mode);
    AD7799_SetRegisterValue(
            AD7799_REG_MODE,
            command,
            2
    );
}
/***************************************************************************//**
 * @brief Selects the channel of AD7799.
 *
 * @param  channel - ADC channel selection.
 *
 * @return  None.    
*******************************************************************************/
void AD7799_SetChannel(unsigned long channel)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_CHAN(0xFF);
    command |= AD7799_CONF_CHAN(channel);
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
}

/***************************************************************************//**
 * @brief  Sets the gain of the In-Amp.
 *
 * @param  gain - Gain.
 *
 * @return  None.    
*******************************************************************************/
void AD7799_SetGain(unsigned long gain)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_GAIN(0xFF);
    command |= AD7799_CONF_GAIN(gain);
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
}
/***************************************************************************//**
 * @brief Enables or disables the reference detect function.
 *
 * @param state - State of the reference detect function.
 *               Example: 0	- Reference detect disabled.
 *                        1	- Reference detect enabled.
 *
 * @return None.    
*******************************************************************************/
void AD7799_SetReference(unsigned char state)
{
    unsigned long command = 0;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_REFDET(1);
    command |= AD7799_CONF_REFDET(state);
    AD7799_SetRegisterValue(AD7799_REG_CONF,
							command,
							2);
}

/***************************************************************************//**
 * @brief Writes data to SPI.
 *
 * @param data - Write data buffer:
 *               - first byte is the chip select number;
 *               - from the second byte onwards are located data bytes to write.
 * @param bytesNumber - Number of bytes to write.
 *
 * @return Number of written bytes.
*******************************************************************************/
unsigned char SPI_Write(unsigned char* data,
                        unsigned char bytesNumber)
{
	unsigned char chipSelect    = data[0];
	unsigned char writeData[4]	= {0, 0, 0, 0};
	unsigned char byte          = 0;
	for(byte = 0;byte < bytesNumber;byte ++)
	{
		writeData[byte] = data[byte + 1];
	}
    if(chipSelect == 1)
    {
        AD7799_CS_LOW;
    }
    if(chipSelect == 2)
    {
        ST7579_CS_LOW;
    }
	for(byte = 0;byte < bytesNumber;byte ++)
    {
        R_SPI_Transfer(0,						    		// Channel selection.
                       PDL_NO_DATA,							// DMAC / DTC control.
                       (unsigned long*)&writeData[byte],	// Transmit data start address.
                       PDL_NO_PTR,							// Receive data start address.
                       1,									// Sequence loop count.
                       PDL_NO_FUNC,							// Callback function.
                       0);									// Interrupt priority level.
    }
 	if(chipSelect == 1)
	{
		AD7799_CS_HIGH;
	}
    if(chipSelect == 2)
	{
		ST7579_CS_HIGH;
	}
	return(bytesNumber);
}

/***************************************************************************//**
 * @brief Reads data from SPI.
 *
 * @param data - As an input parameter, data represents the write buffer:
 *               - first byte is the chip select number;
 *               - from the second byte onwards are located data bytes to write.
 *               As an output parameter, data represents the read buffer:
 *               - from the first byte onwards are located the read data bytes. 
 * @param bytesNumber - Number of bytes to write.
 *
 * @return Number of written bytes.
*******************************************************************************/
unsigned char SPI_Read(unsigned char* data,
                       unsigned char bytesNumber)
{
	unsigned char chipSelect    = data[0];
	unsigned char writeData[4]	= {0, 0, 0, 0};
	unsigned char byte          = 0;
	for(byte = 0;byte < bytesNumber;byte ++)
	{
		writeData[byte] = data[byte + 1];
	}
    if(chipSelect == 1)
    {
        AD7799_CS_LOW;
    }
    if(chipSelect == 2)
    {
        ST7579_CS_LOW;
    }
	for(byte = 0;byte < bytesNumber;byte ++)
    {
        R_SPI_Transfer(0,						    		// Channel selection.
                       PDL_NO_DATA,							// DMAC / DTC control.
                       (unsigned long*)&writeData[byte],	// Transmit data start address.
                       (unsigned long*)&data[byte],			// Transmit data start address.
                       1,									// Sequence loop count.
                       PDL_NO_FUNC,							// Callback function.
                       0);									// Interrupt priority level.
    }
 	if(chipSelect == 1)
	{
		AD7799_CS_HIGH;
	}
    if(chipSelect == 2)
	{
		ST7579_CS_HIGH;
	}

	return(bytesNumber);
}

 

Изменено пользователем Reystlin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделитесь пожалуйста рабочими вариантами либо работы с этим АЦП что-то ничего толкового у меня не выходит из этого...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, Reystlin said:

Поделитесь пожалуйста рабочими вариантами либо работы с этим АЦП что-то ничего толкового у меня не выходит из этого...

У меня есть только AD7789 и AD7792 очень многолетней давности под Майкрочип (PIC), уж не знаю чем оно поможет.

 

Попробуйте поделить задачу на части  и решайте шаг-за-шагом:

1) можете ли стабильно читать из АЦП известные значения (например, ID и значения, которые должны читаться из регистров после сброса)

2) можете ли писать

3) можете ли сконфигурировать

4) можете ли прочитать значение АЦП при неизменяемом поданном на вход напряжении (да хоть резистивный делитель от Vrfef)

5) чтение статических величин с разных входов АЦП

6) чтение динамических данных.

В подобных вопросах логический анализатор (даже дешевый китайский за 10 баксов)- это истина в последней инстанции. Сэкономите сильно больше чем потраченные деньги, да и отладка подобных интерфейсов из мучения превращается в приятное развлечение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 hours ago, Reystlin said:

Поделитесь пожалуйста рабочими вариантами либо работы с этим АЦП что-то ничего толкового у меня не выходит из этого...

Не надейтесь, что код, который выложен в качестве appnote, даже AD, будет оптимален. Может да, а может и нет.

То чо Вы привели выше - скорее нет (IMHO). Вы в ЭТОМ, разберетесь и добьетесь, чтоб ОНО заработало (потратив время на чужой код). Но есть ли смысл ?

Наводят на "смутные сомненья" конструкции вида

	if(size == 1)
	{
		receivedData += (data[0] << 0);
	}

Я работал с AD7794, они во многом похожи, но есть и существенные отличия, поэтому "вчистую" мой софт не подключишь.

Работал с этим давно, надо порыться в архивах. Но, повторяю - это код для 7794. Если будет желание - сможете его адаптировать под 7799. 

В коде, который используете Вы (от AD) - много лишнего - потомукак они сделали его универсальным. Я свой драйвер на 7794 тоже писал факт. с нуля,

тк имевшийся до этого код был "мутноват". Заодно изучил даташит на АЦП.

 

15 hours ago, Reystlin said:

Поделитесь пожалуйста рабочими вариантами либо работы с этим АЦП что-то ничего толкового у меня не выходит из этого...

Вы определитесь с желанием:

A. Получить готовый-рабочий-надежный код "драйвера" для AD7799

B. Заставить-отладить код, с которым Вы сейчас работаете и(ли) написать (переписать) свой "драйвер" с нуля или на какой-то базе.

Если А - я пас :)  Ввиду отсутствия subj

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 hours ago, Ruslan1 said:

У меня есть только AD7789 и AD7792 очень многолетней давности под Майкрочип (PIC), уж не знаю чем оно поможет.

Попробуйте поделить задачу на части  и решайте шаг-за-шагом:

1) можете ли стабильно читать из АЦП известные значения (например, ID и значения, которые должны читаться из регистров после сброса)

2) можете ли писать

. . . .

(1) - я предлагал проверить чтение ID - насколько понял, работает. Те. уровень SPI и внешний hardware рабочие.

ТС использует continuous-conversion режим. Не лучший режим для отладки кода, и вообще "всего".

ТС, почему для отладки не работаете в Single-Conversion ? Для continuous-conversion оптимально было бы использовать апп. прерывания от АЦП,

а их у Вас - 3 шт. , причем без синхронизации. Отдельной линии выхода прерывания у этих АЦП нет, она совмещена с DOUT, что "очень удобно".

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, k155la3 said:

(1) - я предлагал проверить чтение ID - насколько понял, работает. Те. уровень SPI и внешний hardware рабочие.

ТС использует continuous-conversion режим. Не лучший режим для отладки кода, и вообще "всего".

ТС, почему для отладки не работаете в Single-Conversion ? Для continuous-conversion оптимально было бы использовать апп. прерывания от АЦП,

а их у Вас - 3 шт. , причем без синхронизации. Отдельной линии выхода прерывания у этих АЦП нет, она совмещена с DOUT, что "очень удобно".

 

не могу понять как запустить повторное измерение.

после калибровки выбираю режим однократных измерений. проходит 1 измерение, поднимается бит RDY, считываю данные из регистра данных, бит RDY остается поднятым. чип переходит в энергосберегающий режим, я снова отправляю команду о переключении режима в режим однократного измерения и ничего не происходит. RDY так и остается 1 и в регистре данных остаются старые данные.

3 hours ago, k155la3 said:

Не надейтесь, что код, который выложен в качестве appnote, даже AD, будет оптимален. Может да, а может и нет.

То чо Вы привели выше - скорее нет (IMHO). Вы в ЭТОМ, разберетесь и добьетесь, чтоб ОНО заработало (потратив время на чужой код). Но есть ли смысл ?

Наводят на "смутные сомненья" конструкции вида


	if(size == 1)
	{
		receivedData += (data[0] << 0);
	}

Я работал с AD7794, они во многом похожи, но есть и существенные отличия, поэтому "вчистую" мой софт не подключишь.

Работал с этим давно, надо порыться в архивах. Но, повторяю - это код для 7794. Если будет желание - сможете его адаптировать под 7799. 

В коде, который используете Вы (от AD) - много лишнего - потомукак они сделали его универсальным. Я свой драйвер на 7794 тоже писал факт. с нуля,

тк имевшийся до этого код был "мутноват". Заодно изучил даташит на АЦП.

 

Вы определитесь с желанием:

A. Получить готовый-рабочий-надежный код "драйвера" для AD7799

B. Заставить-отладить код, с которым Вы сейчас работаете и(ли) написать (переписать) свой "драйвер" с нуля или на какой-то базе.

Если А - я пас :)  Ввиду отсутствия subj

 

Я и не надеюсь найти готовый код взять и целиком применить его к своему случаю. я хочу понять как другие работают с таким ацп и тем самым вычислить ошибку в своем варианте.

код от АД я взял чтобы оттолкнуться от него и в нем было много мутных моментов, которые пришлось корректировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 hours ago, Ruslan1 said:

У меня есть только AD7789 и AD7792 очень многолетней давности под Майкрочип (PIC), уж не знаю чем оно поможет.

 

Попробуйте поделить задачу на части  и решайте шаг-за-шагом:

1) можете ли стабильно читать из АЦП известные значения (например, ID и значения, которые должны читаться из регистров после сброса)

2) можете ли писать

3) можете ли сконфигурировать

4) можете ли прочитать значение АЦП при неизменяемом поданном на вход напряжении (да хоть резистивный делитель от Vrfef)

5) чтение статических величин с разных входов АЦП

6) чтение динамических данных.

В подобных вопросах логический анализатор (даже дешевый китайский за 10 баксов)- это истина в последней инстанции. Сэкономите сильно больше чем потраченные деньги, да и отладка подобных интерфейсов из мучения превращается в приятное развлечение.

первые 3 пункта успешно выполняются.

4 и 5 завтра проведу.

6 тоже выполняется но с "приколами"

Лог анализатор и так активно использую, о чем чуть выше писал. (Tektronix MSO2002B, 70мгц, 16 каналов цифровых и 2 аналоговых, DPO, модуль расшифровки SPI)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, Reystlin said:

Лог анализатор и так активно использую, о чем чуть выше писал. (Tektronix MSO2002B, 70мгц, 16 каналов цифровых и 2 аналоговых, DPO, модуль расшифровки SPI)

Ну, тогда и проблем особенно быть не должно: если Вы читаете именно то же, что анализатор показывает в потоке SPI данных, то дело не в чтении, а, например, в конфигугровании или в интерпретации принятых данных, или в железе.

Кстати, я долго хотел подобный ЛА в осциллографе. Но знакомство с китайским клоном Saleae анализаторов отбило эту хотелку- осциллографом неудобно, на компьютере сильно удобней анализировать. Особенно когда нужно потоки данных сутками писать, чтобы потом вылавливать редкие глюки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#include <msp430.h>
#include "SPI.h"
#include "AD779x.h"

char status;
__data20 TStr_AD7794_parm AD7794_parm[] =
{
//  ID GAIN	Rx	Ist	IOREG	CFG					MODE					V_Ref
    {0, 6.,	0,	0.,	0x0A	,(cBUF + cVDDIN),	    		(mdSingleConv + mPSW + mFS1+mFS0),	1.17	},
    {1, 32., 	3000,	0.21,	0x02	,(cBUF + cAIN2  + cGAIN32+cREF_DET),	(mdSingleConv + mFS1 + mFS0),		0.63	},
    {2, 8., 	0,	0.,	0x0A	,(cBUF + cAIN1  + cGAIN16),		(mdSingleConv + mPSW + mFS1 + mFS0),	3300.0	},
    {3, 2., 	3000,	0.21,	0x0E	,(cBUF + cAIN3  + cREFSEL0 + cGAIN2 + cREF_DET),  (mdSingleConv + mFS1+mFS0),	3000.0	},
    {4, 2., 	3000,	0.21,	0x0A	,(cBUF + cAIN6  + cREFSEL0 + cGAIN2 + cREF_DET),  (mdSingleConv + mFS1+mFS0),	3000.0	}

};

void AD7794_Init(void)
{
// ------- RESET --------------------------
	SET_CS0_7794;
	SPI_TX_Wait(0xFF);
	SPI_TX_Wait(0xFF);
	SPI_TX_Wait(0xFF);
	SPI_TX_Wait(0xFF);
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + MODEREG);
	SPI_TX16(mdIdle + mPSW + mFS1 + mFS0);
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + IOREG);// IOREG

	//SPI_TX_Wait( 0x0E ); 	// для 3 канала	
	SPI_TX_Wait( 0x0A ); 	// для 6 канала

	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + MODEREG);		// MODREG
	SPI_TX16(mdIdle + mFS1 + mFS0 + mPSW );
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
}

void AD7794_Start_A( TStr_AD7794_parm * ParmSet )

{
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + IOREG);
	SPI_TX_Wait( ParmSet->reg_io );
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + CFGREG);
	SPI_TX16_Wait( ParmSet->reg_cfg );	
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cWRITE + MODEREG);
	SPI_TX16( ParmSet->reg_mode );
	CS_ALL_1;
};

int AD7794_Read_A( unsigned long *long_data )

{
// ----------------------------------------
	SET_CS0_7794;
	SPI_TX_Wait(cREAD + rdSTATUS);
	status = SPI_TX_Wait(0);
	CS_ALL_1;
	__delay_cycles(10);
// ----------------------------------------

	if (status & 0x20)
	{
	    return(0);	// Error
	}
	else
	{
// ----------------------------------------
		SET_CS0_7794;
		SPI_TX_Wait(cREAD + DATAREG);
		*long_data = SPI_RX24();	// save result
		CS_ALL_1;
		__delay_cycles(10);
// ----------------------------------------
		return(1); // Ok
	}

};

"as-is". 

A_D_7_7_9_4.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Ruslan1 said:

Ну, тогда и проблем особенно быть не должно: если Вы читаете именно то же, что анализатор показывает в потоке SPI данных, то дело не в чтении, а, например, в конфигугровании или в интерпретации принятых данных, или в железе. 

Кстати, я долго хотел подобный ЛА в осциллографе. Но знакомство с китайским клоном Saleae анализаторов отбило эту хотелку- осциллографом неудобно, на компьютере сильно удобней анализировать. Особенно когда нужно потоки данных сутками писать, чтобы потом вылавливать редкие глюки.

Данные в дебаге с данными на шине совпадают.

с шиной взаимодействия все норм. с интерпретацией полученных данных тоже(пробовал после сброса считывать регистры и в них именно то, что по даташиту. пробовал записывать свои данные и читывать их после, тоже все верно)

каким образом обвязка может влиять на то, что ацп перестает измерять данные?(возникают паузы, в которых RDY не готов) причем пауза плавающая по времени и зависит от частоты выбранного фильтра?

 

з.ы. имеется у меня тоже клон Saleae. осциллом в разы удобней. так.же плюс что можно одновременно и аналоговый сигнал и цифровой смотреть, можно смотреть качество сигнала на шине данных или синхронизироваться более удобно. так-же есть возможность просмотреть таблицу данных на шине. у этого прибора есть ещё ф-я Wave Inspector которая может вести достаточно долгую запись и её потом можно перемотать и детально изучить все.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какая частота запуска оцифровки, (Update rate,  или интервал между запусками АЦП) ?

(Повтор) Чем чаще запускается АЦП, тем меньше достоверных разрядов Вы получите. См. таблицу в даташите, которую я упоминал ранее.

Максимальная точность-разрядность получится при запуске АЦП 4. 17 Гц. ( Update rate: 4.17 Hz to 470 Hz )

Table 6. Typical Resolution (Bits) vs. Gain and Output Update Rate for the AD7798 Using a 2.5 V Reference

SPECIFICATIONS   Table 1.    24 Bits min AD7799: fADC < 242 Hz   

 

Quote

каким образом обвязка может влиять на то, что ацп перестает измерять данные?

Каким угодно :)  Например шумное питание, наличие рядом генератора импульсной помехи (реле клацает на соседней плате) итд

Отключите все лишнее, запитайте узел от батарейки.

Кроме того, желательно иметь чип-эталон гарантированно от AD. Если на алиэкспресс - это котвмешке.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

 

 

Все видео были записаны с одинаковыми настрйоками, за исключением частоты настройки фильтра ацп.

Ку = 1

напряжение на входе 5 милливольт(задано резисторами)

1 число - регистр Status

5 число - количество измерений, полученных с ацп

6 число - значение последнего измерения

режим измерения - непрерывный.

 

количество измерений замерял вот так

  unsigned char rdy = 0;
  unsigned long reg_stat= AD7799_GetRegisterValue8bit( AD7799_CHIP3,AD7799_REG_STAT);
  rdy = (reg_stat & 0x80);
  if((rdy==0x80)&&((reg_stat& 0x07)==0x00))
    rdy=1;
  if((rdy==0x80)&&((reg_stat& 0x07)==0x01))
    rdy=2;
  if((rdy==0x80)&&((reg_stat& 0x07)==0x02))
    rdy=3;
weigt[0]=reg_stat;

    switch(rdy)
        {
        case 1:
          weigt[4]++;
           weigt[5] = AD7799_GetRegisterValue24bit(AD7799_CHIP3, AD7799_REG_DATA);
              break;
        case 2:
          weigt[5]=AD7799_GetRegisterValue(AD7799_CHIP3, AD7799_REG_DATA,3);
              break;
        }
    }

очень четко прослеживаются зависания в измерениях.

Микросхемы были взяты в компэле, пока за браком эта контора не была замечена.

всю обвязку входов цап отбросил, оставил только конденсатор 100нан между дифф.парой

Изменено пользователем Reystlin

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...