-
Форк fbsder/canfestival т. к. похоже это самый живой форк оригинала.
-
Проект ZhiyangZhou24/CANopen-STM32F1 - основные изменения это переделка на поддержку библиотек HAL
-
При разбирательствах как "ОНО" работает очень помогла статья CAN + CANOpen + CANfestival + STM32. Часть первая.
-
Для настройки проекта в VScode использованы различные материалы найденные на просторах интернета.
- Описание проекта и комментарии в коде в первую очередь сделаны в качестве памятки, чтобы легче было вспомнить как оно работает и имплементировать данные наработки в друой проект.
-
Шаблон Slave устройства для STM32F103. Проект сделан в VScode. На текущий момент работает:
-
отправка
Heartbeat
сообщений. -
получение и отправка
SDO
сообщений. -
регулярная отправка
PDO
сообщений. -
возможность смены
CAN_Id
устройства из тела программы или по команде из сети черезSDO
. -
перезагрузка по команде
NMT
. -
аппаратный CAN фильтр
по индивидуальному и групповому адресу (автоматически перестраивается при смене ** can_ID **). -
реализован обработчик
callback
функции на изменение параметровPDO/SDO
по сети. -
Подправлен генератор словаря
ObjdicEdit
, теперь он работает с текущими библиотеками Python. Включена возможность указать ** can_ID ** устройства при генерации словаря. -
Вывод отладочной информации может быть в main.h и can_driver.h легко отключен или перенастроен с
SWD
наUART
(в этом случае надо через STM32СubeMX активировать соответствующий порт). К контроллеру подключён одноразрядный 7-сегментный индикатор, через него так же можно выводить отладочною информацию (цифры от 0 до F, точку, символ ошибки "Е"). -
Проект тестировался на
STM32F103CB
, в качестве can драйвера использовалсяSN65HVD230
, корреспондентом на шине являлся модульmcp2515
->arduino
-> программаCANHacher
. -
В проекте специально включен полный депозитарий библиотеки CANFestival, так как ее вариантов даже на GitHab много. Во многие проекты включены только используемые в них файлы и тяжело определить какой форк использовался в проекте.
-
Проект содержит MX файл, по этому данный шаблон легко использовать для других более сложных проектов.
-
Включен вывод отладочной информации по использованию задачами стека и кучи.
-
Используется библиотека
printf-stdarg
для подмены стандартных функцийprintf
/sprintf
.
Листинг использования памяти по результатам компиляции
Memory region Used Size Region Size %age Used
RAM: 9432 B 20 KB 46.05%
FLASH: 37612 B 128 KB 28.70%
text data bss dec hex filename
36268 1340 8100 45708 b28c build/RTOS_CANOpen2.elf
при этом, при работе микроконтроллера:
- в среднем использование стека для задач:
- CAN_Tx_Task Free Stack:166
- CAN_Rx_Task Free Stack:156
- FreeHeapSize/MinimumEverFreeHeapSize: 1160/536
Отключение вывода диагностической информации не уменьшает использования RAM, но размер программы во FLASH становится заметно меньше.
Я думаю, минимальное значение кучи 536 зафиксировано до удаление стартовой задачи, и при недостатке памяти в системе можно немного уменьшить HeapSize (хотя он может быть фрагментированный и это не спасет).
Для таймеров CanFestival используется TIM2 (вы можете использовать другой), в нем для отладки делитель установлен в значение ** 7099 ** (**TIM2. Init. Prescaler = 7100-1 **) вместо значения ** 709 **, т. к в этом случае периоды отправки CAN пакетов увеличивается в 10 раз и это удобно для отладки.
откорректированный ObjdicEdit.py
протестирован с:
Python 2. 7. 13 (v2. 7. 13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v. 1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx. __version__
'4. 0. 7. post2'
>>> quit()
также ObjdicEdit.py
должен работать в debian10.
В настройках объектного словаря ** can_ID ** установлен в значение ** 0x00 *, это позволяет на лету менять сетевой адрес устройства через глобальную переменную ** can_ID ** (в проекте ей задано значение *** 0x04 **, что и будет видно в примерах ниже). которая в свою очередь задается в словаре под индексом ** 0x2000sub0x00 **.
Если вам этого не требуется, то можете удалить данную переменную и задавать адрес устройства через Node ID
объектного словаря.
Чтобы не править файлы CANFestival подмена Node ID
производится в драйвере can_driver.c
. Кроме того, для уменьшения размера используемой памяти между CANFestival и HAL используются сокращенные структуры ** CanRxMsg ** и ** CanTxMsg ** (возможно я не прав, и отказ от них позволит сократить использование памяти).
Перед использованием необходимо поправить пути до GCC
и OpenOCD
в файле .vscode/settings.json
после этого во всех скриптах должны правильно отработать ссылки на них. Там же надо установить частоту процессора и проверить значение swoFrequency в файле .vscode/launch.json
(при указании в этом поле переменной скрипт не работает).
(в скобках указаны параметры принятые в проекте):
- Настраиваем тактирование микроконтроллера (** 72 ** Mhz от 8Mhz кварца).
- CAN интерфейс, определяем используемые порты (** PA 11|12 **), скорость (500kBPs), использование прерывания при приеме пакетов (для работы требуется только
USB_LP_CAN1_RX0_IRQ
, если надо отлаживать аппаратный CAN фильтр то включаемCAN1_RX1_IRQ
)/ - включаем таймеры для:
- CANFestival (TIM2), устанавливаем делитель в значение ** 7099 **,
- системных тиков (TIM4).
- включаем
SWD
. - настаиваем прочие порты.
- Включаем FreeRTOS, в нем:
- настаиваем одну задачу (
CAN_Start_Task
) инициирующую все дальнейшие действия на CAN интерфейсе (она инициализирует CANFestival, создаст дочерние задачи и после этого будет удалена). - включаем функции необходимые для отслеживания использования стека и Heap.
- настаиваем одну задачу (
- настаиваем STM32СubeMX на генерацию
Makefile
. - в
Makefile
прописываем пути к библиотекам и*.с
файлам, которые он не видит. Необходимо проверить, чтоTARGET
вMakefile
совпадает именем папки с проектом иначе не будет работать отладка в VScode Если есть желание можно добавить вывод диагностической информации при компиляции как в проекте (см.Lib/Debug/README.md
)
Настаиваем требуемые объекты в разделе ** 0x2000 **, при необходимости делаем их mapping в PDO|SDO
.
После загрузки узел переходит в состояние Pre_operational отправляет Heartbeat сообщение о загрузке Send a Boot-Up msg в CAN очередь:
ID 0x704 - (0x700 + 0x4) cob_id= 1796
DLC 1
data 0x00 - 0 - значит bootup
после чего узел приходит в режим ** Operational ** и отправляет следующее Heartbeat сообщение в CAN очередь:
ID 0x704 - (0x700 + 0x4) cob_id= 1796
DLC 1
data 0x00 - 5 - режим Operational
и сразу за этим данные PDO указанные в индексе 0x1A00
** Heartbeat ** сообщения посылаются каждые 0,5с
(период задан в объектном словаре, может быть оперативно изменен по сети).
ID 0x704 (0x700 + 0x04) cob_id= 1796
DLC 1
data 0x05
0x604 0x08 0x43 0x02 0x20 0x00 0xXX 0xXX 0xXX 0xXX
, где:
ID - 0x604 - 0x600 + Id 0x04
DLC - 0x08 - всегда должно быть 8
Data [0] - 0x43 - спецификатор команды, из них
биты 4-7 - в этом случае это 0х4 - запрос чтения (если 0х2 - запрос записи)
биты 2-3 - b00 количество байт в сообщении, здесь 0
биты 0-1 - х.з. b11 в принципе работает если b00 (т.е в поле 0х40 вместо 0х43)
Data[1-2] - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3] - 0x00 - суб. индекс 0х00
Data[4-7] - неважно
Ответ:
0x584 0x08 0x43 0x02 0x20 0x00 0x00 0x00 0xC8 0x42
, где:
ID - 0x584 - 0x500 + Id 0x04
DLC - 0x08 - количество бит, но пока все пакеты, что я видел 8
Data [0] - 0x43 - спецификатор команды странно должно быть 0х60, из них
биты 4-7 - в этом случае это 0х4 - запрос передачи (если 0х2 - запрос записи)
биты 2-3 - b00
биты 0-1 - х.з. b11
Data[1-2] - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3] - 0x00 - суб. индекс 0х01
Data[4-7] - 0x00 0x00 0xc8 0x42 полезные данные глобальной переменной Temperature=100 (float) в обратном порядке
0x604 0x08 0x23 0x02 0x20 0x00 0x00 0x00 0xC9 0x42
, где:
ID - 0x604 - 0x600 + Id 0x04
DLC - 0x08 - всегда должно быть 8
Data[0] - 0x23 - спецификатор команды, из них:
биты 4-7 - в этом случае это 0х2 - запрос записи
биты 2-3 - b00 количество байт в записываемом значении здесь 4 бата, поэтому 0, если 2 байта то указываем 0x2B, если 1 байт то 0x2F соответственно
биты 0-1 - х.з. почему b11
Data[1-2] - 0x02 0x20 - индекс 0х2000 запись битов идет в обратном порядке
Data[3] - 0x00 - суб. индекс 0х00 Data[4-7] - 0x00 0x00 0xC9 0x42 -новое значение температуры 100.5
Ответ:
0x584 0x08 0x60 0x02 0x20 0x00 0x00 0x00 0x00 0x00
ID - 0x584 - 0x500 + Id 0x04
DLC - 0x08 - количество бит, но пока все пакеты, что я видел 8
Data [0] - 0x60 - спецификатор команды
биты 4-7 - в этом случае это 0х6 успешная запись в случае неуспеха 0х80
биты 2-3 - b00
биты 0-1 - х.з. b11
Data[1-2] - 0x02 0x20 - индекс 0х2002 запись битов идет в обратном порядке
Data[3] - 0x00 - суб. индекс 0х00 Data[4-7] - 0x00 0x00 0x00 0x00 - пустое поле с данными
Чтобы данные через PDO
отправлялись регулярно надо в словаре по индексу ** 0x1800 ** в:
-
суб индекс ** 0x02 ** записать значение ** 0xFF ** - разрешаем спонтанную передачу.
-
суб индекс ** 0x05 ** записать значение ** 0x01F4 ** - устанавливаем таймер на 500 mc. (если в данном регистре будет ** 0 **, то сообщение отправится только один раз).
Эти установки можно задать командами по сети (до следующей перезагрузки, т.к. значение возьмется из словаря указанное в прошивке), для этого:
-
разрешаем спонтанную передачу PDO:
0x604 0x08 0x2F 0x00 0x18 0x02 0xFF 0x00 0x00 0x00
. В случае успеха получаем:0x584 0x08 0x60 0x00 0x18 0x02 0x00 0x00 0x00 0x00
, если получили:0x584 0x08 0x80
- проверь число байт с команде на запись, команда должна быть ** 0x2F **. -
устанавливаем таймер:
0x604 0x08 0x2F 0x00 0x18 0x025 0xF4 0x01 0x00 0x00
.
После этого начинаем получать данные с температурой: 0x284 0x04 0x00 0x00 0xC9 0x42
.
Реализована поддержка команд NMT
, при этом они работают как при обращении по ID
непосредственно данному узлу, так и широковещательно лявсех узлов сети.
Пример команды для перезагрузки устройства:
ID - 0x00
DLC - 0x02 - количество бит
Data[0] - 0x81 - команда перезагрузки устройства
Data[1] - 0x04 - адрес устройства, если 0х00 - широковещательная команда на все устройства соответственно
Функционал реализован через функцию ** NMT_Slave_Node_Reset_Callback_Function() **.
В основном цикле, при инициализации CAN приложений (файл taskcan.c
функция ** CAN_Start_App **) производится регистрация вызовов callback при изменении параметров по сети. В примере реализована всего одна функция callback которая анализирует контекст вызова и в зависимости от этого, производит различные действия (меняет ** can_id ** с пере инициализацией CAN фильтра, либо просто выводит на консоль информацию об изменении переменной ** Dac **).
Если не отравляются CAN сообщения, а TX почтовый ящик забит, надо проверить слышит
ли прием собственную передачу, иначе контроллер думает, что шина занята и блокирует
передачу. У меня была неисправна микросхема Can драйвера и в режиме CAN Lookback
все
работало хорошо, но при переводе в нормальный режим, пакеты перестали
отправляться.
Проект включает файлы:
CANHack-TX-list.txl
- список TX сообщений для программы CANHacher.pulseView.pvs
- конфигурационный файл для программы PulseView для анализатора протокола CAN.