Open SAE J1939
SAE J1939-это протокол для формирования сообщения CAN-BUS определенным образом, который соответствует промышленным транспортным средствам, таким как тракторы, машины, грузовики и многое другое.
SAE J1939-очень простой протокол для использования, но отсутствует информация о SAE J1939 из-за стоимости документа протокола, доступной, как сформировать сообщение CAN-BUS в соответствии со стандартом протокола SAE J1939. Поэтому я пишу протокол SAE J1939, доступный бесплатно для любых встроенных систем, таких как STM32, Arduino, AVR, PIC и т. Д. или ПК.
Чтобы научиться строить этот проект, вам нужно первым, чтобы понять SAE J1939. Я написал этот проект на языке C , потому что C является отраслевым стандартом. Диалект языка C , который я выбрал, - это ANSI C (C89) , и я не использую динамическое распределение памяти в этой библиотеке. Так что это будет работать со стандартом MISRA C
С помощью этой библиотеки вы можете общаться с клапанами, двигателями, приводами, машинами, оборудованием и всеми другими вещами, которые подходят для тяжелых промышленных мобильных приложений. Я создал основную структуру проекта, и я надеюсь, что другие пользователи отправят запрос на притяжение своего C код для дополнительной функциональности в стандарт SAE J1939, потому что SAE J1939 является огромным стандартом.
Ищете библиотеку C Canopen для встроенных систем? https://github.com/danielmartensson/easy-canopen
Ищете структуру графического интерфейса C ++, которая использует Open SAE J1939 над USB? https://github.com/danielmartensson/goobysoft
Ищете проект C STM32 с Open SAE J1939? https://github.com/danielmartensson/stm32-flc
Начиная
Первое, что вам нужно знать, это прочитать мой собственный документ PDF Open SAE J1939 в папке Documentation . Узнайте структуру проекта, иначе вы не сможете понять SAE J1939. После того, как вы получили базовое понимание проекта, вы можете опираться на него. Держите это простым и следуйте стандарту SAE J1939!
После того, как вы поймете структуру проекта, затем выберите «Выбор процессора» в Hardware -> Hardware.h File. Здесь вы можете выбрать, например, STM32 , Arduino , PIC , AVR и т. Д. Или, если вы хотите сначала запустить его на ПК, то выберите PROCESSOR_CHOICE 0 и запустите несколько примеров. Это режим отладки для внутренней отзывы.
Как использовать проект
- Шаг 1: Загрузите этот репозиторий
- Шаг 2: Перейдите в
Hardware -> Hardware.h и выберите свой процессор, если он недоступен, напишите код для него и пришлите мне запрос на вытяжку - Шаг 3: Скопируйте папку
Src в папку проекта внутри вашей IDE. Переименовать Src , например, Open SAE J1939 . Это хорошее имя. - Шаг 4: Используйте
Examples -> Open SAE J1939 -> Main.txt Пример в качестве первоначального начального кода для проекта SAE J1939.
/*
* Main.c
*
* Created on: 16 juli 2021
* Author: Daniel Mårtensson
*/
#include <stdio.h>
/* Include Open SAE J1939 */
#include "Open_SAE_J1939/Open_SAE_J1939.h"
/* Include ISO 11783 */
#include "ISO_11783/ISO_11783-7_Application_Layer/Application_Layer.h"
void Callback_Function_Send ( uint32_t ID , uint8_t DLC , uint8_t data []) {
/* Apply your transmit layer here, e.g:
* uint32_t TxMailbox;
* static CAN_HandleTypeDef can_handler;
* This function transmit ID, DLC and data[] as the CAN-message.
* HardWareLayerCAN_TX(&can_handler, ID, DLC, data, &TxMailbox);
*
* You can use TCP/IP, USB, CAN etc. as hardware layers for SAE J1939
*/
}
void Callback_Function_Read ( uint32_t * ID , uint8_t data [], bool * is_new_data ) {
/* Apply your receive layer here, e.g:
* CAN_RxHeaderTypeDef rxHeader = {0};
* static CAN_HandleTypeDef can_handler;
* This function read CAN RX and give the data to ID and data[] as the CAN-message.
* if (HardWareLayerCAN_RX(can_handler, &rxHeader, ID, data) == STATUS_OK){
* *is_new_data = true;
* }
*
* You can use TCP/IP, USB, CAN etc. as hardware layers for SAE J1939
*/
}
/* This function reads the CAN traffic */
void Callback_Function_Traffic ( uint32_t ID , uint8_t DLC , uint8_t data [], bool is_TX ) {
/* Print if it is TX or RX */
printf ( "%st" , is_TX ? "TX" : "RX" );
/* Print ID as hex */
printf ( "%08Xt" , ID );
/* Print the data */
uint8_t i ;
for ( i = 0U ; i < DLC ; i ++ ) {
printf ( "%Xt" , data [ i ]);
}
/* Print the non-data */
for ( i = DLC ; i < 8U ; i ++ ) {
printf ( "%Xt" , 0U );
}
/* New line */
printf ( "n" );
}
/* Apply your delay here */
void Callback_Function_Delay ( uint8_t delay ){
/* Place your hardware delay here e.g HAL_Delay(delay); for STM32 */
}
int main () {
/* Create our J1939 structure */
J1939 j1939 = { 0 };
/*
* Callbacks can be used if you want to pass a specific CAN-function into the hardware layer.
* All you need to do is to enable INTERNAL_CALLLBACK inside hardware.h
* If you don't want to have the traffic callback, just set the argument as NULL.
* If you don't want any callback at all, you can write your own hardware layer by selecting a specific processor choice at hardware.h
*/
CAN_Set_Callback_Functions ( Callback_Function_Send , Callback_Function_Read , Callback_Function_Traffic , Callback_Function_Delay );
/* Load your ECU information */
Open_SAE_J1939_Startup_ECU ( & j1939 );
/* SAE J1939 process */
bool run = true;
while ( run ) {
/* Read incoming messages */
Open_SAE_J1939_Listen_For_Messages ( & j1939 );
/* Your application code here */
}
/* Save your ECU information */
Open_SAE_J1939_Closedown_ECU ( & j1939 );
return 0 ;
} См. Примеры в Examples -> SAE J1939 Как изменить адрес, имя или идентификации для вашего ECU.
Структура проекта
Рабочий пример, как выполняется структура Open SAE J1939
Эта блок -схема в коде, как работает открытая библиотека SAE J1939. Этот пример демонстрирует, как отправить запрос и получить ответ.
- Шаг 1:
ECU X собирается отправить PGN в ECU Y Интерпретация PGN как код функции. | Enum_j1939_status_codes SAE_J1939_SEND_REQUEST_ECU_IDENITICIFITIACE ( J1939 * J1939 , UINT8_T DA ) { |
| вернуть SAE_J1939_SEND_REQUEST ( J1939 , DA , PGN_ECU_IDENTIFIFICE ); |
| } |
- Шаг 2:
ECU Y будет прочитать это сообщение PGN от ECU X | bool is_new_message = can_read_message ( & id , data ); |
| if ( is_new_message ) { |
| / * Сохранить последний */ |
| J1939 -> id = id ; |
| Memcpy ( J1939 -> Data , Data , 8 ); |
| J1939 -> id_and_data_is_updated = true; |
| |
| uint8_t id0 = id >> 24 ; |
| uint8_t id1 = id >> 16 ; |
| uint8_t da = id >> 8 ; /* Адрес назначения, который является ЭБУ. Если da = 0xff = транслировать во всех ECU. Иногда DA тоже может быть идентификационный номер */ |
| uint8_t sa = id ; / * Адрес источника ЭБУ, что мы получили сообщение от */ |
| |
| / * Читать запрос из других ECU */ |
| if ( id0 == 0x18 && id1 == 0xea && ( da == j1939 -> information_this_ecu . this_ecu_address || da == 0xff )) { |
| SAE_J1939_Read_Request ( J1939 , SA , DATA ); |
- Шаг 3: Код функции
PGN будет интерпретироваться ECU Y . | void sae_j1939_read_request ( j1939 * j1939 , uint8_t sa , uint8_t data []) { |
| uint32_t pgn = ( data [ 2 ] << 16 ) | ( Данные [ 1 ] << 8 ) | данные [ 0 ]; |
| if ( pgn == pgn_acknowledgement ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_address_claimed ) { |
| Sae_j1939_response_request_address_claimed ( J1939 ); |
| } else if ( pgn == pgn_commanded_address ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_address_delete ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); / * Не SAE J1939 Стандарт */ |
| } else if ( pgn == pgn_dm1 ) { |
| Sae_j1939_response_request_dm1 ( J1939 , SA ); |
| } else if ( pgn == pgn_dm2 ) { |
| Sae_j1939_response_request_dm2 ( J1939 , SA ); |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_dm3 ) { |
| Sae_j1939_response_request_dm3 ( J1939 , SA ); |
| } else if ( pgn == pgn_request ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_tp_cm ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_tp_dt ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } else if ( pgn > = pgn_auxiliary_valve_estimated_flow_0 && pgn <= pgn_auxiliary_valve_estimated_flow_15 ) { |
| Iso_11783_response_request_auxiliary_valve_estimated_flow ( j1939 , pgn & 0xf ); / * Pgn & 0xf = valve_number */ |
| } else if ( pgn == pgn_general_purpose_valve_estimated_flow ) { |
| Iso_11783_response_request_general_purpose_valve_estimated_flow ( J1939 , SA ); |
| } else if ( pgn > = pgn_auxiliary_valve_measured_position_0 && pgn <= pgn_auxiliary_valve_measured_position_15 ) { |
| Iso_11783_response_request_auxiliary_valve_measured_position ( j1939 , pgn & 0xf ); / * Pgn & 0xf = valve_number */ |
| } else if ( pgn == pgn_software_identification ) { |
| Sae_j1939_response_request_software_identification ( J1939 , SA ); |
| } else if ( pgn == pgn_ecu_identification ) { |
| Sae_j1939_response_request_ecu_identification ( J1939 , SA ); |
- Шаг 4: Код функции
PGN теперь интерпретируется как ECU Identification по ECU Y Затем ECU Y собирается транслировать ECU Identification для всех ECUs .- Шаг 4.1.1: Для 1 пакетного сообщения
ECU Y собирается транслировать ECU Identification . | Enum_j1939_status_codes sae_j1939_response_request_ecu_identification ( J1939 * J1939 , uint8_t da ) { |
| / * Найти длину полей массива */ |
| uint8_t length_of_each_field = j1939 -> information_this_ecu . это_идентификация . ECU_IDIDICANE . length_of_each_field ; |
| if ( length_of_each_field < 2 ) { |
| / * Если каждое поле имеет длину 1, то мы можем отправить идентификацию ECU, так как это было нормальное сообщение */ |
| uint32_t id = ( 0x18fdc5 << 8 ) | J1939 -> information_this_ecu . this_ecu_address ; |
| data uint8_t [ 8 ]; |
| DATA [ 0 ] = J1939 -> Information_THIS_ECU . это_идентификация . ECU_IDIDICANE . ecu_part_number [ 0 ]; |
| ДАННЫЕ [ 1 ] = J1939 -> Information_THIS_ECU . это_идентификация . ECU_IDIDICANE . ecu_serial_number [ 0 ]; |
| Данные [ 2 ] = J1939 -> Information_THIS_ECU . это_идентификация . ECU_IDIDICANE . ecu_location [ 0 ]; |
| Данные [ 3 ] = J1939 -> Information_THIS_ECU . это_идентификация . ECU_IDIDICANE . ecu_type [ 0 ]; |
| Данные [ 4 ] = 0xff ; /* Сдержанный */ |
| Данные [ 5 ] = 0xff ; /* Сдержанный */ |
| Данные [ 6 ] = 0xff ; /* Сдержанный */ |
| Данные [ 7 ] = 0xff ; /* Сдержанный */ |
| вернуть can_send_message ( id , data ); |
| } еще { |
- Шаг 4.1.2:
ECU X Прочитайте ответ от ECU Y , потому что ECU Identification транслируется. | } else if ( id0 == 0x18 && id1 == 0xfd && da == 0xc5 ) { |
| Sae_j1939_read_response_request_ecu_identification ( j1939 , sa , data ); |
- Шаг 4.2.1: Для многоучетного сообщения контрольный байт может быть BAM или RTS. BAM используется только в том случае, если вы отправляете во все
ECUs например, адрес 0xFF = 255 . Но если контрольный байт является RTS, например, адрес не является 0xFF , то ECU Y собирается отправить RTS и выслушать ответ CTS от ECU X RTS - это вопрос: «Дайте мне знать, когда я смогу передать сообщение?» и CTS - это ответ Now you can transmit the message to me . | J1939 -> this_ecu_tp_cm . total_message_size = 0 ; |
| uint8_t i ; |
| for ( i = 0 ; i < length_of_each_field ; i ++ ) { |
| J1939 -> this_ecu_tp_dt . data [ i ] = J1939 -> information_this_ecu . это_идентификация . ECU_IDIDICANE . ecu_part_number [ i ]; |
| J1939 -> this_ecu_tp_dt . data [ length_of_each_field + i ] = j1939 -> information_this_ecu . это_идентификация . ECU_IDIDICANE . ecu_serial_number [ i ]; |
| J1939 -> this_ecu_tp_dt . data [ length_of_each_field * 2 + i ] = j1939 -> information_this_ecu . это_идентификация . ECU_IDIDICANE . ecu_location [ i ]; |
| J1939 -> this_ecu_tp_dt . data [ length_of_each_field * 3 + i ] = J1939 -> information_this_ecu . это_идентификация . ECU_IDIDICANE . ecu_type [ i ]; |
| J1939 -> this_ecu_tp_cm . total_message_size += 4 ; |
| } |
| |
| / * Отправить TP CM */ |
| J1939 -> this_ecu_tp_cm . number_of_packages = j1939 -> this_ecu_tp_cm . total_message_size % 8 > 0 ? J1939 -> this_ecu_tp_cm . total_message_size / 8 + 1 : J1939 -> this_ecu_tp_cm . total_message_size / 8 ; / * Закругление */ |
| J1939 -> this_ecu_tp_cm . Pgn_of_the_packeted_message = pgn_ecu_identification ; |
| J1939 -> this_ecu_tp_cm . control_byte = da == 0xff ? CONTROL_BYTE_TP_CM_BAM : CONTROL_BYTE_TP_CM_RTS ; / * Если транслировать, используйте байт управления BAM */ |
| Enum_j1939_status_codes status = sae_j1939_send_transport_protocol_connection_management ( J1939 , da ); |
- Шаг 4.2.2: Если
ECU Y отправляет RTS, то ECU X будет читать RTS и ответ с CTS обратно на ECU Y | if ( j1939 -> from_other_ecu_tp_cm . control_byte == control_byte_tp_cm_rts ) { |
| J1939 -> this_ecu_tp_cm = j1939 -> from_other_ecu_tp_cm ; / * Копировать - нам нужно иметь одинаковые данные */ |
| J1939 -> this_ecu_tp_cm . control_byte = control_byte_tp_cm_cts ; / * Нам нужно только изменить контрольный байт с RTS на CTS */ |
| Sae_j1939_send_transport_protocol_connection_management ( J1939 , SA ); |
| } |
- Шаг 4.2.3: После того, как
ECU Y получил CTS, он собирается передавать данные, в данном случае ECU Identification , обратно в ECU X | if ( j1939 -> from_other_ecu_tp_cm . control_byte == control_byte_tp_cm_cts ) { |
| SAE_J1939_SEND_TRANSPORT_PROTOCOL_DATA_TRANSFER ( J1939 , SA ); |
| } |
- Шаг 4.2.3: После того, как
ECU Y отправляет пакет после пакета ... | Enum_j1939_status_codes sae_j1939_send_transport_protocol_data_transfer ( J1939 * J1939 , uint8_t da ) { |
| uint32_t id = ( 0x1ceb << 16 ) | ( Da << 8 ) | J1939 -> information_this_ecu . this_ecu_address ; |
| uint8_t i , j , package [ 8 ]; |
| uint16_t bytes_sent = 0 ; |
| Enum_j1939_status_codes status = status_send_ok ; |
| for ( i = 1 ; i <= j1939 -> this_ecu_tp_cm . number_of_packages ; i ++ ) { |
| пакет [ 0 ] = i ; / * Количество пакета */ |
| for ( j = 0 ; j < 7 ; j ++ ) { |
| if ( bytes_sent < J1939 -> this_ecu_tp_cm . total_message_size ) { |
| Пакет [ j + 1 ] = J1939 -> this_ecu_tp_dt . data [ bytes_sent ++ ]; / * Данные, которые мы собрали */ |
| } еще { |
| пакет [ j + 1 ] = 0xff ; /* Сдержанный */ |
| } |
| } |
| status = can_send_message ( id , пакет ); |
| Can_delay ( 100 ); / * Важно может задержать в соответствии со стандартом */ |
| if ( status ! = status_send_ok ) { |
| Статус возврата ; |
| } |
| } |
| Статус возврата ; |
| } |
- Шаг 4.2.4: тогда
ECU X приобретает каждый пакет и создает сообщение, зная код функции PNG . | void sae_j1939_read_transport_protocol_data_transfer ( j1939 * J1939 , uint8_t sa , uint8_t data []) { |
| / * Сохранить данные последовательности */ |
| J1939 -> from_other_ecu_tp_dt . sequence_number = data [ 0 ]; |
| J1939 -> from_other_ecu_tp_dt . from_ecu_address = sa ; |
| uint8_t i , j , index = data [ 0 ] - 1 ; |
| for ( i = 1 ; i < 8 ; i ++ ) { |
| J1939 -> from_other_ecu_tp_dt . ДАННЫЕ [ ИНДЕКС * 7 + I - 1 ] = DATA [ i ]; / * Для каждого пакета мы отправляем 7 байтов данных, где данные первого байта [0] являются номером последовательности */ |
| } |
| / * Проверьте, заполнили ли мы наше сообщение - return = не завершено */ |
| if ( j1939 -> from_other_ecu_tp_cm . number_of_packages ! = J1939 -> from_other_ecu_tp_dt . sequence_number || j1939 -> from_other_ecu_tp_cm . Number_of_packages == 0 ) {> |
| возвращаться ; |
| } |
| |
| / * Наше сообщение завершено - создайте его и назовите его overse_data [total_message_size] */ |
| uint32_t pgn = j1939 -> from_other_ecu_tp_cm . Pgn_of_the_packeted_message ; |
| uint16_t total_message_size = j1939 -> from_other_ecu_tp_cm . total_message_size ; |
| uint8_t worth_data [ max_tp_dt ]; |
| uint16_t inserted_bytes = 0 ; |
| for ( i = 0 ; i < J1939 -> from_other_ecu_tp_dt . sequence_number ; i ++ ) { |
| for ( j = 0 ; j < 7 ; j ++ ) { |
| if ( inserted_bytes < total_message_size ) { |
| ulep_data [ inserted_bytes ++ ] = J1939 -> from_other_ecu_tp_dt . данные [ i * 7 + j ]; |
| } |
| } |
| } |
| |
| / * Отправить конец сообщения ack обратно */ |
| if ( j1939 -> from_other_ecu_tp_cm . control_byte == control_byte_tp_cm_rts ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTROL_BYTE_TP_CM_ENDOFMSGACK , GROUP_FUNCE_VALUE_NORMAL , PGN ); |
| } |
А затем, наконец, реализуйте сообщение. | case pgn_ecu_identification : |
| Sae_j1939_read_response_request_ecu_identification ( j1939 , sa , ushom_data ); |
| перерыв ; |
SAE J1939 Функциональность
- SAE J1939: 21 Транспортный слой
- Подтверждение
- Запрос
- Управление соединением транспортного протокола с BAM, CTS, RTS и EOM
- Передача данных транспортного протокола
- SAE J1939: 71 слой приложения
- Запрос идентификация компонента
- Запросить идентификацию ECU
- Запросить идентификацию программного обеспечения
- Запрос запатентованный а
- Запрос запатентованный б
- SAE J1939: 73 Диагностический слой
- DM1
- DM2
- DM3
- DM14
- DM15
- DM16
- SAE J1939: 81 Уровень управления сетью
- Адрес заявлено
- Командный адрес
- Адрес не заявлен
- Удалить адрес
Дополнительная функциональность
- ISO 11783 Тракторы и машины для сельского хозяйства и лесного хозяйства
- ISO 11783-7 Реализация сообщений.
- Команда вспомогательного клапана
- Основной поток вспомогательного клапана
- Измеренное положение вспомогательного клапана
- Команда клапана общего назначения
- Расчетный поток клапана общего назначения
Вопросы и ответы
- В: Можно ли использовать эту библиотеку с
C++ ?- A: Да, это можно использовать с
C++
- В: Я хочу построить эту библиотеку, что мне делать?
- A: Сначала вам нужно знать
ANSI C (C89) и бить. Затем вам нужно понять структуру SAE J1939:21 Transport Layer . Не забудьте обновить PDF с вашей новой функциональностью.
- В: Могу ли я использовать это на своем Arduino?
- A: Да, этот
C -код составляет 100% Cure C -код и используется только стандартная библиотека C , а также код не учитывает, какое оборудование вы используете.
- В: Нужно ли установить библиотеку, чтобы использовать библиотеку?
- A: Нет, просто скопируйте файлы
.c и .h в ваш проект и компиляция. Я использовал это с QT Framework.
- В: Этот проект сейчас довольно старый и не так много обновлений, стоит ли его использовать?
- A: Да, эта библиотека обновляется только тогда, когда я или другой включает в себя больше функциональности от SAE J1939. Причина, по которой я написал это в
ANSI C (C89) заключается в том, что это отраслевой стандарт, и вы всегда сможете собрать эту библиотеку и использовать ее на всех системах.
- В: Каков ваш план с библиотекой?
- A: Чтобы сделать SAE J1939 доступным для всех
- Q: У меня нет байса, но могу ли я использовать эту библиотеку в любом случае с UART, USB, WiFi и т. Д.?
- A: Да. Это только способ сформировать сообщение определенным образом.
- В: Могу ли я отправить данные с этой библиотекой, даже если у меня нет байса?
- A: Да. Есть что -то, что называется запросом на передачу DM14, ответ статуса DM15 и бинарная передача DM16. Используйте это, если вы хотите перенести данные промышленным способом.
- В: Могу ли я одновременно отправлять несколько пакетных сообщений из нескольких ECU в один ECU?
- A: Нет. Если вы начинаете отправлять многочисленные многочисленные ответы из нескольких ECU в другой ECU, то этот ECU не может понять сообщение. Передайте только многократные сообщения по одному в то время, если адрес назначения одинаково.
- В: Я не хочу использовать
ANSI C (C89) с открытым SAE J1939. Могу ли я использовать последний стандарт C с Open SAE J1939?- Да, вы можете использовать последний стандарт C с этой библиотекой.
- В: Можно ли составить эту библиотеку на машине Windows MS-DOS или Windows 95?
- C89, совместимый компилятор и IDE, и это не должно быть никакой проблемой
- В: Могу ли я настроить память, занятую программой?
- A: Да, вы можете настроить определение
MAX_PROPRIETARY_A , MAX_PROPRIETARY_B и MAX_PROPRIETARY_B_PGNS в файлах Structs.h в соответствии с вашим вариантом использования. Значение «SANE» по умолчанию предоставляется, но вы можете установить их на минимум, если запатентованная поддержка PGNS не требуется, или увеличить его, если необходимо использовать больше PGN.
Проблемы и ответы
- Я: я не могу скомпилировать эту библиотеку. Я использую
Keil Microvision .- A:
Keil Microvision не может обрабатывать двоичные числа, такие как 0b010101 . Попробуйте STM32CubeIDE , потому что Open SAE J1939 сделан в STM32CubeIDE
- Я: Можете ли вы предоставить нам несколько аппаратных примеров, например,
STM32 ?- A: Да! Существует пример STM32, как подключиться к CAN-BUS, включая слушателя прерываний для сообщений. Перейдите к
Examples -> Hardware папка в поисках CAN_STM32.txt . Также есть пример USB для QT C++ .