Устройства на stm32 своими руками

Добавил пользователь Евгений Кузнецов
Обновлено: 04.10.2024

Решил написать книгу …
… про реальную разработку устройств на stm32. Поэтому думаю обновления если и будут, то нерегулярным и в основном в виде кусочков из книги.
Что бы не было скучно, вот вам малюсенький кусочек, можно сказать бета-версия про кварцевые резонаторы и вообще частоты.

Сами по себе микроконтроллеры работать не умеют. Им нужны всякие сопутствующие элементы. Вот к примеру, STM32L05 умеет работать с USB без всяких внешних кварцевых резонаторов, а STM32L152 — нет. Если мы планируем использовать более-менее точное время в наших проектах, то нам жизненно необходим внешний часовой кварцевый резонатор. Без него уход времени на 5-10 минут в сутки станет совершенно нормальным. И более того, он будет не постоянным и зависеть от температуры, напряжения питания и кучи других вещей.

В общем, время брать и читать описание микроконтроллера. Что ему надо, когда надо и зачем. Описание (или даташит как калька с datasheet) ищется легко прямо в интернете по коду микроконтроллера.

Но просто так читать даташиты смысла особого нет, ибо ничего в голове не откладывается. Я обычно начинаю рисовать схему, консультируясь с даташитами на предмет уровней и прочего, а с кубом — на предмет возможного назначения ножек и вообще конфигурации кристалла. Кстати о конфигурации.

Клоки, тайминги и шины

Одна из самых распространенных причин неработоспособности чего-либо — неправильная конфигурация частот и всего, что с этим связано. Наступило время раскрытия еще одной вкладки в кубе — Clock configuration. Я открыл новый проект, взял выбранный микроконтроллер, и включил rtc, usb и пару uart. Просто для примера. Открываем вкладку и видим примерно следующее

Давайте начнем слева. У stm32 могут быть источники тактовых сигналов высокой (HS) и низкой (LS) частоты. Они могут быть внутренними (I) или внешними (E). Те, что сейчас в работе — подсвечиваются синим. Например, сейчас используется два источника — на 37 килогерц и на 16 мегагерц.

Ок, идем на первую вкладку и около RCC видим такую картину

Аббревиатура ppm означает parts per million или количество миллионных частей от основной частоты. Говоря иначе, погрешность 100 ppm для 100 МГц означает уход частоты на 100/1000000 часть от 100 МГц. Таким образом, частота может уйти на 100000000 * 100 / 1000000 = 10000 Гц (10 кГц, или 0.01 МГц), то есть финальная частота может быть любой в диапазоне 99.99 . 100.01 МГц. Или говоря другими словами чем меньше ppm, тем лучше. Итак, смотрим в даташит и находим следующую табличку

Нашли? А теперь смотрим уже в даташит на кварцевый резонатор и ищем там параметр нагрузочная емкость. А потом снова в даташит, но уже процессора.

Если кратко, то там есть следующая схема

и вот такая вот сложная формула

Cs — это паразитная емкость на плате. Обычно берут в диапазоне 3-5pF.
СL — это берем из даташита на резонатор. У меня 16

Воспользовавшись знаниями математики за 5 класс среднеобразовательной школы (хотя могу и ошибаться), решим это сложнейшее уравнение:
16 = (Х*X)/(X+X)+3
16-3=X*X/2*X
13=X/2
X=26
Итак, ответ ответ – конденсаторы CL1/2 должны быть 26pf. Таких в природе нет, зато есть 27pF, что нам более чем подходит.
Теперь надо подсчитать, запустится ли генератор. Там чуть дальше есть формула

Считаем
G=4*60*(2*3.14*(8*(10^6))^2*((7+16)*10^(-12))^2)
Возведение в степень я обозначил как ^, её же использует и excel.
Запутаться очень легко, поэтому я сделал простую считалку в excel (файл называется resonator)

Как видим, везде все стало хорошо и микроконтроллер будет работать на максимальной для него частоте — 32 мегагерца.

А проверить?

Но вот гложет меня, правильно ли я подсчитал все. Надо провериться. Достаю описание на stm32l-discovery и открываю там схему. Нахожу часть с резонатором

Как видим, около резонатора стоят конденсаторы по 20pF. Как видно, инженеры из ST решили перестраховаться и взяли паразитную емкость платы в 5pF. Если взглянуть на плату, то вроде да, кварцевый резонатор довольно (относительно конечно) далеко от ножек. На некоторых платах он часто его чуть ли не на ножки кладут. Но в общем и целом надо будет учесть этот момент в дальнейшем.

Примеры постоянно дополняются и корректируются. Иногда не синхронно с выходом новых статей о STM32.

Крайняя редакция: 15.02.2017

Перечень проектов

Example_First_Programm - GPIO. Первая программа. Мигание светодиодом

Example_GPIO - GPIO. Пример работы с входами и выходами

Example_StepMotor - GPIO. Пример работы с шаговым двигателем 28BYJ-48

Example_Nokia5110 - GPIO. Remap. Пример работы с выходами

Example_WG12864A - GPIO. Пример работы с LCD дисплеем WG12864A (KS0108/KS0107)

Example_ADC - ADC. Простой пример работы с АЦП

Example_ADC_DMA - ADC. Работа с АЦП с использованием DMA

Example_ADC_Injected - ADC. Работа с АЦП с настройкой Injected каналов

Example_ADC_Temperature - ADC. Использование встроенного термометра

Example_ADC_Watchdog - ADC. Аналоговый Watchdog

Example_Sonar - EXTI. Пример работы с сонаром HC-SR04

Example_USART1 - USART. Пример простого терминала

Example_USART_DMA - USART. Отправка данных через последовательный порт с помощью DMA

Example_DFPlayerMini - USART. Пример работы с MP3 плеером DFPlayer Mini. Функция произнесения числа

Example_SysTick - Таймер. Системный таймер SysTick. Задержка на SysTick

Example_TIM_CLK - Таймер. Генерирование прерывания через равные промежутки времени

Example_TIM_Time - Таймер. Измерение времени между двумя событиями

Example_PPM - Таймер. Захват сигнала

Example_Encoder - Таймер. Работа с энкодером

Example_Encoder_IT - Таймер. Работа с энкодером

Example_PWM_LED - Таймер. PWM. Управление яркостью светодиода

Example_PWM_RGB - Таймер. PWM. Управление цветом RGB светодиода

Example_PWM_Servo - Таймер. PWM. Управление сервоприводом

Example_PWM_Sound - Таймер. PWM. Генерирование звука

Example_RTC - RTC. Пример работы с часами реального времени

Example_BKP - BKP. Пример работы с регистрами Backup registers

Example_FLASH - FLASH. Пример сохранения настроек во FLASH память

Example_Watchdog - Watchdogs. Пример использование IWDG и WWDG

Example_I2C_Master - I 2 C. Работа с шиной I 2 C на примере датчика атмосферного давления BMP280

Example_I2C_Slave - I 2 C. Работа с шиной I 2 C в качестве Slave устройства

Example_BMP280 - I 2 C. Пример работы с датчиком атмосферного давления BMP280

Example_MS5611 - I 2 C. Пример работы с датчиком атмосферного давление MS5611

Example_USB_Virtual_Com_Port - USB. Пример работы с USB. Виртуальный последовательный порт

Example_USB_Keyboard - USB. Пример работы с USB. Эмуляция клавиатуры и мышки

Example_USB_Mass_Storage - USB. Пример работы с USB. STM32F103 в качестве Mass Storage Device

Example_PWR_Sleep - PWR. Использование энергосберегающего режима SLEEP

Example_PWR_Stop - PWR. Использование энергосберегающего режима STOP

Example_PWR_Standby - PWR. Энергосберегающий режим Standby. Пробуждение от Wake Up Pin

Example_PWR_Standby_RTC - PWR. Энергосберегающий режим Standby. Пробуждение от RTC

Example_Bootloader - Bootloader. Пример собственного загрузчика

Example_BLDC - Управление бесколлекторным двигателем с датчиками Холла (Sensored Brushless)

Example_PMSM - Управление PMSM с датчиками Холла с помощью STM32

Спасибо! Здесь все описано в доступной форме. Я надеюсь, что будет примером для управления бездатчиковом BLDC с этим STM32, как это было sdelano с ATmega168.

У меня есть пару-тройку полезные статии на интересные разработки для управления бездатчиковом BLDC, я даю та, которая обещают closed loop после 3-4 оборотов в минуту. A ето уже интересно. Применили опер. усилитель, точка 10.2.1, документ: ST AN1946 "SENSORLESS BLDC MOTOR CONTROL AND BEMF SAMPLING METHODS WITH ST7MC".
Извините мой gTranslate русскии, а украинский я вовсе не понимаю.


Эта статья в некотором роде продолжение предыдущей статьи, связанной с инерциальными системами отсчета, но на этот раз речь пойдет о том, как собрать и заставить работать навигатор, используя микроконтроллер и набор недорогих датчиков. Законный вопрос — нафиг он нужен, если почти в каждом телефоне есть необходимый набор датчиков и приложений типа “компас”?

  1. Весьма неочевидное управление. В некоторых приложениях я так и не понял, как заставить стрелку показывать в нужном мне направлении. Показывать на север — сколько угодно. Как задать другую точку назначения — почти всегда проблема.
  2. Часть приложений начинает показывать на юг, а не на север, если перевернуть телефон.
  3. Мой смартфон работает без подзарядки дня 3, не больше. Некоторые работают вообще 1 день. Маловато, честно говоря.

Есть разные аналоги подобного устройства — GPS-возвращатели для грибников, путешественников и т.п. Если бы не было требования получать направление из любого положения устройства в пространстве — можно было бы существенно упростить конструкцию, а то и просто порекомендовать один из таких девайсов. Но одной из ключевых особенностей является возможность показывать направление из любого положения в пространстве.

Постановка задачи

Итак, необходимо с нуля собрать устройство, которое будет:

  1. Показывать направление из текущей точки и ориентации в пространстве в сторону заранее определенной координаты (например мой дом или местная достопримечательность).
  2. Иметь простой интерфейс и малые размеры.
  3. Питаться от батарейки и работать в автономном режиме без подзарядки не меньше месяца.
  4. Рассчитано на “эконом” сектор рынка.

В ходе обсуждения деталей подумали, что было бы неплохо, если бы устройство также показывало текущую дату и время, уровень заряда и имело на борту будильник. Дополнительно добавили bootloader для того чтобы облегчить обновление прошивки и замену целевых координат по USB и возможность работы от аккумулятора с контроллером зарядки/разрядки.

И всё же самыми главными требованиями оставались миниатюрность, экономичность и точность навигации.

Определение азимута

Для того, чтобы показать направление куда-то, нужно знать всего 2 вещи — где мы, собственно, находимся и ориентацию в пространстве. Зная текущую координату можно получить азимут, решая обратную геодезическую задачу.


Геодезическая задача связана с определением взаимного положения точек земной поверхности и подразделяется на прямую и обратную задачу. Прямой геодезической задачей называют вычисление геодезических координат — широты и долготы некоторой точки, лежащей на земном эллипсоиде, по координатам другой точки и по длине и азимуту геодезической линии, соединяющей эти точки. Обратная задача заключается в определении по геодезическим координатам двух точек на земном эллипсоиде длины и азимута геодезической линии между этими точками. В зависимости от длины геодезической линии, соединяющей рассматриваемые точки, применяются различные методы и формулы, разработанные в геодезии. По размерам принятого земного эллипсоида составляются таблицы, облегчающие решение геодезической задачи и рассчитанные на использование определённой системы формул.

Определение текущей ориентации

Для определения текущей ориентации использовали фильтр Маджвика — ПО с открытым исходным кодом, рассчитанное, в первую очередь, на низкую вычислительную мощность целевой системы. В качестве входных данных он использует показания акселерометра, гироскопа и магнитометра. На выходе получается кватернион, описывающий положение устройства в пространстве. Для лучшего понимания работы кватерниона рекомендую этот ресурс. Фильтр работает действительно быстро — на моём контроллере с тактовой частотой 24МГц он успевает сработать 360 раз в секунду, с учетом того, что еще тратится время на получение данных от датчиков. Фильтр почти не тратит ресурсы (в документации утверждается, что используется 160 операций сложения, 172 умножения, 5 делений и 5 извлечений квадратного корня) и имеет всего 2 параметра: частота опроса датчиков и коэффициент усиления. Можно модифицировать функцию и использовать не частоту получения данных, а подсчитывать разницу времени между двумя порциями измерений. Это улучшает показатели фильтра. Коэффициент усиления нужно подбирать в поисках компромисса между скоростью стабилизации и точностью.

Куда должна показывать стрелка?

Зная азимут и текущее положение устройства в пространстве, можно определить угол, на который надо повернуть стрелку, чтобы она указывала в нужном направлении. В этой реализации используются сразу 2 угла : dX и dY (соответственно угол, на который надо повернуть ось X и Y). Два угла нужны, если одна из осей вдруг совпадет с осью Z. В этом случае просто используется второй угол.


Так выглядит нормальный режим работы, когда устройство показывает туда, куда нужно, т.е. угол dX = О.

Наверняка есть более простые и аккуратные способы вычисления угла dX. Если у вас есть предложения, как это улучшить, пожалуйста, отпишите в комментариях.

Итак, у нас есть кватернион, описывающий текущее положение устройства в глобальной системе координат и азимут. Кватернион текущего положения обозначим через qCurrent. Возьмем проекцию единичного вектора на ось X и обозначим её через iX. Повернув iX кватернионом qCurrent, получаем вектор srcX. Если же повернуть iX на величину азимута, то получим вектор dstX. Разницу между этими векторами и нужно отобразить на дисплее. Для определения угла между этими векторами используется скалярное произведение векторов:


Для определения знака угла использовал векторное произведение векторов, точнее знак определителя.


Собственно на этом вся математика в проекте заканчивается :). У нас есть угол, на который нужно повернуть стрелку дисплея, чтоб она указывала в нужном направлении. При этом если dX будет равен 0, то компонент рысканье (можно вычислить из текущего кватерниона) текущего кватерниона будет равен найденному азимуту.

Используемые компоненты

В качестве контроллера решили использовать ARM по многим причинам. Основная — экономичность. Они дешевые, 32 битные, имеют гибкие настройки энергопотребления и т.п. Выбор пал на stm32f100rbt6 (180 рублей). Отладочная плата именно этой модели была у меня в наличии сразу, контроллер по характеристикам вполне подходил. Конечно жаль, что на нем нет аппаратного USB. С ним было бы ещё проще сделать bootloader. Да и по потреблению тока есть модели поинтересней. Но в сравнении с тем сколько потребляет GPS разница не очень заметна :). Остальные компоненты подбирались по мере доступности в нашем городе. Изначальный сет модулей выглядел так:

  1. Микроконтроллер stm32f100rbt6
  2. LCD дисплей Nokia 5110
  3. Акселерометр + гироскоп MPU6050
  4. GPS приемник Neo-6m
  5. Магнитометр LIS3MDL

В конечном варианте пришлось заменить магнитометр на QMC5883L. Связано это с тем, что все магнитометры LIS3MDL у меня сгорели. Не знаю, как по-другому назвать это явление. Один из модулей сразу перестал отзываться по I2C шине, 2 других выдают рандомные данные. Использовались эти магнитометры в виде модулей от российского производителя, которого я не буду называть. Но, судя по всему, эти модули можно использовать только с контроллерами, которые работают от 5В, но не от 3.3В. В документации, конечно, сказано, что можно использовать и так и так, но на деле ничего не получилось.

С QMC5883L тоже дружба завязалась не сразу. Дело в том, что я заказал магнитометры HMC5883L. Когда стал запрашивать данные по адресу 0x1E — получал ошибку, что устройства с таким адресом на шине нет. Быстренько собрав сканер I2C я убедился, что какое-то устройство имеет адрес 0x0d. Оказалось, что корпусы похожи и часто QMC принимают за HMC. Если вдруг кто-то удивляется, почему его HMC не отвечает — имейте в виду.

GPS используется всего для 2х вещей:

  1. Коррекция времени, если разница со значением в RTC (встроенные часы реального времени) больше, чем 5 секунд.
  2. Коррекция своего положения и азимута.

В финальной версии прошивки GPS приемник будет включаться только по запросу в целях экономии батарейки.

Скорее всего заменим дисплей на какой-нибудь OLED и улучшим подсветку.

Аппаратная часть

Сразу скажу, что разводка печатной платы в Kicad выглядит значительно лучше. Здесь схема приведена в чисто ознакомительных целях.

В конечном итоге получилось следующее:

  1. Контроллер общается с дисплеем по SPI.
  2. Магнитометр, гироскоп и акселерометр висят на шине I2C1.
  3. GPS модуль NEO-6M посылает данные по USART3.

Каждый из компонентов подключен через транзистор, что дает мне возможность включать/выключать устройства по мере надобности. Можно было бы магнитометр и гироскоп запитать от ног контроллера, но ток 5мА показался мне великоватым. В документации говорится, что IO выводы могут выдержать до 20мА, но на деле контроллер иногда просто перезагружался. Решилось дело хорошим стабилизатором и правильной разводкой питания, так что транзисторы для магнитометра и гироскопа остались просто как исторический элемент.

Что не так с I2C в stm32f100x?

Как я писал выше, магнитометр, гироскоп и акселерометр общаются с контроллером по шине I2C.

I2С гарантирует неплохую скорость работы при относительной простоте разработки. Есть 2 режима:

• Обычный режим — до 100КГц
• Быстрый режим — до 400КГц

I2С использует две линии, которые подтянуты к напряжению питания. Одна линия — линия данных, другая — линия тактирования. В интернете очень много подробных спецификаций и описания того, что это за шина и как она работает, поэтому сразу перейдем к особенностям реализации в контроллерах stm32f100x

Основные характеристики шины:

Каждое устройство может выступать как в роли Master, так и Slave.

В режиме Master реализуется:

  • Генерация тактового сигнала
  • Генерация старт-сигнала и стоп-сигнала

В режиме Slave реализуется:

  • Механизм подтверждения адреса
  • Использование двух Slave адресов
  • Обнаружение стоп-бита, выданного ведущим на линию
  • Генерация и определение 7/10 битных адресов
  • Поддержка разных скоростей передачи данных
  • Наличие множества флагов, сигнализирующих о событиях, а также об ошибках на линии

Возможна работа в одном из следующих режимов:

По умолчанию установлен режим slave, но как только устройство генерирует старт-бит оно сразу же превращается из подчиненного в ведущего.

В нашем случае используются только 2 режима: master приемник и master передатчик. Причем как передатчик наш контроллер используется только для инициализации и настройки модулей.

Схема автономного ЧПУ контроллера на базе STM32 собрать своими руками.

Стоимость готового контроллера 19 500 руб .

ВНИМАНИЕ.
Ниже информация для САМОСТОЯТЕЛЬНОЙ сборки контроллера.
для самодельщиков, т.е. людей которые хотят спаять контроллер самостоятельно.

Прошивка от 24.11.17 Armatura-ural.bin для самодельной платы, описанной ниже.
есть скрытое меню настройки станка, при загрузке нужно удержать THC ON ,
если при загрузке удержать THC ON и THC OFF будут загружены заводские настройки по умолчанию

Прошивка для заводской платы, купленной у меня. (разница в подключении периферии к микроконтроллеру. LCD , кнопки и выходы подключены к другим выводам МК в отличии от прошивки выше)
MyBootload.bin MyBootload.hex - автозагрузчик прошивки (для самопрограммирования)
Armatura-ural.bin - рабочая программа (от 3.09.18 поддержка отрицательных координат g -кодов)
Armatura-ural.bin - версия от 02.10.18
при изменении траектории движения менее 30 градусов не тормозит, т.е. можно рисовать мелкими отрезками контроллер их склеивает в одну кривую.
также есть два новых параметра настроек - z_plasma_on - высота включения плазмы/газа, можно сделать отличное от z_start - высоты начала движения, этот параметр введён в основном для аппаратов с контактным поджигом.
и thc_time - время измерения thc , по умолчанию нужно выставить 1000, что соответствует 0,1сек, т.е. 10 измерений ТНС за одну секунду, этот параметр введён для корректировки показаний ТНС программным способом.
ALL.bin или ALL.hex - всё в одном - автозагрузчик, программа и настройки. Лучше загружать его вместо бутлодыря, сначала установите эту прошивку как базовую, а затем обновляете..
Armatura-ural.bin - версия от 24.03.19г (постпроцессор Armatura-ural.cff )
Чтобы обновить прошивку, нужно этот файл сохранить на СДкарту, вставить в контроллер и нажать "Сброс"
ВНИМАНИЕ. перед обновлением сохраните настройки на бумажку, т.к. ранее я слишком много памяти отвёл для этих настроек, сейчас пришлось их подвинуть, и придётся их вводить заново.
Эта версия сделана для слишком-сильно-мощно-помехоизлучающих аппаратов. При больших помехах сам микроконтроллер работает стабильно, а периферия отваливается.
При чтении данных с флэшки она бывает "сбрасывается" и начинает выдавать данные сначала либо просто передаёт данные с ошибкой в цифре. Бывает, что после работы на плазме, вставляешь её в комп и он, падла, предлагает её форматировать. Повторю - это бывает не часто, т.е. не на всех аппаратах, я сталкивался с такими помехами только на аппаратах на 220В.
В данном варианте ПО, при нажатии на СТАРТ вся программа (если она менее 200кб, для сравнения - чтобы вырезать 100 квадратов любых размеров нужно менее 2кб) переписывается на внутреннюю память микроконтроллера, далее флэшку можно убирать, если G коды более 200кб то чтение производится как и ранее, с флэшки. Если что-либо есть в памяти, при нажатии на СТАРТ контроллер начинает выполнять эти инструкции, не смотря на наличии флэшки, чтобы очистить внутреннюю память нужно нажать УДАЛИТЬ. При первом нажатии на СТАРТ копируется программа, при втором - запускается.

Пример G -кода Untitled .cnc от ProNest и пример той же детали от SheetCam Untitled.cnc


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

Предлагаю сотрудничество - нужны люди для изготовления и самое главное для его сопровождения (консультаций).
Объясню - заказать изготовление клонов можно и в Китае, но их нужно подключить и настроить, также нужно настроить компьютер для работы с данным устройством (сохранение чертежей в определённом формате, перевод в G- коды). У каждого станка есть свои особенности, разные хотелки и убеждения их хозяев и т.д.
Кто может и хочет заняться изготовлением, модернизацией, ремонтом станков ЧПУ, роботов сварщиков и т.д. - пишите мне на электронку, интересуют все регионы СНГ и Ваши возможности (самостоятельная сборка контроллера ЧПУ (желательно, но не обязательно), программирование, контроллера (переделка кода под определённый станок и задачу), монтаж и ремонт у заказчика, консультации по телефону и др.)
Порядок работы - заказчик обращается ко мне, я даю контакты ближайшего грамотного специалиста, при необходимости высылаю контроллер (работа на дому - пайка и программирование для желающих), монтаж, пуско-наладка, последующие консультации, оплата.

Сразу оговорюсь - это мой первый проект с STM32 и с данным контроллером столкнулся впервые, т.ч. критика ПО СУЩЕСТВУ приветствуется.
На вопросы "у меня не открывается rutracker.org", "как купить на taobao.com", "дайте ссылку тоже самое но на aliexpress.com" не отвечаю и переписку прекращаю, т.к. если этот вопрос человек не может решить даже с помощью я ндекс/ google , то в изготовлении контроллера он далеко не продвинется и тратить на него время бессмысленно. (это касается самодельщиков, т.е. людей которые хотят спаять контроллер самостоятельно)

Сейчас я заказываю платы в Китае. Готовые платы из Китая дешевле чем у нас купить текстолит.



Стоимость набора для самостоятельной сборки 12 500 руб.
Стоимость только плат (основная + одна маленькая) 2 500руб.

Ниже я описал способ быстрого (я это делаю примерно за час), самостоятельного изготовления платы в домашних условиях.

Я делаю плату по ЛУТ технологии из одностороннего стеклотекстолита 1мм (1мм важно. )





























Схема автономного контроллера ЧПУ плазменной резки на микроконтроллере STM32
STM32F103RCT6 с контролем высоты THC по напряжению дуги плазмы

Эта схема для платы описанной выше

в формате Splan70 скачать схему

Преобразователь напряжение-частота с двойной гальванической развязкой (трансформатор и оптопара)

Схема для заводской платы (купленной у меня) как вот эта
(схема обновлена 16.06.18, если просматривали её ранее, то нажмите F5 )

в формате Splan70 скачать схему

Для начала загружаем Bootloader в контроллер пользуясь программой "Flash Loader Demo" и переходником UART например https://detail.tmall.com/item.htm?id=528794539661 или самодельным
Bootloader - это программа для самопрограммирования контроллера, при включении она открывает флэшку и если там есть файл "Armatura-ural.bin", то переписывает его в область программ и стирает с флэшки. Очень удобная вещь как для себя, так и для удалённой поддержки клиентов.
Процесс первой загрузки хорошо описан здесь http://easystm32.ru/useful-things/42-bootloader-stm32, затем все последующие перепрограммирования будет делать "бутлодырь".

Т.к. у нас начальную область памяти занимает bootloader , то нам надо настроить чтобы начало программы было после него.
Находим файл STM32F103RC.mlk у меня он C:\Users\Public\Documents\Mikroelektronika\mikroBasic PRO for ARM\Defs
и меняем ROM - MIN_ADDR - 0x00008000


при запуске надо отключить библиотеку USB


Если вы будете делать другой проект то вам пригодятся настройки тактирования ( рабочий пример)


После компиляции копируем файл "Armatura-ural.bin" на флэшку, вставляем в автономный контроллер ЧПУ и нажимаем ресет

Сразу пару комментариев:
1) С Алгоритмом Брезенхэма я не подружился . Н акопительная ошибка и разница в скоростях перехода на шаг по X и Y ( т.е. при разной длине шага X и Y нужно менять задержку)
2) В данных исходниках отсутствует меню настроек констант (т.е. настройки станка), если человек может скомпилировать программу, ему не сложно изменить константы в компиляторе.
Готовые прошивки будут выкладываться с более расширенными возможностями. Это сделано сознательно, для того чтобы этот контроллер не ушёл в китайскую серию в кратчайший срок.
3) Все прошивки полнофункциональные. Никаких демо-ограничений и т.п.

Прошивки буду выкладывать вверху страницы, для обновления нужно скопировать файл "Armatura-ural.bin" на флэшку, вставить в автономный контроллер ЧПУ и нажать ресет

Это первая моя программа (я не программист), т.ч. советы, комментарии, алгоритмы, идеи и многое другое приветствуется ))) пишите мне на электронку.


чертёж

N1 G21
N2 G53 G90 G40
N3
N4 S500
N5 G00X63.158Y94.018
N6 M03
N7 G04 P0.6
N8 G03X49.436Y90.597I58.007J85.446
N9 G03X49.436Y90.597I70.865J77.721
N10 G03X51.146Y83.736I53.722J88.022
N11 M05
N12 G00X110.912Y123.777
N13 M03
N14 G04 P0.6
N15 G01X113.332Y114.074
N16 G01X119.38Y89.817
N17 G03X149.685Y71.607I143.637J95.865
N18 G02X131.476Y41.302I155.733J47.35
N19 G02X82.961Y29.206I107.218J35.254
N20 G01X34.446Y17.11
N21 G01X10.254Y114.139
N22 G01X113.332Y114.074
N23 G01X118.332Y114.071
N24 M05
N25 M30

Ряд микроконтроллеров STM32 имеют на борту USB интерфейс для связи с компьютерами. Как правило, удобнее всего использовать предоставляемый компаний ST Microelectronics драйвер класса CDC (Communication Device Class ). Он позволяет использовать на стороне компьютера UART через USB и не требует установки драйверов. Со стороны STM32 при этом требуется только поменять операции вывода данных, остальное делается самостоятельно. Причём скорость такого соединения может быть практически любой, поддерживаемой компьютером.

Однако ряд разработок, особенно, когда приходишь в другую компанию, где используется HID Class (Human Interface Device), в случае разработки новой версии устройства требуется поддерживать ранее выбранный интерфейс. Что, собственно, и случилось. Примеры проектов от самой ST, которые они дают при загрузке STM32 Cube MX и IDE, как обычно, дали только минимальное понимание, но не раскрыли, что и как надо делать. Я когда-то разбирался с USB, даже писал собственный драйвер, но это было так давно… Остались только общие воспоминания. Посему пришлось искать дополнительную информацию, чтобы получить стартовую точку.

Первое найденное было видеороликом на youtube в стиле HID за 5 минут :-) Автор даёт доступ к своему коду на GitHub. Всё, типа круто, красиво, просто вставляйте к себе и всё будет чудесно. Судя по отзывам под роликом, некоторым этого хватило. Изучив исходники понял, что минимального прозрения не наступило, да и уровень полученной информации мал для того, чтобы решить поставленную задачу. Но закомство с этим материалом было явно полезным. Решение вопроса с использованием кубика (STM32Cube MX) мне лично импонирует больше, чем другие подходы, поскольку позволяет отвлечься от ряда низкоуровневых операций и генерация проекта всегда происходит в одном стиле. Соответственно, изучение этого примера показало, на какие файлы надо обратить внимание, где и что надо поменять или добавить, какие функции использовать для получения и отправки данных именно для нашей выбранной среды программирования.

Следующий поиск оказался весьма удачным. Хабр — известный сайт, на котором можно найти много полезного по разной электронной тематике. Нашлась там и статья STM32 и USB-HID — это просто. Я не являюсь постоянным клиентом Хабра и не знаю автора этой статьи RaJa, но на мой взгляд это очень хорошая статья, описывающая основные положения работы HID интерфейся. Без её прочтения читать дальше здесь бессмысленно, поскольку далее будут, в основном, комментарии для адаптации кода к среде разработки STM32IDE/STM32CubeMX + Atollic TrueStudio. (Далее STM32IDE). Да и столь популярный в 2014 году и реально очень неплохой проект EmBlocks, увы, умер.

Первое, что необходимо решить — как тестировать вновь создаваемое устройство. Лет… дцать назад я использовал для этого анализатор и синтезатор трафика USB — очень полезные, но дорогие игрушки :-) Сейчас у меня такой возможности нет, да и должен же быть более простой путь. Тем более для простого стандартного интерфейса без написания собственного драйвера. Авторы обоих рассмотренных выше проектов пошли самы простым для них путём — написание простой программы на известных им языках. Но автор статьи на Хабре сделал очень правильный шаг — он написал свой проект, совместимый с программой ST HID Demonstrator (ссылка есть в статье), позволяющей поуправлять нашим устройством, как графически, так и послать свои данные и посмотреть, что пришло от нашего устройства. Фактически программа может использоваться и в дальнейшем для отладки будущей программы на выбранном микроконтроллере.

Своё ознакомление с проектом для HID я осуществлял с платой STM32L476 Discovery. Плата, вообще говоря, может быть любой, где USB интерфейс микроконтроллера физически подключён к отдельному разъёму USB. Есть у меня и Nucleo 32 с STM32L4, но там один разъём USB тспользуется и для программирования/отладки, и для связи с хостом, что добавляет интриги в интерфейс и может служить источником дополнительных непоняток. Оно нам надо?

Итак, комментарии и дополнения к статье по привязке HID к STM32IDE примерно по тем же шагам, как и в хабровской статье.

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

В STM32IDE структура всех проектов задаётся при генерации проекта из среды назначения функциональности пинов и пользователю о том заботиться не надо. В частности, в кубике (что отдельном STM32Cube MX, что в встроенном в STM32IDE) активируем USB, как Device, и добавляем Middleware USB Custom HID.

Заходим в Clock Configuration. Вполне вероятно, что могут быть проблемы с системными частотами, которые маркируются малиновым цветом.


Рис. 3 Возможные проблемы по установке частот

Если так, нажимаем Resolve Clock Issues и, скорее всего, всё будет настроено на максимальные частоты. Главное — USB Clock будет выставлен на 48 МГц. Надо заметить, что в семействе STM32L4 генератор на 48МГц имеет автоподстройку по SOF (Start Of Frame), что позволяет создавать USB устройства без внешнего кварца/генератора. Если, конечно, остальной дизайн допускает использование некварцованных генераторов. Для других семейств не проверял, поскольку для моего текущего проекта был выбран именно L4. Только надо отметить, что при использовании USB есть некоторая минимальная частота работы микроконтроллера. Я делал прикидку для другого проекта, где надо общаться с хостом и при этом потреблять минимум тока. Задачи простые, не требуют большой скорости и я хотел запустить МК на 8МГц. Оказалось, что меньше 14МГц при подключении USB ставить не могу, RCC не позволяет. Пришлось остановиться на следующем круглом значении 16МГц.

Это страшное слово Descriptor

Дескриптор от RajaДескриптор от STФайл в проекте
RHID_DeviceDescriptorUSBD_FS_DeviceDescusbd_desc.c
RHID_ConfigDescriptorUSBD_CUSTOM_HID_CfgFSDescusbd_customhid.c
RHID_ReportDescriptorCUSTOM_HID_ReportDesc_FSusbd_custom_hid_if.c

Поскольку для простоты сейчас будем работать только с ST HID Demonstrator, то не мудрствуя лукаво я просто скопировал содержимое RHID_ReportDescriptor в соответствующее место моего проекта. Только подставил свои константы на место длины. Надо отметить, что надо точно посчитать количество байтов в этом дескрипторе (в этом проекте 79) и убедиться, что именно это значение стоит в Class Parameters. Не больше и не меньше. Иначе хост не опознает подключённое устройство. Проверено :-)

Далее заходим в файл usbd_customhid.h и меняем значения CUSTOM_HID_EPIN_SIZE и CUSTOM_HID_EPOUT_SIZE на 0x40U. Честно говоря, немного напрягает то, что ST не даёт альтернатив смене значения по умолчанию 2 на другое значение и далее в коде с использованием этих констант стоит комментарий, что не более 2х байт. Но, с другой стороны, это было рекомендовано в первом найденном описании и, вообще говоря, установка такого значения выглядит достаточно логично. Иначе в чём отличие CustomHID от обычного? Проблема в том, что при регенерации проекта из кубика, что на этапе первичного кода происходит довольно часто, это значение не сохраняется и его надо восстанавливать ручками. Для этого я себе в main вывел строку warning, чтобы не забывать проверить эти константы. Возможно я ошибаюсь, и в дальнейшем всё окажется проще. Но в такой конфигурации работает :-)

Цикл обмена (пишем/читаем)

Для выдачи данных на хост всё достаточно аналогично описанию на Хабре. Только название функции другое: USBD_CUSTOM_HID_SendReport(). Все остальные реомендации из той статьи подходят по полной программе.

А вот чтение здесь интереснее, чем на Хабре. И на самом деле несколько проще. Обработка принятого массива происходит в usbd_custom_hid_if.c / static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state).

В этом тестовом проекте я не заморачивался с обработкой входных параметров и следуя своей обычной практике минимальности времени обработки прерываний, просто копирую полученные данные в заранее определённый массив и устанавливаю флаг готовности данных от USB

Звпускаем на хосте USB HID Demonstrator. На плате, с которой я запускал этот проект, не имеет органов для работы с Variable Inputs/Outputs, поэтому в разделе Graphic customization были убраны соответствующие назначениями, оставлено 5 кнопок и назначены ID, определённые в проекте: 1, 2 для Output report (входные данные для ST) и 4 для Input Report (выход от ST).


Рис. 4 Настройка демонстратора

Для дальнейшей работы обязательно прочтите указанную статью RaJa с Хабра. Она даст понимание того, что и как должно быть сделано для других проектов с USB HID интерфейсом. А ещё лучше начать с неё :-)

И при выборе класса устройства для Вашего проекта надо учитывать следующее: минимальный период опроса HID устройств — 1ms. И если я правильно помню, это скорее пожелание системе от внешнего устройства. В стандартном HID устройстве за один кадр (frame) передаётся только два байта, т.е. скорость обмена не более 2 кбайт/с. В Custom HID на
Full Speed (12 мбит/с) объём данных отчёта (report) - не более 64 байт, т.е. скорость обмена с Вашим HID не более 64 кбайт/с. Для High Speed (480 мбит/с) — максимальный объём данных 512 байт (512 кбайт/с). Не будь у меня ограничения совместимости с предыдущим софтом, используемым в компании, использовал хотя бы CDC.

У меня изучение статей и адаптация под мои хотелки заняло три дня. Описание заняло больше :-) Надеюсь, что у тех, кто воспользуется этой статьёй, аналогичный процесс займёт не более одного дня. Комментируйте, спрашивайте. Что смогу — отвечу. Что не смогу, вместе поищем решение.

Читайте также: