Программирование PC Visual Studio C#: работа с USB-CAN адаптером SYSTEC Mon, October 14 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Visual Studio C#: работа с USB-CAN адаптером SYSTEC Печать
Добавил(а) microsin   

Модуль USB-CAN SYSTEC electronic 3204001 Rev.03 (USB-CANmodul Series) предназначен для передачи в компьютер информации через интерфейс CAN (коннектор DB9 папа). Модуль подключается к компьютеру через USB (через разъем USB тип B или miniUSB тип B).

usb-canmodul-SYSTEC

[Установка]

Скачайте драйвер SO-387_V4.15.ZIP [1]. Не подключая пока модуль по USB, запустите установщик setup.exe. В процессе установки будет выведено предупреждение, что после установки и подключения возможно автоматическое обновление firmware (прошивки) модуля. Обновление прошивки показывается миганием красного светодиода с частотой 4 Гц и скважностью 1/3, во время этого процесса не отключайте от модуля шнур USB, иначе можете испортить модуль USB-CAN. Дождитесь окончания процесса установки, после чего подключите модуль по USB. Запустится мастер установки оборудования Windows, укажите ему установить драйвер автоматически. После установки драйвера у Вас в системе появится новое устройство USB-CAN-Hardware -> Systec USB-CANmodul Device Driver.

usb-canmodul-SYSTEC-installed

В панели управления также появится оснастка USB-CANmodul Control, которая позволяет управлять параметрами подключенных USB CAN адаптеров. Оснастка может понадобится для изменения номера устройства (DevNr.), чтобы на одном компьютере могли работать одновременно несколько USB CAN адаптеров.

USB-CANmodul-Control

Для просмотра данных в сыром виде (которые посланы в адаптер по CAN) и отправки пакетов имеется утилита PCANView (USBCAN).

[Работа с модулем в Visual Studio на C#]

Основная работа с модулем USB CAN производится через библиотеку USBCAN32.DLL (USBCAN-library), предоставленную компанией SYSTEC. Имеются также примеры готового кода и документация, см. USB-CANmodul Utilities -> Manuals и Sources. Большинство функций возвращает значение типа UCANRET, в котором содержится код ошибки. Расшифровка этого кода одинаковая для всех функций. В документации, помимо синтаксиса функций, показаны также значения и параметры каждой функции, и возможные коды ошибки.

С кодом на Visual basic .NET, Managed C++ и C# библиотекой USBCAN32.DLL можно пользоваться через dll-обертку UcanDotNET.dll. Чтобы воспользоваться библиотекой UcanDotNET.dll, скопируйте её в корень проекта и добавьте на неё ссылку (меню Проект -> Добавить ссылку... -> перейдите на закладку Обзор -> выберите файл UcanDotNET.dll). После этого появится возможность пользоваться функциями USBCAN32.DLL, но не напрямую, а через объект класса USBcanServer. Документация по этому классу находится в документе "USB-CANmodul GW-001, GW-002, 3004006, 32040xx, 34040xx Systems Manual" (файл L-487e_22.pdf, находится в папке USB-CANmodul Utility Disk\Docu после установки драйверов USB CAN модуля).

Краткое описание методов USBcanServer

int USBcanServer.GetFwVersion() возвращает версию firmware модуля USB CAN
int USBcanServer.GetUserDllVersion() возвращает версию библиотеки USBCAN
byte USBcanServer.InitHardware(byte bDeviceNr_p = USBCAN_ANY_MODULE) инициализирует USB CAN устройство с указанным номером (USBCAN_ANY_MODULE означает первый попавшийся модуль)
byte USBcanServer.Shutdown() отключает инициализированное устройство, которое ранее было инициализировано методом InitHardware() или InitCan(). Программное обеспечение возвращается в состояние DLL_INIT.
byte USBcanServer.InitCan (параметры) инициализирует специфичный канал CAN на устройстве.
byte USBcanServer.ResetCan (byte pbChannel_p) сбрасывают канал CAN на устройстве.
byte USBcanServer.GetHardwareInfo (параметры) возвращает расширенную информацию по аппаратуре устройства.
byte USBcanServer.GetStatus (параметры) возвращает статус ошибки указанного канала CAN.
byte USBcanServer.SetBaudrate (параметры) используется для установки скорости указанного канала CAN.
byte USBcanServer.SetAcceptance (параметры) используется для настройки фильтра принимаемых сообщений указанного канала CAN.
byte USBcanServer.ReadCanMsg (параметры) читает одно или большее количество CAN-сообщений из буфера указанного канала CAN.
byte USBcanServer.WriteCanMsg (параметры) передает одно или большее количество CAN-сообщений через указанный канал CAN.
byte USBcanServer.GetMsgCount (параметры) читает счетчики сообщений указанного канала CAN.
String USBcanServer.GetCanStatusMessage (параметр) возвращает строковое описание указанного кода статуса.
String USBcanServer.GetBaudrateMessage (параметры) возвращает строку, содержащую значения регистров BTR.
String USBcanServer.GetBaudrateExMessage (параметр) возвращает строку, содержащую указанную скорость.
SetDebugMode (&HC0000306, ".\MyLogFile.log") запуск режима записи диагностических отладочных сообщений в текстовый лог.

Краткое описание callback-событий USBcanServer

event USBcanServer.CanMsgReceivedEvent (канал) принято CAN-сообщение.
event USBcanServer.InitHwEvent() устройство инициализировано.
event USBcanServer.InitCanEvent(канал) указанный канал CAN инициализирован.
event USBcanServer.StatusEvent(канал) поменялся статус ошибки канала CAN.
event USBcanServer.DeinitCanEvent(канал) выключен канал CAN.
event USBcanServer.DeinitHwEvent() устройство CAN выключено.
event USBcanServer.ConnectEvent() к порту USB подключено новое устройство.
event USBcanServer.DisconnectEvent() от порта USB было отключено ранее выключенное устройство.
event USBcanServer.FatalDisconnectEvent() от порта USB было отключено устройство без предварительного выключения.

Далее рассмотрен процесс создания простейшего проекта на C#, использующего USBCAN32.DLL для работы с модулем USB-CAN адаптером SYSTEC, по шагам. Подразумевается, что у Вас установлен драйвер USB-CAN адаптера, и он нормально работает с утилитой PcanView (USBCAN).

1. Создайте в Visual Studio C# проект для GUI приложения pkrc_m_CAN.

2. Скопируйте UcanDotNET.dll в корень проекта, добавьте на него ссылку ссылку в проекте.

3. В модуле Form1.cs добавьте использование UcanDotNET.dll:
using UcanDotNET;

4. Создайте экземпляр класса USBcanServer. Это можно сделать в определении класса формы:

namespace MyApp_CAN
{
   public partial class Form1 : Form
   {
      USBcanServer CANsrv = new USBcanServer();
      ...

5. Вызовите InitHardware без параметра (вызов без параметра то же самое, что и с параметром USBCAN_ANY_MODULE, т. е. будет использоваться первый найденный модуль SYSTEC). Вызвать InitHardware можно в событии загрузки формы Form1_Load:

         bRet = CANsrv.InitHardware();
         if (USBCAN_SUCCESSFUL != bRet)
         {
            applog.write("InitHardware error");
            return;
         }

6. Вызовите InitCan с нужными параметрами, например:

         bRet = CANsrv.InitCan(USBCAN_CHANNEL_CH0,
                               USBCAN_BAUD_125kBit,
                               USBCAN_BAUDEX_USE_BTR01,
                               USBCAN_AMR_ALL,
                               USBCAN_ACR_ALL,
                               kUcanModeNormal,
                               USBCAN_OCR_DEFAULT);
         if ( USBCAN_SUCCESSFUL != bRet)
         {
            applog.write("InitCan error");
            return;
         }

В этом примере устройство USB CAN SYSTEC инициализируется на использование канала 0, скорость 125 кбит, маски приема AMR и ACR настроены на прием всех сообщений (фильтрация по адресу отключена). Назначение остальных параметров пока не понял. После успешного вызова InitCan на устройстве гаснет красный светодиод State.

usb-can-state-LED-3204001 usb-can-state-LED-GW-002
Светодиод статуса USB CAN 3204001 Светодиод статуса USB CAN GW-002

7. При закрытии программы нужно добавить вызов Shutdown. Это можно сделать в событии закрытии формы:

      private void Form1_FormClosed (object sender, FormClosedEventArgs e)
      {
         bRet = CANsrv.Shutdown();
         if (USBCAN_SUCCESSFUL != bRet)
         {
            applog.write("Shutdown error");
         }
         applog.write("[EXIT]");
      }

8. Для приема данных по каналу CAN нужно добавить обработчик события CanMsgReceivedEvent. Добавьте следующий оператор в Form1_Load:

CANsrv.CanMsgReceivedEvent += new USBcanServer.CanMsgReceivedEventEventHandler(CANsrv_CanMsgReceivedEvent);

И еще добавьте обработчик события приема сообщения CANsrv_CanMsgReceivedEvent:

      private void CANsrv_CanMsgReceivedEvent(byte bChannel_p)
      {
         applog.write("Data arrived");
      }

Для упрощенного добавления обработчика выполните следующие шаги:
- в коде Form1_Load напечатайте CANsrv. (в конце поставьте точку);
- нажмите Ctrl+Space, из появившегося списка методов и событий выберите CanMsgReceivedEvent;
- допечатайте пробел, + и =. Появится подсказка в виде текста:
"new USBcanServer.CanMsgReceivedEventEventHandler(CANsrv_CanMsgReceivedEvent); (Нажмите клавишу TAB для вставки)"
- нажмите клавишу TAB, и в коде автоматически будет создана строка:

CANsrv.CanMsgReceivedEvent += new USBcanServer.CanMsgReceivedEventEventHandler(CANsrv_CanMsgReceivedEvent);

После этого останется вручную создать процедуру CANsrv_CanMsgReceivedEvent.

9. Чтобы получить данные из сообщения, вызовите в обработчике CANsrv_CanMsgReceivedEvent функцию ReadCanMsg.

      private void CANsrv_CanMsgReceivedEvent(byte bChannel_p)
      {
         byte channel = USBCAN_CHANNEL_CH0;
         UcanDotNET.USBcanServer.tCanMsgStruct[] msg = new UcanDotNET.USBcanServer.tCanMsgStruct[10];
         int pdwCount_p = 0;
 
         applog.write("Data arrived");
         bRet = CANsrv.ReadCanMsg(ref channel, ref msg, ref pdwCount_p);
      }

После успешного вызова (bRet == USBCAN_SUCCESSFUL) в переменной channel будет номер канала, по которому принято сообщение, в массиве msg будут содержаться сами сообщения, а в переменной pdwCount_p будет находиться количество принятых сообщений.

10. Чтобы отправить сообщение по CAN, нужно вызвать метод WriteCanMsg. Пример отправки одного сообщения, в котором можно передать 8 байт данных (данные берутся из массива byte msgdata [8]):

         byte channel = USBCAN_CHANNEL_CH0;
         UcanDotNET.USBcanServer.tCanMsgStruct[] msg = new UcanDotNET.USBcanServer.tCanMsgStruct[1];
         msg[0].m_bData = new byte[8];
         int pdwCount_p = 0;
 
         //заполняем поля tCanMsgStruct
         for (byte dataidx = 0; dataidx < 8; dataidx++)
            msg[0].m_bData[dataidx] = msgdata[dataidx];
         msg[0].m_bDLC = 8;                  //CAN data length code, количество байт данных 
         msg[0].m_bFF  = USBCAN_MSG_FF_STD;  //CAN frame format, формат фрейма
         msg[0].m_dwID = 0x0101;             //адрес CAN для приемника
         msg[0].m_dwTime = 10;               //время таймаута передачи в миллисекундах
         bRet = CANsrv.WriteCanMsg(channel, ref msg, ref pdwCount_p);

Выполнение шагов 1..10 предоставляет минимально необходимый функционал для рабочего приложения адаптера USB CAN SYSTEC. Можно принимать и передавать данные по каналу CAN с нужной скоростью.

[Добавление дополнительных событий]

Для создания полнофункционального приложения полезно добавить обработку других событий - отключение и подключение USB CAN адаптера по порту USB компьютера, изменение статуса физической линии связи CAN (которая выходит на разъем DB9 адаптера), инициализация и деинициализация интерфейса обмена с адаптером. Кроме вышеописанного события CanMsgReceivedEvent, класс USBcanServer предоставляет также события InitCanEvent, StatusEvent, DeinitCanEvent, DeinitHwEvent, ConnectEvent, DisconnectEvent, FatalDisconnectEvent (см. таблицу callback-событий). Особенно полезны события отключения (FatalDisconnectEvent) и подключения (ConnectEvent) по USB, так как они позволяют восстанавливать работу приложения без перезапуска, если адаптер USB CAN был случайно отключен от компьютера.

Добавление событий в экземпляр класса CANsrv происходит стандартным образом во время старта приложения (например, в конструкторе формы или в конструкторе класса, работающего с USBcanServer).

         //добавление событий
         CANsrv.InitCanEvent        += new USBcanServer.InitCanEventEventHandler       (CANsrv_InitCanEvent);
         CANsrv.StatusEvent         += new USBcanServer.StatusEventEventHandler        (CANsrv_StatusEvent);
         CANsrv.DeinitCanEvent      += new USBcanServer.DeinitCanEventEventHandler     (CANsrv_DeinitCanEvent);
         CANsrv.DeinitHwEvent       += new USBcanServer.DeinitHwEventEventHandler      (CANsrv_DeinitHwEvent);
         USBcanServer.ConnectEvent  += new USBcanServer.ConnectEventEventHandler       (USBcanServer_ConnectEvent);
         USBcanServer.DisconnectEvent += new USBcanServer.DisconnectEventEventHandler  (USBcanServer_DisconnectEvent);
         CANsrv.FatalDisconnectEvent += new USBcanServer.FatalDisconnectEventEventHandler(CANsrv_FatalDisconnectEvent);
         CANsrv.CanMsgReceivedEvent += new USBcanServer.CanMsgReceivedEventEventHandler(CANsrv_CanMsgReceivedEvent);

Обратите внимание - обработчики событий ConnectEvent и DisconnectEvent объявляются привязанными к классу, а не к экземпляру класса, так как они объявлены с атрибутом static. Таким образом, если у Вас в приложении будут несколько экземпляров класса USBcanServer, то они будут использовать общие для всех обработчики событий ConnectEvent и DisconnectEvent.

[Создание файла отладки (debug file) из DLL]

Если при работе программ, использующих DLL SYSTEC, возникают проблемы с драйвером, то можно создать лог отладки из USBCAN32.DLL. Этот файл нужно всегда отправлять в службу поддержки SYSTEC по email, чтобы Вам помогли разобраться в проблеме. Чтобы активизировать эту возможность, запустите апплет USB-CANmodul Control из Панели Управления Windows. При запуске появится окно, которое предложит выбрать учетную запись, от имени которой будет запущена утилита управления. Обязательно выберите учетную запись администратора, и снимите галочку "Защитить компьютер от несанкционированных действий ...".

usb-can-SYSTEC-enable-debug1

Перейдите на закладку Debug, внизу поставьте галочку Enable Debug. В списке log functionality можно выбрать, что будет записываться в лог. Кнопку Browse позволяет указать месторасположения лог-файла (по умолчанию место назначено на папку документов пользователя). После изменения установок нажмите кнопку Применить и ОК.

usb-can-SYSTEC-enable-debug2

Создаваемый файл лога получит имя USBCAN_XXXXXXXX_YYYYYY_ZZZ.LOG. Здесь XXXXXXXX представляет дату создания в формате YYYYMMDD (год, месяц, день), YYYYYY соответствует времени создания в формате HHMMSS (час, минута, секунда), ZZZ имя работающего приложения.

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

По мере использования файл лога отладки будет увеличиваться в размере. Можно активировать опцию “Check max. LOG file size”. В этом случае код USBCAN32.DLL будет мониторить размер файла отладки. Если максимальный размер лога будет превышен, то предыдущие (старые) записи отладки будут удалены. По умолчанию размер debug file задан в 10240 килобайт (порядка 10 мегабайт).

Начиная с версии V3.11 USBCAN-library, приложение пользователя может вызвать функцию UcanSetDebugMode() для активизации этой опции. Подробности см. в секции 2.3.2.1 документации на модули GW-001, GW-002, 3004006, 32040xx, 34040xx (USB-CANmodul GW-001, GW-002, 3004006, 32040xx, 34040xx Systems Manual) [1].

[Индикационные светодиоды статуса USB-CANmodul]

Состояние каждого канала модуля USB-CANmodul отображаются двумя светодиодами, красным и зеленым светодиодами. Чтобы отделить разные состояния, применяется разный характер циклов мигания (blinking cycle). Cycle 1 соответствует частому миганию с частотой примерно 10 Гц, где время выключенного состояния светодиода равно включенному. Cycle 2 соответствует медленному миганию с частотой примерно 2 Гц, где время выключенного состояния светодиода также равно включенному. Cycle 3 соответствует миганию с частотой примерно 4 Гц, где время выключенного состояния светодиода в 3 раза меньше времени включенного состояния.

usb-can-SYSTEC-LED-timing-daigram

Циклы мигания могут сообщать о таких событиях, как обновление программного обеспечения (firmware), записи в лог, состояние ошибки на канале, неподключенном кабеле USB и т. п. Подробности см. в документации USB-CANmodul GW-001, GW-002, 3004006, 32040xx, 34040xx Systems Manual [1].

[Ссылки]

1. Драйвер, пакет примеров и документация USB-CANmodul Utility Disk.
2. Интерфейс CAN в микроконтроллере ARM AT91SAM7X256.

 

Комментарии  

 
0 #3 Владимир 25.04.2019 16:52
Пытаюсь повторить, но затык с обработчиком и процедурой...
Ошибка CS0123 Нет перегруженного метода для "USBcan_CanMsgRe ceivedEvent", который соответствует делегату "USBcanServer.CanMsgReceivedE ventEventHandle r".

IDE0060 Удалить неиспользуемый параметр "bChannel_p", если он не является частью предоставляемог о общедоступного API.

microsin: сейчас не могу подсказать, в чем проблема, очень давно писался этот код. Возможно, что поменялось API. Посмотрите в документации, какие есть доступные методы у класса.
Цитировать
 
 
0 #2 Владислав 23.11.2015 22:26
Если будете читать это сообщение, то оставьте пожалуйста комментарий в статье! Все дело в том, что повторяя данный проект, выявил один очень неприятный момент, который отнял много времени. Ошибка кроется в библиотеке UcanDotNET.dll, она имеет несколько версий. Те что я сперва использовал (она весит 35 килобайта) не удавалось метод CANsrv.InitHardware() без аргументов, как в статье. Поиск по "мусоре" выявил наличие нескольких вариантов этого файла. Для проекта нужна версия Сборка UcanDotNET.dll, v2.4.5515.17365. она весит чуть более 38 килобайт. и с ней проект собрался без ошибок по данному методу как в примере - без передачи аргументов. Между прочим в данной библиотеке имеются два данных метода, разных по описанию только аргументов.

microsin: в C++ одно и то же имя функции может использоваться по-разному, с разным набором аргументов. Эта фича объектно-ориентированног о программировани я называется перезагрузка (overloading). Две версии одной и той же функции в библиотеке - наверняка именно этот случай.
Цитировать
 
 
+4 #1 Владислав 22.11.2015 18:38
Пытаюсь собрать проект описанный вами в данной статье, но не получается. а именно: собрал проект. все выполнил и проект собирается, все до пункта 4. Когда создаю обработчик, который выполняется при загрузке формы (Form1_Load) и вставляю в него:

bRet = CANsrv.InitHardware();
if (USBCAN_SUCCESS FUL != bRet)
{
applog.write("InitHardware error");
return;
}

Студия ругается на имена bRet, USBCAN_SUCCESSF UL, applog. Не подскажете, почему их не видит компилятор?
Цитировать
 

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


Защитный код
Обновить

Top of Page