Adc описание. Описание протокола ADC. Регистры АЦП в STM32

ADC - это текстовый протокол для клиент-серверных сетей, наподобие Neo-Modus" Direct Connect (NMDC) . Целью является создание простого протокола, который не нагружает ни клиент, ни сервер, и который можно расширять. В нём исправлены некоторые неудачные решения протокола NMDC, но не все.

Рассматриваются те-же самые взаимодействия: клиент-клиент и клиент-сервер. Данная документация разделена на две части; первая часть описывает структуру протокола, вторая - специфичность системы протокола для использования этой структуры. Advanced Direct Connect - это первая версия, которая будет постепенно улучшаться.

Большинство идей для протокола пришли из проекта DCTNG (Jan Vidar Krey"s). Основные участники разработки: Dustin Brody, Walter Doekes, Timmo Stange, Fredrik Ullner, Fredrik Stenberg и другие. Jon Hess посодействовал как создатель протокола NMDC.

Преимущества протокола

  • SID, а также названия команд протокола, состоят из четырёх латинских символов в верхнем регистре. Протокол достаточно хорошо подходит для реализации на языке СИ. По стандарту языка СИ sizeof(char) == 1, то есть 4 символа будут занимать 4 байта, или могут быть представлены в виде четырёхбайтового целого числа. Преобразование строки в число и обратно значительно упрощает и оптимизирует работу с командами и даёт возможность хранить команду в виде объединения.

Недостатки протокола

  • Разделителями протокола являются очень распространённые символы (пробел и перенос), которые нужно заменять на \s и \n. Так как эти символы очень распространены в сообщениях чата, то число замен всегда будет большим, чего не было в протоколе NMDC.
  • По сравнению с протоколом NMDC, в протоколе ADC есть возможность в UserCommand удалить определённое меню. Однако, по-прежнему отсутствует возможность удаления определённого меню в определённом контексте .

История версий

Последующие версии этого документа, а также промежуточные и более старые версии могут быть получены по адресу: . Эта версия представляется к ревизии:

Версия 1.0.1, 2008-05-02

  • Расширения выделены в отдельный документ.
  • Спецификации выделены в отдельный проект на SourceForge.

Версия 1.0, 2007-12-01

  • Первый релиз

Структура протокола

  • Все команды протокола начинаются с четырёх букв. Первая буква определяет то, как команда должна быть послана, следующие три показывают что должно быть выполнено.
  • Параметры разделяются пробелами, а каждая команда заканчивается символом переноса строки (код 0x0a). Экранируются элементы: "\s" - пробел, "\n" - новая строка и "\\" - обратный слеш. Данная версия протокола резервирует все остальные экранированные символы для возможного дальнейшего использования; любые команды, содержащие неизвестные экранированные символы, должны игнорироваться.
  • Все отсылаемые команды должны отправляться в кодировке UTF-8 - закодированный Юникод в С нормализации.
  • Клиенты должны игнорировать неизвестные/неправильные команды. Хабы должны игнорировать неправильные команды, и должны отсылать неизвестные команды, согласно их типу (префиксу).
  • Адреса клиентов должны быть определены в виде десятичных чисел, разделённых точками ("x.x.x.x") для IPv4 или в формате RFC (1884) для IPv6. Адреса хабов должны быть определены ссылкой с добавкой "adc" спереди, которая показывает специфику данного протокола ("adc://server:port/").
  • Числа отсылаются как строки в соответствии со стандартом плавающей точки, в качестве разделителя между целой дробной частью используется точка "." . Целыми являются числа без дробной части и без экспоненциальной добавки. Приложения должны иметь возможность оперировать с 64-битными положительными числами и с 64-битными числами с плавающей точкой. Префиксом отрицания является знак "-".

D (Direct message) Хаб должен отправить эту команду для пользователя с указанным SID .

E (Echo message) Хаб должен отправить команду для пользователей с sid и my_sid.

F (Feature broadcast) Хаб должен отослать эту команду всем клиентам, которые поддерживают(+)/не поддерживают(-) данную характеристику. Поддержка клиентом той или иной характеристики определяется из поля SU, которое содержится в команде INF , отсылаемой клиентом.

H (Hub message) Клиенты должны использовать данный тип для отсылки команды, которая предназначена только хабу.

I (Info message) Хабы должны использовать данный тип для отсылки команды, которая не была отослана другим клиентом.

U (UDP message) Клиенты должны использовать эту команду только для прямого соединения по протоколу UDP .

Хеш-функции

Некоторые команды используются для определяния хеш-функций. При установке каждого нового соединения по команде SUP происходит обмен хеш-функциями. При коннекте клиент передаёт серверу несколько хеш-функций посредствам параметров команды SUP . Сервер вбирает одну из них и передаёт её клиенту, поставив её до любой другой хеш-функции в команде SUP , которая отправится с сервера. Клиент и хаб должны иметь по крайней мере одну одинаковую хеш-функцию, которая будет использоваться в протоколе и в файловой идентификации.

Идентификация клиента

Каждый клиент идентифицируется по трём различным идентификаторам: идентификатор сессии - Session ID (SID), личный идентификатор - Private ID (PID) и идентификатор клиента - Client ID (CID).

Файлы

Имена файлов отсчитываются от относительного (вымышленного) корня в шаре пользователя. "/" - разделитель директорий; каждый файл или имя директории должно быть уникальным в регистро-независимом контексте. Все печатные символы, включая пробел, допустимы в имени файла, символы "/" и "\" экранируются символом "\". Клиенты должны использовать фильтры для имён под свои файловые системы, имена файлов, полученные от других клиентов, должны также подчиняться этим правилам. Специальные имена "." и ".." не могут содержаться в директории или имени файла; любой полученный файл-лист, содержащий эти имена должен быть проигнорирован. Все имена директорий должны оканчиваться на "/".

Расшаренные файлы идентифицируются относительно безымянного корня "/" ("/dir/subdir/filename.ext"), тогда как дополнения могут добавить имя корня. Например, "TTH/…" для TIGR дополнения используют имя корня "TTH" для идентификации файлов по их "Tiger Tree Hash". Это недопустимо для имён из безымянного корня, которые попали в шару с идентификатором по контрольной сумме.

Без корневое имя файла "files.xml" определяет полный файл-лист, в формате XML в кодировке UTF-8 . Клиентам рекомендуется использовать дополнения чтобы сжимать данный файл-лист.

Дополнения могут добавлять к имени файла свои расширения, обычно это делается для того, чтобы избежать повторения имён.

Специальный тип "list" используется для просмотра списков файлов. Частичный файловый список имеет ту же структуру, что и нормальный список, но директории могут быть теговыми с атрибутом Incomplete="1", который показывает на частичность. Только директории без корневых файлов могут начинаться с символа "/". Содержимое такой директории в последствии будет послано просящему клиенту на глубину, выбранную им (это нужно для отправки только того уровня, который требуется пользователю). Атрибут "Base" для поля "FileListing" определяет к какой конкретной директории принадлежит данный файл.


Описание работы Аналого-цифрового преобразователя.
Прерывания от АЦП

ATMega16 содержит в себе 10-битовый АЦП, вход которого может быть соединён с одним из восьми выводов Port A. АЦП Mega16, как и любому другому АЦП, нужно опорное напряжение для целей сравнения со входным (если измеряемое равно опорному, то получаем максимальный код в двоичном виде). Опорное напряжение подаётся на вывод ADRef или может использоваться внутренний генератор с фиксированным напряжением 2,65 В. Полученный результат можно представить в таком виде:

АЦП включается установкой бита ADEN в регистре ADCSRA. После преобразования, 10-битный результат оказывается в 8-битных регистрах ADCL и ADCH. По умолчанию, младший бит результата находится справа (то есть в bit 0 регистра ADCL, так называемое правое ориентирование). Но порядок следования битов на левое ориентирование можно сменить установив бит ADLAR в регистре ADMUX. Это удобно, если требуется получить 8-битовый результат. В таком случае требуется прочитать только регистр ADCH. В противном случае, Вы должны сначала прочитать регистр ADCL первым, а ADCH вторым, чтобы быть уверенным в том, что чтение этих двух регистров относится к результату одного преобразования.

Одиночное преобразование может быть вызвано записью бита ADSC в регистр ADCSRA. Этот бит остаётся установленным всё время, занимаемое преобразованием. Когда преобразование закончено, бит автоматически устанавливается в 0. Можно также начинать преобразования по событиям из разных источников. Модуль АЦП также может работать в режиме "свободного полёта". В таком случае АЦП постоянно производит преобразование и обновляет регистры ADCH и ADCL новыми значениями.

Для выполнения преобразования модулю АЦП необходима тактовая частота. Чем выше эта частота, тем быстрее будет происходить преобразование (оно, обычно, занимает 13 тактов, первое преобразование занимает 25 тактов). Но чем выше частота (и выше скорость преобразования), тем менее точным получается результат. Для получения максимально точного результата, модуль АЦП должен тактироваться частотой в пределах от 50 до 200 КГц. Если необходим результат с точностью менее 10 бит, то можно использовать частоту больше 200 КГц. Модуль АЦП содержит делитель частоты, чтобы получать нужную тактовую частоту для преобразования из частоты процессора.

Регистр ADMUX задаёт входной контакт порта A для подключения АЦП, ориентирование результата и выбор опорной частоты. Если установлен бит ADLAR, то результат лево-ориентирован. Опорная частота от внутреннего генератора задаётся выставленными в 1 битами REFS1 и REFS0. Если оба бита сброшены, то опорная частота берётся от контакта AREF. В случае, если REFS1=0 а REFS0=1, опорная частота берётся от AVCC с внешним конденсатором, подключенным к AREF. Выбор контакта ввода выполняется следующим образом:

Регистр контроля и статуса АЦП ADCSRA :

Бит ADEN=1 включает модуль АЦП.
Запись единицы в ADSC запускает цикл преобразования. В режиме "свободного полёта" запись единицы запускает первое преобразование, последующие запускаются автоматически.
ADIF - флаг прерывания АЦП. Этот бит устанавливается в 1 когда АЦП завершено преобразование и в регистрах ADCL и ADCH находятся актуальные данные. Этот флаг устанавливается даже в том случае, если прерывания запрещены. Это необходимо для случая программного опроса АЦП. Если используются прерывания, то флаг сбрасывается автоматически. Если используется программный опрос, то флаг может быть сброшен записью лог.1 в этот бит.
ADIE - Если в этом бите установлена единица, и прерывания разрешены глобально, то при окончании преобразования будет выполнен переход по вектору прерывания от АЦП.
Биты ADPS2..0 задают коэффициенты предделителя частоты:


Нужно сначала разобраться с компонентами, которые использовались нами для создания прошивки. А использовался нами только один компонент - PWM8. PWM расшифровывается как Pulse Width Modulator, что значит Широтно-импульсный модулятор. Суть прибора в том, что он позволяет изменять широту импульсов, генерируемых микроконтроллером. Тем самым, меняя выходное напряжения для устройств, не чувствительных к частоте.
Например: рабочая частота микроконтроллера 1Гц (то есть, период генерации импульсов 1с), ширина импульса 0.5с, напряжение импульса 5В.

Тогда среднее выходное напряжение за секунду равно 2.5 вольта. А получается эта величина просто: сложением подимпульсных площадей и делением их на общий промежуток времени. На всякий случай распишу подробней. Допустим, мы взяли промежуток времени в 1 секунду, из рисунка видно первый импульс длился 0.5. Умножаем 0.5с*5В (напряжение импульса) и все это делим на интервал времени. 0.5с*5В/1с = 2.5В. Если нам понадобится выходное напряжение в 3.33В, мы должны будем увеличить подимпульсную площадь до 75%. В литературе ещё часто фигурирует термин скважность. Так вот, скважность и есть отношений длительности импульса к длительности нулевого потенциала, например, для первого случая, она была 50%, для второго - 75%.

Я думаю, что теории уже достаточно и с установкой PWM на схему проблем не случилось. А вот настройки самого компонента стоит рассмотреть подробней. Для этого приведу скриншот с выделенными изменёнными параметрами.

Clock - это рабочая частота ШИМа, любой цифровой или аналогово-цифровой блок должен работать на определённой тактовой частоте. Для этого и придуманы делители частоты и поле Clock. SysClk - это системная частота, выставленная в закладке Global Resources. Интересно заметить то, что в выпадающем списке Clock присутствуют такие поля, как Row_0_Input_0. Это значит, что тактовый генератор модуля может быть снаружи чипа и синхронизироваться они будут через шину Row_0_Input_0.

Enable - уровень логической единицы данного блока. Обычно используются два стандарта: High = 5В и Low = 3В. Сам микроконтроллер, кстати, можно так же перевести на один из режимов High или Low.

CompareOut - выход широтно-импульсного модулятора.

Может возникнуть вопрос: зачем была дана выше приведенная теория, если на практике мы это нигде не использовали? А ответ в том, что мы использовали дефолтные значения для длинны импульса и времени периода (поля Period и PulseWidth) 0 0. При таких значениях на выходе PWM будет сплошной сигнал, равный по величине логической единице. Менять время периода и значения ширины импульса можно так же программно в режиме работы микроконтроллера, функциями PWM8_1_WritePeriod() и PWM8_1_WritePulseWidth().

ADC или АЦП

АЦП - аналого-цифровой преобразователь (или ADC Analog-to-digital converter) - это устройство, позволяющие преобразовать аналоговый сигнал в цифровой. Любые физические величины (давление, скорость, угол поворота, напряжение, ток, сила света) являются аналоговыми, и задача ADC - переводить их в цифровой сигнал. На практике же, для перевода в цифровой сигнал обычно используется величина напряжения.
Из многочисленных характеристик АЦП следует выделить три основных:

  1. Разрядность - это наименьшая единица аналогового сигнала, изменение которой может зафиксировать ADC, обычно измеряется в битах.
  2. Частота преобразования - количество измерений в секунду, измеряется в SPS (samples per second)
  3. Рабочий диапазон - диапазон величин, в котором работает данный преобразователь.

Так как АЦП уже не такой простой прибор, как PWM. Придется разобрать ещё некоторые теоретические аспекты микроконтроллера и некоторые фичи самого АЦП.

Общие характеристики микроконтроллера

Перечень некоторых понятий и обозначений о которых нужно знать при работе c чипами PSoC(кстати и не только всё ниже сказанное будет верно и для микроконтроллеров AVR)

В описаниях и на принципиальных схемах в даташитах часто фигурируют такие обозначения как Vcc, Vdd, Vss, AGND. И разница между ними порой не самая очевидная. Vcc - это напряжение питания микроконтроллера (сс - collector-to-collector), то же самое что и Vdd, так уж исторически сложилось что одна и та же величина имеет 2 обозначения. Vss - минимальный потенциал на микроконтроллере, очень часто бывает, что эта величина эквивалентна AGND. Буква "A" в аббревиатуре AGND указывает на что, это artificial граунд или искусственная земля. Стоит упомянуть про такое напряжение на схеме, которое обычно называется как BandGap. BandGrap - это опорное напряжения. Опорное напряжение означает то что оно остаётся постоянным не зависимо от напряжения питания МК, температуры и других внешних показателей. Vref - опорное напряжения отдельно рассматриваемого модуля. Очень долго я не мог врубиться, что такое Rail-to-Rail. А попадалась мне эта фраза в контекстах типа: "Данный модуль может работать в режиме Rail-to-Rail". Так вот Rail-to-Rail означает то, что элемент может работать на всем размахе напряжений от Vcc до AGND.

Пример 2. Voltage Measuring

Задача: Измерить напряжение на потенциометре, зашитом в отладочную плату и вывести значение на экран.

Вот тут уже будет по интересней. Как обычно запускаем дизайнер, создаем проект. Идем в User Modules -> Misc Data -> LCD и левой кнопкой перетягиваем его на микроконтроллер. LCD очень полезный и простой модуль, да к тому же ещё и не занимающий место на цифровых блока. Увидеть его можно в закладке Workspace Explorer. Из настоек ему нужно выбрать только LCDPort = Port_2. Теперь заходим в файл main.c, напомню, что он лежит в Workspace Explorer -> [Имя проекта] -> Source Files -> main.c. И добавляем в функцию main() следующий код.

LCD_Start(); LCD_Position(0,0); LCD_PrCString("Measured Voltage");

Компилируем код, прошиваем микроконтроллер. Если всё было правильно сделано, получим на экране строку которая была прописана выше. Более простого управления экраном, и придумать не могли. И это радует. Теперь дело осталось за ADC. Выбираем User Modules -> Legacy -> ADCINC12 и выкидываем его на контроллер. Может возникнуть вопрос "Почему мы не выбрали просто ADCINC, а ADCINC12 да и ещё в придачу из папки Legacy? Причина кроется в сложности инициализации модулей. ADCINC более сложный и гибкий модуль, который требует более тщательной и доскональной настройки. В папке Legacy, что значит унаследованные, уже храниться модуль который менее гибкий, зато более простой в реализации. Далее не думая заходим в папку, amplifers и выкидываем на схему PGA(Programmable Gain Amplifier). Программируемый операционный усилитель. Он нужен не столько для усиления, сколько для повышения входного сопротивления. Что бы величина текущего тока в цепи не влияла на точность измерения.
Выставляем настройки PWM как на скриншоте.

  1. Gain - коэффициент усиления.
  2. Input - вход прибора.
  3. Reference - опорное напряжение.

Настройки ADC выставляем так:

  1. TMR Clock - тактовая частота таймера.
  2. Input - вход прибора (подключен к PGA).
  3. CNT Clock - частота счетчика.

Последнее, что понадобиться нам для нормальной работы, это глобальный ресурс называемый Ref Mux. Ref Mux - это рабочий диапазон напряжений аналоговых блоков. Если мы выставим значение (Vdd/2)+/-(Vdd/2) то получим полную разбежку напряжений от 0 до 5В. Но в этом есть один определённый минус. Так как за опорное напряжение принимается напряжение питания. Если будет плавать напряжение Vdd, это повлияет на правдивость результатов. В таком случае нам и пригодился бы BandGap. Но пока не будем париться, и выставляем (Vdd/2)+/-(Vdd/2).
Для перепроверки скину скрин получившейся коммутации аналоговых блоков.

Переходим в main.c и добавляем в функцию main() следующий код:

PGA_Start(PGA_HIGHPOWER); //запуск PGA ADCINC12_Start(ADCINC12_HIGHPOWER); //запуск АЦП ADCINC12_GetSamples(0); //установка АЦП на песперерывную работу M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts while(1) // главный цикл прошивки { if (ADCINC12_fIsDataAvailable() != 0) //проверка на данных в ADC { result = ADCINC12_iGetData() + 2048; ADCINC12_ClearFlag(); LCD_Position(1,0); //установка позиции для вывода LCD_PrHexInt(result); //вывод результата в хексе } }

К данным функции iGetData() прибавляется 2048 для того что перевести данные в беззнаковый эквиваленте (если интересно смотреть google "c++ знаковые и беззнаковые переменные").

Соединяем потенциометр с платой следующим образом.

Прошиваем микроконтроллер и оцениваем результат работы.

Осталось только перевести хексы в напряжение и проверить корректность данных тестером. Добиваться этой цели будем чисто опытным путём. Облегчим себе ситуацию, и примем нулевой потенциал за 0x0000 значение на выходе ADC. Затем запускаем нашу уже написанную программу, выкручиваем потенциометр на максимум и смотрим получившиеся значения. У меня, например, получилось 0х0FEC. Затем берём тестер и измеряем реальное напряжение на потенциометре. У меня получилось 4.78В. Теперь делим 4.78/0х0FEC (у кого проблемы с системами исчисления, советую подкачаться) и получаем шаг квантования, то есть единицу напряжения, которой соответствует одно значение выхода АЦП. У меня получилась 0.0011727183513248 вот такое вот число. Теперь просто результат с АЦП перемножаем на эту величину и выводим на экран. Для этого добавим переменные в глобальное поле видимости (это всё то что вне функции main()).

Пришло время разобраться, что из себя представляет модуль АЦП в микроконтроллерах STM32. Давайте по привычной схеме, сначала теория, под конец небольшая программка для работы с аналого-цифровым преобразователем.

Начнем-с…Вот некоторые характеристики аналого-цифрового преобразователя в STM32f10x:

  • АЦП является 12-ти битным
  • Возможна генерация прерывания по окончанию преобразования, по окончанию преобразования с инжектированного канала, а также возможно прерывание от Analog Watchdog (что это такое расскажу чуть ниже)
  • Возможно одиночное преобразование и преобразование в непрерывном режиме
  • Самокалибровка
  • Запуск преобразования от внешнего события
  • Работа с ПДП (DMA, прямой доступ к памяти)

Вот структурная схема из даташита, полюбуйтесь)

Пока не забыл про Analog Watchdog, опишу его работу.
Он нужен для того, чтобы следить, что напряжение попадает в определенные пределы. Причем он может сканировать как конкретный канал, так и группу каналов. В регистры ADC_HTR и ADC_LTR заносим значения верхнего и нижнего порога соответственно. И в случае, если проверяемое напряжение выходит за эти пределы, генерируется прерывание. Полезнейшая вещица!

Каналы АЦП делятся на регулярные и инжектированные. Причем, если запустить измерение инжектированных каналов, то измерение регулярных будет приостановлено. В некоторых ситуациях тоже крайне полезная фича.

Как и в микроконтроллерах AVR возможно выравнивание результата по правому или по левому краю. Тут правда результат 12-ти битный. Но суть та же. Вот как все это выглядит в регистрах:

Видим, как меняются данные в регистре данных. Программа работает правильно, так что можем переходить к дальнейшему изучению STM32. Продолжение следует…



Просмотров