Контроллер can шины usb

Преобразователь шины интерфейса CAN на USB

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Данный проект предназначен для изготовления простого устройства для мониторинга шины CAN. Я выбрал микропроцессор NUC140LC1CN 32K Cortex-M0 по одной главной причине – он имеет периферийные блоки USB и CAN.

Характеристики проекта

Схемное решение

Для разрешения периферийному блоку NUC140 CAN соединяться с шиной CAN необходимо наличие приемопередатчика CAN. Для этой цели наиболее пригодна микросхема TJA1051T от компании NXP. Блок NUC140 может работать от источника питания напряжением 5В. Поэтому нет необходимости для применения дополнительного стабилизатора напряжение на 3.3В. Это позволяет значительно упростить задачу реализации интерфейса шины CAN. В схеме предусмотрено три светодиодных индикатора состояния:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Загрузчик

Флэш-память NUC140LC1 разделена на две секции. Одна из них предназначена для выполнения кода пользовательской программы (APROM) размером 32K, а другая для загрузчика (LDROM). Размер LDROM только 4K, что делает проблематичным создание полностью функционального USB загрузчика. Я использовал загрузчик, размещенный на запоминающемся устройстве (MSD), предоставленный Nuvoton. Установка джампера JP1 запускает выполнение загрузчика. В результате съемный диск будет отображаться в файловой системе хоста размером 32 кБ. Просто скопируйте и вставьте или перетащите и опустите обновление микропрограммы CAN-USB на диск загрузчика. Отсоедините USB кабель, снимите джампер и подсоедините кабель снова. Теперь должна выполняться обновленная микропрограмма.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Программирование интерфейса CAN-USB и NuTiny-SDK-140

Для программирования процессора NUC140 потребуется программатор Nu-Link от Nuvoton и программное приложение Nuvoton ICP. Но вместо него я решил использовать демонстрационную плату NUC140 (NuTiny-SDK-140), доступную от Digi-Key. Она имеет две части, часть с микросхемой NUC140 и собственно программатор Nu-Link. Плата равномерно перфорирована, что позволяет отсоединить часть Nu-Link. На самом деле вы может изготовить данное устройство исключительно на демонстрационной плате NuTiny-SDK-140, добавив только дополнительную микросхему приемопередатчика CAN.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

При подсоединении Nu-Link процесс программирования NUC140 становится несложным. Ключевым вопросом является выбор загрузки из LDROM вместо APROM (в Config настройках) для обеспечения функционирования USB загрузчика.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Программное обеспечение

Интерфейс CAN-USB совместим с протоколом LAWICEL CANUSB и будет работать с приложениями, предназначенными для данного протокола. Я протестировал два приложения с интерфейсом CAN-USB:

CANHacker V2.00.02

Это бесплатное приложение CANHacker. Я не смог найти руководство пользователя для этого приложения. Однако оно достаточно простое и интуитивное при использовании.

Источник

Побеждаем шину CAN. Часть 1. Технология

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Сегодня я хочу познакомить вас с интересной микроконтроллерной платформой CANNY. Это обзорная статья в которой вы узнаете о технологии, а в последующих статьях я расскажу вам о работе с сообщениями CAN, интеграции CANNY c Arduino Mega Server и о тех возможностях, которые предоставляет эта связка.

Почему CANNY? От названия шины CAN, которая широко используется на транспорте и, в частности, во всех современных автомобилях в качестве бортовой сети. Итак, что же можно сделать, имея специализированный контроллер, подключённый к CAN шине вашего автомобиля?

Шина CAN

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

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

Контроллеры CANNY

Это целое семейство специализированных контроллеров, имеющих встроенную «родную» поддержку работы с шиной CAN. Это касается как «железной» части, так и поддержки на уровне «софта».

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Флагманом линейки является контроллер CANNY 7, наиболее мощный и имеющий максимум возможностей. Большое количество памяти, мощные выходы, позволяющие напрямую управлять реле автомобиля, интеллектуальная система защиты от коротких замыканий, защита от бросков тока и напряжения в бортовой сети автомобиля — всё это делает этот контроллер отличным решением для воплощения любых ваших идей и проектов.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Кроме CANNY 7 в линейке контроллеров присутствует ещё несколько моделей, мы будем проводить свои эксперименты с более простой встраиваемой моделью CANNY 5 Nano. Она также поддерживает работу с CAN шиной, но при этом похожа на уже знакомую нам Arduino Nano.

Визуальное программирование

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Развитая поддержка шины CAN это не единственная особенность этих контроллеров, кроме этого CANNY имеют свою собственную среду программирования, CannyLab, но не «обычную», а визуальную, где весь процесс написания программ сводится к манипулированию готовыми структурными блоками, заданию их параметров и соединению входов и выходов этих блоков в определённой последовательности, в соответствии с алгоритмом решаемой задачи.

Ни одной строчки кода!

Хорошо это или плохо? На мой взгляд, это дело привычки. Мне, как человеку привыкшему к «традиционному» программированию, было непривычно манипулировать блоками, вместо написания строк кода. С другой стороны, существует множество приверженцев именно такого подхода к составлению алгоритмов и считается, что для инженеров и «не программистов» это наиболее простой и доступный метод программирования микроконтроллеров.

Мне, как минимум, было «прикольно» составлять программы таким образом и через некоторое время мне это стало даже нравиться. Возможно, что если продолжить этим заниматься, то через некоторое время уже написание кода покажется неудобным.

CannyLab является бесплатной средой разработки и вы можете свободно скачать её с сайта разработчиков, она также не требует специальной процедуры инсталляции — достаточно распаковать файл с архивом — и вы можете начинать работу.

Подключение

Подключение CANNY 5 Nano к компьютеру мало чем отличается от подключения контроллеров Arduino. При наличии в системе драйвера Silicon Labs CP210x, либо после его установки из скаченного дистрибутива CannyLab, Windows создаёт виртуальный COM порт и CANNY готов к работе. В моём случае понадобилось ещё перезагрузить компьютер, но возможно это особенность моей системы.

Практические примеры

Давайте на простых примерах разберём, как в CannyLab выполнять действия, привычные нам в Arduino IDE. Начнём с традиционного мигания светодиодом.

В контроллере CANNY 5 на выводе С4 (Channel 4) присутствует тестовый светодиод (аналог светодиода, находящегося на 13 выводе в Arduino). И его тоже можно использовать для индикации и экспериментов, чем мы и воспользуемся.

Что же нужно, чтобы помигать светодиодом в контроллере CANNY? Нужно сделать всего две вещи — сконфигурировать пин четвертого канала как выход и подать на этот выход сигнал с ШИМ генератора. Все эти действия мы уже не раз проделывали в Arduino IDE, посмотрим как это выглядит в CannyLab.

Итак, конфигурируем пин четвертого канала как выход

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Настраиваем генератор ШИМ. Задаём период 500 миллисекунд, заполнение — 250 миллисекунд (то есть 50 %) и 1 (true) на входе генератора «Старт» и… всё! Больше ничего делать не нужно — программа готова, осталось только залить её в контроллер.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Режим симуляции

Тут нужно сказать пару слов о процессе симуляции на компьютере работы контроллера и заливке разработанной программы в память «железного» контроллера.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Среда разработки CannyLab позволяет запускать и отлаживать программу, не записывая её в память контроллера. В режиме симуляции вы можете видеть результат работы программы прямо в реальном времени и даже вмешиваться в её работу.

Заливка в контроллер

Для работы контроллеров CANNY, перед заливкой программы (в терминологии разработчиков «диаграммы») нужно сначала залить операционную систему «Устройство/Системное ПО/Записать». Это нужно сделать только один раз, для этого нужно выбрать соответствующий вашему контроллеру файл с расширением .ccx.

После того, как программа написана и отлажена, её можно загрузить в ваш контроллер. Это делается просто — в меню выбираете пункт «Устройство/Диаграмма/Записать» и через несколько секунд программа оказывается записанной в контроллер.

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

Аналоговые входы

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

Мы будем отслеживать уровень напряжения на 10 пине контроллера и если он находится в диапазоне 2,5 В ± 20%, будем зажигать встроенный в плату светодиод.

Как и в предыдущем примере, конфигурируем 4-й пин как выход для того, чтобы иметь возможность управлять работой светодиода.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Включаем АЦП на 10-м канале.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Далее пользуемся двумя логическими блоками, которые выдают 1 на выход, если напряжение находится в заданном диапазоне. Полный диапазон от 0 до 4095.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Блок «Логическое И» довершает работу и со своего выхода управляет работой светодиода на плате.

Вот и всё. То, что мы привычно делали на Arduino, мы легко сделали в CannyLab. Осталось только освоиться в этой среде программирования и вы сможете легко и непринуждённо создавать свои проекты на этой платформе.

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

Заключение по вводной статье цикла

Если вам нравится визуальное программирование в стиле CannyLab, то контроллеры CANNY могут стать для вас интересной альтернативой Arduino или работать в связке с контроллерами Arduino. Об этом мы поговорим во второй статье цикла, в которой я расскажу вам об интеграции контроллеров CANNY с системой Arduino Mega Server.

Напомню, что AMS теперь работает не только на платах Arduino, но и на беспроводных Wi-Fi модулях ESP8266 и именно о такой связке пойдёт речь в следующий раз.

И как обычно, оставайтесь с нами, будет интересно!

Источник

CAN-USB адаптер из stm32vldiscovery

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

При разработке устройств с CAN-интерфейсом желательно иметь удобный инструмент для отслеживания сообщений в сети. Для RS232/485 существует множество бюджетных USB адаптеров и куча разнообразного софта, а вот для CAN мне не удалось найти недорогое готовое решение.

В то же самое время на сайтах автолюбителей находились самодельные устройства для подключения к CAN шине автомобиля. Одними из готовых проектов были USB<>CAN Bus Interface (CAN Hacker), реализованный на Atmega+SJA1000 и проект STM32-CAN-Busadapter, реализованный на STM32F105. Работают они с программой CAN Hacker, которая выглядит достаточно удобной для работы. Беглый анализ протокола команд по USB показал, что эти устройства представляются COM портом, и дальнейшее общение происходит в виде передачи команд из ASCII символов.

В закромах была найдена плата STM32VLDiscovery, которая и стала объектом испытаний. На ней мы будем повторять «STM32-CAN-Busadapter».

Первым делом придётся заменить микроконтроллер STM32F100, установленный на STM32VLDiscovery. Дело в том, что одновременная работа CAN и USB в серии F1 возможна только в микроконтроллерах STM32F105/107. Хорошо, что у STM заявлена pin-to-pin совместимость микроконтроллеров различных серий, но выполненном в одинаковом корпусе.

В местном магазине были приобретены:
1. STM32F105RBT6 297 руб.
2. PCA82C250T 115 руб.
3. TJA1055T 138 руб.
4. PBS-40, 2шт. 114 руб.
Макетная плата «с дырочками 2,54» уже давно ждала своего часа.

Попытка сделать всё по-быстрому

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

С сайта проекта STM32-CAN-Busadapter загружаем (требуется регистрация) бинарный файл прошивки и при помощи «STM32 ST-LINK Utility» зашиваем в наш контроллер.

Упрощённая схема выглядит так. Более подробная — на сайте проекта STM32-CAN-Busadapter.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Припаиваем USB D+,D-,Vbus в соответствии со схемой. Добавляем джампер/переключатель на PA2, у автора названый «Bootloader».

Вспоминаем, что для определения подключения по USB необходимо линию D+ подтянуть на 5В через 1,5КОм резистор. После этого наше устройство начинает определяться как «неизвестное устройство» с vid/pid 0000.

Дальше было несколько часов попыток разобраться, что же происходит, и принято решение написать тестовую прошивку для проверки USB подключения.

Пишем тестовую прошивку, для проверки USB

Для написания тестовой прошивки используем STM32CubeMX, что позволит нам по-быстрому состряпать тестовую прошивку. По утверждениям ST и дистрибьютеров, использование CubeMX — это «модно, стильно, молодёжно», надо же когда-то попробовать разобраться с этим Cub-ом.

С сайта STMicroelectronic скачиваем STM32CubeMX. Версия периодически обновляется, у меня v4.7.0.

В установленном Cube входим в «Help»->«Install New Libraries» и устанавливаем «Firmware Package for Family STM32F1» (у меня V1.0.0).

В «Help»->«Updater Settings» можно посмотреть «Repository Folder» — место, куда скачалась наша «Firmware Package», там лежат в том числе и примеры с исходниками для различных отладочных плат.

Создаём новый проект в Cube

MCU — STM32F105RBTx.
В «Configuration»->«Peripheals»->«RCC» выбираем тактирование от внешнего кварцевого резонатора, HSE устанавливаем в «Crystal/Ceramic Resonator».
В «Configuration»->«Peripheals»->«USB_OTG_FS» выбираем режим «Device_Only», и устанавливаем галочку «Activate_VBUS» — для автоматического определения момента подключения к USB. После этого у нас автоматически назначаться ножки PA9, PA11 и PA12 на работу с USB.
В «Configuration»->«MiddleWares»->«USB_DEVICE»->«Class For FS IP» выбираем «Communication Device Class (Virtual Port Com)».

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Дальше на закладке «Clock Configuration» настроим систему тактирования для нашего микроконтроллера. Подсмотреть готовые значения коэффициентов PLL и Prescaler-ов можно в примерах, посмотрев процедуру SystemClock_Config. У нас должна получиться такая «картина»:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Теперь можно сгенерировать проект для компиляции.

Перед первой генерацией запросит ввести название, место хранения проекта и IDE для которой будет формироваться проект. Я выбрал Keil 4, как более привычный. Возможны варианты Keil5, Keil4, IAR, TrueStudio, SW4STM32. После генерации нажимаем «Open Project» и открывается наша среда разработки. Ничего не меняя компилируем и загружаем.
И…, оно работает. Определилось устройство, драйвера нашлись на сайте ST. Теперь в «Диспетчере устройств» видим «STMicroelectronics Virtual COM Port (COM4)».

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

Помню, что в начале программы идут вектора прерываний и в нашей прошивке мы видим что-то похожее, а в скачанной прошивке данные совсем не похожи на команды перехода по адресам.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Более того, гугль подсказал, что первые 4 байта прошивки — адрес стека, следующие 4 байта — адрес первой команды программы.

ОК, смотрим как оно работает

Допаиваем микросхемы трансиверов CAN, получаем вот такую «красоту». Подтягивающий резистор к D+ линии USB можно убрать, он есть внутри микроконтроллера.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Прошиваем, запускаем CAN Hacker, изучаем. Здесь нам понадобится подключение к какой-нибудь CAN сети. У меня это была плата openmcu с STM32F107 контроллером, которая выдавала CAN посылки. Поигравшись с программой «CAN Hacker», понял, что штука подходящая, есть режимы monitor и tracer — сообщения выводятся или в таблицу или в список по мере поступления.

Вот небольшое видео, не моё.

Теперь можно попробовать написать свою прошивку для адаптера. Тем более заготовка прошивки у нас уже есть.

Пишем свою прошивку.
Открываем в нашей IDE проект, сгенерированный Cube и дописываем недостающие куски кода.
Основное правило — писать в промежутках между
/* USER CODE BEGIN… */
и
/* USER CODE END… */
Иначе всё, что написано вне таких специально отведённых мест будет нещадно перезаписано Cub-ом при следующей генерации проекта.

Для начала сделаем эхо: всё, что отправили в наш виртуальный COM порт получаем обратно.
При приёме данных по USB вызывается процедура CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) в файле «usbd_cdc_if.c«.

Добавим отправку обратно всего, что получили.

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
<
/* USER CODE BEGIN 6 */

CDC_Transmit_FS(Buf, *Len); //отправляем всё, что получили

USBD_CDC_SetRxBuffer(hUsbDevice_0,&UserRxBufferFS[0]);
USBD_CDC_ReceivePacket(hUsbDevice_0); // разрешаем приём следующего пакета

return (USBD_OK);
/* USER CODE END 6 */
>

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

Подстраиваемся под CAN Hacker

Теперь начнём реализацию протокола для работы с программой «CAN Hacker». Сам протокол можно посмотреть на странице проекта USB<>CAN Bus Interface (CAN Hacker), в файле «описание», или поискать на просторах интернета по названию «Lawicel Protokol».

Программой USBTrace был подсмотрен процесс инициализации адаптера.

Необходимо ответить на команду «запрос версии», на все остальные запросы просто отвечаем «ОК» (0x0D).

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
<
/* USER CODE BEGIN 6 */

uint32_t num_bytes;
uint8_t res;
uint8_t tmp_byte;

switch(Buf[0])
<
case ‘V’:
num_bytes = sprintf((char*)UserTxBufferFS,«V0101\r»);
break;

case ‘v’:
num_bytes = sprintf((char*)UserTxBufferFS,«vSTM32\r»);
break;

default:
num_bytes = sprintf((char*)UserTxBufferFS,»\r»);
break;
>

USBD_CDC_SetTxBuffer(hUsbDevice_0, (uint8_t*)&UserTxBufferFS[0], num_bytes);
USBD_CDC_TransmitPacket(hUsbDevice_0);

return (USBD_OK);
/* USER CODE END 6 */
>

После этого программа «CAN Hacker» сможет «увидеть» наш адаптер.

Добавим интерфейс CAN к нашему проекту

В Cube устанавливаем «Configuration»->«Peripheals»->«CAN1» галочку «Master mode». На закладке «Configuration» «CAN1» настраиваем скорость и разрешаем прерывание по приёму:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Генерируем проект в Cube, открываем в IDE.

В «main.c» необходимо добавить буферы для CAN, настроить фильтр входящих сообщений и добавить процедуру HAL_CAN_RxCpltCallback. Эта процедура будет вызываться из прерывания по приёму CAN. Название, разумеется, может быть только таким, т.к. именно оно прописано в «недрах» проекта, сгенерированного Cub-ом. Всё что приняли по CAN будем пересылать в USB, в соответствии с протоколом. Например по CAN с адреса 0x123 приняли 8 байт данных 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88, запаковываем это в посылку для USB «t12381122334455667788» добавляем в конце символ 0x0D и отправляем в наш виртуальный СОМ порт на ПК.

буферы для приёма/передачи
/* USER CODE BEGIN PV */
static CanTxMsgTypeDef can1TxMessage;
static CanRxMsgTypeDef can1RxMessage;
/* USER CODE END PV */

процедура, вызываемая при приёме посылки
/* USER CODE BEGIN 0 */
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
<
uint32_t num_bytes;
uint8_t buf[200];

num_bytes = sprintf((char*)buf,«t%3.3X%1.1X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%4.4X\r», \
CanHandle->pRxMsg->StdId,\
CanHandle->pRxMsg->DLC,\
CanHandle->pRxMsg->Data[0],\
CanHandle->pRxMsg->Data[1],\
CanHandle->pRxMsg->Data[2],\
CanHandle->pRxMsg->Data[3],\
CanHandle->pRxMsg->Data[4],\
CanHandle->pRxMsg->Data[5],\
CanHandle->pRxMsg->Data[6],\
CanHandle->pRxMsg->Data[7]\
);
CDC_Transmit_FS(buf,num_bytes); // отправляем в USB то, что получили по CAN

HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0); //ждём следующую посылку
>
/* USER CODE END 0 */

в основном цикле main добавим инициализацию буферов и настроим приёмный фильтр
/* USER CODE BEGIN 2 */
hcan1.pTxMsg = &can1TxMessage;
hcan1.pRxMsg = &can1RxMessage;
/* USER CODE END 2 */

// настраиваем фильтр — приём всех посылок
CAN_FilterConfTypeDef canFilterConfig;
canFilterConfig.FilterNumber = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
canFilterConfig.FilterIdHigh = 0x0000;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x0000 Реализация кольцевого буфера

буфер для отправки USB у нас уже определён
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];

в «usb_cdc_if.c» определим указатели в этот буфер
uint32_t ptrWriteUserTxBufferFS = 0; //запись в буфер при приёме из CAN
uint32_t ptrReadUserTxBufferFS = 0; //чтение из буфера, отправка в USB
/* USER CODE END 1 */

опишем процедуры добавления данных в буфер и отправки из буфера
к сожалению, нормального места в «usb_cdc_if.c» не нашлось, поэтому пришлось пихать в секцию «USBD_CDC_Private_Macros»
/* USER CODE BEGIN 2 */
extern uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
extern uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];
extern uint8_t interface_state;
extern USBD_HandleTypeDef *hUsbDevice_0;

while(_cnt)
<
UserTxBufferFS[ptrWriteUserTxBufferFS] = *Buf;
ptrWriteUserTxBufferFS++;
Buf++;
ptrWriteUserTxBufferFS %= APP_TX_DATA_SIZE; //закольцовываем
_cnt—;
>
return(0);
>

if(USBD_CDC_TransmitPacket(hUsbDevice_0) == USBD_OK)
<
ptrReadUserTxBufferFS += buffsize;
if (ptrReadUserTxBufferFS == APP_TX_DATA_SIZE)
<
ptrReadUserTxBufferFS = 0; //закольцовываем
>
>
>
return(0);
>
/* USER CODE END 2 */

в «main.c» добавим переменную
uint8_t interface_state = 0;
пока от CAN Hacker не придёт команда «O» — переход в рабочий режим из настроечного, не будем ничего слать в USB, т.к. считаем что интерфейс ещё не сконфигурирован

заменим в прерывании CAN прямую отправку в USB на добавление в буфер отправки
CDC_Transmit_FS на CDC_add_buf_to_transmit

и добавим периодический опрос буфера для отправки
while (1)
<
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
CDC_periodic_callback();
>
/* USER CODE END 3 */

Компилируем, загружаем. Видим, что теперь в CAN Hacker отображаются все сообщения, без пропусков.

Добавим Timestamp

В протоколе CAN Hаcker предусмотрены «отметки времени» для каждого сообщения. Диапазон значений 0..60000 мс.
Используем для этого TIM1.
В Cub-е, в «Configuration»->«Peripheals»->«TIM1» выбираем «Clock source»=«Internal Clock».
Для настройки частоты тактирования таймера 1000 Гц (1мс). Придётся понизить частоту тактирования APB2.
Убеждаемся, что от APB2 не тактируется ничего для нас важного по быстродействию.
Из «reference manual» на «STM32F1»:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb
Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Видим, что от APB2 тактируются таймер1, порты ввода-вывода, АЦП, SPI, USART, и мы можем смело понижать частоту APB2.

В Cub-е, на закладке «Clock Configuration» устанавливаем «APB2 Prescaler» равным 8, получаем частоту тактирования таймера 18 МГц.

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

На закладке «Configuration»->«TIM1» устанавливаем
Prescaler(PSC — 16 bit value) = 18000
Counter period (AutoReload Register) = 60000

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Генерируем код, открываем в IDE.

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
<
uint32_t num_bytes;
uint8_t buf[200];
static uint32_t time;

num_bytes = sprintf((char*)buf,«t%3.3X%1.1X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%4.4X\r», \
CanHandle->pRxMsg->StdId,\
CanHandle->pRxMsg->DLC,\
CanHandle->pRxMsg->Data[0],\
CanHandle->pRxMsg->Data[1],\
CanHandle->pRxMsg->Data[2],\
CanHandle->pRxMsg->Data[3],\
CanHandle->pRxMsg->Data[4],\
CanHandle->pRxMsg->Data[5],\
CanHandle->pRxMsg->Data[6],\
CanHandle->pRxMsg->Data[7],\
time
);
if(interface_state == 1) CDC_add_buf_to_transmit(buf,num_bytes);

Опять, вроде работает, но при интенсивном обмене в CAN обмен по USB «затыкается».
На этот раз виновата процедура sprintf, которая долго выполняется в прерывании CAN.

Перепишем формирование посылки из CAN в USB без использования sprintf.

uint8_t halfbyte_to_hexascii(uint8_t _halfbyte)
<
_halfbyte &= 0x0F;
if(_halfbyte >= 10) return(‘A’ + _halfbyte — 10);
else return(‘0’ + _halfbyte);
>

uint8_t hexascii_to_halfbyte(uint8_t _ascii)
<
if((_ascii >= ‘0’) && (_ascii = ‘a’) && (_ascii = ‘A’) && (_ascii изменим процедуру HAL_CAN_RxCpltCallback

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
<
uint32_t num_bytes;
uint8_t buf[200];
static uint32_t time;

time = __HAL_TIM_GetCounter(&htim1);
/*
num_bytes = sprintf((char*)buf,«t%3.3X%1.1X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%4.4X\r», \
CanHandle->pRxMsg->StdId,\
CanHandle->pRxMsg->DLC,\
CanHandle->pRxMsg->Data[0],\
CanHandle->pRxMsg->Data[1],\
CanHandle->pRxMsg->Data[2],\
CanHandle->pRxMsg->Data[3],\
CanHandle->pRxMsg->Data[4],\
CanHandle->pRxMsg->Data[5],\
CanHandle->pRxMsg->Data[6],\
CanHandle->pRxMsg->Data[7],\
time
);
*/
num_bytes = 0;
buf[num_bytes++] = ‘t’;
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->StdId)>>8);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->StdId)>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->StdId));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->DLC));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[0])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[0]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[1])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[1]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[2])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[2]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[3])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[3]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[4])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[4]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[5])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[5]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[6])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[6]));
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[7])>>4);
buf[num_bytes++] = halfbyte_to_hexascii((CanHandle->pRxMsg->Data[7]));
buf[num_bytes++] = halfbyte_to_hexascii((time)>>12);
buf[num_bytes++] = halfbyte_to_hexascii((time)>>8);
buf[num_bytes++] = halfbyte_to_hexascii((time)>>4);
buf[num_bytes++] = halfbyte_to_hexascii((time)>>0);
buf[num_bytes++] = ‘\r’;

if(interface_state == 1) CDC_add_buf_to_transmit(buf,num_bytes);

Некоторые эксперименты по быстродействию на приём: в CAN формируем 1000000 посылок с адреса 0x321 и в CAN Hacker смотрим сколько из них примем.

Скорость 500 Кбит/сек, посылки без перерывов, потери 0,2%:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Скорость 1 Мбит/сек, посылки без перерывов, потери 50%:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

Скорость 1 Мбит/сек, по две посылки каждые 1 мс, потери 0%:

Контроллер can шины usb. Смотреть фото Контроллер can шины usb. Смотреть картинку Контроллер can шины usb. Картинка про Контроллер can шины usb. Фото Контроллер can шины usb

По-моему неплохой результат.

Добавим возможность отправки сообщений в CAN

В файле «usbd_cdc_if.c», в процедуру USB CDC_Receive_FS добавим:

hcan1.pTxMsg->StdId = hexascii_to_halfbyte(Buf[i++]);
hcan1.pTxMsg->StdId = (hcan1.pTxMsg->StdId StdId = (hcan1.pTxMsg->StdId DLC = hexascii_to_halfbyte(Buf[i++]);
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[0] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[1] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[2] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[3] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[4] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[5] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[6] = tmp_byte;
tmp_byte = hexascii_to_halfbyte(Buf[i++]); tmp_byte = (tmp_byte Data[7] = tmp_byte;
HAL_CAN_Transmit(&hcan1, 10);

num_bytes = sprintf((char*)UserTxBufferFS,»\r»);
break;

Компилируем, загружаем, проверяем, работает.

Заключение

На этом, пожалуй, можно остановиться. Рубрика ведь «Сделай сам» называется. Если кто захочет, сможет самостоятельно добавить поддержку разных скоростей CAN, работу с 29 битными расширенными идентификаторами, фильтры сообщений, remote frames.

Хочу сказать, что принцип работы через ASCII команды мне понравился. В будущем планирую реализовать USB-SPI, USB-I2C функционал. Например, настраиваем наш виртуальный COM порт на 115200 бод — работаем с CAN, настраиваем на 57600 — работаем с I2C, настраиваем на 9600 — работаем с SPI. Разумеется, при работе с SPI или I2C «CAN Hacker» уже нельзя будет использовать и придётся какой-то свой протокол придумывать.

Готовый проект к данной статье можно скачать по ссылке.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *