В этой статье я расскажу о том, как можно захватывать аналоговый черно-белый видеосигнал с помощью платы STM32F4-DISCOVERY, и об особенностях передачи его на компьютер при помощи USB.
Используя плату STM32F4-DISCOVERY, можно создавать различные USB устройства — периферийный модуль USB в используемом микроконтроллере обладает большим функционалом. А вот примеров необычных конструкций с его использованием в сети мало — в большинстве случаев USB используют для реализации классов HID (эмуляция клавиатур, мышей и джойстивов) и CDC (эмуляция COM-порта). Встроенный USB-host обычно используют для подключения USB флешек.
Мне хотелось сделать какое-либо необычное USB устройство, например, web-камеру. Реализовать его можно двумя путями — написать свой собственный класс USB-устройства, и драйвер для него, либо, что значительно проще, воспользоваться стандартным для USB классом видеоустройств UVC (USB video device class). Драйверы для таких устройств встроены даже в Windows XP. Основное описание на UVC можно найти в этом документе (я использовал версию UVC 1.0, хотя есть и более новая 1.1).
Примеров реализации UVC на микроконтроллере в интернете очень мало. Достаточно большую сложность представляет правильное составление дескрипторов устройства (дескрипторы описывают весь его функционал). Даже небольшая ошибка в дескрипторе может приводить к тому, что устройство предстанет определятся, или даже к BSOD. Можно скопировать дескрипторы из имеющейся web-камеры, однако они могут быть излишне сложными — камеры часто содержат микрофон, позволяют производить захват одиночного изображения (Still image capture в терминологии UVC), позволяют изменять большое число настроек камеры. Во всем этом легко запутаться, так что мне хотелось сделать максимально простой проект.
При составлении дескрипторов, среди прочего, нужно указать параметры передаваемого изображения. Я остановился на размере изображения в 320×240 пикселей и формате изображения NV12. Стандарт UVC позволяет предавать только два формата несжатых изображений: NV12 и YUY2.
Второй формат более распространен, но NV12 больше подходит для кодирования черно-белых изображений и занимает меньше места. В этом формате данные кодируются по типу YUV 4:2:0 (на четыре пикселя приходится два байта информации о цвете). Сначала идет информация о яркости всего изображения (320*240 байт в моем случае), затем информация о цвете (поочередно идут байты U и V):
Всего изображение будет занимать (320*240*3/2) байт. У данного формата есть недостаток — не все программы умеют с ним работать.
В качестве базового проекта я взят свой проект USB-микрофона. В нем тоже была реализована передача данных на компьютер через изохронную конечную точку. Работа с USB реализована при помощи библиотеки от производителя контроллера (STSW-STM32046). После замены дескрипторов, VID/PID (как я понял, можно установить любые), контроллер обнаружился как устройство обработки изображений. Следующий этап — передача на компьютер потока видеоинформации (для начала — тестового изображения, хранящегося в памяти контроллера).
Предварительно стоит упомянуть о различных USB запросах (Request), которые нужно обрабатывать. При получении контроллером запроса от компьютера (хоста) некоторых видов запросов, библиотека USB вызывает функцию usbd_video_Setup, которая должна обработать запрос.
Большая часть этой функции взята из кода микрофона — это обработка Standard Device Requests. Здесь можно обратить внимание на переключение между альтернативными интерфейсами, которое происходит при получении запроса SET_INTERFACE. UVC устройство должно предоставлять как минимум два альтернативных интерфейса, на один из которых (Zero Bandwidth, идет под 0 номером) компьютер переключает USB устройство, когда оно не нужно, тем самым ограничивая поток данных по шине. Когда какая-либо программа на компьютере готова принимать данные от устройства, она передает на него запрос на переключение на другой альтернативный интерфейс, после чего устройство начинает получать от хоста IN Token Packets, сигнализирующие о том, что хост ожидает передачи данных.
В процессе создания проекта обнаружилось, что библиотека USB иногда некорректно обрабатывает запросы передачи данных на хост — после передачи некоторого небольшого объема данных передача данных прекращается, и возобновить ее можно только перезагрузить компьютер. Это касается как передачи видеоинформации (через 1 конечную точку), так и управляющей информации (через 0 конечную точку). Исправляется это предварительной очисткой FIFO нужной конечной точки перед началом записи в нее.
После того, как все нужные запросы переданы, и компьютер отправил запрос на переключение альтернативного интерфейса в основной режим, можно начинать передавать видеоданные. Компьютер начинает выдавать на шину IN Token Packet каждую миллисекунду, при получении которых контроллер вызывает функцию usbd_video_DataIn, из которой нужно вызвать библиотечную функцию передачи данных DCD_EP_Tx.
#define RX_FIFO_FS_SIZE 64 #define TX0_FIFO_FS_SIZE 16 #define TX1_FIFO_FS_SIZE 232 #define TX2_FIFO_FS_SIZE 0 #define TX3_FIFO_FS_SIZE 0
Для FIFO приема команд от компьютера нужно выделить не менее 64 слов, на FIFO предачи управляющей информации на компьютер через 0 конечную точку нужно еще 16 слов. Все остальное можно выделить на первую конечную точку для передачи видеоданных. Суммарно получается (64 + 16 + 232)*4 = 1248 байта. Так как имеется ограничение на 232 слово (928 байт), то размер пакета (VIDEO_PACKET_SIZE) был установлен равным (768+2) байт. Таким образом, один кадр состоит из (320*240*3/2) / (768) = 150 пакетов, которые будут предаваться 150*1мс, что дает 6,6 FPS.
Не очень-то много, но при передаче несжатого изображения при том же размере большего не получить. Поэтому я решил попробовать сжимать изображение на микроконтроллере.
Стандарт UVC поддерживает разные виды сжатия, один из которых — MJPEG. В данном виде сжатия каждый исходный кадр изображения сжимается по стандарту JPEG. Полученный сжатый кадр можно отправить на компьютер так, как описано выше. Особенности дескрипторов и передачи данных для MJPEG описаны в документе «Universal Serial Bus Device Class Definition for Video Devices: Motion-JPEG Payload».
Передача статического изображения, подготовленного на компьютере, оказалось довольно простой — преобразуем обычный JPEG файл в .h файл, добавляем его к проекту, передаем его по пакетам, также как и раньше. Так как размер сжатого изображения может быть произвольным, то длина последнего пакета данных тоже получается переменной, так что ее нужно вычислять.
Особенность использования памяти CCM
В используемом контроллере RAM разделена на несколько блоков. Один из них — (64 Кбайта) называется CCM, и к нему нельзя получить доступ через DMA. Я решил поместить сюда два массива для хранения сжатого изображения.
Для того, чтобы использовать эту память, в IAR нужно отредактировать используемый .icf файл, добавив в него строки:
define symbol __ICFEDIT_region_RAMCCM_start__ = 0x10000000; define symbol __ICFEDIT_region_RAMCCM_end__ = 0x1000FFFF; ....... define region CCMRAM_region = mem:[from __ICFEDIT_region_RAMCCM_start__ to __ICFEDIT_region_RAMCCM_end__]; ....... place in CCMRAM_region {section .ccmram};
Массивы в коде нужно объявлять так:
#pragma location = ".ccmram" uint8_t outbytes0[32000]; #pragma location = ".ccmram" uint8_t outbytes1[32000];
Получившаяся конструкция заработала, однако только в программе ContaCam и в браузере (проверялось здесь). На статическом изображении удалось получить 35 FPS.
Пример сжатого изображения (размер изображения 17 Кбайт):
Изображение перевернуто, так как информация в bmp файлах хранится именно так.
А вот другие программы или не работали вовсе, или давали вот такое изображение:
Это связано с тем, что стандарт UVC не поддерживает передачу черно-белых изображений при помощи MJPEG.
Требования в JPEG к изображению такие:
• Color encoding — YCbCr
• Bits per pixel — 8 per color component (before filtering/subsampling)
• Subsampling — 422
Таким образом, требовалось переделать имеющийся кодировщик для формирования псевдоцветных изображений — по настоящему в таком изображении кодируются только данные о яркости (Y), а вместо данных о цвете (Cb и Cr) передаются нули. Пришлось ознакомится со структурой формата JPEG глубже.
Как работал кодировщик раньше:
1. Формируется заголовок JPEG файла.
2. Поблочная (8×8 пикселей) обработка исходного изображения.
2.1 Каждый блок считывается из памяти, производится его дискретное косинусное преобразование (DCT)
2.2 Получившиеся 64 значения квантуются и результат пакуется с использованием кодов Хаффмана.
3. Формируется маркер конца данных и подсчитывается размер сжатого изображения.
Более подробно про JPEG можно почитать здесь и здесь.
Информация о наличии цвета в сжатом изображении хранится в заголовке JPEG, так что его нужно изменить. Менять надо секции SOF0 и SOS, указав в них использование трех компонентов, для яркостного компонента прореживание 22, для цветовых 11. Везде в качестве идентификатора таблиц квантования я указывал 0.
Теперь можно изменить методику кодирования информации. Так как цветовая информация кодируется с прореживанием, то двум цветовым блокам информации должны соответствовать четыре блока яркостной информации. Таким образом, сначала последовательно кодируются четыре блока яркостной информации, после чего нужно произвести кодирование еще двух блоков цветовой информации (пример из вышеуказанной статьи):
В использованной библиотеке квантование, окончательное сжатие обработанных данных, и запись их в память выполняются отдельной функцией, так что для формирования цветовой информации достаточно обнулить массив DCT коэффициентов и вызвать эту функцию дважды.
Однако в JPEG кодировании есть важная особенность — кодируются не DC-коэффициенты, идущие в начале каждого блока, а разность текущего DC-коэффициента, и DC-коэффициента предыдущего блока соответствующего компонента. В библиотеке эта разность изначально вычислялась перед квантованием, так что пришлось модифицировать вышеуказанную функцию, так, чтобы во время обработки каналов Cr и Cb разность не вычислялась — в этих компонентах и так идут нули.
В результате картинка начала отображаться корректно во всех используемых программах видеозахвата. Недостаток такого псевдоцветного кодирования — несколько упала его скорость. Сжатие тестового изображение стало занимать 35 мс, что дает 28 FPS.
Теперь, когда появился способ передавать видеоданные на компьютер с приемлемой скоростью, можно заняться и захватом видеосигнала. С самого начала экспериментов с USB я предполагал реализовать захват видеосигнала от аналоговой видеокамеры средствами самой отладочной платы.
Так как раньше я уже делал самодельный телевизор на микроконтроллере, то методика захвата черно-белого видеосигнала не была для меня чем-то новым. Конечно, контроллер STM32F4 сильно отличается от ATxmega, так что и подход к захвату видео пришлось поменять.
Сам формат PAL уже многократно описан на различных ресурсах, так что остановлюсь на его основных положениях, и только для черно-белого варианта.
Кадровая частота этого формата — 25 Гц, но при этом используется чересстрочная развертка — то есть при передаче кадра сначала передаются сначала четные, а затем нечетные строки. Каждый такой набор строк называется полем. Поля в данном формате идут с частотой 50 Гц (20 мс). В одном поле передается 312,5 строк (из них видеоинформацию содержат только 288,5). Все строки разделяются синхроимпульсами, которые следуют с периодом 64 мкс. Сам видеосигнал в строке при этом занимает 52 мкс.
Поля разделяются кадровыми и уравнивающими синхроимпульсами. Важная особенность уравнивающих синхроимпульсов — их период в два раза меньше периода строк — 32 мкс, так что их легко отличить от синхроимпульсов.
Таким образом, для того, чтобы захватывать изображение в память контроллера, нужно написать программу, способную обнаруживать синхросигналы, выделять из них уравнивающие импульсы, и запускать преобразование АЦП в перед началом передачи видеоданных каждой строки.
Теперь следует подробнее остановится на методике оцифровки видеосигнала.
В контроллере STM32F4 имеются три отдельных АЦП, каждый из которых может работать со скоростью 2.4 MSPS при разрядности 12 бит. При уменьшении разрядности скорость работы увеличивается, но и этого не хватит для получения разрешения 320*240. Однако контроллер позволяет объединять несколько АЦП — можно настроить захват всеми АЦП одновременно, а можно установить задержку захвата между АЦП, в результате чего общая скорость захвата возрастает.
Какая же скорость захвата будет при использовании сразу двух АЦП (Interleaved dual mode)?
Для тактирования АЦП используется шина APB2, тактовая частота которой при инициализации контроллера устанавливается раной половине системной частоты (168 MHz / 2) = 84 MHz. Для АЦП это слишком много, так что при настройке АЦП приходится устанавливать предделитель на 2. Получившаяся частота 42 MHz все равно больше максимальной допустимой по даташиту (36 MHz), но у меня АЦП хорошо работает и при такой частоте.
В случае, если бы каждый АЦП при установленной разрядности 8 бит работал бы отдельно, то максимальная скорость преобразования была бы (42 MHz / (3+8)) = 3.81 MSPS. Установив задержку между временем захвата данных в 6 циклов, можно получить скорость 7 MSPS, а при 7 циклах — 6 MSPS.
Я выбрал последний вариант. При этом получается, что вся строка (64 мкс) займет 384 байта, а активная часть строки с видеосигналом (52 мкс) займет 312 байт (пикселей).
АЦП передает результаты преобразования в память при помощи DMA. При использовании двух 8-битных АЦП, данные передаются в память в виде 16-битных слов в момент завершения преобразования второго АЦП. В принципе, можно было бы захватывать в память содержимое практически всего кадра целиком — для этого нужно (384*240) = 92,16 Кбайт. Но я пошел по другому пути — захват данных начинается после обнаружения контроллером импульса синхронизации, и останавливается после захвата 366 байт (183 передачи DMA). Почему выбрано такое число — расскажу далее. В результате видеоданные занимают (366*240) = 87,84 Кбайт ОЗУ.
Рассмотрим методику обнаружения синхросигнала. В идеале, его лучше обнаруживать специальной микросхемой, или хотя бы компаратором, но это усложняет конструкцию. Так как у меня остался один не использованный АЦП, то я решил применить его для обнаружения синхросигналов. В состав каждого АЦП входит специальный модуль «Analog watchdog». Он может формировать прерывание в случае, если оцифрованное значение выходит за заданные пределы. Однако этот модуль не способен реагировать на изменение фронта оцифровываемого сигнала — он будет формировать прерывание до тех пор, пока не изменится входной сигнал или настройки модуля. Так как мне нужно было обнаруживать фронты сигнала, то пришлось сделать перенастройку этого модуля при каждом его прерывании. Я не стал реализовывать в программе автоматическое определение порогов срабатывания Analog watchdog, так что они указываются вручную для используемой камеры.
Для того, чтобы обнаруживать уравнивающие импульсы, используется один из таймеров контроллера, работающий с частотой 1 МГц. Таймер работает постоянно, а в обработчике прерывания Analog watchdog (при обнаружении переднего фронта синхроимпульса) считывается его текущее значение, и сравнивается с предыдущим. Таким образом можно отличать строчные синхроимпульсы от уравнивающих. После того, как уравнивающие синхроимпульсы закончились, контроллер пропускает 17 строчных синхроимпульсов, и при обнаружении переднего фронта синхроимпульса начинает захват видеоданных текущей строки. Так как вход в обработчик прерывания в данном контроллере может может происходить за переменное время, а так же из-за того, что АЦП 3 работает медленнее, чем первые два вместе, то время между фронтом синхроимпульса и началом захвата может отличатся, что приводит к «дрожанию» строк. Именно поэтому захват видеоданных начинается еще с переднего фронта синхроимпульса, а строка занимает 366 байт — таким образом часть синхроимпульса попадает в кадр, и ее можно убрать программно для каждой строки.
На осциллограмме видно, как идет захват видеосигнала (во время работы DMA «желтый» канал устанавливается в 1):
Захват начинается только после появления видеоданных:
Не все строки в одном поле захватываются, так как установлено ограничение в 240 строк.
В результате получается вот такое необработанное изображение (получено с использованием ST-Link Utility):
После того, как изображение захвачено в память контроллера, его нужно обработать — для каждой строки убрать смещение, связанное с захватом синхросигнала, и вычесть из значений яркости пикселей величину уровня черного. Я не старался оптимизировать этот участок кода, так что его выполнение занимает 5 мс.
После того, как изображение обработано, его можно начинать кодировать в JPEG, при этом одновременно начинается передача по USB уже закодированных данных предыдущего изображения.
Таким образом, кадр захватывается 20 мс, обработка идет 5 мс, и кодирование вместе с передачей данных идут 35 мс, что суммарно дает 60 мс, или частоту кадров 16.6 FPS. В результате получается, что один кадр (на самом деле поле) захватывается, а два пропускаются. Так как развертка в формате PAL чересстрочная, то выходит, что поочередно захватываются то четное, то нечетное поле, что приводит к дрожанию изображения на один пиксель. Избавится от этого можно, добавив дополнительную задержку между захватом кадров — тогда будет пропускаться еще одно поле, и частота кадров на выходе упадет до (50 / 4) = 12.5 FPS.
Изначально я планировал использовать в качестве источника сигнала видеокамеру видеонаблюдения KPC-190S (этой камере уже практически 15 лет). Нельзя сказать, что она обеспечивает хорошее качество изображения — оно достаточно шумное, с не очень высоким контрастом, и маленькой амплитудой (из осциллограммы видно, что она близка к 1 В). Для небольшой подстройки выходного сигнала камера подключается к контроллеру через резисторный делитель на переменном резисторе. Единственный сигнальный вывод платы, к которому подключена камера — это PC2 (к нему подключены все АЦП).
Внешний вид конструкции:
Так как камера не обеспечивала хорошего качества изображения, я решил попробовать брать сигнал с фотоаппарата Canon A710. У него имеется аналоговый выход для подключения к телевизору, на который выводится все, что отображается на экране фотоаппарата. Качество сигнала у фотоаппарата получше, однако видеосигнал у него цветной. Для того, чтобы убрать из сигнала цветовую составляющую, я использовал вот такой фильтр:
Кроме того, синхроимпульсы на выходе фотоаппарата имеют отрицательную полярность, так что для того, чтобы они обнаруживались АЦП контроллера, пришлось добавить к сигналу дополнительное напряжение смещения при помощи регулируемого источника питания. Так же пришлось немного изменить пороги срабатывания Analog watchdog.
Внешний вид конструкции с подключенным фотоаппаратом:
Пример изображения, получаемого от фотоаппарата:
Видео работы устройства:
Исходные коды проектов: github. com/iliasam/STM32F4_UVC_Camera
Быстрый всплеск популярности микроконтроллеров STM32 в большой степени обеспечен дешевыми отладочными средствами серии Discovery. Низкая стоимость и наличие встроенного отладчика сделали эти платы востребованными у широкого круга любителей и разработчиков. Но, как и все в этом мире, платы Discovery не лишены недостатков. Одним из самых существенных можно считать необходимость изготовления специальной платы с периферийными устройствами, либо какое-то другое решение, позволяющее подключать к отладочной плате внешние элементы. Если использовать Discovery в качестве процессорного модуля, то разработать такое решение особого труда не составляет. Другое дело, если требуется оборудование для изучения возможностей процессора. В этом случае сложно заранее предсказать, что и где потребуется. Выходом может стать использование специальных плат носителей.
В качестве одного из вариантов платы-носителя, можно выбрать модель Open407V-D от китайского производителя WaveShare. Данная плата разработана для установки STM32F4-Discovery и позволяет простым образом подключать периферийные устройства с помощью множества специализированных разъемов. Фактически Open407V-D есть плата – переходник с Discovery на внешние устройства. Встроенной периферии за исключением джойстика на плате нет.
Плата Open407V-D с установленной платой STM32F4-Discovery |
Конструктивно плата Open407V-D выполнена из двухстороннего стеклотекстолита и имеет размеры 150х147 мм. Для установки на различные поверхности в комплекте предусмотрены металлические ножки в количестве 8 шт. Такое число позволяет устанавливать различные модули, не опасаясь возможного разрыва дорожек вследствие прогиба платы. Для внешнего питания предусмотрен специальный разъем и регулятор на 3.3 вольта. Подача напряжения доступна с помощью небольшого переключателя. Напряжение питания платы равно 5В. Для удобства в комплекте можно найти небольшой кабель, позволяющий питать плату от разъема USB.
1 |
Разъемы для установки STM32F4Discovery |
14 |
Разъем интерфейса Ethernet |
2 |
Разъем интерфейса USART |
15 |
Разъем внешнего питания |
3 |
Разъем интерфейса SPI |
16 |
Гребенка шин питания |
4 |
Разъем интерфейса CAN1 |
17 |
Габариты STM32F4Discovery |
5 |
Разъем интерфейса CAN2 |
18 |
Разъем программатора/отладчика JTAG/SWD |
6 |
Разъем интерфейса I2C1 |
19 |
Джампер обнаружения SD-карты |
7 |
Разъем интерфейсов I2C1/I2C2 |
20 |
Джамперы подключения джойстика |
8 |
Разъем интерфейса цифровой камеры DCMI |
21 |
Переключатель выбора области загрузки |
9 |
Разъем подключения карты SD |
22 |
Перемычка включения подсветки LCD |
10 |
Разъем подключения LCD |
23 |
Регулятор напряжения 3. 3В |
11 |
Разъем подключения внешней памяти FSMC |
24 |
Выключатель питания |
12 |
Разъем интерфейса UART3 |
25 |
Светодиод питания |
13 |
Разъем интерфейса ULPI |
26 |
Джойстик |
С обратной стороны платы можно найти перемычки, позволяющие изменить распиновку разъемов. Дополнительно на плате разведены гребенки, повторяющие внешние контакты STM32F4-Discovery. Все разъемы выполнены в виде колодок типа PBD. Их использование несколько упрощает подключение нестандартных устройств. Кроме этого фирма WaveShare предлагает множество собственных периферийных модулей, нацеленных на работу именно с этими разъемами. В числе этих модулей можно найти устройства беспроводной связи, преобразователи интерфейсов, АЦП, модули памяти и LCD дисплеи.
Обратная сторона Open407V-D |
В комплекте с платой, производитель поставляет набор кабелей, предназначенных для подключения STM32F4-Discovery и платы к ПК и другим устройствам. Самым интересным из них можно считать переходник с ответной части разъема miniUSB, установленного на плате Discovery, на ответную часть типа А обычного размера. С Open407V-D также идет компакт диск, содержащий описания платы и внешних модулей, фирменную документацию от STMicroelectronics, и примеры программ для работы с внешними устройствами.
Кроме платы Open407V-D, предназначенной для STM32F4-Discovery, производитель предлагает подобные решения и для других вариантов отладочных устройств. Имеются в каталоге и собственные процессорные модули.
Еще по теме:
Отладочная плата STM32F4-Discovery
Отладочная плата STM32 Discovery от фирмы STMicroelectronics
You have no rights to post comments
АЦП выполняет операцию счетчика, аналогичную ЦАП, в то время как АЦП (АЦП) преобразует аналоговое напряжение в цифровые данные, ЦАП (ЦАП) преобразует цифровые числа в аналоговое напряжение на выходном контакте.
АЦП является одним из самых дорогих электронных компонентов, особенно когда он имеет высокую частоту дискретизации и высокое разрешение. Таким образом, это ценный ресурс в микроконтроллерах, и разные производители предоставляют нам (разработчикам микропрограмм) различные функции, чтобы наилучшим образом использовать его. А также гибкость для принятия множества решений, таких как жертвование разрешением в обмен на более высокое разрешение или запуск АЦП по сигналу внутреннего таймера для периодической выборки аналоговых каналов, и многое другое, как мы увидим в этом руководстве.
Учебный курс SCADA 26 — SCADA и…
Включите JavaScript
Учебный курс SCADA 26 — SCADA и моделирование ПЛК — Учебные пособия для начинающих низкий уровень, различные типы АЦП, ошибки АЦП, уравнения и все остальные детали. Приведенный ниже учебник ADC представляет собой полное вводное руководство по этой теме и настоятельно рекомендуется.
STM32F103C8 (Blue Pill) и STM32F432KC имеют 12-разрядный АЦП, который представляет собой аналого-цифровой преобразователь последовательного приближения. Он имеет до 18 мультиплексированных каналов, позволяющих измерять сигналы от шестнадцати внешних и двух внутренних источников. Аналого-цифровое преобразование различных каналов может выполняться в одиночном, непрерывном, сканирующем или прерывистом режиме. Результат АЦП сохраняется в 16-разрядном регистре данных с выравниванием по левому или правому краю.
Функция аналогового сторожевого таймера позволяет приложению определять, выходит ли входное напряжение за установленные пользователем верхние или нижние пороговые значения. Входной тактовый сигнал АЦП генерируется из тактового сигнала PCLK2, деленного на прескалер, и он не должен превышать 14 МГц.
Функции АЦП
STM32 ADC Block Diagram
Часы АЦП
Часы ADCCLK, предоставляемые контроллером часов, синхронны с PCLK2 (часы APB2). Контроллер RCC имеет специальный программируемый прескалер для тактовой частоты АЦП, частота которого не должна превышать 14 МГц.
Выбор канала
Имеется 16 мультиплексированных каналов. Конверсии можно разделить на две группы: обычные и инжектированные. Группа состоит из последовательности конверсий, которые можно выполнять на любом канале и в любом порядке. Например, можно выполнить преобразование в следующем порядке: Ch4, Ch8, Ch3, Ch3, Ch0, Ch3, Ch3, Ch25.
Обычная группа состоит из 16 преобразований. Обычные каналы и их порядок в последовательности преобразования должны быть выбраны в регистрах ADC_SQRx. Общее количество преобразований в обычной группе должно быть записано в битах L[3:0] в регистре ADC_SQR1.
Впрыскиваемая группа состоит из 4 преобразований. Вводимые каналы и их порядок в последовательности преобразования должны быть выбраны в регистре ADC_JSQR. Общее количество преобразований в инжектируемой группе должно быть записано в битах L[1:0] в регистре ADC_JSQR.
Время преобразования АЦП и временная диаграмма
АЦП требуется время стабилизации t STAB , прежде чем он начнет точное преобразование. После начала преобразования АЦП и через 14 тактов устанавливается флаг EOC и 16-разрядный регистр данных АЦП содержит результат преобразования.
Аналоговый сторожевой таймер АЦП (AWD)
Бит состояния аналогового сторожевого таймера AWD устанавливается, если аналоговое напряжение, преобразованное АЦП, ниже нижнего или выше верхнего порога. Эти пороги программируются в 12 младших битах 16-битных регистров ADC_HTR и ADC_LTR. Прерывание может быть разрешено с помощью бита AWDIE в регистре ADC_CR1. Пороговое значение не зависит от выбранного выравнивания. Аналоговый сторожевой таймер можно включить на одном или нескольких каналах.
Выравнивание данных результата АЦП
Бит ALIGN в регистре ADC_CR2 выбирает выравнивание данных, сохраняемых после преобразования. Данные могут быть выровнены по левому или правому краю, как показано на диаграмме ниже.
Значение преобразованных данных введенных групповых каналов уменьшается на заданное пользователем смещение, записанное в регистры ADC_JOFRx, поэтому результатом может быть отрицательное значение. Бит SEXT является расширенным значением знака. Для обычных групповых каналов смещение не вычитается, поэтому значимыми являются только двенадцать битов.
Режим одиночного преобразования
, в режиме одиночного преобразования АЦП выполняет одно преобразование. Этот режим запускается либо установкой бита ADON в регистре ADC_CR2 (только для обычного канала), либо внешним триггером (для обычного или введенного канала), при этом бит CONT равен 0. После преобразования выбранного канала Complete:
Затем АЦП останавливается.
Непрерывный режим преобразования
В режиме непрерывного преобразования АЦП начинает другое преобразование, как только заканчивает одно. Этот режим запускается либо по внешнему триггеру, либо установкой бита ADON в регистре ADC_CR2, при этом бит CONT равен 1. После каждого преобразования:
Режим сканирования
Этот режим используется для сканирования группы аналоговых каналов. Одно преобразование выполняется для каждого канала группы. После каждого окончания преобразования следующий канал группы преобразуется автоматически. Если бит CONT установлен, преобразование не останавливается на последнем выбранном групповом канале, а снова продолжается с первого выбранного группового канала.
При использовании режима сканирования должен быть установлен бит DMA и контроллер прямого доступа к памяти используется для передачи преобразованных данных обычных групповых каналов в SRAM после каждого обновления регистра ADC_DR. Введенные преобразованные данные канала всегда сохраняются в регистрах ADC_JDRx.
Прерывистый режим
Этот режим включается установкой бита DISCEN в регистре ADC_CR1. Его можно использовать для преобразования короткой последовательности из n преобразований (n <= 8), которая является частью последовательности преобразований, выбранной в регистрах ADC_SQRx. Значение n задается записью в биты DISCNUM[2:0] в регистре ADC_CR1.
Когда возникает внешний триггер, он запускает следующие n преобразований, выбранных в регистрах ADC_SQRx, пока не будут выполнены все преобразования в последовательности. Общая длина последовательности определяется битами L[3:0] в регистре ADC_SQR1.
Преобразование может быть запущено внешним событием (например, захватом таймера, линией EXTI). Если бит управления EXTTRIG установлен, то внешние события могут инициировать преобразование. Управляющие биты EXTSEL[2:0] и JEXTSEL[2:0] позволяют приложению выбирать, какое из 8 возможных событий может инициировать преобразование для обычной и введенной групп.
Если для обычного или инжектированного преобразования АЦП выбран внешний триггер, только нарастающий фронт сигнала может запустить преобразование. Ниже приведена таблица возможных вариантов внешних триггерных входов АЦП 1 и 2 для запуска преобразования на обычных групповых каналах. Калибровка АЦП STM32 Калибровка значительно снижает ошибки точности из-за внутренних изменений конденсаторной батареи. Во время калибровки для каждого конденсатора вычисляется код исправления ошибок (цифровое слово), и во время всех последующих преобразований вклад каждого конденсатора в ошибку удаляется с помощью этого кода.
Калибровка запускается установкой бита CAL в регистре ADC_CR2. После завершения калибровки бит CAL сбрасывается аппаратно, и можно выполнить обычное преобразование. Рекомендуется калибровать АЦП один раз при включении питания. Коды калибровки сохраняются в ADC_DR, как только фаза калибровки заканчивается. Рекомендуется выполнять калибровку после каждого включения питания.
STM32 HAL предоставляет функцию в API-интерфейсах АЦП, предназначенную для запуска процесса калибровки, и, как было сказано ранее, это рекомендуемый шаг после инициализации аппаратного обеспечения АЦП при включении системы.
АЦП производит выборку входного напряжения в течение нескольких циклов ADC_CLK, которые можно изменить с помощью битов SMP[2:0] в регистрах ADC_SMPR2 и ADC_SMPR1. Каждый канал может быть сэмплирован с разными интервалами дискретизации.
Общее время преобразования АЦП рассчитывается следующим образом:
Tconv = время выборки + 12,5 циклов
Пример:
циклы = 1 мкс
Скорость отбора проб ADC (частота) рассчитывается с использованием этой формулы:
SamplingRate = 1 / TCONV
для предыдущего примера, где TCONV = 1 млекс, SAMPLINGRATE = 1000000 = 1MS / SEC
Разрешение АЦП STM32
АЦП STM32 имеет разрешение 12 бит, что дает общее время преобразования SamplingTime+12,5 тактовых циклов. Однако более высокие частоты дискретизации могут быть достигнуты за счет снижения высокого разрешения. Таким образом, разрешение может быть снижено до 10-битного, 8-битного или 6-битного, и, следовательно, время преобразования становится намного короче, а частота дискретизации увеличивается. Это может быть настроено и реализовано программистом в программном обеспечении, и STM32 HAL предоставляет API-интерфейсы для установки всех параметров АЦП, включая его разрешение.
Опорное напряжение АЦП
Выводы опорного напряжения АЦП определены в техническом описании и предполагаются подключенными к уровню напряжения в определенном диапазоне. Это показано в таблице ниже. Вы можете установить опорное напряжение на его максимально допустимый уровень для более широкого диапазона преобразования, но с меньшим разрешением измерения напряжения. Или, в качестве альтернативы, вы можете установить опорное напряжение на минимально допустимое значение для лучшего разрешения считывания напряжения.
Если вы используете отладочную плату, вам может понадобиться проверить ее принципиальную схему, так как она может вообще не подключать Vref АЦП или, например, подключать его к 2,5 В, поэтому АЦП насыщается и дает вам 4096 до того, как входное аналоговое напряжение достигнет 3,3 В, и вам интересно, почему! это может быть связано с тем, что опорное напряжение установлено на значение менее 3,3 В, так что это следует учитывать.
Формулы АЦП STM32
Время преобразования АЦП
TCONV = время выборки + 12,5 циклов
Скорость отбора проб ADC
SamplingRate = 1 / TCONV
ADC Результат напряжение (аналоговое входное значение)
VIN = ADC_RES X (Ссылка / 4096)
VIN = ADC_RES X (Ссылка / 4096)
VIN = ADC_RES x (Ссылка / 4096)
VIN = ADC_RES X (Ссылка / 4096) VIN = ADC_RES X. Напряжение = (V REF +) – (V REF -)Поскольку значение преобразованного канала необходимо использовать в регистре, преобразованное в обычный канал, значение сохраняется в регистре DMA. для преобразования более чем одного обычного канала. Это позволяет избежать потери данных, уже сохраненных в регистре ADC_DR.
Только окончание преобразования обычного канала генерирует запрос DMA, который разрешает передачу его преобразованных данных из регистра ADC_DR в место назначения, выбранное пользователем.
Прерывание может быть создано в конце преобразования для обычных и введенных групп и когда установлен бит состояния аналогового сторожевого устройства. Отдельные биты разрешения прерывания доступны для гибкости.
1 — метод опроса
Это самый простой способ кода для выполнения аналога с цифровым преобразованием, используя ADC на анальном входе. канал. Тем не менее, это не эффективный способ во всех случаях, так как он считается блокирующим способом использования АЦП. Таким образом, мы запускаем аналого-цифровое преобразование и ждем, пока АЦП завершит преобразование, чтобы ЦП мог возобновить обработку основного кода.
2 – Метод прерывания
Метод прерывания является эффективным способом выполнения преобразования АЦП неблокирующим образом, поэтому ЦП может возобновить выполнение основного кода до тех пор, пока АЦП не завершит преобразование и не выдаст сигнал прерывания. поэтому ЦП может переключиться на контекст ISR и сохранить результаты преобразования для дальнейшей обработки.
Однако, когда вы имеете дело с несколькими каналами в циклическом режиме или около того, у вас будут периодические прерывания от АЦП, которые ЦП не сможет обработать. Это приведет к внедрению джиттера, задержке прерывания и всевозможным проблемам синхронизации в системе. Этого можно избежать, используя DMA.
3 – Метод прямого доступа к памяти
Наконец, метод прямого доступа к памяти является наиболее эффективным способом преобразования нескольких каналов АЦП с очень высокой скоростью и по-прежнему передает результаты в память без вмешательства ЦП, что является таким крутым и экономящим время методом. .
Обратите внимание, что : примеры кода для трех методов приведены в следующем руководстве. После завершения щелкните следующий учебник, чтобы просмотреть примеры.
В этом разделе перечислены основные типы ошибок, влияющие на точность аналого-цифрового преобразования. Эти типы ошибок возникают во всех аналого-цифровых преобразователях, и качество преобразования зависит от устранения источника каждой из них.
1 Ошибки АЦП из-за самого АЦП
1.1 — Ошибка смещения АЦП
Ошибка смещения — это отклонение между первым фактическим переходом и первым идеальным переходом. Первый переход происходит, когда цифровой выход АЦП изменяется с 0 на 1. В идеале, когда аналоговый вход находится в диапазоне от 0,5 LSB до 1,5 LSB, цифровой выход должен быть равен 1. Тем не менее, в идеале первый переход происходит при 0,5 LSB. Ошибка смещения обозначается E О . Погрешность смещения можно легко откалибровать с помощью прошивки приложения.
1.2- Ошибка усиления АЦП
Ошибка усиления представляет собой отклонение между последним фактическим переходом и последним идеальным переходом. Обозначается E G . Последний фактический переход — это переход от 0xFFE к 0xFFF. В идеале должен быть переход от 0xFFE к 0xFFF, когда аналоговый вход равен V REF + – 0,5 LSB. Так для V REF += 3,3 В, последний идеальный переход должен произойти при 3,299597 В. Если АЦП обеспечивает показание 0xFFF для V AIN < V REF + – 0,5 LSB, то получается отрицательная ошибка усиления. Ошибка усиления определяется по следующей формуле:
E G = Последний фактический переход – идеальный переход
1.3 – Ошибка интегральной линейности линия корреляции конечной точки. ИЛЭ обозначается E л . Линия корреляции конечной точки может быть определена как линия на кривой аналого-цифрового преобразования, которая соединяет первый фактический переход с последним фактическим переходом.
E L — отклонение от этой линии для каждого перехода. Таким образом, линия корреляции конечной точки соответствует фактической кривой переноса и не имеет никакого отношения к идеальной кривой переноса. ILE также известен как интегральная ошибка нелинейности (INL). ИЛЭ является интегралом ДЛЭ по всему диапазону.
2 Ошибки АЦП из-за условий окружающей среды
2.1 – Шум опорного напряжения АЦП
изменение преобразованного цифрового значения. Аналоговый источник питания V DDA используется на некоторых корпусах в качестве опорного напряжения (V REF +), поэтому качество источника питания V DDA влияет на ошибку АЦП.
2.2 – Шум аналогового входного сигнала
Небольшие, но высокочастотные колебания сигнала могут привести к большим ошибкам преобразования во время выборки. Этот шум создается электрическими устройствами, такими как двигатели, зажигание двигателя, линии электропередач. Он влияет на исходный сигнал (например, датчики), добавляя нежелательный сигнал. Как следствие, результаты преобразования АЦП неточны.
2.3 – Плохое согласование динамического диапазона АЦП
Для достижения максимальной точности преобразования АЦП очень важно, чтобы динамический диапазон АЦП соответствовал максимальной амплитуде преобразуемого сигнала. Предположим, что сигнал, который необходимо преобразовать, варьируется от 0 В до 2,5 В, а VREF+ равно 3,3 В. Максимальное значение сигнала, преобразуемого АЦП, равно 3102 (2,5 В), как показано на диаграмме ниже. В данном случае имеется 993 неиспользованных перехода (4095 – 3102 = 993). Это подразумевает потерю точности преобразованного сигнала.
2.4 – Полное сопротивление источника аналогового сигнала (сопротивление)
Полное сопротивление источника аналогового сигнала или последовательное сопротивление (R AIN ) между источником и контактом вызывает падение напряжения на нем из-за ток течет в штырь. Зарядка внутреннего конденсатора выборки (C ADC ) управляется переключателями с сопротивлением R АЦП . С добавлением сопротивления источника (с R ADC ) время, необходимое для полной зарядки конденсатора хранения, увеличивается.
Если время выборки меньше, чем время, необходимое для полной зарядки C ADC через R ADC + R AIN (ts < tc), цифровое значение, преобразованное АЦП, меньше фактического значения.
Эту ошибку можно уменьшить или полностью устранить, установив время выборки аналогового канала таким образом, чтобы гарантировать наличие соответствующего уровня напряжения на входном контакте до того, как АЦП начнет преобразование.
2.5 – Емкость источника аналогового сигнала и паразиты
При преобразовании аналоговых сигналов необходимо учитывать емкость источника и паразитную емкость на контакте аналогового входа. Сопротивление и емкость источника образуют RC-цепочку. Кроме того, результаты преобразования АЦП могут быть неточными, если внешний конденсатор (C AIN + C p ) не будет полностью заряжен до уровня входного напряжения.
Большее значение (C AIN + C p ), тем более ограничена частота источника. Внешняя емкость в истоке и паразитная емкость обозначаются C AIN и C p соответственно.
2.6 – Влияние тока инжекции
Отрицательный ток инжекции на любой аналоговый контакт (или близко расположенный цифровой входной контакт) может вызвать ток утечки на вход АЦП. В худшем случае это соседний аналоговый канал. Отрицательный ток инжекции вводится, когда V AIN < V SS , вызывая протекание тока с контакта ввода/вывода. Что потенциально может сместить уровень напряжения на выводе и исказить результат измерения.
2.7 – Перекрестные связи выводов ввода/вывода
Переключение вводов/выводов может вызвать некоторый шум на аналоговом входе АЦП из-за емкостной связи между вводами/выводами. Перекрёстные помехи могут быть вызваны дорожками печатной платы, которые проходят близко друг к другу или пересекаются друг с другом.
Внутреннее переключение цифровых сигналов и входов/выходов создает высокочастотный шум. Переключение входов/выходов с высоким потреблением может вызвать некоторые провалы напряжения в источнике питания, вызванные скачками тока. Цифровая дорожка, пересекающая аналоговую входную дорожку на печатной плате, может повлиять на аналоговый сигнал.
2.8 – Шум, вызванный электромагнитными помехами
Электромагнитные излучения от соседних цепей могут вносить высокочастотный шум в аналоговый сигнал, поскольку дорожки печатной платы могут действовать как антенна. Это называется шумом электромагнитных помех (EMI).
В следующих нескольких руководствах мы попрактикуемся с периферийным устройством ADC и проведем несколько практических лабораторных работ, чтобы научиться выполнять определенные задачи и программировать ADC. по-разному. Примеры приложений ADC будут включать следующее:
1
2
Вы нашли это полезным? Если да, рассмотрите возможность поддержки этой работы и публикации этих руководств!
Следите за выходом новых руководств и не забывайте ДЕЛИТЬСЯ ими. И подумайте о ПОДДЕРЖКЕ этой работы, чтобы продолжать публиковать бесплатный контент!
ADC -> DSP -> DAC Пример
Автор Росс Волин — последнее обновление 19 января 2014 г.
Этот проект создает цепочку, которая:
Среда сборки: Этот проект был построен на Ubuntu Linux 12. 04 LTS, скомпилирован с помощью GNU Tools для встроенных процессоров ARM 4.8-2013q4 и запрограммирован в STM32F4 Discovery Kit с использованием фиксации 2014.01.18 STLINK. Если вам нужно установить и настроить цепочку инструментов, обратитесь к моему предыдущему сообщению в блоге: STM32 Discovery Development on Linux
Файлы проекта размещены на Github, вы можете клонировать репозиторий с помощью:
cd ~ git-клон https://github.com/rowol/adc_dsp_dac
Исходный код примера ADC_DSP_DAC теперь находится в ~/adc_dsp_dac/project
Я также включил исходный код библиотеки STM, необходимый для сборки проекта, в каталог ~/adc_dsp_dac/STM32F4-Discovery_FW_V1.1.0. Если вам нужна полная библиотека STM, утилита и исходный код примеров, загрузите их с веб-сайта STM 9.0639
Если вы не хотите клонировать репозиторий с помощью Git, вы также можете восстановить проект как zip-файл.
Создание кода путем запуска:
делать
Запрограммируйте STM32F4 Discovery с помощью STLINK, выполнив:
сжечь
STM32F4 может делать с АЦП всевозможные причудливые вещи, например, заставлять АЦП работать непрерывно и сохранять результаты с помощью DMA, генерировать прерывание по завершении преобразования и т. д. В нашем реальном времени Приложение DSP мы хотели бы обрабатывать каждый образец АЦП, когда он доступен, поэтому мы отключаем непрерывные преобразования АЦП, DMA и прерывания и запускаем АЦП в однократном режиме.
В функции adc.c::ADC_init() канал 15 ADC1 настроен на однократный режим с отключенными функциями прямого доступа к памяти и прерываний. ADC выполняет преобразование, когда вы сообщаете ему об этом, вызывая ADC_SoftwareStartConv() , и устанавливает флаг, который вы можете отслеживать с помощью ADC_GetSoftwareStartConvStatus() , чтобы определить, когда преобразование завершено.
Я запускаю АЦП с тактовой частотой, разделенной на 8, чтобы уменьшить тактовую частоту 84 МГц APB2 до 10,5 МГц, чтобы она попала в диапазон 600–30 МГц, разрешенный для тактовой частоты АЦП в таблице данных STM32F4. Я также установил время выборки (как долго АЦП «измеряет/усредняет» сигнал перед началом преобразования) на 144 цикла. Предполагая, что АЦП занимает около 16 циклов для преобразования, это означает, что выборка + преобразование займет около 160 циклов или 15,2 мкс с нашим тактовым сигналом АЦП 10,5 МГц. Частота дискретизации 44 кГц, генерируемая нашим прерыванием по таймеру, дает нам 22,7 мкс между выборками, поэтому у нас достаточно времени для завершения преобразования АЦП между каждой выборкой. Частота дискретизации 44 кГц была выбрана потому, что теорема семплирования Найгуиста-Шеннона утверждает, что вы хотите сэмплировать на удвоенной максимальной частоте входного сигнала: аудио компакт-диски сэмплируются примерно на частоте 44 кГц.
DAC2 также настроен с отключенным DMA. Когда вы записываете в ЦАП с помощью dac.c::DAC2_set() , значение DAC2 изменяется с помощью библиотечной функции DAC_SetChannel2Data() .
В модуле tmr_sample функция tmr_sample::tmr_sample_init() настраивает базовый таймер TIM6 для генерации прерываний с частотой 44 кГц, что означает, что main::TIM6_DAC_IRQHandler() вызывается приблизительно каждые 22,7 мкс. Этот обработчик IRQ делает несколько вещей:
В моем примере простой цифровой фильтр представляет собой режекторный фильтр с центром пика на частоте 880 Гц. На графике показан отклик от 0 Гц до 5500 Гц с единичным усилением на вершине пика. Я разработал этот фильтр с помощью FIVIEW, используя команду «fiview 44000 -i BpRe/50/880»
Сводка контактов ввода-вывода
Подключив перемычкой PC.4 к PC.5, вы можете подать прямоугольный сигнал 880 Гц на АЦП, через цифровой фильтр, на выход ЦАП и наблюдать за результатами с помощью осциллографа. на PA.5. Прямоугольные волны состоят из последовательности синусоидальных волн основной частоты и нечетных гармоник: пропускание прямоугольной волны через хороший режекторный фильтр с центром вокруг основной частоты даст синусоидальную волну.
Эти события происходят в нашем проекте с перемычкой ПК.4 на ПК.5: