|
ADC3 в режиме сканирования и DMA2, Необъяснимые "лишние" данные и рассинхронизация |
|
|
|
Jul 21 2014, 12:04
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Здравствуйте, коллеги.
Не побеждается ADC3.
Имеем: - STM32F103VC на 24MHz (не 72 для уменьшения потребления, т.к. есть back up на аккумуляторе), - ADC3 в режиме сканирования трех каналов (11, 12 и 13), ADC тактируется 12MHz. - естественно DMA2, канал 5, который складывает оцифрованное в буфер U16 длиной 32 триплета - всего 96 слов; таких буферов, конечно, два: один заполняем, из другого читаем. - таймер 8, который с частотой 100Hz (замеряно) пихает ADC3 своим событием обновления (TRGO). - прерывание от завершения передач DMA (по флагу TC), которое устанавливает флаг готовности буфера, переключает буферы и перегружает DMA канал.
В принципе, вся кухня работает. Но. После рестарта может случиться, что данные оказываются смещенными в буфере: например, на месте канала 11 будут данные из канала 12, на месте 12 - из 13, ну а на месте 13 - из 11. Может случиться и сдвиг более дальнего порядка - в 11 - из 13, ну и так далее, по кругу. Причем этот сдвиг случается один раз при старте системы, а в процессе работы все остается фиксированно, без перескоков.
Я тщательно проанализировал последовательность инициализации и попытался в прерывании DMA сбрасывать бит STRT в ADC3->SR и "прочищать" ADC3->DR (чтением) перед тем как перегрузить DMA. Тем не менее в прерывании я мог всегда(!) поймать ситуацию при самом _первом_ вхождении, когда после перегрузки DMA его счетчик тут же уменьшался на единицу, словно ADC3 припрятал запрос к DMA несмотря на "прочистку". Последнее, что я сделал, - поднял приоритет DMA до "kill 'em all", а в прерывании - выключал бит DMA в ADC3->CR2, делал прочистку ADC и перегрузку DMA и включал ADC3->CR2 снова. На моей плате это вроде привело к успеху (счетчик DMA не уменьшался сразу), а вот у коллеги - нет.
Идеи? Заранее благодарен.
Сообщение отредактировал KnightIgor - Jul 21 2014, 12:44
|
|
|
|
|
 |
Ответов
|
Jul 21 2014, 18:47
|

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

|
Ой, сложно как все...
Буферов два? Расположите их подряд. Пусть ПДП таскает в них данные в циклическом режиме. Без взяких перенастроек. "Пустил-забыл". ПДП дает два прерывания - "половину буфера заполнил" и "весь буфер запомнил". По первому флагу обрабатываем первый буфер, по второму - второй. В обработчике проверяем флаги ПДП, сбрасываем сработавший, запускаем обработку соответствующей половины "склеенного" буфера. Все. Больше ничего не трогаем.
Ваш ADC_ClearRegular() делает совсем не то, что вы хотели. Он может вычитать результат максимум только одного преобразования. А может и вообще ни одного не вычитать. Потому что DR хранит результат одного (последнего) преобразования, никакого буфера типа FIFO на несколько результатов там нет. Если бы мне понадобилась подобная функция, я бы в ней выбросил параметр cnt, проверял STRT и если он выставлен (преобразование началось) - дожидался EOC, после чего сбрасывал бы EOC чтением DR, а STRT - записью в него 0.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 21 2014, 20:29
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Сергей Борщ @ Jul 21 2014, 20:47)  Ой, сложно как все...
Буферов два? Расположите их подряд. Пусть ПДП таскает в них данные в циклическом режиме. Без взяких перенастроек. "Пустил-забыл". ПДП дает два прерывания - "половину буфера заполнил" и "весь буфер запомнил". По первому флагу обрабатываем первый буфер, по второму - второй. В обработчике проверяем флаги ПДП, сбрасываем сработавший, запускаем обработку соответствующей половины "склеенного" буфера. Все. Больше ничего не трогаем.
Ваш ADC_ClearRegular() делает совсем не то, что вы хотели. Он может вычитать результат максимум только одного преобразования. А может и вообще ни одного не вычитать. Потому что DR хранит результат одного (последнего) преобразования, никакого буфера типа FIFO на несколько результатов там нет. Если бы мне понадобилась подобная функция, я бы в ней выбросил параметр cnt, проверял STRT и если он выставлен (преобразование началось) - дожидался EOC, после чего сбрасывал бы EOC чтением DR, а STRT - записью в него 0. Хорошие идеи. Спасибо. И все же интересно, почему происходит сдвиг данных. P.S. Итак, я реализовал Вашу идею, все замечательно. Еще раз спасибо. И кажется, я обнаружил-таки, в чем была причина "лишних" неполных данных. В доке написано, что повторное разрешение ADC (то есть, запись "1" на уже "1" в CR2.ADON) приводит к запуску преобразования: Conversion starts when this bit holds a value of 1 and a 1 is written to it. Тут же далее курсивом упомянуто, что если в этом регистре одновременно меняются и другие биты (например CR2.DMA), то запуск преобразования не происходит: If any other bit in this register apart from ADON is changed at the same time, then conversion is not triggered. This is to prevent triggering an erroneous conversion.
Так вот, враки это все! Этот "предохранитель" не работает, и преобразование запускается. Четко в отладчике видно. Тема для errata. Вот и получалось, что команда ADC_DMACmd(ADCx, DISABLE) запрещала передачу запросов в DMA, но запускала каждый раз преобразование. Оттуда и "лишние" данные и сдвиги.
Сообщение отредактировал KnightIgor - Jul 22 2014, 08:35
|
|
|
|
Сообщений в этой теме
KnightIgor ADC3 в режиме сканирования и DMA2 Jul 21 2014, 12:04 ViKo Еще бы таймер "прочистить", чтобы событи... Jul 21 2014, 12:33 KnightIgor Цитата(ViKo @ Jul 21 2014, 14:33) Еще бы ... Jul 21 2014, 12:53  ViKo Цитата(KnightIgor @ Jul 21 2014, 15:53) Н... Jul 21 2014, 14:00   KnightIgor Цитата(ViKo @ Jul 21 2014, 16:00) По тайм... Jul 21 2014, 15:15 AlHakim Цитата(KnightIgor @ Jul 21 2014, 18:04) В... Jul 21 2014, 13:28 KnightIgor Цитата(AlHakim @ Jul 21 2014, 15:28) вот ... Jul 21 2014, 15:41 Сергей Борщ Цитата(KnightIgor @ Jul 21 2014, 15:04) П... Jul 21 2014, 15:25 AlHakim Цитата(KnightIgor @ Jul 21 2014, 21:41) К... Jul 21 2014, 17:01
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|