Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ацп at91sam7s256
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
sergey sva
Возникло несколько вопросов по поводу использования ацп с PDC.
Использую 4 канала ацп, один буфер, вопрос собственно в порядке записи
результатов измерения в буфер, результат измерения будет записываться сначала с
одного канала потом с другого, или сначала буфер заполнится с одного канала, после
будет прерывание по заполнению буфера?
Код
//------------------------------------------------------------
unsigned char ADCBUFER[4] = {0,0,0,0};

void InitADC(void){
p_PMC->PMC_PCER = BV(AT91C_ID_ADC);
/* razreshenie tactirovanija ADC  */
p_ADC->ADC_CR = AT91C_ADC_SWRST;
/* sbros ADC  */
p_ADC->ADC_CHER = AT91C_ADC_CH1 | AT91C_ADC_CH2 | AT91C_ADC_CH3 | AT91C_ADC_CH4;
/* razreshenie kanalov 1 2 3 4 */
p_ADC->ADC_MR = AT91C_ADC_LOWRES_10_BIT   |  ( (MCK/2/ADC_CLK - 1) << 8 )   |  (5 << 24);
/* razreshenie 8 ili 10 bit; chastota sinh ADC; wrema viborki hranenija;   */
p_AIC->AIC_SVR[AT91C_ID_ADC] = (unsigned long)Func_Irq_Adc;
/*  vector programm prer. ADC */
p_AIC->AIC_SMR[AT91C_ID_ADC] = 0x05;
/* prioritet prer. ot T0 0 7  */
p_AIC->AIC_IECR = BV(AT91C_ID_ADC);
/* razreshenie prer. ot ADC */
p_ADC->ADC_RPR = (unsigned long)(ADCBUFER);
/*  ukazatel na bufer priema */
p_ADC->ADC_RCR =  sizeof(ADCBUFER);
/* razmer bufera priema */
p_ADC->ADC_RNPR = 0;
/*  ukazatel na bufer 2 priema */
p_ADC->ADC_RNCR = 0;
/* razmer bufera 2 priema */
p_ADC->ADC_PTCR = AT91C_PDC_RXTEN;
/* razreshenie priema peredachi */
p_ADC->ADC_IER = AT91C_ADC_ENDRX; /*| AT91C_ADC_EOC3; */
/* Prerivanie po zapolneniu bufera */
// p_ADC->ADC_CR = AT91C_ADC_START;
}
//------------------------------------------------------------
Сергей Борщ
Цитата(sergey sva @ Jan 2 2009, 20:20) *
вопрос собственно в порядке записи
результатов измерения в буфер, результат измерения будет записываться сначала с
одного канала потом с другого, или сначала буфер заполнится с одного канала, после
будет прерывание по заполнению буфера?
PDC включен после АЦП и не влияет на его работу. Значит он никак не может сообщить АЦП, что бцфер полон и можно переключать канал. АЦП работает само по себе, перебирая по очереди разрешенные каналы, а PDC вычитывает результаты из выходного регистра. Поэтому результаты в выходном буфере тоже будут последовательно с разных каналов: канал1_результат1, канал2_результат1...канал4_результат1, канал1_результат2, канал2_результат2...
Есть один нюанс - если вы не успеете подсунуть PDC очередной пустой буфер, то результаты одного или нескольких каналов будут потеряны и последовательность результатов в этом месте нарушится. Эту ситуацию можно отловить по биту RXBUFF в ADC_SR. Для восстановления синхронизации я не придумал ничего кроме рестарта АЦП.
sergey sva
С этим, разобрался, записывается со всех каналов по порядку, так же сохраняется в буфер.
Не хочется разводить темы с простыми вопросами, спрошу сдесь.
Как запретить все прерывния на время ?
Код
AT91C_BASE_AIC->AIC_IDCR = 0xffffffff //запрещаются полностью все прерывания
AT91C_BASE_AIC->AIC_IECR = (1 <<....) //разрешаем нужные прерывания
этот вариант не очень нравится.
как бы сделать примерно так:

ulong temp;

temp = AT91C_BASE_AIC->AIC_IDCR;
AT91C_BASE_AIC->AIC_IDCR = 0xffffffff
/* off    */


AT91C_BASE_AIC->AIC_IECR = temp;
/* on   */


Цитата(Сергей Борщ @ Jan 3 2009, 02:40) *
Эту ситуацию можно отловить по биту RXBUFF в ADC_SR. Для восстановления синхронизации я не придумал ничего кроме рестарта АЦП.

Код
void Func_Irq_Adc(void)      __irq{
unsigned int status;
/* peremennaja statusa preobrazovanija */
status = p_ADC->ADC_SR;
/* zapis v peremennuu statusa */
if(status & AT91C_ADC_ENDRX){
/* proverca zapolnenija bufera */
p_ADC->ADC_RPR = (unsigned long)(ADCBUFER);
p_ADC->ADC_RCR = sizeof(ADCBUFER);
}//end if(status & AT91C_ADC_ENDRX)

if(status & AT91C_ADC_RXBUFF)p_ADC->ADC_CR = AT91C_ADC_SWRST;  // ?

p_AIC->AIC_EOICR = status;
}//end void          Func_Irq_Adc(void)      __irq

Поправьте если что не так.
defunct
Цитата
Как запретить все прерывния на время ?

В Svsr mode можно так:
Код
static __inline U32 __ILock(void)
{
    U32 r, iStatus;
     __asm { MRS iStatus, CPSR }
     __asm { ORR r, iStatus, #0xC0 }  // Disable FIQ + IRQ
     __asm { MSR CPSR_c, r}
     return iStatus;
}

static __inline void __IUnlock(U32 iStatus)
{
     __asm { MSR CPSR_c, iStatus}
}



В user mode можно так:
Код
static __inline U32 __ILock(void)
{
    U32 iMask = AT91C_AIC_IMR;
    AT91C_AIC_IDCR = 0xFFFFFFFF; // disable all interrupt sources
    return iMask;
}

static __inline void __IUnlock( U32 iMask)
{
    AT91C_AIC_IECR = iMask;  // restore interrupt sources
}



Пользовать и то и другое одинаково:
Код
{
    U32 iStatus = __ILock();
       ... тут прерывания запрещены
    __IUnlock( iStatus );
       ... тут восстановлены
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.