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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> AT91SAM7xxxx, ADC, 2 канала и PDC
RabidRabbit
сообщение Dec 14 2012, 07:28
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Цитата(Сергей Борщ @ Dec 13 2012, 11:09) *
Обработка бывает разной. Кроме обработки могут быть и другие задачи. Если размер буфера недостаточен - можно и не успеть.

Я с Вами всё же не согласен. Переключение буферов (АКА запись в регистры PDC) производится в прерывании по ENDRX. И помешать этому может только запрещение прерываний где-то ещё на всё время оцифровки буфера. Ну согласитесь, что это экстремальный вариант, который и рассматривать не стоит sm.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 14 2012, 09:59
Сообщение #17


Гуру
******

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



QUOTE (RabidRabbit @ Dec 14 2012, 09:28) *
И помешать этому может только запрещение прерываний
В принципе - да. У меня же ситуация возникала элементарно - достаточно было остановить выполнение программы под отладчиком. И все - после продолжения выполнения программы каналы иногда путались. Я убил довольно много времени пока понял откуда растут ноги у этого явления.


--------------------
На любой вопрос даю любой ответ
"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
hd44780
сообщение Dec 14 2012, 12:21
Сообщение #18


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Народ, я не понял, зачем регистры RNPR (Receive Next Pointer Register) и RNCR (Receive Next Counter Register)?
Типа, если я не перепрограммирую RPR/RCR, он сам на те кинется?

Я их пока не программирую, т.к. по прерыванию ENDRX глушу таймер. Правильно ли это
Или их надо инициализировать тем же? В смысле ставить RNCR=RCR=count. И указатель аналогично.

Спасибо.


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 14 2012, 13:10
Сообщение #19


Гуру
******

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



QUOTE (hd44780 @ Dec 14 2012, 14:21) *
Народ, я не понял, зачем регистры RNPR (Receive Next Pointer Register) и RNCR (Receive Next Counter Register)?
Типа, если я не перепрограммирую RPR/RCR, он сам на те кинется?
Типа да. Точнее, в прерывании программировать надо именно RNPR/RNCR, а в RPR/RCR значения из RNPR/RNCR протолкнет DMA контроллер. RPR/RCR программируются только перед запуском процесса.


--------------------
На любой вопрос даю любой ответ
"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
hd44780
сообщение Dec 14 2012, 13:28
Сообщение #20


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Спасибо, примерно понял, но хочу уточнить.

Если я остановлю процесс выборки, а потом захочу запустить повторно, то перед стартом таймера мне надо будет заполнить только RNPR/RNCR, а RPR/RCR вообще не трогать?


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 14 2012, 14:29
Сообщение #21


Гуру
******

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



QUOTE (hd44780 @ Dec 14 2012, 15:28) *
мне надо будет заполнить только RNPR/RNCR, а RPR/RCR вообще не трогать?
Тогда он будет складывать туда, где остановился перед остановкой. Если вы хотите, чтобы он начал складывать с начала буфера, надо перегрузить RPR/RCR тоже.


--------------------
На любой вопрос даю любой ответ
"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
hd44780
сообщение Dec 14 2012, 15:02
Сообщение #22


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Сергей Борщ, спасибо. Понял.

Пошёл доделывать sm.gif


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 14 2012, 18:46
Сообщение #23


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Написал так:

1. Инициализация АЦП

Код
void ConfigureAdc(void)
{
  dword shtim, startup, prescal, trgSel;
    
  AT91C_BASE_PMC->PMC_PCER = (1UL << AT91C_ID_ADC);    // разрешить тактовую для ADC
  AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;            // reset ADC

  shtim=8;
  startup=0x0F;
  prescal=0x02;
  trgSel=1;     // Запуск по TIOA1 (TC1)

  ADC_CfgModeReg (AT91C_BASE_ADC, (shtim << 24) | (startup << 16) | (prescal << 8) |
                  AT91C_ADC_SLEEP_NORMAL_MODE | AT91C_ADC_LOWRES_8_BIT |
                  (trgSel << 1) | AT91C_ADC_TRGEN_EN);

  // выкл все каналы
  AT91C_BASE_ADC->ADC_CHDR = 0xFF;
  
  // Включить канал 6, 7
  AT91C_BASE_ADC->ADC_CHER = (1 << ADC_CHANNEL_LEFT) | (1 << ADC_CHANNEL_RIGHT);
  
  // Разрешить прерывания каналов 6 и 7 в ADC
  AT91C_BASE_ADC->ADC_IER = ( 1 << ADC_CHANNEL_LEFT ) | ( 1 << ADC_CHANNEL_RIGHT );

  // Установка прерывания ADC
  IRQ_ConfigureIT ( AT91C_ID_ADC, 6, ADC_IrqHandler );
  
  // Set AIC_IECR
  IRQ_EnableIT(AT91C_ID_ADC);
  
  ////////////////////////////////////////////////////////////////////////////////  
  // PDC
  //  Буфер данных
  AT91C_BASE_ADC->ADC_RPR = (dword)ADCbuf;
  AT91C_BASE_ADC->ADC_RNPR = (dword)ADCbuf;
  
  //  Set receive counter register (number of transfers)
  AT91C_BASE_ADC->ADC_RCR = sizeof ( ADCbuf );    
  AT91C_BASE_ADC->ADC_RNCR = sizeof ( ADCbuf );    

  // ENDRX - End of receive buffer interrupt enable (когда регистр ADC_RCR досигает нуля)
  AT91C_BASE_ADC->ADC_IER = AT91C_ADC_ENDRX;

  // Конфигурирование  TC1 на переключение TIOA1  23.81kHz
  ConfigureTc1 ( );
} // ConfigureAdc


Всё, что до комментария PDC - рабочее на 100%. Без PDC работает нормально.

2. Запуск:

Код
void StartConversion ( void )
{
  //  Буфер данных
  AT91C_BASE_ADC->ADC_RCR = sizeof ( ADCbuf );    
  AT91C_BASE_ADC->ADC_RNCR = sizeof ( ADCbuf );    

  //  Set receive counter register (number of transfers)
  AT91C_BASE_ADC->ADC_RCR = sizeof ( ADCbuf );    
  AT91C_BASE_ADC->ADC_RNCR = sizeof ( ADCbuf );    

  //  Enable PDC receiver requests, disable transmitter requests
  AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS;
  
  // запуск ТС1
  AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN;
} // StartConversion


До PDC здесь был только запуск TC1.
Инициализация проходит нормально, а после вызова StartConversion всё наглухо виснет. Даже прерываний от АЦП нету.
Проверялось через DBGU.

В чём я ошибся?


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Dec 15 2012, 07:35
Сообщение #24


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Я немного не понимаю, инициализация указателей для PDC происходит только в коде 1.? Зачем в коде 2. дважды инициализируются счётчики? Может, все исходники прицепите?

Вот это лишнее
AT91C_BASE_PMC->PMC_PCER = (1UL << AT91C_ID_ADC); // разрешить тактовую для ADC
ADC и так олвэйс клокед.
Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 15 2012, 09:02
Сообщение #25


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Цитата(RabidRabbit @ Dec 15 2012, 09:35) *
Я немного не понимаю, инициализация указателей для PDC происходит только в коде 1.? Зачем в коде 2. дважды инициализируются счётчики?

Да то в полусне вчера писал biggrin.gif . Поправил - всё равно виснет sad.gif .

Цитата(RabidRabbit @ Dec 15 2012, 09:35) *
Может, все исходники прицепите?

Прицепил, посмотрите. Компилятор - IAR 6.40.

Цитата(RabidRabbit @ Dec 15 2012, 09:35) *
AT91C_BASE_PMC->PMC_PCER = (1UL << AT91C_ID_ADC); // разрешить тактовую для ADC
ADC и так олвэйс клокед.

У коллег списал sm.gif .
Прикрепленные файлы
Прикрепленный файл  SoundAnalyzer_2Ch_PDC_all.zip ( 546.69 килобайт ) Кол-во скачиваний: 7
 


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Dec 15 2012, 13:19
Сообщение #26


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Я бы убрал вот это
// Разрешить прерывания каналов 6 и 7 в ADC
AT91C_BASE_ADC->ADC_IER = ( 1 << ADC_CHANNEL_LEFT ) | ( 1 << ADC_CHANNEL_RIGHT );

И выкинул бы нафик из обработчика прерывания от ADC вызовы DebugSendString() - у Вас один символ будет передаваться дольше, чем оцифровка одного отсчёта.
Ну и может в конце обработчика прерывания ADC поставить запись в регистр AIC_EOICR, на всякий случай... хотя мож яр сам ставит...

Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 15 2012, 15:34
Сообщение #27


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Поправил. Прерывания каналов вырубил, добавил AT91C_BASE_AIC->AIC_EOICR = 0; в конец прерывания. Хотя раньше оно и без него работало ...
Даже сделал 2-й буфер, для ADC_RNPR ..

Ни фига, всё равно виснет sad.gif .

Вот нашёл осцилл самодельный на таком же проце - http://www.tomeko.net/miniscope_v2.php . Там ADC вроде через PDC тоже шурует. Только буферов там 3 или 4 штуки, в прерывании переключаются.
Вроде всё также ....


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
Jack_of_Shadows
сообщение Dec 17 2012, 10:23
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 46
Регистрация: 29-10-10
Пользователь №: 60 513



hd44780, памяти для буфера ацп в куче точно хватает? У меня в похожей программе (только писалось под Crossworks) тоже проц вис когда запускал АЦП, пока не поставил heap побольше.
Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 17 2012, 10:51
Сообщение #29


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Jack_of_Shadows, у меня кучи и динамического распределения нет, все буфера статические и фиксированные.

// Размер буфера одного канала
#define ADC_DATA_SIZE 512

// Буфер ADC PDC (размер под 2 канала)
static volatile byte ADCbuf [ADC_DATA_SIZE*2];
static volatile byte ADCbufNext [ADC_DATA_SIZE*2];

Регистры инициализирую так:

// Буфер данных
AT91C_BASE_ADC->ADC_RPR = (dword)ADCbuf;
AT91C_BASE_ADC->ADC_RNPR = (dword)ADCbufNext;

// Set receive counter register (number of transfers)
AT91C_BASE_ADC->ADC_RCR = sizeof ( ADCbuf );
AT91C_BASE_ADC->ADC_RNCR = sizeof ( ADCbuf );

byte == unsigned char (через typedef). Может ещё sizeof косячит - не проверял его ...


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post

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

 


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


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