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

 
 
> AT91SAM7S работа ADC совместно с PDC (прямой доступ к памяти)
kumle
сообщение Dec 7 2011, 12:17
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 149
Регистрация: 15-12-09
Из: Москва
Пользователь №: 54 280



Очень плохо этот момент описан в даташите и примера в IAR как назло нет.
Пробовал сам сделать но не получилось. Может там есть какая то хитрость ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
kumle
сообщение Dec 9 2011, 08:25
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 149
Регистрация: 15-12-09
Из: Москва
Пользователь №: 54 280



Цитата
Так показывайте, будем искать ошибку.


Вот инициализация ADC, PDC и таймера

Код
//ADC init
  
  ADC_Initialize( AT91C_BASE_ADC,
                    AT91C_ID_ADC,
                    AT91C_ADC_TRGEN_EN,
                    AT91C_ADC_TRGSEL_TIOA0,
                    AT91C_ADC_SLEEP_NORMAL_MODE,
                    AT91C_ADC_LOWRES_10_BIT,
                    BOARD_MCK,
                    BOARD_ADC_FREQ,
                    10,
                    1200);
  ADC_EnableChannel(AT91C_BASE_ADC, ADC_NUM_3);
  
  IRQ_ConfigureIT(AT91C_ID_ADC, AT91C_AIC_PRIOR_LOWEST, ADCC0_IrqHandler);
  IRQ_EnableIT(AT91C_ID_ADC);

  
  //PDC init
  ADC_Ptr1 = ADC_Result;
  AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTDIS;
  AT91C_BASE_ADC->ADC_RPR = (unsigned long)ADC_Ptr1; // Receive Pointer Register
  AT91C_BASE_ADC->ADC_RCR = 64; // Receive Counter Register
  //  Set receive pointer register for next transfer
  AT91C_BASE_ADC->ADC_RNPR = (unsigned long)ADC_Ptr1;
  //  Set receive counter register for next transfer
  AT91C_BASE_ADC->ADC_RNCR = 64;    
  
  
  AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX; //enable interrupt on transfer complete
  AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; //ADC start


//timer init
TC_Configure( AT91C_BASE_TC0,
                    (AT91C_TC_ASWTRG_CLEAR | AT91C_TC_ACPC_CLEAR | AT91C_TC_ACPA_SET | AT91C_TC_LDRA_RISING |
                     AT91C_TC_WAVE  | AT91C_TC_WAVESEL_UP_AUTO | 0 ));

TC_Start(AT91C_BASE_TC0); //старт таймера



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

Код
void ADCC0_IrqHandler(void)
{
  unsigned int status, i;
  unsigned short* ADC_Ptr2;
  status = AT91C_BASE_ADC->ADC_SR;
  if (status & AT91C_ADC_ENDRX)
  {
    ADC_Ptr2 = ADC_Result;
    AT91C_BASE_ADC->ADC_RPR = (unsigned long) ADC_Ptr2; // Receive Pointer Register
    AT91C_BASE_ADC->ADC_RCR = AD_DATA_BUFFER_SIZE; // Receive Counter Register
    //AT91C_BASE_ADC->ADC_RNPR = (unsigned long)ADC_Ptr_Next; // Receive Next Pointer Register
    //AT91C_BASE_ADC->ADC_RNCR = AD_DATA_BUFFER_SIZE; // Receive Next Counter Register
    conv_done = 1;
  }
  else if((status & AT91C_ADC_ENDRX) == AT91C_ADC_ENDRX)
  {
    AT91C_BASE_ADC->ADC_RNCR = AD_DATA_BUFFER_SIZE;
  }
}


Цитата(Genadi Zawidowski @ Dec 8 2011, 11:09) *
Готовый проект возмите - там в файле hardware.c начиная с функции adc_initialize().

Спасибо буду смотреть и сравнитвать со своим, правда я делал с помощью
функций из папки at91lib, придется в них залесть
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 9 2011, 09:42
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (kumle @ Dec 9 2011, 10:25) *
Вот инициализация ADC, PDC и таймера
Покажите еще объявление ADC_Result. И не совсем понятно - вы используете всего один буфер? То есть пока вы вынимаете из него результаты измерений, PDC складывает в него же следующие отсчеты? А вы уверены, что успеете "выгрести" первые результаты до того, как они затрутся?
И в прерывании:
CODE
if (status & AT91C_ADC_ENDRX)
  {
    .....
  }
  else if((status & AT91C_ADC_ENDRX) == AT91C_ADC_ENDRX)
второе условие никогда нее будет выполнено, ибо идентично первому.
У меня примерно так:
CODE
struct sample_t
{
    uint8_t Audio;
    uint8_t RSSI;
};

sample_t                Buffer[BUFFERS][BUFFER_SIZE];

volatile uint_fast8_t   wr_idx;
volatile uint_fast8_t   rd_idx;

void adc_init()
{
    wr_idx = 2;    // buffers 0 and 1 in PDC.
    rd_idx = 0;

    AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;

    AT91C_BASE_ADC->ADC_CHER = 0
        | (1<<4)                        // Audio
        | (1<<6)                        // RSSI
    ;

    AT91C_BASE_ADC->ADC_RPR = (uintptr_t)Buffer[0];
    AT91C_BASE_ADC->ADC_RCR = sizeof(Buffer[0])/sizeof(Buffer[0][0]);
    AT91C_BASE_ADC->ADC_RNPR = (uintptr_t)Buffer[1];
    AT91C_BASE_ADC->ADC_RNCR = sizeof(Buffer[1])/sizeof(Buffer[1][0]);
    AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN;
    AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX;

    AT91C_BASE_ADC->ADC_MR = 0
        | (4 * AT91C_ADC_SHTIM / 0x0F)
        | (0 * AT91C_ADC_STARTUP / 0x1F)
        | (2 * AT91C_ADC_PRESCAL / 0x3F)
        | AT91C_ADC_SLEEP_NORMAL_MODE
        | AT91C_ADC_LOWRES_8_BIT
        | AT91C_ADC_TRGSEL_TIOA0
        | AT91C_ADC_TRGEN_EN
    ;
}


void adc_handler()
{
    uint_fast8_t Tmp = wr_idx;

    AT91C_BASE_ADC->ADC_RNPR = (uintptr_t)Buffer[Tmp];
    AT91C_BASE_ADC->ADC_RNCR = sizeof(Buffer[Tmp]) /sizeof(Buffer[Tmp][0]);

    wr_idx = (Tmp + 1) & (BUFFERS - 1);
    Ready.signal_isr();
    AT91C_BASE_AIC->AIC_EOICR = 0;            // Reset AIC logic
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 28th July 2025 - 17:45
Рейтинг@Mail.ru


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