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

 
 
 
Reply to this topicStart new topic
> sam7s/7x пример ADC c PDC, sam7s/7x пример ADC c PDC
taoga
сообщение Jun 7 2013, 14:09
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809



Здравствуйте! Может кто-нибудь поделиться примером непрерывного приема данных от АЦП с использованием PDC для at91sam7s/sam7x?
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Jun 17 2013, 05:03
Сообщение #2


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Вот код целиком и з модуля, рабочий. Надеюсь разберетесь.

CODE
#include "adc.h"

/*==========================================================
=======================*/

static t_adc_channels *buf1;
static t_adc_channels *buf2;
static u8 adcflag = 0;

u16 channel0;
u16 channel2;
u16 channel4;
u16 channel5;
u16 channel6;
#if DEVICE < AUTO
u16 channel1;
u16 channel3;
#endif
t_adc_channels *adc_buf;
struct pt_sem adc_dtmf_sem = {0};
struct pt_sem adc_sem = {0};

/*===============================================================================
=======================*/
/*
================================================================================
===================
Description:
Returns :
Notes :
================================================================================
===================
*/
__irq __arm __ramfunc static void adc_interrupt_handler (void)
{
volatile u32 status = AT91C_BASE_ADC->ADC_SR & AT91C_BASE_ADC->ADC_IMR;

/* обрабатываем ovverrrun перезапуская АЦП сначала */
if ( status & AT91C_ADC_GOVRE)
{
AT91C_BASE_ADC->ADC_LCDR;
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_MR = AT91C_ADC_TRGEN_EN
|AT91C_ADC_TRGSEL_TIOA0
|AT91C_ADC_LOWRES_10_BIT
|AT91C_ADC_SLEEP_NORMAL_MODE
| ((unsigned int)(0x3) << 8) & AT91C_ADC_PRESCAL //1
| ((unsigned int)(0xA) << 16) & AT91C_ADC_STARTUP
| ((unsigned int)(0xF) << 24) & AT91C_ADC_SHTIM;


/* конфигурируем прерывания от ADC_PDC */
AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX | AT91C_ADC_GOVRE;

/* включаем приемник PDC */
/* Initialize the Transmit and Receive Pointer */
if (adc_buf == buf2)
{ AT91C_BASE_ADC->ADC_RPR = (unsigned int)buf1; }
else
{ AT91C_BASE_ADC->ADC_RPR = (unsigned int)buf2; }
/* Intialize the Transmit and Receive Counters */
AT91C_BASE_ADC->ADC_RCR = (DTMF_BLOCK_SIZE*ADC_CHANNEL_NUM);


/* включаем нужные каналы, входы мультиплексированные в PIO должны автомантически стать входами ADC */
#if DEVICE < AUTO
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH0 | AT91C_ADC_CH1 | AT91C_ADC_CH2 | AT91C_ADC_CH3 |
AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7;
#else
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH0 | AT91C_ADC_CH2 |
AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7;
#endif

/* запуск АЦП */
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;

AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
} else

/* преключаем буферы при нормальной работе ADC */
if ( status & AT91C_ADC_ENDRX)
{
if (adc_buf == buf2)
{ AT91C_BASE_ADC->ADC_RPR = (unsigned int)buf2; adc_buf = buf1; }
else
{ AT91C_BASE_ADC->ADC_RPR = (unsigned int)buf1; adc_buf = buf2; }
AT91C_BASE_ADC->ADC_RCR = (DTMF_BLOCK_SIZE*ADC_CHANNEL_NUM);
adcflag = 1;
}

AT91C_BASE_AIC->AIC_EOICR = 1;
}


/*
================================================================================
===================
Description: Конфигурируем АЦП
Returns :
Notes : Вклюяаются каналы DTMF и аналоговых входов. Триггер АЦП - таймер 2, генерирующий
меандр с частотой 8000 Гц. Количество включенных каналов зависит от версии устройства
================================================================================
===================
*/
int adc_open
(
t_adc_channels *ext_buf1, /* (вх.) буфер для dma работы с АЦП */
t_adc_channels *ext_buf2 /* (вх.) буфер для dma работы с АЦП */
)
{
buf1 = ext_buf1;
buf2 = ext_buf2;
adc_buf = buf1;

AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
AT91C_BASE_ADC->ADC_IDR = 0xFFFFFFFF;
AT91C_BASE_AIC->AIC_IDCR = 0x1u << AT91C_ID_ADC;


AT91C_BASE_ADC->ADC_CHDR = AT91C_ADC_CH0 | AT91C_ADC_CH1 | AT91C_ADC_CH2 | AT91C_ADC_CH3 |
AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7;

//* Disable the RX and TX PDC transfer requests
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTDIS;

//* Reset all Counter register Next buffer first
AT91C_BASE_ADC->ADC_TNPR = 0;
AT91C_BASE_ADC->ADC_TNCR = 0;
AT91C_BASE_ADC->ADC_RNPR = 0;
AT91C_BASE_ADC->ADC_TNCR = 0;
AT91C_BASE_ADC->ADC_TPR = 0;
AT91C_BASE_ADC->ADC_TCR = 0;
AT91C_BASE_ADC->ADC_RPR = 0;
AT91C_BASE_ADC->ADC_RCR = 0;

AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;

/* режим АЦП */
/* выбираем в качестве триггера TIOA2, 10 бит, чатота оцифровки максимальная MCK/10 */
AT91C_BASE_ADC->ADC_MR = AT91C_ADC_TRGEN_EN
|AT91C_ADC_TRGSEL_TIOA0
|AT91C_ADC_LOWRES_10_BIT
|AT91C_ADC_SLEEP_NORMAL_MODE
| ((unsigned int)(0x3) << 8) & AT91C_ADC_PRESCAL //1
| ((unsigned int)(0xA) << 16) & AT91C_ADC_STARTUP
| ((unsigned int)(0xF) << 24) & AT91C_ADC_SHTIM;

/* конфигурируем AIC на обработку прерываний от ADC */
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_ADC] = (unsigned int) adc_interrupt_handler;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_ADC] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | ADC_INTERRUPT_LEVEL;
AT91C_BASE_AIC->AIC_IECR = 0x1u << AT91C_ID_ADC;

/* конфигурируем прерывания от ADC_PDC */
AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX | AT91C_ADC_GOVRE;

/* включаем приемник PDC */
/* Initialize the Transmit and Receive Pointer */
AT91C_BASE_ADC->ADC_RPR = (unsigned int)buf1;
/* Intialize the Transmit and Receive Counters */
AT91C_BASE_ADC->ADC_RCR = (DTMF_BLOCK_SIZE*ADC_CHANNEL_NUM);

AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN;

AT91C_BASE_ADC->ADC_SR & AT91C_BASE_ADC->ADC_IMR;

/* включаем нужные каналы, входы мультиплексированные в PIO должны автомантически стать входами ADC */
#if DEVICE < AUTO
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH0 | AT91C_ADC_CH1 | AT91C_ADC_CH2 | AT91C_ADC_CH3 |
AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7;
#else
AT91C_BASE_ADC->ADC_CHER = AT91C_ADC_CH0 | AT91C_ADC_CH2 |
AT91C_ADC_CH4 | AT91C_ADC_CH5 | AT91C_ADC_CH6 | AT91C_ADC_CH7;
#endif

/* запуск АЦП */
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;

return 0;
}


/*
================================================================================
===================
Description:
Returns :
Notes :
================================================================================
===================
*/
__arm __ramfunc PT_THREAD ( pt_adc_oversampling
(
struct pt *pt /* (вх) структура состояния потока */
))
{
u8 i, j;
u16 sample_channel0 = 0;
u16 sample_channel2 = 0;
u16 sample_channel4 = 0;
u16 sample_channel5 = 0;
u16 sample_channel6 = 0;
#if DEVICE < AUTO
u16 sample_channel1 = 0;
u16 sample_channel3 = 0;
#endif


PT_BEGIN(pt);

PT_WAIT_UNTIL(pt, adcflag);
adcflag = 0;

PT_SEM_SIGNAL(pt, &adc_dtmf_sem);
PT_SEM_SIGNAL(pt, &adc_sem);

/* указатель буфера для DTMF устанавливаем на определенный заполненный буфер и выставляем семафор */
/* для остальных каналов сумммируем полученное число для оversamlinga */
for (j = 0; j < DTMF_BLOCK_SIZE / 64; j++)
{
sample_channel0 = 0;
sample_channel2 = 0;
sample_channel4 = 0;
sample_channel5 = 0;
sample_channel6 = 0;
#if DEVICE < AUTO
sample_channel1 = 0;
sample_channel3 = 0;
#endif
for (i = (j*64); i < ((j*64)+64); i++ )
{
sample_channel0 += adc_buf[i].ch0;
sample_channel2 += adc_buf[i].ch2;
sample_channel4 += adc_buf[i].ch4;
sample_channel5 += adc_buf[i].ch5;
sample_channel6 += adc_buf[i].ch6;
#if DEVICE < AUTO
sample_channel1 += adc_buf[i].ch1;
sample_channel3 += adc_buf[i].ch3;
#endif
}

/* 13 бит */
/* вычисляем текущее среднее для каналов */
channel0 = (channel0 * j + (sample_channel0 >> 3)) / (j+1);
channel2 = (channel2 * j + (sample_channel2 >> 3)) / (j+1);
channel4 = (channel4 * j + (sample_channel4 >> 3)) / (j+1);
channel5 = (channel5 * j + (sample_channel5 >> 3)) / (j+1);
channel6 = (channel6 * j + (sample_channel6 >> 3)) / (j+1);
#if DEVICE < AUTO
channel1 = (channel1 * j + (sample_channel1 >> 3)) / (j+1);
channel3 = (channel3 * j + (sample_channel3 >> 3)) / (j+1);
#endif
}

PT_END(pt);
}


Сообщение отредактировал IgorKossak - Jun 17 2013, 06:46
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!! (и не новичок, вроде бы)


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
taoga
сообщение Jun 17 2013, 14:41
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 8-10-09
Пользователь №: 52 809



Здравствуйте!

Спасибо! Есть еще кто-то живой rolleyes.gif. Я уже разобрался.
Вопрос правда к вашему коду есть. Уже второй раз вижу код, который мне вроде бы подходит но, без инициализации таймера. К чему бы это? sad.gif
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Jun 18 2013, 05:07
Сообщение #4


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Цитата(taoga @ Jun 17 2013, 18:41) *
Спасибо! Есть еще кто-то живой rolleyes.gif.


Я давно под эти процессоры все нужное мне написал. На них только старые проекты, так что скорее полуживой.

Надеюсь они больше не выпустят ревизий s256 после которых нужно будет переписывать воркараунды.


Цитата(taoga @ Jun 17 2013, 18:41) *
Вопрос правда к вашему коду есть. Уже второй раз вижу код, который мне вроде бы подходит но, без инициализации таймера. К чему бы это? sad.gif


Инициализация таймера в другом модуле, вместе с остальными таймерами. Я подумал, что там всё очевидно, потому выкладывать не стал. А так он настроен на waveform 8000 Гц.


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post

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

 


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


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