Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Разбираюсь с ADS1255/1256.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Filov
Здравствуйте!

Хочу мерить напряжение с электронного умножителя (минимальное порядка 10^-7V) с частотой примерно 500-1000Hz. Выбрал в качестве АЦП ADS1255/1256.

Подключаю его к ATmega168 через USART в MSPIM. Т.к. основной SPI к сожалению занят. Для этого использую код из AppNote AVR317: Using the USART on the ATmega48/88/168 as a SPI master. Там как я понял организуется циклический буфер в который можно записывать данные и забирать оттуда данные, а он сам будет делать все остальное smile.gif.

DRDY от ADS1255 подключаю к INT1. Хочу заполнять массив по прерыванию INT1.


Делаю вот так:

*****main.c*****

Код
#define F_CPU 12500000UL  // 12.5 MHz

int main(void){

        /***init SPI as USART MSPIM and ~SS line ***/
        //Calculation of BRREG value. USART MSPIM:
        #define BPS 10000                                 //Desired bit rate for SPI communication.
        #define BRREG ((F_CPU/(2*BPS))-1)       // Calculated brreg value.
                                                                    //SPI clock t1: max = 4*tclock_ads1256 = 2 MHz
        init_usart_spi(0, BRREG);

        /***enable interrupt***/
        sei();

        /***enable ADS1256***/
        init_ads1256();

        while(1){.....}
}

** Инициализация ads1256

void init_ads1256(void){

        //***Initialise ADS1256
        char Byte=(WREG | 0x00);                //Starting at address 0x00,
        queue_byte(Byte);
        queue_byte(0x04);                       //write to a total of 5 registers (5 - 1 = 0x04)
        queue_byte(0x06);                       //STATUS register = 0x06
        queue_byte(0x01);                       //MUX register = 0x01
        queue_byte(0x01);                       //ADCON register = 0x01
        queue_byte(0xC1);                       //DRATE register = 0xC1
        queue_byte(0x00);                       //GPIO register = 0x00
        //ADS1256 Self Calibration
        queue_byte(SELFCAL);                    //Initiate self calibration
        _delay_ms(10);
//      do{char temp   =   PD3;} while((temp & 0x08) == 0x08);       //Wait for DRDY to go low
        //Set sample freq. to 500SPS

        //***Initialise External interrupt 1
        //PORTD3 is input by default
        //The low level of INT1 generates an interrupt request
        cbi(EICRA, ISC11);
        cbi(EICRA, ISC10);
        //enable INT1 interrupt
        sbi(EIMSK, INT1);

}


** Действия когда DRDY становится низким

//The following function will be called when analog conversion is done: DRDY connecting to PD3/INT1 is going low
ISR(INT1_vect) {

        //spi_send_mssp(_ADS1256_cmd_read_regs | _ADS1256_regs_io)
        queue_byte(RDATA);
        //spi_send_mssp(0)
        queue_byte(0);
        _delay_us(10);                 //*ADS1256 t6 VERY IMPORTANT* min_us=t6/F_ADS1256=50/7.68MHz=7us
        //spi_read_mssp(data)
        DAT[conv]=fetch_byte();
        DAT[conv+1]=fetch_byte();
        DAT[conv+2]=fetch_byte();
        conv=conv+3;
        //clear INT1 interrupt flag
        sbi(EIFR, INTF1);
}


файл USART in MSPIM в аттаче. там определяются функции init_usart_spi(), queue_byte(), fetch_byte()


Подскажите пожалуйста, все ли я делаю правильно? Будет ли такое вообще работать?
Filov
Всего я понял есть 2 варианта:

1) Все нормально и работать это будет.

2) Все настолько плохо, что замучаешься объяснять чего не так.

Вот.

Проблема в том, что начал я не так давно и такие сложные системы для меня трудны... Поэтому и прошу помощи...
forever failure
Это надо включить и посмотреть, как работает, какие значения возвращаются.
Не работать может по многим причинам, в частности аппаратным.

Кроме двух вышеупомянутых вариантов работоспособности есть ещё бесчисленное количество градаций вида "работает, но как-то не так".
Filov
Цитата(forever failure @ Jan 29 2008, 16:17) *
Это надо включить и посмотреть, как работает, какие значения возвращаются.
Не работать может по многим причинам, в частности аппаратным.

Кроме двух вышеупомянутых вариантов работоспособности есть ещё бесчисленное количество градаций вида "работает, но как-то не так".



ОК smile.gif

Так и собираюсь сделать... Только вот проблема как этот чип (ADS1255) припаять. Хотел купить оценочную плату ADS1256EVM , но их завезут в терраэлектронику только в марте. А сами чипы у меня есть. Сейчас ищу термотрансферную бумагу чтобы сделать печатную плату под этот АЦП. Таких маленьких схем еще не паял, вот и боюсь smile.gif. Вдруг вообще не будет работать...
Filov
Купил я оценочную плату ADS1256EVM. Подсоединил к МК atmega168.

Инициализировал USART в MSPIM как приведено в AppNote:

Код
/* Calculation of BRREG value. */
#define CPUFREQ 12500000UL
#define BPS 10000 //!< Desired bit rate for SPI communication.
#define brreg ((CPUFREQ/(2*BPS))-1) //!< Calculated brreg value.
/* USART line definitions. */
#define USARTDDR DDRD //!< The data direction register for the USART lines.
#define XCKPIN PD4 //!< The bit position for the USART XCK line.

uint8_t spimode=0;


        // Baud rate must be set to 0 prior to enabling the USART as SPI
        // master, to ensure proper initialization of the XCK line.
        UBRR0 = 0;

        // Set XCK line to output, ie. set USART in master mode.
        USARTDDR |= (1<<XCKPIN);

        // Set USART to Master SPI mode.
        UCSR0C = (1<<UMSEL01) | (1<<UMSEL00);

        // Set clock polarity and phase to correct SPI mode.
        if( spimode & 0x01 ) UCSR0C |= (1<<UCPOL0);
        if( spimode & 0x02 ) UCSR0C |= (1<<UCPHA0);

        // Enable RX and TX.
        UCSR0B = (1<<RXEN0) | (1<<TXEN0);

        // Set baud rate. Must be set _after_ enabling the transmitter.
        UBRR0 = brreg;




Пытаюсь прочесть содержимое регистров АЦП:


Код
        // Wait for empty transmit buffer.
        do {} while( (UCSR0A & (1<<UDRE0)) == 0 );
        Byte=(RREG | 0x00);                //прочитать регистры начиная с 0x00
        UDR0 =  Byte;
        // Wait for transfer to complete
        do {} while( (UCSR0A & (1<<RXC0)) == 0 );
        UDR0 =  0x03;                        //прочитать 4 регистра
        // Wait for transfer to complete
        do {} while( (UCSR0A & (1<<RXC0)) == 0 );
        delay_us(10);                         //Задержка перед чтением
        a0=UDR0;
        a1=UDR0;
        a2=UDR0;
        a3=UDR0;


Получается какая-то ерунда. Первые две попытки считать регистры выдают нули во всех 4 регистрах. Далее начинается циклически:

Код
     a0 a1 a2 a3

1n  90 78 90 90
2n  70 ff 70 70
3n  00 00 00 00
4n  18 00 18 18


И т.д по кругу. Причем цифры после сброса питания могут меняться - но обычно 3 из них совпадают.

Если отключено питание АЦП читаются только нули.


Подскажите, пожалуйста, куда копать?
Xenia
Цитата(Filov @ Feb 20 2008, 16:39) *
Пытаюсь прочесть содержимое регистров АЦП:
Код
    // Wait for empty transmit buffer.
    do {} while( (UCSR0A & (1<<UDRE0)) == 0 );
    Byte=(RREG | 0x00);    //прочитать регистры начиная с 0x00
    UDR0 =  Byte;
    // Wait for transfer to complete
    do {} while( (UCSR0A & (1<<RXC0)) == 0 );
    UDR0 =  0x03;        //прочитать 4 регистра
    // Wait for transfer to complete
    do {} while( (UCSR0A & (1<<RXC0)) == 0 );
    delay_us(10);        //Задержка перед чтением
    a0=UDR0;
    a1=UDR0;
    a2=UDR0;
    a3=UDR0;

Получается какая-то ерунда. Первые две попытки считать регистры выдают нули во всех 4 регистрах.


Между подачей команды чтения UDR0=(RREG | 0x00) и собственно чтением a0=UDR0, согласно даташита, необходимо сделать паузу, как минимум, в 50 (!) циклов ADC-clock. Иначе одни нули прут. Если ваш МК работает на более высокой частоте, чем АЦП, то его тактов потребуется еще больше. Это только когда в регистры пишут задержка не нужна, а когда читают - обязательна. А ваше ожидание - это ожидание отправки байта, этого мало.

P.S. Ожидание короче писать не через конструкцию do-while, а просто через while. Вот так:
while( (UCSR0A & (1<<UDRE0)) == 0);
Herz
Цитата(Filov @ Jan 28 2008, 14:20) *
Здравствуйте!

Хочу мерить напряжение с электронного умножителя (минимальное порядка 10^-7V) с частотой примерно 500-1000Hz. Выбрал в качестве АЦП ADS1255/1256.

Подключаю его к ATmega168 через USART в MSPIM. Т.к. основной SPI к сожалению занят.

Вот это не понятно. Как это занят? Он что, на одно устройство рассчитан или ему некогда с АЦП общаться? Тут что-то не так. Привели бы схему, пояснили что и как. Есть подозрения, что не тот путь Вы выбрали...
Filov
Цитата(Herz @ Feb 21 2008, 11:51) *
Вот это не понятно. Как это занят? Он что, на одно устройство рассчитан или ему некогда с АЦП общаться? Тут что-то не так. Привели бы схему, пояснили что и как. Есть подозрения, что не тот путь Вы выбрали...



Он занят Ethernet модулем. Там отлаженная схема и программное обеспечение и не хотелось бы туда влезать. Просто я понял, что USART в MSPIM - полный аналог SPI в master mode - что мне собственно и нужно. И не хотелось бы просто все в одну кучу мешать. Я надеялся что тут есть специалисты, которые работали с этим АЦП и им подобными - и смогли бы подсказать в чем может быть ошибка. Какой шаг я не делаю или что делаю лишним.
Herz
А, так у Вас и ПО заимствованное...
Filov
Цитата(Herz @ Feb 21 2008, 20:32) *
А, так у Вас и ПО заимствованное...


Ну и так можно сказать. Мне нужно построить систему управления шаговым двигателем - двигать задвижку прибора, систему сбора данных - собирать данные о магнитном поле и напряжение с электронного умножителя и термопары, и регулируемый источник питания. 4-5 месяцев назад у меня не было даже мультиметра. Я начал решать задачи используя основу - связь микрочиповского контроллера ethernet через spi - интерфейс с atmega168, написанну. хорошим человеком и выложенную в открытый доступ.

Я считаю, что в рамках моей задачи поступаю верно. Я только учусь.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.