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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Вопрос по АЦП, Free running mode
IGK
сообщение Jan 17 2008, 22:47
Сообщение #31


Местный
***

Группа: Свой
Сообщений: 313
Регистрация: 7-01-07
Из: Севастополь
Пользователь №: 24 170



Цитата(_Pasha @ Jan 17 2008, 22:14) *
Чушь! Вы чего-то не договариваете. Потому что ADMUX буферизован, и "слишком рано" записать нельзя. "Слишком поздно" - это можно, но тогда на следующем прерывании будет принят предыдущий канал.


Да, каюсь, не договорил. У меня ADMUX+2 канала, именно чтобы не принимать предыдущий канал, и только тогда работает нормально...
Так, как в даташите, +1, как раз дает примерно то же, что описал SasaVitebsk. А насчет буферизации - я же писал, что не стал проводить всесторонних исследований, нормально заработало после сдвига.
Просто это первое, что я проверил. Дело в том, что у меня есть второе, совсем уж непредсказуемое по времени появления, прерывание. И первое, что бросилось мне в глаза, это периодическая и довольно редкая запись в мультиплексор после окончания нового цикла выборки. Я сформировал стробы на программный осциллограф и увидел довольно точную привязку этих событий к "дрожанию" данных. Ну и сделал сдвиг.

Pasha - я, например, точно не знаю, как там буфериризация сделана. Может, криво. Может, я сам код криво написал - хотя там ровно два байта того кода...

SasaVitebsk, буду ждать результатов.

Сообщение отредактировал IGK - Jan 17 2008, 22:50
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 18 2008, 09:36
Сообщение #32


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SasaVitebsk @ Jan 16 2008, 02:54) *
Тем не менее при съёме с периодом 75 тактов АЦП примерно 1 раз в 15 - 20 секунд и более (иногда до нескольких минут) АЦП запущенное на частоте 16М/128=125кГц каким то образом ловило предыдущий канал. Это я установил абсолютно точно.

Кстати, тут еще вспомнил один нюансик в работе АЦП.
Судя по частоте появления ошибки, возможно Вы натыкаетесь на то, что преобразование
заканчивается сразу же после считывания ADCL и до считывания ADCH.
В этой ситуации запись со стороны ADC к ADCL и ADCH заблокированна и очередное
преобразование просто теряется.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 18 2008, 14:26
Сообщение #33


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ Jan 18 2008, 13:36) *
...сразу же после считывания ADCL и до считывания ADCH.
В этой ситуации запись со стороны ADC к ADCL и ADCH заблокированна и очередное
преобразование просто теряется.

Вообще-то в момент чтения ADCL содержимое ADCH записывается во временный регистр, извините за банальность smile.gif , и таким образом за раз читаются все 16(10) бит.
Было бы нелогично запрещать операции записи результата АЦП до завершения чтения временного регистра.
Вы ничего не путаете?
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 18 2008, 14:35
Сообщение #34


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Pasha @ Jan 18 2008, 17:26) *
Вообще-то в момент чтения ADCL содержимое ADCH записывается во временный регистр, извините за банальность smile.gif , и таким образом за раз читаются все 16(10) бит.
Было бы нелогично запрещать операции записи результата АЦП до завершения чтения временного регистра.
Вы ничего не путаете?
А где это вы нашли временный регистр для хранения ADCH ?
Вы случайно с таймерными 16бит регистрами не путаете ? smile.gif

Читаем внимательно даташит:
Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the data
registers belongs to the same conversion. Once ADCL is read, ADC access to data registers is
blocked. This means that if ADCL has been read, and a conversion completes before ADCH is
read, neither register is updated and the result from the conversion is lost. When ADCH is read,
ADC access to the ADCH and ADCL Registers is re-enabled.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 19 2008, 04:54
Сообщение #35


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ Jan 18 2008, 18:35) *
А где это вы нашли временный регистр для хранения ADCH ?
Вы случайно с таймерными 16бит регистрами не путаете ? smile.gif
Читаем внимательно даташит:

Мда-с...
Проблема восприятия большого количества инфы...
Спасибо, вразумили. beer.gif
Тогда это действительно многое объясняет. Получается, что в авто-триггерных режимах даже из-за приоритета прерывания можно на граблях кататься.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 19 2008, 14:18
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Ну это не мой вариант. Я работаю с 8-ми битным режимом и читаю только ADCH.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 19 2008, 15:55
Сообщение #37


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SasaVitebsk @ Jan 19 2008, 17:18) *
Ну это не мой вариант. Я работаю с 8-ми битным режимом и читаю только ADCH.
Ну тогда покажите код, телепатить не всегда получается. laughing.gif
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 19 2008, 19:43
Сообщение #38


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ Jan 19 2008, 19:55) *
Ну тогда покажите код, телепатить не всегда получается. laughing.gif

Вы, сишники, народ абстрактный... biggrin.gif вот SasaVitebsk нам сишный код и покажет.
SasaVitebsk, листинг последний горбатый более-менее детально выложите.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 19 2008, 20:04
Сообщение #39


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Pasha @ Jan 19 2008, 22:43) *
Вы, сишники, народ абстрактный... biggrin.gif
Если это ко мне, то я не синшник, у меня чуть другой ник.... sad.gif
Похоже с первого раза вразумить не удалось.... smile.gif
Вы видимо крутой асемблерщик ? хотите посоревноваться в написании кода на асм ?
тогда welcome, тока другую тему откройте...
Цитата
вот SasaVitebsk нам сишный код и покажет.
Ну и ? У него(сишного кода), есть очень четкий эквивалент на асм в виде
листинга компилятора...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 19 2008, 20:45
Сообщение #40


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ Jan 20 2008, 00:04) *
Вы видимо крутой асемблерщик ? хотите посоревноваться в написании кода на асм ?
тогда welcome, тока другую тему откройте...

Ну и ? У него(сишного кода), есть очень четкий эквивалент на асм в виде
листинга компилятора...


1. Открою, но чуть позже, извините.
2. У сишного кода нет четкого эквивалента. Оный был бы у Паскаля, но, к сожалению (моему), данная тема ниже плинтуса. Все. Пока флейма не будет.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 20 2008, 01:56
Сообщение #41


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



2 SashaVitebsk.

IMHO считывать АЦП по таймеру немного неестветвенно (не природно) выглядит.

Я пользуюсь таким подходом - периодически запускаю АЦП в Single Conv режиме, с флажком "доверия" == "0", т.е. результат первого преобразования я всегда считаю неправильным. По прерыванию от АЦП вычитываю и выбрасываю результат, перезапускаю АЦП для того же самого канала и устанавливаю флажек "доверия" в "TRUE", что означает, что следующему результату однозначно можно доверять. На следующем прерывании от АЦП вычитываю и сохраняю результат текущего канала как (Vintegral = Vcurrent - Vaverage) и меняю канал, флажек "доверия" сбрасываю в "0" (т.е. первый рез-тат после смены канала будет выброшен), и так до тех пор пока не получу результат последнего, интересующего меня, канала.

Т.о. единожды запустив опрос АЦП - у меня получаются данные по всем каналам и опрос сам собой прекращается. Эта схема всегда работает - как часы.

Никогда не заморачивался с подсчетом тактов и ассемблером в этом вопросе.
Go to the top of the page
 
+Quote Post
alux
сообщение Apr 15 2008, 08:02
Сообщение #42


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Имею проблему с выводом по UART результата измерения АЦП (Mega48, 20Мгц), работающего в free running mode. Настроен только на измерение с одного канала. Синхронизация передачи значения АЦП в BCD формате по UART осуществляется в главном цикле по флагу DISPLAY. UART работает с использованием прерывания (avr306 - interrupt controlled UART). В программе еще используется прерывание от таймера1 (вызывается через 10 мсек), в котором осуществляется динамическая индикация и обработка кнопок.
Код
void Initialise(void)
{
.................
  //ADC initialisation:
  ADMUX=(1<<REFS1)|(1<<REFS0);//Установка Photo_Channel (ADC0),  
                     //Internal 1.1V Voltage Reference with external capacitor at AREF pin
  //Старт непрерывного преобразования с частотой 156,25 кГц, Предделитель = 128,
  //Разрешить прерывание АЦП
  ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

////////////////////////////////////////////////
void main(void)
{
  Initialise();          
  __enable_interrupt();
  for(;;)
  {
    if(Flags&DISPLAY)
    {
      itoa(tmp, buf2);
      TransmitByte(*(buf2+0)+'0');
      TransmitByte(*(buf2+1)+'0');
      TransmitByte(*(buf2+2)+'0');
      TransmitByte(*(buf2+3)+'0');
      TransmitByte(13);   //CR
      TransmitByte(10);   //LF
//     delay_ms(250);
      Flags &= ~DISPLAY;
    }
   __sleep();   //Idle mode
  }
}

//////////////////////////////
#pragma vector=ADC_vect
__interrupt void ADC_ISR(void)
{
  acum += ADC;

  if(++SampleCounter == max)
  {
    value = acum/max;
    SampleCounter=0;
    acum=0;
    
      if(!(Flags&DISPLAY))
      {
        tmp = value;
        Flags |= DISPLAY;
      }
  }
....
}

Собственно, я подошел к сути проблемы.
На терминале получаю значения АЦП, чередующиеся с 0, типа так:

0031
0031
0030
0000
0000
0000
0031
0031
0030
0000
0000
0000

Если остановить таймер1, то выводит то, что положено - без нулей. Если запустить таймер1 и после очередной отправки результата по UART вставить задержку 250ms (в приведенном коде закомментирована), то выводит также без нулей. При уменьшении задержки до 100ms начинают вылазить нули.
Почему так происходит?

PS. Выводить результат на UART нужно максимально быстро. Single Mode не предлагать.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 15 2008, 09:19
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



А Flags у вас объявлен как volatile?
Просто похоже данная проблема к АЦП не имеет отношения. Обычный хомут какой-то. Попробуйте по шагам пройти, либо asm просмотрите.
Go to the top of the page
 
+Quote Post
alux
сообщение Apr 15 2008, 12:38
Сообщение #44


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(SasaVitebsk @ Apr 15 2008, 12:19) *
А Flags у вас объявлен как volatile?

Flags объявлен глобально, без volatile. volatile в данном случае здесь ни при чем. Но на всякий случай проверил: с volatile проблема осталась. На мой взгляд проблема как-то связана с прерываниями. Если за время обработки прерывания от таймера1 произошло несколько прерываний от АЦП (которые имеют низкий приоритет), то после окончания обработки прерывания от таймера1 попадаем в обработчик прерывания от АЦП. В момент между считываниями ADCL и ADCH возможна ситуация, когда происходит следующее преобразование АЦП, и предыдущий результат теряется. Но не обнуляется ведь!
Это только моя версия происходящего. Какие будут еще ваши предположения?

PS. Чем объяснить такую строгую периодичность: после трех правильных данных идут три нулевых?

PS2. Версию, что таймер своими шумами влияет на работу АЦП, я тоже отбрасываю.
Может быть нехватка стека? Но я не использую ресурсоемких функций. И пробовал увеличить CSTACK(0x100), RSTACK(0x64). Не помогло.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 15 2008, 14:07
Сообщение #45


Гуру
******

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



Цитата(alux @ Apr 15 2008, 15:38) *
volatile в данном случае здесь ни при чем.
Но Flags должен быть volatile, также как и tmp. Лучше сразу писать правильно, чем ждать, когда начнется "при чем". Есть еще одно потенциальное место для бага: Flags &= ~DISPLAY; Оно компилируется примерно в такое:
Код
register Tmp = Flags; (1)
Tmp = Tmp & DISPLAY; (2)
Flags = Tmp; (3)
Что произойдет, если между командами 1 и 3 произойдет прерывание, изменяющее Flags? Обращения к подобным переменным надо делать атомарными, т.е. с запретом прерываний.
Цитата(alux @ Apr 15 2008, 15:38) *
Но не обнуляется ведь!
Попробуйте присваивать tmp в прерывании константу, т.е. исключите АЦП из получения результата.


--------------------
На любой вопрос даю любой ответ
"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

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

 


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


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