Öffnen Sie SAE J1939
SAE J1939 ist ein Protokoll zur Gestaltung der Can-Bus-Nachricht auf eine bestimmte Art und Weise, die Industriefahrzeuge wie Traktoren, Maschinen, Lastwagen und mehr entspricht.
SAE J1939 ist ein sehr einfaches Protokoll, aber es fehlen Informationen zu SAE J1939, da die Kosten des Protokolldokuments verfügbar sind, wie eine Can-BuS-Nachricht gemäß SAE J1939 Protokollstandard geformt wird. Daher schreibe ich ein SAE J1939 -Protokoll, das kostenlos für eingebettete Systeme wie STM32, Arduino, AVR, PIC usw. oder PC verwendet werden kann.
Um auf diesem Projekt aufzubauen, müssen Sie SAE J1939 zuerst verstehen. Ich habe dieses Projekt in C -Sprache geschrieben, weil C ein Branchenstandard ist. Der von mir ausgewählte C -Sprachdialekt ist ANSI C (C89) und ich verwende in dieser Bibliothek keine dynamische Speicherzuweisung. Es wird also mit MISRA C Standard funktionieren.
Mit dieser Bibliothek können Sie mit Ventilen, Motoren, Aktuatoren, Maschinen, Hardware und allen anderen Dingen kommunizieren, die für schwere industrielle mobile Anwendungen geeignet sind. Ich habe eine grundlegende Struktur des Projekts aufgebaut und hoffe, dass andere Benutzer die Pull -Anfrage ihres C -Codes für zusätzliche Funktionen an SAE J1939 Standard senden, da SAE J1939 ein großer Standard ist.
Suchen Sie nach C Canopen Library für eingebettete Systeme? https://github.com/danielmarensson/easy-canopen
Suchen Sie nach einem C ++ - GUI -Framework, das Open SAE J1939 über dem USB verwendet? https://github.com/danielmarensson/goobysoft
Auf der Suche nach einem C STM32 -Projekt mit Open SAE J1939? https://github.com/danielmarensson/stm32-plc
Erste Schritte
Das erste, was Sie wissen müssen, ist, mein eigenes PDF -Dokument von Open SAE J1939 im Documentation zu lesen. Erfahren Sie die Struktur des Projekts, sonst werden Sie SAE J1939 nicht verstehen. Nachdem Sie ein grundlegendes Verständnis des Projekts erhalten haben, können Sie darauf aufbauen. Halten Sie es einfach und folgen Sie dem SAE J1939 Standard!
Nachdem Sie die Struktur des Projekts verstanden haben, wählen Sie dann die Auswahl der Prozessor in Hardware -> Hardware.h -Datei aus. Hier können Sie zum Beispiel STM32 , Arduino , PIC , AVR usw. auswählen oder wenn Sie es zuerst auf dem PC ausführen möchten, dann wählen Sie PROCESSOR_CHOICE 0 und führen Sie einige Beispiele aus. Das ist der Debugging -Modus für interne Feedback.
So verwenden Sie das Projekt
- Schritt 1: Laden Sie dieses Repository herunter
- Schritt 2: Gehen Sie zu
Hardware -> Hardware.h und wählen Sie Ihren Prozessor aus. Wenn er nicht verfügbar ist, schreiben Sie bitte Code und senden Sie mir eine Pull -Anfrage - Schritt 3: Kopieren Sie den
Src -Ordner in Ihrem Projektordner in Ihrer IDE. Benennen Sie Src um zum Beispiel Open SAE J1939 . Das ist ein guter Name. - Schritt 4: Verwenden Sie die
Examples -> Open SAE J1939 -> Main.txt Beispiel als anfänglicher Startcode für ein SAE J1939 -Projekt.
/*
* 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 ;
} In den Beispielen finden Sie in Examples -> SAE J1939 wie Sie die Adresse, den Namen oder die Identifikationen für Ihr ECU ändern.
Die Struktur des Projekts
Ein funktionierendes Beispiel, wie die Struktur der offenen SAE J1939 fertig ist
Dieses Flussdiagramm in Code Wie öffnet die SAE J1939 -Bibliothek. In diesem Beispiel wird gezeigt, wie Sie eine Anfrage senden und eine Antwort erhalten.
- Schritt 1:
ECU X wird ein PGN an ECU Y senden. Interpretieren Sie PGN als Funktionscode. | Enum_j1939_status_codes sae_j1939_send_request_ecu_identification ( j1939 * j1939 , uint8_t da ) { |
| return sae_j1939_send_request ( J1939 , DA , pgn_ecu_identification ); |
| } |
- Schritt 2:
ECU Y wird diese PGN -Nachricht von ECU X lesen. | bool is_new_message = can_read_message ( & id , data ); |
| if ( is_new_message ) { |
| / * Neueste speichern */ |
| J1939 -> id = id ; |
| memcpy ( J1939 -> Daten , Daten , 8 ); |
| J1939 -> id_and_data_is_updated = true; |
| |
| uint8_t id0 = id >> 24 ; |
| uint8_t id1 = id >> 16 ; |
| uint8_t da = id >> 8 ; /* Zieladresse, die dieses ECU ist. Wenn da = 0xff = an alle ECU übertragen wird. Manchmal kann da auch eine ID -Nummer sein */ |
| uint8_t sa = id ; / * Quelladresse der ECU, dass wir die Nachricht von */erhalten haben |
| |
| / * Anfrage von einem anderen ECU lesen *// * |
| if ( id0 == 0x18 && id1 == 0xea && ( da == j1939 -> Information_this_ecu . this_ecu_address || da == 0xff )) { |
| Sae_j1939_read_request ( j1939 , sa , data ); |
- Schritt 3: Der
PGN -Funktionscode wird durch ECU Y interpretiert. | void sae_j1939_read_request ( j1939 * j1939 , uint8_t sa , uint8_t data []) { |
| UINT32_T PGN = ( Daten [ 2 ] << 16 ) | ( Daten [ 1 ] << 8 ) | Daten [ 0 ]; |
| if ( pgn == pgn_acknowledGement ) { |
| Sae_j1939_send_acknowledGement ( j1939 , sa , control_byte_acknowledgement_pgn_supported , gruppe_function_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 , gruppe_function_value_normal , pgn ); |
| } else if ( pgn == pgn_address_delete ) { |
| Sae_j1939_send_acknowledGement ( j1939 , sa , control_byte_acknowledgement_pgn_supported , gruppe_function_value_normal , pgn ); / * Nicht SAE J1939 Standard */ |
| } 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 , gruppe_function_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 , gruppe_function_value_normal , pgn ); |
| } else if ( pgn == pgn_tp_cm ) { |
| Sae_j1939_send_acknowledGement ( j1939 , sa , control_byte_acknowledgement_pgn_supported , gruppe_function_value_normal , pgn ); |
| } else if ( pgn == pgn_tp_dt ) { |
| Sae_j1939_send_acknowledGement ( j1939 , sa , control_byte_acknowledgement_pgn_supported , gruppe_function_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_purple_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_meesured_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 ); |
- Schritt 4: Der
PGN -Funktionscode wird jetzt als ECU Identification durch ECU Y interpretiert. Dann wird ECU Y die ECU Identification an alle ECUs übertragen.- Schritt 4.1.1: Für 1 Paketnachricht wird
ECU Y die ECU Identification übertragen. | Enum_j1939_status_codes sae_j1939_response_request_ecu_identification ( j1939 * j1939 , uint8_t da ) { |
| / * Finde die Länge der Array -Felder */ |
| uint8_t length_of_each_field = j1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . Länge_OF_EACH_FIELD ; |
| if ( länge_of_each_field < 2 ) { |
| / * Wenn jedes Feld die Länge 1 hat, können wir die ECU -Identifikation senden, da es sich um eine normale Nachricht handelte */ |
| uint32_t id = ( 0x18fdc5 << 8 ) | J1939 -> Information_this_ecu . this_ecu_address ; |
| Uint8_t -Daten [ 8 ]; |
| Daten [ 0 ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_part_number [ 0 ]; |
| Daten [ 1 ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_serial_number [ 0 ]; |
| Daten [ 2 ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_location [ 0 ]; |
| Daten [ 3 ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_type [ 0 ]; |
| Daten [ 4 ] = 0xff ; / * Reserviert */ |
| Daten [ 5 ] = 0xff ; / * Reserviert */ |
| Daten [ 6 ] = 0xff ; / * Reserviert */ |
| Daten [ 7 ] = 0xff ; / * Reserviert */ |
| return CAN_SEND_MESSAGE ( ID , Daten ); |
| } anders { |
- Schritt 4.1.2:
ECU X Lesen Sie die Antwort aus ECU Y , da die ECU Identification ausgestrahlt wird. | } else if ( id0 == 0x18 && id1 == 0xfd && da == 0xc5 ) { |
| Sae_j1939_read_response_request_ecu_identification ( j1939 , sa , data ); |
- Schritt 4.2.1: Für eine Multi -Paket -Nachricht kann das Steuerbyte entweder BAM oder RTS sein. BAM wird nur verwendet, wenn Sie an alle
ECUs -EG -Adresse 0xFF = 255 senden. Wenn das Steuerungsbyte jedoch RTS ist, ist z. B. die Adresse nicht 0xFF , dann wird ECU Y eine RTS senden und auf eine CTS -Antwort von ECU X anhören. RTS ist eine Frage zu "Lassen Sie mich wissen, wann ich die Nachricht übertragen kann?" Und CTS ist eine Antwort Now you can transmit the message to me . | J1939 -> this_ecu_tp_cm . total_message_size = 0 ; |
| uint8_t i ; |
| für ( i = 0 ; i < länge_of_each_field ; i ++ ) { |
| J1939 -> this_ecu_tp_dt . Daten [ i ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_part_number [ i ]; |
| J1939 -> this_ecu_tp_dt . Daten [ Länge_of_each_field + i ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_serial_number [ i ]; |
| J1939 -> this_ecu_tp_dt . Daten [ Länge_of_each_Field * 2 + i ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_location [ i ]; |
| J1939 -> this_ecu_tp_dt . Daten [ Länge_of_ach_field * 3 + i ] = J1939 -> Information_this_ecu . this_identifications . ECU_Identifikation . ecu_type [ i ]; |
| J1939 -> this_ecu_tp_cm . total_message_size += 4 ; |
| } |
| |
| / * TP cm */senden |
| 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 ; / * Runding auf */ |
| J1939 -> this_ecu_tp_cm . PGN_OF_THE_PACKETED_MESSAGE = PGN_ECU_IDIENTIFIZIERUNG ; |
| J1939 -> this_ecu_tp_cm . contrel_byte = da == 0xff ? Control_byte_tp_cm_bam : control_byte_tp_cm_rts ; / * Wenn ausgestrahlt wird, dann verwenden Sie BAM Control Byte */ |
| Enum_j1939_status_codes status = sae_j1939_send_transport_protocol_connection_management ( j1939 , da ); |
-
ECU Y 4.2.2: Wenn ECU Y ECU X RTS sendet | 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 ; / * Kopie - Wir müssen die gleichen Daten haben */ |
| J1939 -> this_ecu_tp_cm . control_byte = control_byte_tp_cm_cts ; / * Wir müssen nur das Steuerbyte von RTS auf CTS */ändern |
| Sae_j1939_send_transport_protocol_connection_management ( j1939 , sa ); |
| } |
- Schritt 4.2.3: Sobald
ECU Y die CTS erhalten hat, wird die Daten, in diesem Fall ECU Identification , nach ECU X übertragen. | if ( j1939 -> from_other_ecu_tp_cm . control_byte == control_byte_tp_cm_cts ) { |
| Sae_j1939_send_transport_protocol_data_transfer ( j1939 , sa ); |
| } |
- Schritt 4.2.3: Sobald
ECU Y Paket nach dem Paket sendet ... | 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 , Paket [ 8 ]; |
| uint16_t bytes_ent = 0 ; |
| Enum_j1939_status_codes status = status_send_ok ; |
| für ( i = 1 ; i <= j1939 -> this_ecu_tp_cm . number_of_packages ; i ++ ) { |
| Paket [ 0 ] = i ; / * Anzahl des Pakets */ |
| für ( j = 0 ; j < 7 ; j ++ ) { |
| if ( bytes_sen < j1939 -> this_ecu_tp_cm . Total_message_size ) { |
| Paket [ j + 1 ] = j1939 -> this_ecu_tp_dt . Daten [ bytes_sent ++ ]; / * Daten, die wir gesammelt haben */ |
| } anders { |
| Paket [ j + 1 ] = 0xff ; / * Reserviert */ |
| } |
| } |
| status = can_send_message ( id , paket ); |
| CAN_DELAY ( 100 ); / * Wichtig kann nach Standard */// |
| if ( Status ! = Status_Send_OK ) { |
| Rückgabestatus ; |
| } |
| } |
| Rückgabestatus ; |
| } |
- Schritt 4.2.4: Dann erhält
ECU X jedes Paket und erstellt die Nachricht, indem Sie den PNG -Funktionscode kennen. | void sae_j1939_read_transport_protocol_data_transfer ( j1939 * j1939 , uint8_t sa , uint8_t data []) { |
| / * Speichern Sie die Sequenzdaten */ |
| J1939 -> von_other_ecu_tp_dt . sequence_number = data [ 0 ]; |
| J1939 -> von_other_ecu_tp_dt . from_ecu_address = sa ; |
| uint8_t i , j , index = data [ 0 ] - 1 ; |
| für ( i = 1 ; i < 8 ; i ++ ) { |
| J1939 -> von_other_ecu_tp_dt . Daten [ Index * 7 + i - 1 ] = Daten [ i ]; / * Für jedes Paket senden wir 7 Bytes von Daten, wobei die ersten Byte -Daten [0] die Sequenznummer *///// |
| } |
| / * Überprüfen Sie, ob wir unsere Nachricht abgeschlossen haben - return = nicht abgeschlossen */ |
| if ( j1939 - > from_other_ecu_tp_cm . number_of_packages ! |
| zurückkehren ; |
| } |
| |
| / * Unsere Nachricht ist abgeschlossen - erstellen und nennen |
| 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 complete_data [ max_tp_dt ]; |
| uint16_t incited_bytes = 0 ; |
| für ( i = 0 ; i < j1939 -> from_other_ecu_tp_dt . sequence_number ; i ++ ) { |
| für ( j = 0 ; j < 7 ; j ++ ) { |
| if ( incised_bytes < Total_message_size ) { |
| complete_data [ invised_bytes ++ ] = j1939 -> from_other_ecu_tp_dt . Daten [ i * 7 + j ]; |
| } |
| } |
| } |
| |
| / * Senden Sie ein Ende der Nachricht ack zurück */ |
| 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 , gruppe_function_value_normal , pgn ); |
| } |
Und dann schließlich die Nachricht implementieren. | Fall PGN_ECU_Identifikation : |
| Sae_j1939_read_response_request_ecu_identification ( j1939 , sa , complete_data ); |
| brechen ; |
SAE J1939 Funktionalität
- SAE J1939: 21 Transportschicht
- Anerkennung
- Anfrage
- Transportprotokollverbindungsmanagement mit BAM, CTS, RTS und EOM
- Transportprotokolldatenübertragung
- SAE J1939: 71 Anwendungsschicht
- Anfragekomponentenidentifikation
- Fordern Sie die ECU -Identifizierung an
- Software -Identifizierung anfordern
- Anfrage proprietär a
- Anfrage proprietär b
- SAE J1939: 73 Diagnostikschicht
- DM1
- DM2
- DM3
- DM14
- DM15
- DM16
- SAE J1939: 81 Netzwerkverwaltungsschicht
- Adresse behauptet
- Kommandierte Adresse
- Adresse nicht geltend
- Adresse löschen
Zusätzliche Funktionalität
- ISO 11783 Traktoren und Maschinen für Landwirtschaft und Forstwirtschaft
- ISO 11783-7 Implementieren der Nachrichtenanwendungsschicht
- Hilfsventilbefehl
- Hilfsventil geschätzter Fluss
- Hilfsventil gemessene Position
- Allzweckventilbefehl
- Allzweckventil geschätzter Fluss
Fragen und Antworten
- F: Kann diese Bibliothek mit
C++ verwendet werden?- A: Ja, es kann mit
C++ verwendet werden
- F: Ich möchte auf dieser Bibliothek aufbauen. Was soll ich tun?
- A: Zuerst müssen Sie
ANSI C (C89) und bitweise Operationen kennen. Dann müssen Sie die SAE J1939:21 Transport Layer verstehen. Vergessen Sie nicht, die PDF mit Ihrer neuen Funktionalität zu aktualisieren.
- F: Kann ich das auf meinem Arduino verwenden?
- A: Ja, dieser
C -Code ist 100% reinen C -Code und nur C -Standardbibliothek verwendet, und auch der Code berücksichtigt nicht, welche Hardware Sie verwenden.
- F: Muss ich die Bibliothek für die Verwendung der Bibliothek installieren?
- A: Nein, kopieren Sie einfach die Dateien
.c und .h in Ihr Projekt und kompilieren Sie. Ich habe dies mit QT -Framework verwendet.
- F: Dieses Projekt ist jetzt ziemlich alt und nicht so viele Updates. Lohnt es sich immer noch, es zu benutzen?
- A: Ja, diese Bibliothek aktualisiert nur, wenn ich oder andere mehr Funktionen von SAE J1939 enthält. Der Grund, warum ich dies in
ANSI C (C89) geschrieben habe, ist, dass es sich um einen Branchenstandard handelt und Sie diese Bibliothek immer kompilieren und auf allen Systemen verwenden können.
- F: Was ist Ihr Plan mit der Bibliothek?
- A: SAE J1939 für alle verfügbar machen
- F: Ich habe keinen Can-Bus, aber kann ich diese Bibliothek sowieso mit UART, USB, WiFi usw. verwenden?
- A: Ja. Dies ist nur eine Möglichkeit, eine Nachricht auf eine bestimmte Weise zu formen.
- F: Kann ich Daten mit dieser Bibliothek senden, auch wenn ich keinen Can-Bus habe?
- A: Ja. Es gibt etwas, das als DM14 -Senderanforderung, DM15 -Statusantwort und DM16 -Binärübertragung bezeichnet wird. Verwenden Sie dies, wenn Sie Daten auf industrielle Weise übertragen möchten.
- F: Kann ich gleichzeitig Multi -Paket -Nachrichten von mehreren ECUs an ein ECU senden?
- A: Nein. Wenn Sie anfangen, Multipackages von mehreren ECUs an ein anderes ECU zu senden, kann diese ECU die Nachricht nicht verstehen. Übertragen Sie nur Multipackage -Nachrichten zu der Zeit, wenn die Zieladresse gleich ist.
- F: Ich möchte
ANSI C (C89) mit offenem SAE J1939 nicht verwenden. Kann ich den neuesten C -Standard mit Open SAE J1939 verwenden?- Ja, Sie können den neuesten C -Standard mit dieser Bibliothek verwenden.
- F: Ist es möglich, diese Bibliothek auf einem Windows MS-DOS oder Windows 95-Computer zu kompilieren?
- Ein C89 -kompatibler Compiler und eine IDE und es sollte kein Problem sein
- F: Kann ich den vom Programm besetzten Speicher einstellen?
- A: Ja, Sie können die Defines
MAX_PROPRIETARY_A , MAX_PROPRIETARY_B und MAX_PROPRIETARY_B_PGNS in der Structs.h gemäß Ihrem Anwendungsfall anpassen. Es wird ein „vernünftiger“ Standardwert bereitgestellt, aber Sie können sie auf das Minimum einstellen, wenn eine proprietäre PGNS -Unterstützung nicht benötigt wird, oder sie erhöhen oder erhöhen, wenn mehr PGNs verwendet werden müssen.
Probleme und Antworten
- I: Ich kann diese Bibliothek nicht kompilieren. Ich benutze
Keil Microvision .- A:
Keil Microvision kann Binärzahlen wie 0b010101 nicht verarbeiten. Versuchen Sie stattdessen STM32CubeIDE , da Open SAE J1939 in STM32CubeIDE hergestellt wird
- I: Können Sie uns einige Hardware -Beispiele zur Verfügung stellen, z. B.
STM32 ?- A: Ja! Es gibt ein STM32-Beispiel, wie Sie eine Verbindung zu Can-Bus erhalten, einschließlich eines Interrupt-Listeners für Nachrichten. Gehen Sie zu
Examples -> Hardware -Ordner bei Suchen Sie nach CAN_STM32.txt . Außerdem gibt es auch ein USB -Beispiel für QT C++ .