Продолжаем серию об основах STM32MXCube и программировании микроконтроллеров STM32.
→ Часть 1
→ Часть 2
В предыдущих частях мы освоили основные настройки микроконтроллера, работающего с GPIO, таймером, DMA и ЦАП.
В этой части мы познакомимся с АЦП и USB.
Краткое введение в третью часть
Сначала хочу сказать, что в этой части я буду использовать макетную плату NUCLEO-F767ZI. Эта плата более доступна, чем STM32F746G Discovery, использует микроконтроллер в корпусе LQFP144, а не BGA, а сама плата более удобна для встраивания в различные DIY-проекты.Он имеет Ethernet и USB, а также отладчик JTAG. Недостатком платы является отсутствие ЖК-дисплея, но он нам пока не нужен.
Хотя на плате другой микроконтроллер, все проекты из предыдущих частей перенесены на него практически без изменений (нужно только поменять номера выводов).
Также следует отметить, что на этой плате микроконтроллер тактируется источником 8 МГц.
Кварц для тактирования микроконтроллера предусмотрен в схеме, но не припаян; сигнал 8 МГц берется из отладчика JTAG. Если в вашем проекте используется интерфейс USB, то желательно включить тактирование от HSE, а не от внутреннего RC-генератора, так как RC-генератор не обладает достаточной точностью и стабильностью частоты.
При попытке включить RC-генератор, если в проекте есть USB, STM32CubeMX выдаст предупреждение и предложит переключиться на HSE (то есть на внешний высокостабильный источник тактовой частоты).
Для того, чтобы использовать внешний источник синхронизации (8 МГц) на вкладке PinOut, следует включить HCE в пункте RCC и выбрать пункт BYPASS Clock Source. На практике USB-интерфейс все равно работает, даже с пульта, но лучше не рисковать.
Я перенес проекты из предыдущих частей на эту доску и загрузил их на github .
В комментариях к предыдущим частям были вопросы по поводу IDE. STM32CubeMX позволяет автоматически создавать проекты для различных IDE: IAR (EWARM), MDK ARM v4, MDK ARM v5, Atollic TRUEStudio, SW4STM32 и др.
Я использую Atollic TRUEStudio, который доступен для скачивания с официального сайта бесплатно.
Также я проверил материал из предыдущих частей и внес ряд поправок.
я хочу поблагодарить Шамрель за ценные комментарии к предыдущей части.
USB-ВКП
Одним из самых простых режимов работы USB является VCP — режим виртуального COM-порта.Настройка работы с ним потребует от вас минимальных усилий.
В STM32CubeMX на вкладке Pinout найдите раздел USB_OTG_FS и установите Mode=Device_Only:
В разделе USB_DEVICE установите для параметра «Класс для FS IP» режим CDC VCP (класс виртуального Com-порта коммуникационного устройства):
Теперь нужно настроить конфигурацию часов так, чтобы частота USB составляла 48 МГц:
Переходим далее на вкладку Configuration и отключаем параметр VBUS Sensing:
Генерируем код и открываем проект в IDE.
Найдите файл usbd_cdc_if.c и вставьте в него следующее:
Иstatic int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); CDC_Transmit_FS(Buf, *Len); USBD_CDC_ReceivePacket(&hUsbDeviceFS); return (USBD_OK); /* USER CODE END 6 */ }
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
/* USER CODE END 7 */
return result;
}
Здесь реализован режим эха: все, что приходит в порт, тут же отправляется обратно.
Компилируем и прошиваем микроконтроллер.
Затем подключаем разъем User USB платы к компьютеру.
Система должна обнаружить новый COM-порт. Для Linux: проверьте ls /dev/tty*, появится устройство /dev/ttyACM0. Проверяем, и здесь нас ждет еще один сюрприз: доступ запрещен.
Вам необходимо добавить себя в группу дозвона: sudo adduser user dialout
(где пользователь — ваше имя пользователя)
Для работы с устройством в Windows вам потребуется скачать и установить Водитель .
Для работы в OS X и Linux не требуется специальный драйвер.
Запускаем (например) Putty, настраиваем параметры порта.
Они должны соответствовать параметрам, указанным в свойствах порта (см.
«Диспетчер устройств/порты»).
Попробуем открыть порт в Putty и отправить что-нибудь в порт:
Если порт не открывается, можно попробовать выйти из режима отладки в IDE и перезагрузить плату.
Все должно работать.
Дополнение от дизайнерSTM :
как бороться с кодом ошибки 10 виртуального порта? Помогает поставить в файле usbd_cdc.h 256 вместо 512 в строке: #define CDC_DATA_HS_MAX_PACKET_SIZE (512 были) 256 /* Размер пакета конечной точки IN и OUT */Как мы убедились, работать с USB в режиме виртуального COM-порта очень просто.
Единственным недостатком этого режима является очень низкая скорость передачи данных.
Интерфейс USB в режиме Full Speed обеспечивает скорость до 12 Мбит/с, в режиме High Speed — до 480 Мбит/с, но VCP ограничивает скорость жалкими 128 Кбит/с.
Можно сделать высокую скорость передачи данных, но пока отложим это до следующего раза.
АЦП
Теперь попробуем запустить АЦП, получить от него значения и отправить на компьютер, реализовав очень простой (и очень медленный) «осциллограф».Чтобы было интереснее, мы будем подавать на АЦП синусоидальный сигнал, генерируемый ЦАП.
Поскольку в прошлой части мы это уже делали, я просто скопирую код в новый проект (с небольшими изменениями, не имеющими большого значения).
Сначала немного о встроенном в микроконтроллер АЦП.
Микроконтроллер STM32F767ZI имеет три 12-разрядных АЦП типа SAR (последовательное приближение) с производительностью до 2 MSPS (миллионов выборок в секунду).
Этот тип АЦП имеет высокую скорость преобразования, но меньшую точность, чем сигма-дельта АЦП.
Вход опорного напряжения VREF подключен к VDDA и через индуктивность к VDD. Таким образом, опорное напряжение в нашем случае составляет 3,3В.
Особенностью АЦП SAR является использование схемы выборки и хранения с конденсатором на входе.
В момент дискретизации значения сигнала конденсатор подключается ко входу и заряжается до значения входного сигнала.
Если источник сигнала будет иметь слишком большое внутреннее сопротивление, конденсатор не успеет зарядиться полностью, и мы получим заниженное значение.
Этот и другие аспекты использования АЦП описаны в [1].
АЦП этого микроконтроллера имеет множество режимов работы [2], мы рассмотрим только один из них.
Попробуем одновременно получить два значения сигнала от двух АЦП, строго синхронно, и записать их в буфер по DMA. Итак, создадим новый проект, добавим в него готовый код для формирования синусоидального сигнала на ЦАП и для USB VCP (через который мы будем отправлять данные на компьютер).
Далее (проводами) подключаем выход ЦАП ко входам АЦП1 и АЦП2. Чтобы как-то различать сигналы на аналоговых входах, я подключил АЦП1 к ЦАП напрямую, а АЦП2 через делитель напряжения на переменном резисторе, чтобы можно было изменять амплитуду сигнала.
Остерегайтесь аналоговых схем! Если вы подаете на вход АЦП сигнал от внешнего источника, то следует помнить, что сигнал на любом входе микроконтроллера должен быть ограничен значениями 0 – Vcc, что в большинстве практических случаев приводит к необходимости смещения и усилить (или ослабить) сигнал.
Также следует учитывать, что в микроконтроллерах STM32 используются АЦП последовательного приближения (SAR), которые потребляют достаточно большой ток от источника сигнала в момент измерения и требуют источника сигнала с низким импедансом.
Рис.
1. Схема выборки-хранения АЦП SAR (не из STM32, но полностью аналогичная) В моменты дискретизации сигнала конденсаторы (рис.
1) подключаются ко входу АЦП и должны зарядиться до полного уровня сигнала за очень короткое время, потребляя при этом значительный ток.
Если источник сигнала будет иметь высокое сопротивление, они не успеют зарядиться, и показания АЦП будут неверными.
На практике это означает, что в большинстве случаев мы должны использовать внешний буферный усилитель.
Поскольку сегодня речь пойдет о программных аспектах проблемы, то можно обойтись и без усилителя, но следует помнить, что без усилителя показания АЦП будут существенно искажаться, а в реальных проектах он необходим.
Рис.
2. Схема выборки и хранения вызывает провалы уровня сигнала на входе АЦП.
К сожалению, эти вопросы слабо освещены в документации STM32, но я могу порекомендовать руководство [3].
Если читателям интересно, я могу рассмотреть базовые схемы интерфейсов аналоговых сигналов с АЦП в следующей статье.
В нашем проекте нам понадобятся два таймера.
Один из них будет устанавливать период работы ЦАП, второй – АЦП.
Настроим аналого-цифровой преобразователь для работы в двухканальном режиме с одновременной дискретизацией.
Выборка будет происходить по таймеру TIM2. Полученные значения будут добавлены в буфер с помощью DMA. Мы будем использовать однократный режим работы DMA (есть еще циклический режим, с которым мы уже познакомились при изучении ЦАП).
После того, как буфер заполнится значениями от АЦП, копируем его содержимое в другой буфер (с некоторой обработкой), переносим по USB и запускаем процесс заново.
Также для отладки и индикации режима работы мы используем два порта GPIO, к которым подключены светодиоды.
Итак, мы создали проект, в который добавили ЦАП и таймер TIM1. Нам также необходимо добавить АЦП1 (вход IN9), АЦП2 (вход IN12) и таймер TIM2. Еще нам понадобится USB_OTG_FS.
Настраиваем АЦП1 для работы в режиме одновременной выборки, запускаемом таймером 2:
ADC2 настраивается автоматически:
Настройка DMA:
Обратите внимание, что размер передаваемых данных — Word, а не Half Word, т.к.
данные от двух АЦП передаются одновременно, упакованные в 32-битное слово.
Настройка таймера TIM2:
Настраиваем USB так же, как уже делали.
Давайте сгенерируем код. Я не буду здесь описывать весь исходный код проекта, остановлюсь лишь на ключевых моментах.
Запускаем цепочку таймер-АЦП-DMA: //start adc
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)adc_buf, ADC_BUF_SIZE);
HAL_TIM_Base_Start_IT(&htim2);
Обработчик прерываний: void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
Теги: #stm32 #микроконтроллеры #Программирование микроконтроллеров #таймер #прерывание #АЦП #ЦАП #АЦП #DAC #Программирование микроконтроллеров
-
Особенности Мышления И Звуковосприятия
19 Oct, 24 -
Мой Алгоритм Шифрования
19 Oct, 24 -
Несколько Вопросов О .Net И C#
19 Oct, 24