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

Reystlin

Участник
  • Постов

    128
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Reystlin


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

    а почему нет? у нас 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);
    }
    

     

  2. 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 итерации цикла проходит и потом все что считалось склеивается со сдвигом

  3. ацп у меня работает в непрерывном режиме измерений. после считывания данных измерение должно запускаться автоматически. Reg_ID считывается как 0х49

    #define AD7799_CS_LOW(selected_chip) AD7799_CS_PORT->ODR &=~(selected_chip);
    #define AD7799_CS_HIGH(selected_chip) AD7799_CS_PORT->ODR |=(selected_chip);
    
    AD7799_CS_LOW(AD7799_CHIP3);
    	SPI1->DR = 0x60; 
    	while(!(SPI1->SR & SPI_SR_RXNE));
    
    	weigt[3] = SPI1->DR; 
    AD7799_CS_HIGH(AD7799_CHIP3);
    AD7799_CS_LOW(AD7799_CHIP3);
    	SPI1->DR = 0x60; 
    	while(!(SPI1->SR & SPI_SR_RXNE));
    
    	weigt[3] = SPI1->DR; 
    AD7799_CS_HIGH(AD7799_CHIP3);

     

  4. 1 hour ago, k155la3 said:

    Может оно ?

    Ну, еще уровень функций интерфейса SPI надо проверять.

    так я же ничего в дата регистр не пишу.

    unsigned char AD7799_SPI_Init( void )
    {
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//Включаем тактирование SPI1
      
      //Настройка внутреннего SPI1
      SPI_InitTypeDef spi;  
      SPI_StructInit(&spi);
        spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//Направление передачи        
        spi.SPI_Mode = SPI_Mode_Master;                     //Режим передачи
        spi.SPI_DataSize = SPI_DataSize_8b;                 //Размер пакета
        spi.SPI_CPOL = SPI_CPOL_High;                        //idle тактового сигнала
        spi.SPI_CPHA = SPI_CPHA_2Edge;                      //рабочий фронт тактового сигнала
        spi.SPI_NSS = SPI_NSS_Soft;                         //режим работы пина NSS
        spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//Предделитель
        spi.SPI_FirstBit = SPI_FirstBit_MSB;                //Первый бит - младший
        spi.SPI_CRCPolynomial = 7;                          //Контрольная сумма
        SPI_Init(SPI1, &spi);
        SPI_Cmd(SPI1, ENABLE);
        //Насройка выводов под SPI1
      GPIO_InitTypeDef port;
      GPIO_StructInit(&port);
        port.GPIO_Mode = GPIO_Mode_AF_PP;
        port.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
        port.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &port);    
    
      //Насройка выводов под ~CS
      GPIO_StructInit(&port);
        port.GPIO_Mode = GPIO_Mode_Out_PP;
        port.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
        port.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(AD7799_CS_PORT, &port);
        AD7799_CS_PORT->ODR |=((1<<4)|(1<<5)|(1<<6));
        return(1);
    }
    
    unsigned char AD7799_SpiTransferByte(unsigned char data)
    {
    	unsigned char temp;
    
    	SPI1->DR = data; 
    	while(!(SPI1->SR & SPI_SR_RXNE));
    
    	temp = SPI1->DR; 
    	return temp;
    }

     

  5. 3 minutes ago, k155la3 said:

    У Вас работа с одним чипом АЦП и одним его каналом получается корректно ?

    Не знаю, по-моему Вам надо пересмотреть построение (логику) функций интерфейса. Если это не Ваш код изначально, тем более.

    Так как наличие и время устновки CS я не вижу. 

    Где-то в подобном стиле (хотя, "дело вкуса")

    int AD77xx_IsReady(void) { if( AD77xx_GetStatus() & 0x80 ) return(0); else return(1);  }; // не помню, возможно инверсно

    тогда считывание 

    
    SPI_CS_ACTIVE_ADC_00    (макро, устанавливает нолик на нужный пин порта)
    // ----------------
    
    if( AD77xx_IsReady() )
    
    {
    
    	AD77xx_SetChannel( 0 );
    	if( AD77xx_IsReady() ) 
    		AD77xx_Go();
    	else
    		.... error 
    }
    else
    	. . . . wait or error .....
    
    // ----------------
    SPI_CS_PASSIVE_ADC_00    
    

     

    Я взял пример от аналогдевайс, переписал там ф-и раоты в SPI и дописал нехватающих функций

    вот код где CS дергается и происходит отправка и прием данных

    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;
      
    }
    void AD7799_SetRegisterValue(unsigned char CS,unsigned char regAddress,
                                 unsigned long regValue, 
                                 unsigned char size)
    {
      unsigned char data[4] = { 0x00, 0x00, 0x00, 0x00};	
      data[0] = AD7799_COMM_WRITE |  AD7799_COMM_ADDR(regAddress);
        if(size == 1)
        {
            data[1] = (unsigned char)regValue;
        }
        if(size == 2)
        {
    		data[2] = (unsigned char)((regValue & 0x0000FF) >> 0);
            data[1] = (unsigned char)((regValue & 0x00FF00) >> 8);
        }
        if(size == 3)
        {
    		data[3] = (unsigned char)((regValue & 0x0000FF) >> 0);
    		data[2] = (unsigned char)((regValue & 0x00FF00) >> 8);
            data[1] = (unsigned char)((regValue & 0xFF0000) >> 16);
        }
        
        AD7799_CS_LOW(CS);
        for(char i=0;i<=(size);i++)
              AD7799_SpiTransferByte(data[i]);
        AD7799_CS_HIGH(CS);
    }

    На данный момент задействован 1 ацп и 1 его канал

  6. 7 minutes ago, k155la3 said:

    обратите внимание на Table 5. Output RMS Noise (µV) vs. Gain and Output Update Rate for the AD7798 Using a 2.5 V Reference

    и на табл. Table 14. Update Rates Available. Чем выше частота запуска АЦП, тем меньше у Вас получится достоверная разрядность.

    При переключении канала следует учитывать время на "установление" режима входа АЦП (при наличии внешних RC фильтров, усилителей, конденсаторов).

    Это аналогично настройке времени отработки УВХ для АЦП посл. приближения.

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

    считывание сейчас сделано вот таким кодом

      unsigned char rdy = 0;
      unsigned long reg_stat= AD7799_GetRegisterValue( AD7799_CHIP3,AD7799_REG_STAT,1);
      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;
    weigt[1]=AD7799_GetRegisterValue( AD7799_CHIP3,AD7799_REG_MODE,2);
    weigt[2]=AD7799_GetRegisterValue( AD7799_CHIP3,AD7799_REG_CONF,2);
    weigt[3]=AD7799_GetRegisterValue( AD7799_CHIP3,AD7799_REG_OFFSET,3);
    weigt[4]=AD7799_GetRegisterValue( AD7799_CHIP3,AD7799_REG_FULLSALE,3);
          switch(rdy)
            {
            case 1:
    
              weigt[5] = filter(ADCFilter(4,AD7799_GetRegisterValue(AD7799_CHIP3, AD7799_REG_DATA,3)));
                  break;
            case 2:
              //weigt[5]=AD7799_GetRegisterValue(AD7799_CHIP3, AD7799_REG_DATA,3);
                  break;
            }
        }

    т.е. происходит только по наличию бита готовности в регистре статуса

  7. 13 minutes ago, Ruslan1 said:

    Это несколько интересных эффектов:

    1. перезаряд всех имеющихся в схеме емкостей на входе АЦП (и внешних реальных-паразитных и внутренней) от неизвестного уровня предыдущего входа к новому измеряемому уровню током нового подключенного измеряемого входа, с учетом входного сопротивления АЦП и других токов утечки.

    2. перегрузка фильтр АЦП новыми данными. Процесс и технология обычно описаны в даташите АЦП. Но следует понимать, что сеачала должно произойти (1) и тольео потом начаться (2).

     

    У меня был случай, когда, паразитные емкости электронных коммутаторов мешали. Вводил даже специальный вход, перезаряжающий все емкости измерителя до среднего уровня, от которого уже можно было посчитать максимальное время перезаряда до измеряемого уровня. То есть In1-Ref-In2-Пауза-Измерение_In2.

    Это все считается (ну или хоть симулируется в симуляторе как набор цепочек R-C), подбирать тут опасно- будет на одном входе -Vmax, а  на другом входе +Vmax, и окажется что емкости недоперезарядились.

    тензодатчик же низкоомный прибор. ток перезарядки этих емкостей будет достаточно большим

  8. 11 minutes ago, alexunder said:

    Встречал такое у АЦП с мултиплексором на входе, вроде у AD7949. Канал с низким напряжением на входе хорошо чувствовал своего соседа (опрошенного перед ним), у которого на входе был потенциал заметно выше (в режиме по умолчанию эта ИМС перебирала каналы последовательно от 0 до N). Проблема решилась отключением режима последовательного перебора канала и двух- трехкратным чтением каждого канала.

    Пробовал делать переключение каналов на каждое 10ое измерение, все-равно каналы друг в друга проникают. после переключения один канал плавно подбирается к уровню второго

    было решено отказаться от использования вторых каналов.

  9. вывел все регистры на экран. считываю их в цикле измерений.

    1 - STATUS

    2 -  MODE

    3 - CONFIGURATION

    4 - OFFSET

    5 - FULLSALE

    6- значение ацп.

     

    по видео видны странности:

    1. в моменты пауз в регистре статуса биты ready и error = 0

    положительное усилие на датчик не влияет на эту ситуацию

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

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

    так-же после снятия положительного усилия с датчика с очень большой задержкой он возвращается в нулевое положение по показаниям.

    куда копать? всю голову сломал, не могу понять природу происходящей магии

  10. Доброго времени суток ув. форумчане

    Столкнулся я тут с задачей на AD7799, имеется 3 таких ацп на общей шине с раздельными CS ессно. К двум каналам каждого АЦП подключены свои мостовые тензодатчики.

    Устройство занимается дозированием, посему требуется достаточно быстрый опрос значений с ацп с приемлимой точностью.

    Столкнулся вот с какими проблемами:

    1. Не совсем понятно как себя ведет внутренний фильтр.

    youtu.be/sv3gs0dkyPo

    На видео показана проблема.

    5 число сверху - вход к которому подключен датчик.

    результаты измерения ацп иногда замирают, причем на разное время.

    так-же время замирания зависит от частоты фильтра. чем выше частота фильтра тем короче эти задержки

    режим работы ацп - непрерывный. данные считываю по флагу в регистре статуса.

    2. Если часто переключать каналы то возникает проникание сигнала одного канала в другой. я подозреваю, что это связано с наличием фильтра после преобразователя а каналы там муксом на входе преобразователя выбираются... есть ли лайфхаки обойти сею проблему?

    код инициализации:
     

    void AD7799_Config(unsigned char chip)
    {
        AD7799_Init(chip);
        AD7799_SetUnipolar(chip,1);
        AD7799_SetGain(chip,AD7799_GAIN_1);               
        
       AD7799_SetFilterMode(chip,AD7799_Filter_16_7_50hz);
        
        AD7799_SetChannel(chip,AD7799_CH_AIN2P_AIN2M);  
        
        AD7799_SetMode(chip,AD7799_MODE_CAL_INT_ZERO);
        while(AD7799_Ready(chip));
        
        AD7799_SetMode(chip,AD7799_MODE_CAL_INT_FULL);
        while(AD7799_Ready(chip));
        
        AD7799_SetChannel(chip,AD7799_CH_AIN1P_AIN1M);
    
        AD7799_SetMode(chip,AD7799_MODE_CAL_INT_ZERO);
        while(AD7799_Ready(chip));
        
        AD7799_SetMode(chip,AD7799_MODE_CAL_INT_FULL);
        while(AD7799_Ready(chip));
    
        AD7799_SetFilterMode(chip,AD7799_Filter_10);
        
        AD7799_SetMode(chip,AD7799_MODE_CONT);
    }

    код опроса регистра статуса

    unsigned char AD7799_Ready(unsigned char CS)
    {
      unsigned char rdy = 0;
      unsigned long reg_stat= AD7799_GetRegisterValue( CS,AD7799_REG_STAT,1);
      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;
      return(rdy);
    }

    код опроса ацп

           switch(AD7799_Ready(AD7799_CHIP2))
            {
            case 1:
                  weigt[2] = AD7799_GetRegisterValue(AD7799_CHIP2, AD7799_REG_DATA,3);
                  AD7799_SetChannel(AD7799_CHIP2,AD7799_CH_AIN2P_AIN2M);
                  break;
            case 2:
                  weigt[3] = AD7799_GetRegisterValue(AD7799_CHIP2, AD7799_REG_DATA,3);
                  AD7799_SetChannel(AD7799_CHIP2,AD7799_CH_AIN1P_AIN1M);
                  break;
            }

     

  11. все никак не могу нормально сделать экспорт из Solidworks PCB в Solidworks....

    сейчас вот с какой проблемой столкнулся

    есть плата, на ней стоят детали нарисованные вручную в солиде и вставленные в библиотеку.

    нажимаю кнопку Push в Solidworks PCB Collaboration, все проходит без ошибок, в папке проекта создается папка в которой повляются парасолидовские файлы компонентов, эти файлы открываются солидом отдельно без проблем.

    когда в солиде нажимаю Pull Board from PCB Services, начинается процесс загрузки платы, и вылетает ошибка "Failed to import: D:\Projects\Downloaded Models\POSISTOR16P_Rp.x_t, error: 0"

    при этом в рабочей папке так-же появляются файлы парасолидовских моделей но вот они уже солидом отдельно не открываются...

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

  12. Доброго времени суток ув. форумчане

    юазю для составления схем и разводки ПП пакет Solidworks PCB, по сути тот-же Альтиум, но упрощенный.

    понадобилось нарисовать футпринт для компонента, у которого два вывода внутри корпуса соединены

    Вычитал, что в Альтиуме для этого есть параметр у Pad-a Jubmer ID, в Солиде он тоже есть, установил там одинаковые номера отличные от 0 и присовил Pad-ам разные Designator-ы, но Солид не хочет их электрически связывать...

  13. так ведь полуавтомат это источник напряжения с ограничением по току, это дуговой и тиг аппараты являются источниками тока с ограничением по напряжению

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

  14. Спасибо за ответы, кажется необходимо конкретизировать суть моего вопроса

    разрабатываю сварочный инверторный полуавтомат с управлением на мк.

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

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

  15. Доброго времени суток ув. форумчане

    Пытаюсь создать проект в IAR под STM32F401C-Discovery опираясь на видеоуроки с канала https://www.youtube.com/channel/UCZqlkhxfy2hA045jEBp9vwA

    все было замечательно до тех пор, пока не раскомменитровал строку #define STM32F401xx в файле stm32f4xx.h

    после чего начинают сыпаться ошибки

    что делаю не так?

    прикладываю архив с проектом

     

    нашел проблему...

    в свойствах проекта был один тип МК указан а в h файле другой тип раскомментирован

    Induct.rar

  16. Доброго времени суток, ув. форумчане

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

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

    аппаратно думаю ставить STM32F407

    каким образом лучше всего реализовать такую задачу?

     

    мне на ум пока приходит только вот такое решение задачи

    X1(t1), X2(t2) - измерения АЦП

    x = X2 -L*((x2-x1)/(t2-t1))

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