реклама на сайте
подробности

 
 
> Разный результат чтения АЦП AD7799, методом опроса RDY или по прерыванию от RDY.
alux
сообщение Aug 27 2008, 14:00
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



24-битное АЦП AD7799 меряет сигнал мостового датчика давления. Вывод MISO AT90USB1287 (DOUT AD7799) соединен с INT7 на AT90USB1287. Привожу код, чтобы было понятно о чем речь. Если читать АЦП через опрос вывода RDY, то все в порядке - вывожу на ЖКИ в виде кодов АЦП (0х000000 соответствует максимальному отрицательному давлению, 0х800000 соответствует отсутствию давления, 0хffffff соответствует максимальному положительному давлению). А если вместо
Код
while(!ad7799_data_ready());
написать
Код
Int7.Wait();
(это OS::TEventFlag - флаг события из ОС scmRTOS. В данном случае сигнал сообщения возникает из прерывания Int7.SignalISR(); ) , то вместо 0х800000 выводится 0хС00000, т.е. появляется "лишняя" единица в старшем предпоследнем разряде. Почему так происходит, - не пойму никак.
Код
void ad7799_Init(void)
{  
  ad7799_reset();
  delay_ms(500);
  ad7799_init_status = ad7799_status();
  
  // Enable external interrupt INT7
  ENABLE_INT7;      // Enable external interrupt INT7  falling edge
}


//============================================================
// Запуск непрерывного преобразования на AIN1
//______________________________________________________________________________
void start_Measure(void)
{
  ad7799_write_config(1, 0, AD7799_32_GAIN, 1, 1, AD7799_AIN1_CHAN);        //burnout, bipolar, gain, ref_det, buf, chan
  ad7799_set_mode(AD7799_CONTINUOUS_CONVERSION_MODE, 0, AD7799_470_HZ+rate);  //mode, psw=0(OFF), rate    

  while(!ad7799_data_ready());
  ad7799_request_data(1);           // 1 -> Continuous Read
  PORTB &= ~(1<<DIN);               // Held Low in Continuous-Read mode
}


/*** External interrupt handler ***/
#pragma vector=INT7_vect
OS_INTERRUPT void INT7_ISR()
{
  OS::TISRW_SS ISRW;
  
//  DISABLE_INT7;          // Prevent further external interrupts
  
  Int7.SignalISR();  
}

//////////////////////////////////////////////
//-------------------------------------------------------------------------------
OS_PROCESS void TMeasure::Exec()    //TProc2
{
    for(;;)
    {
        for(unsigned char volatile i=0; i < nmax; i++)
        {
          //Int7.Wait();                   // Ждем окончания преобразования АЦП (RDY => 0)
          while(!ad7799_data_ready());
          accumulator += ad7799_read_data();  // Накапливаем результат в аккумуляторе
        }        

        m.data[mux] = accumulator/nmax;     // Усреднение результата
        accumulator=0;

        //Int7.Wait();                   // Ждем окончания преобразования АЦП (RDY => 0)
        while(!ad7799_data_ready());
        ad7799_request_data(0);     // 0 -> Not Continuous Read  
        
         // Maintain multiplexing of input channels
          if(++mux > 1)  mux=0;      
          ad7799_write_config(1, 0, AD7799_32_GAIN, 1, 1, AD7799_AIN1_CHAN+mux); //burnout, bipolar, gain, ref_det, buf, chan  

//        ad7799_set_mode(AD7799_CONTINUOUS_CONVERSION_MODE, 0, AD7799_16_7_1_HZ); //mode, psw=0(OFF), rate

        //Int7.Wait();                   // Ждем окончания преобразования АЦП (RDY => 0)  
        while(!ad7799_data_ready());
        ad7799_request_data(1);     // 1 -> Continuous Read    
        PORTB &= ~(1<<DIN);         // Held Low in Continuous-Read mode

        if(!mux)
        {
          m.src = TValueADC::AD7799_SRC;
          ValueMsg = m;       // put the content to the OS::message object
          ValueMsg.send();    // send the message
        }
        Sleep(100);
      }
}

Это делается для того, чтобы не тратить время процессора на опрос бита RDY. Во время Int7.Wait(); ОС передает управление другим процессам. Но почему-то вылазит лишняя единица.
Какие будут предположения по этому поводу?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
sensor_ua
сообщение Aug 28 2008, 16:38
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Стоит посмотреть, не перенастраивается ли пин CS при разрешениях/запрещениях источника прерываний. Ну и какое чтение - аппаратный SPI (тогда он может с неподключенным MISO начинать читать, хотя был бы скорее лишний ноль) или ручками? А то куча текста, а ключевые моменты зачем-то отсутствуют. И не знаю, и не развернут у меня фриртос - как там (или у Вас) этот обработчик прописан и обрамление - не видел.


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
alux
сообщение Aug 28 2008, 18:34
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(sensor_ua @ Aug 28 2008, 19:38) *
не перенастраивается ли пин CS при разрешениях/запрещениях источника прерываний.

Нет, не перестраивается. В данном случае по SPI работает только AD7799.
Цитата(sensor_ua @ Aug 28 2008, 19:38) *
Ну и какое чтение - аппаратный SPI (тогда он может с неподключенным MISO начинать читать, хотя был бы скорее лишний ноль) или ручками?

SPI в данном случае аппаратный без использования прерывания:
Код
//------------------------------------------------------------------------------
unsigned char spiTransferByte(unsigned char data)
{
  unsigned char temp;
  
#ifdef SPI_USEINT
    spiTransferComplete = false;
    SPDR = data;                    // send the given data
    while(!spiTransferComplete);    // wait for transfer to complete
#else
    SPDR = data;                    // send the given data
    while(!(SPSR & (1<<SPIF)));    // wait for transfer to complete
#endif
        temp = SPDR;            // read value in SPI data reg.
    return temp;                    // return the received data                
}


Цитата(sensor_ua @ Aug 28 2008, 19:38) *
А то куча текста, а ключевые моменты зачем-то отсутствуют.
Какие еще ключевые моменты нужны? Я не вижу смысла расписывать мелкие функции драйвера АЦП. На мой взгляд проблема в том, что после готовности данных АЦП и моментом чтения проходит время, и портится результат следующего преобразования.
Цитата(GPP @ Aug 28 2008, 16:39) *
Нужно читать данные в прерывании и только после этого сигналить.
Попробовал так:
Код
#pragma vector=INT7_vect
OS_INTERRUPT void INT7_ISR()
{
  OS::TISRW_SS ISRW;

  accumulator += ad7799_read_data();  // Накапливаем результат в аккумуляторе
  
  if(++count > nmax)
  {
    count = 0;
    m.data[mux] = accumulator/nmax;   // Усреднение результата
    accumulator = 0;
    Int7.SignalISR();
  }
}
стало еще хуже - вместо 0х800000 выводит 0хffffff.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 03:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01391 секунд с 7
ELECTRONIX ©2004-2016