Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как грамотно использовать DMA для ADC?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Мур
Необходимо по пускам ADC от таймера (по доке до 500кГц!) загружать массив в ОЗУ. По прерыванию не годится. Преимущество DMA в архитектуре основной козырь Smart-проца, к тому же задача требует жёсткой привязки к таймеру на пределе 400кГц. Первый опыт после AVR, так что непривычна архитектура. Может у кого фрагменты С кода есть? Ссылочки какие? В конце концов не обязательно под ADC.... Это важно для понимания.. santa2.gif Поделитесь, корефаны! biggrin.gif Мне-б зацепится в теме...
Вообще, скудная информация по апликейшен... Мне советуют филлипок для старта. Пока упрямлюсь!
Vix
Настриваем таймер, АЦП и его DMA. Прерывание АЦП по заполнению буфера DMA. Здесь есть лишние моменты (часть убрал), но что-нибудь можно понять.

AT91PS_PIO p_PIO = AT91C_BASE_PIOA;
AT91PS_USART p_US0 = AT91C_BASE_US0;
AT91PS_TC p_TC0 = AT91C_BASE_TC0;
AT91PS_TC p_TC1 = AT91C_BASE_TC1;
AT91PS_TC p_TC2 = AT91C_BASE_TC2;
AT91PS_AIC p_AIC = AT91C_BASE_AIC;
AT91PS_PMC p_PMC = AT91C_BASE_PMC;
AT91S_ADC *p_ADC = AT91C_BASE_ADC;

void IntT0(void) __irq{
p_ADC->ADC_CR = AT91C_ADC_START;
p_AIC->AIC_EOICR = p_TC0->TC_SR;
}

void IntADC(void) __irq{
unsigned int status;
status = p_ADC->ADC_SR;
if(status & AT91C_ADC_ENDRX)
{
p_ADC->ADC_RPR = (uint)(US0.TXpage0 + 4); // + adcpagecnt*(sizeof(US0.TXpage0)/2); //offset 4x16bit Чтобы не затереть заголовок буфера
p_ADC->ADC_RCR = sizeof(US0.TXpage0) - 12;
}
p_AIC->AIC_EOICR = status;
}

void InitT0(void){
p_PMC->PMC_PCER = BV(AT91C_ID_TC0);
p_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_CPCTRG;
// p_TC0->TC_RC = 150 - 1; //0.0004 with 48MHz/128
p_TC0->TC_RC = (unsigned int)(100*(FMCK/1000.0/128.0)/(sizeof(US0.TXpage0)/2 - 6 + 3) - 1); // CV=(t_ms/1000)*(Fmcu/128)*(1/bufsize) - 1
///Init Interrupt
p_TC0->TC_IER = AT91C_TC_CPCS;
p_AIC->AIC_SVR[AT91C_ID_TC0] = (uint)IntT0;
p_AIC->AIC_SMR[AT91C_ID_TC0] = PRIOR7 | AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED;
p_AIC->AIC_IECR = BV(AT91C_ID_TC0);

p_TC0->TC_CCR = AT91C_TC_CLKEN;
p_TC0->TC_CCR = AT91C_TC_SWTRG;
}

void InitADC(void){
p_PMC->PMC_PCER = BV(AT91C_ID_ADC);
p_ADC->ADC_CR = AT91C_ADC_SWRST;
p_ADC->ADC_CHER = /*AT91C_ADC_CH3 | AT91C_ADC_CH2 | AT91C_ADC_CH1 |*/ AT91C_ADC_CH4;
p_ADC->ADC_MR = AT91C_ADC_LOWRES_10_BIT | /*resolution*/
( (FMCK/2/ADC_CLK - 1) << 8 ) | /*PRESCAL*/
(5 << 24); /*SHTIM*/
p_AIC->AIC_SVR[AT91C_ID_ADC] = (uint)IntADC;
p_AIC->AIC_SMR[AT91C_ID_ADC] = PRIOR5 | AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED;
p_AIC->AIC_IECR = BV(AT91C_ID_ADC);
p_ADC->ADC_RPR = (uint)(US0.TXpage0 + 4); //offset 4x16bit Чтобы не затереть заголовок буфера
p_ADC->ADC_RCR = sizeof(US0.TXpage0) - 12; //in bytes
p_ADC->ADC_RNPR = 0;
p_ADC->ADC_RNCR = 0;
p_ADC->ADC_PTCR = AT91C_PDC_RXTEN;
p_ADC->ADC_IER = AT91C_ADC_ENDRX; /*| AT91C_ADC_EOC3; */
// p_ADC->ADC_CR = AT91C_ADC_START;
}

//В main вызываем функции инициализации таймера и АЦП.
Удачи!
Мур
Огромное спасибо!! cheers.gif
Думаю, сторонников ARM7 добавится...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.