Open SAE J1939
SAE J1939 est un protocole pour façonner le message CAN-bus d'une manière spécifique qui convient aux véhicules industriels tels que les tracteurs, les machines, les camions et plus encore.
SAE J1939 est un protocole très facile à utiliser, mais il y a un manque d'informations sur SAE J1939, en raison du coût du document de protocole, disponible sur la façon de façonner un message CAN-BUS conformément à la norme de protocole SAE J1939. Par conséquent, j'écris gratuitement un protocole SAE J1939 disponible sur tous les systèmes intégrés tels que STM32, Arduino, AVR, PIC, etc. ou PC.
Pour apprendre à s'appuyer sur ce projet, vous avez d'abord besoin de comprendre SAE J1939. J'ai écrit ce projet en langue C car C est une norme de l'industrie. Le dialecte du langage C que j'ai choisi est ANSI C (C89) et je n'utilise pas d'allocation de mémoire dynamique dans cette bibliothèque. Cela fonctionnera donc avec MISRA C Standard.
Avec cette bibliothèque, vous pouvez communiquer avec les vannes, les moteurs, les actionneurs, les machines, le matériel et toutes les autres choses qui conviennent aux applications mobiles industrielles lourdes. J'ai accumulé une structure de base du projet et j'espère que d'autres utilisateurs enverront la demande de traction de leur code C pour des fonctionnalités supplémentaires à la norme SAE J1939 car SAE J1939 est une énorme norme.
Vous cherchez une bibliothèque C Canopen pour les systèmes intégrés? https://github.com/danielmartensson/easy-canopen
Vous cherchez un cadre d'interface graphique C ++ qui utilise Open SAE J1939 sur l'USB? https://github.com/danielmartensson/goobysoft
Vous cherchez un projet C STM32 avec Open SAE J1939? https://github.com/danielmartensson/stm32-plc
Commencer
La première chose que vous devez savoir est de lire mon propre document PDF d'Open SAE J1939 dans le dossier Documentation . Apprenez la structure du projet, sinon vous ne pourrez pas comprendre SAE J1939. Après avoir obtenu une compréhension de base du projet, vous pouvez y construire. Restez simple et suivez la norme SAE J1939!
Après avoir compris la structure du projet, sélectionnez le choix du processeur dans le fichier Hardware -> Hardware.h . Ici, vous pouvez sélectionner par exemple STM32 , Arduino , PIC , AVR etc. ou si vous souhaitez d'abord l'exécuter sur PC, puis sélectionnez PROCESSOR_CHOICE 0 et exécutez quelques exemples. Il s'agit du mode de débogage pour les commentaires internes de l'internes.
Comment utiliser le projet
- Étape 1: Téléchargez ce référentiel
- Étape 2: Accédez au
Hardware -> Hardware.h et sélectionnez votre processeur, s'il n'est pas disponible, veuillez écrire du code pour cela et envoyez-moi une demande de traction - Étape 3: Copiez le dossier
Src dans votre dossier de projet à l'intérieur de votre IDE. Renommer Src pour par exemple Open SAE J1939 . C'est un bon nom. - Étape 4: Utilisez les
Examples -> Open SAE J1939 -> Main.txt comme code de départ initial pour un projet 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 ;
} Voir les exemples dans Examples -> SAE J1939 Comment modifier l'adresse, le nom ou les identifications de votre ECU.
La structure du projet
Un exemple de travail comment la structure de l'Open SAE J1939 est effectuée
Ce tableau de flux dans le code comment fonctionne la bibliothèque Open SAE J1939. Cet exemple montre comment envoyer une demande et obtenir une réponse.
- Étape 1:
ECU X va envoyer un PGN à ECU Y . Interprétez PGN comme un code de fonction. | 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 ); |
| } |
- Étape 2:
ECU Y va lire ce message PGN à partir de ECU X . | bool is_new_message = can_read_message ( & id , data ); |
| if ( is_new_message ) { |
| / * Enregistrer le dernier * / |
| J1939 -> id = id ; |
| MEMCPY ( J1939 -> Données , données , 8 ); |
| J1939 -> id_and_data_is_updated = true; |
| |
| uint8_t id0 = id >> 24 ; |
| uint8_t id1 = id >> 16 ; |
| uint8_t da = id >> 8 ; / * Adresse de destination qui est ce ECU. Si da = 0xff = diffuser à tous les ECU. Parfois, DA peut aussi être un numéro d'identification * / |
| uint8_t sa = id ; / * Adresse source de l'ECU dont nous avons reçu le message * / |
| |
| / * Lire la demande d'autres ECU * / |
| if ( id0 == 0x18 && id1 == 0XEA && ( da == j1939 -> information_this_ecu . this_ecu_address || da == 0xff )) { |
| SAE_J1939_READ_REQUEST ( J1939 , SA , données ); |
- Étape 3: Le code de fonction
PGN sera interprété par ECU Y | void sae_j1939_read_request ( J1939 * J1939 , uint8_t sa , uint8_t data []) { |
| uint32_t pgn = ( data [ 2 ] << 16 ) | ( données [ 1 ] << 8 ) | données [ 0 ]; |
| if ( pgn == PGN_ACKNOWLEDGEMENT ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_address_claimed ) { |
| SAE_J1939_RESPONSE_REQUEST_ADDRESS_CLAMED ( J1939 ); |
| } else if ( pgn == pgn_commanded_address ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_address_delete ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); / * Pas 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 , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_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 , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_tp_cm ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } else if ( pgn == pgn_tp_dt ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } else if ( pgn > = pgn_auxiliary_valve_stimemated_flow_0 && pgn <= pgn_auxiliary_valve_stimated_flow_15 ) { |
| Iso_11783_response_request_auxiliary_valve_stimemated_flow ( J1939 , pgn & 0xf ); / * Pgn & 0xf = valve_number * / |
| } else if ( pgn == PGN_GENERAL_PURPOSE_VALVE_ESTIMated_flow ) { |
| Iso_11783_response_request_general_purpose_valve_stimated_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_RESPONSONS_REQUEST_SOFTWARE_IDENTIFICATION ( J1939 , SA ); |
| } else if ( pgn == pgn_ecu_identification ) { |
| SAE_J1939_RESPONSE_REQUEST_ECU_IDENTIFICATION ( J1939 , SA ); |
- Étape 4: Le code de fonction
PGN est désormais interprété comme ECU Identification par ECU Y ECU Y va ensuite diffuser l' ECU Identification à tous ECUs .- Étape 4.1.1: Pour 1 message de package,
ECU Y va diffuser l' ECU Identification . | Enum_j1939_status_codes sae_j1939_response_request_ecu_identification ( j1939 * j1939 , uint8_t da ) { |
| / * Trouvez la longueur des champs de tableau * / |
| uint8_t longueur_of_each_field = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . LONGNEMENT_OF_EACH_FIELD ; |
| if ( longueur_of_each_field < 2 ) { |
| / * Si chaque champ a la longueur 1, alors nous pouvons envoyer l'identification de l'ECU car c'était un message normal * / |
| uint32_t id = ( 0x18fdc5 << 8 ) | J1939 -> information_this_ecu . this_ecu_address ; |
| data uint8_t [ 8 ]; |
| data [ 0 ] = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_part_number [ 0 ]; |
| données [ 1 ] = J1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_serial_number [ 0 ]; |
| données [ 2 ] = J1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_location [ 0 ]; |
| données [ 3 ] = J1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_type [ 0 ]; |
| données [ 4 ] = 0xff ; / * Réservé * / |
| données [ 5 ] = 0xff ; / * Réservé * / |
| données [ 6 ] = 0xff ; / * Réservé * / |
| données [ 7 ] = 0xff ; / * Réservé * / |
| return can_send_message ( id , data ); |
| } autre { |
- Étape 4.1.2:
ECU X a lu la réponse de ECU Y car l' ECU Identification est diffusée. | } else if ( id0 == 0x18 && id1 == 0xfd && da == 0xc5 ) { |
| SAE_J1939_READ_RESPONSE_REQUEST_ECU_IDENTIFICATION ( J1939 , SA , DATA ); |
- Étape 4.2.1: Pour le message multi-package, l'octet de contrôle peut être BAM ou RTS. BAM n'est utilisé que si vous envoyez à toute l'adresse
ECUs EG 0xFF = 255 . Mais si l'octet de contrôle est RTS, l'adresse par exemple n'est pas 0xFF , alors ECU Y va envoyer un RTS et écouter une réponse CTS par ECU X RTS est une question pour "Faites-moi savoir quand je peux transmettre le message?" Et CTS est une réponse Now you can transmit the message to me . | J1939 -> this_ecu_tp_cm . Total_Message_Size = 0 ; |
| uint8_t i ; |
| pour ( i = 0 ; i < nough_of_each_field ; i ++ ) { |
| J1939 -> this_ecu_tp_dt . data [ i ] = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_part_number [ i ]; |
| J1939 -> this_ecu_tp_dt . Données [ longueur_of_each_field + i ] = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_serial_number [ i ]; |
| J1939 -> this_ecu_tp_dt . Données [ longueur_of_each_field * 2 + i ] = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_location [ i ]; |
| J1939 -> this_ecu_tp_dt . Données [ longueur_of_each_field * 3 + i ] = j1939 -> information_this_ecu . this_identifications . ECU_IDENTIFICATION . ecu_type [ i ]; |
| J1939 -> this_ecu_tp_cm . Total_Message_Size + = 4 ; |
| } |
| |
| / * Envoyer 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 ; / * Arrondir * / |
| J1939 -> this_ecu_tp_cm . Pgn_of_the_packeted_message = pgn_ecu_identification ; |
| J1939 -> this_ecu_tp_cm . contrôle_byte = da == 0xff ? CONTROL_BYTE_TP_CM_BAM : CONTROL_BYTE_TP_CM_RTS ; / * Si difficulté, utilisez l'octet de contrôle BAM * / |
| Enum_j1939_status_codes status = sae_j1939_send_transport_protocol_connection_management ( j1939 , da ); |
-
ECU Y 4.2.2: Si ECU X ECU Y envoie un RT | if ( j1939 -> from_other_ecu_tp_cm . Control_byte == Control_Byte_TP_CM_RTS ) { |
| j1939 -> this_ecu_tp_cm = j1939 -> de_other_ecu_tp_cm ; / * Copie - nous devons avoir les mêmes données * / |
| J1939 -> this_ecu_tp_cm . CONTROL_BYTE = CONTROL_BYTE_TP_CM_CTS ; / * Nous devons seulement changer l'octet de contrôle de RTS à CTS * / |
| SAE_J1939_SEND_TRANSPORT_PROTOCOL_CONNECTION_MANIGAGNEMENT ( J1939 , SA ); |
| } |
- Étape 4.2.3: Une fois que
ECU Y a reçu le CTS, il va transmettre les données, dans ce cas, ECU Identification , de retour à ECU X . | if ( j1939 -> from_other_ecu_tp_cm . Control_byte == Control_Byte_TP_CM_CTS ) { |
| SAE_J1939_SEND_TRANSPORT_PROTOCOL_DATA_TRANSER ( J1939 , SA ); |
| } |
- Étape 4.2.3: Une fois que
ECU Y envoie un package après le package ... | 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 ; |
| pour ( i = 1 ; i <= j1939 -> this_ecu_tp_cm . Number_of_packages ; i ++ ) { |
| package [ 0 ] = i ; / * Nombre de packages * / |
| pour ( j = 0 ; j < 7 ; j ++ ) { |
| if ( bytes_sent < j1939 -> this_ecu_tp_cm . total_message_size ) { |
| package [ J + 1 ] = J1939 -> this_ecu_tp_dt . data [ bytes_sent ++ ]; / * Données que nous avons collectées * / |
| } autre { |
| package [ j + 1 ] = 0xff ; / * Réservé * / |
| } |
| } |
| status = can_send_message ( id , package ); |
| Can_delay ( 100 ); / * Important peut retarder en fonction de la norme * / |
| if ( status ! = status_send_ok ) { |
| statut de retour ; |
| } |
| } |
| statut de retour ; |
| } |
- Étape 4.2.4:
ECU X reçoit alors chaque package et construit le message en connaissant le code de fonction PNG . | void sae_j1939_read_transport_protocol_data_transfer ( j1939 * j1939 , uint8_t sa , uint8_t data []) { |
| / * Enregistrer les données de séquence * / |
| 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 ; |
| pour ( i = 1 ; i < 8 ; i ++ ) { |
| J1939 -> From_other_ecu_tp_dt . data [ index * 7 + i - 1 ] = data [ i ]; / * Pour chaque package, nous envoyons 7 octets de données où les premières données d'octets [0] sont le numéro de séquence * / |
| } |
| / * Vérifiez si nous avons terminé notre message - return = non terminé * / |
| 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 ) { |
| retour ; |
| } |
| |
| / * Notre message est terminé - construisez-le et appelez-le complet_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 complet_data [ max_tp_dt ]; |
| uint16_t inséré_bytes = 0 ; |
| pour ( i = 0 ; i < j1939 -> de_other_ecu_tp_dt . Sequence_number ; i ++ ) { |
| pour ( j = 0 ; j < 7 ; j ++ ) { |
| if ( inserted_bytes < total_message_size ) { |
| complet_data [ inserted_bytes ++ ] = j1939 -> from_other_ecu_tp_dt . data [ i * 7 + j ]; |
| } |
| } |
| } |
| |
| / * Envoyer une fin du message ACK * / |
| if ( j1939 -> from_other_ecu_tp_cm . Control_byte == Control_Byte_TP_CM_RTS ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , CONTRÔLE_BYTE_TP_CM_ENDOFMSGACK , GROUP_FUNCTION_VALUE_NORMAL , PGN ); |
| } |
Puis finalement implémenter le message. | Case PGN_ECU_IDENTIFICATION : |
| SAE_J1939_READ_RESPONSE_REQUEST_ECU_IDENTIFICATION ( J1939 , SA , complet_data ); |
| casser ; |
SAE J1939 Fonctionnalité
- SAE J1939: 21 Couche de transport
- Reconnaissance
- Demande
- Gestion des connexions du protocole de transport avec BAM, CTS, RTS et EOM
- Transfert de données du protocole de transport
- SAE J1939: 71 Couche d'application
- Demander l'identification des composants
- Demander l'identification de l'ECU
- Demander l'identification du logiciel
- Demander propriétaire un
- Demander le propriétaire b
- SAE J1939: 73 Couche de diagnostic
- Dm1
- Dm2
- Dm3
- DM14
- DM15
- DM16
- SAE J1939: 81 Couche de gestion du réseau
- Adresse revendiquée
- Adresse commandée
- Adresse non revendiquée
- Supprimer l'adresse
Fonctionnalité supplémentaire
- Tracteurs et machines ISO 11783 pour l'agriculture et la foresterie
- ISO 11783-7 implémenter la couche d'application des messages
- Commande de vanne auxiliaire
- Valve auxiliaire flux estimé
- Position mesurée de la vanne auxiliaire
- Commande de valve à usage général
- Valve à usage général Flux estimé
Questions et réponses
- Q: Cette bibliothèque peut-elle être utilisée avec
C++ ?- R: Oui, il peut être utilisé avec
C++
- Q: Je veux construire sur cette bibliothèque, que dois-je faire?
- R: Vous devez d'abord connaître les opérations
ANSI C (C89) et Bitwise. Ensuite, vous devez comprendre la structure SAE J1939:21 Transport Layer . N'oubliez pas de mettre à jour le PDF avec votre nouvelle fonctionnalité.
- Q: Puis-je l'utiliser sur mon Arduino?
- R: Oui, ce code
C est un code C 100% pur et uniquement en utilisant la bibliothèque standard C et le code ne tient pas compte du matériel que vous utilisez.
- Q: Dois-je installer la bibliothèque pour utiliser la bibliothèque?
- R: Non, copiez simplement les fichiers
.c et .h à votre projet et compilez. J'ai utilisé cela avec le framework QT.
- Q: Ce projet est assez vieux maintenant et pas tant des mises à jour, est-ce toujours la peine de l'utiliser?
- R: Oui, cette bibliothèque ne met à jour que lorsque je ou autre comprend plus de fonctionnalités de SAE J1939. La raison pour laquelle j'ai écrit ceci dans
ANSI C (C89) est parce que c'est une norme de l'industrie et que vous pourrez toujours compiler cette bibliothèque et l'utiliser sur tous les systèmes.
- Q: Quel est votre plan avec la bibliothèque?
- R: Pour rendre SAE J1939 disponible pour tout le monde
- Q: Je n'ai pas de can-bus, mais puis-je utiliser cette bibliothèque de toute façon avec UART, USB, WiFi, etc.?
- R: Oui. Ce n'est qu'un moyen de façonner un message d'une manière spécifique.
- Q: Puis-je envoyer des données avec cette bibliothèque, même si je n'ai pas de can-bus?
- R: Oui. Il y a quelque chose appelé la demande de transmission DM14, la réponse à l'état DM15 et le transfert binaire DM16. Utilisez-le si vous souhaitez transférer des données de manière industrielle.
- Q: Puis-je envoyer des messages multi-packages de plusieurs ECU à un ECU en même temps?
- R: Non. Si vous commencez à envoyer des multipackages de plusieurs ECU à un autre ECU, alors l'ECU ne peut pas comprendre le message. Transmettez uniquement les messages multipackage un à l'époque si l'adresse de destination est la même.
- Q: Je ne veux pas utiliser
ANSI C (C89) avec Open SAE J1939. Puis-je utiliser la dernière norme C avec Open SAE J1939?- Oui, vous pouvez utiliser la dernière norme C avec cette bibliothèque.
- Q: Est-il possible de compiler cette bibliothèque sur une machine MS-DOS Windows ou Windows 95?
- Un compilateur compatible C89 et un IDE et ce ne devrait pas être un problème
- Q: Puis-je ajuster la mémoire occupée par le programme?
- R: Oui, vous pouvez ajuster les définies
MAX_PROPRIETARY_A , MAX_PROPRIETARY_B et MAX_PROPRIETARY_B_PGNS dans le fichier Structs.h selon votre cas d'utilisation. Une valeur par défaut «saine» est fournie, mais vous pouvez les définir sur le support PGNS minimum si le PGNS n'est pas nécessaire ou l'augmentation si plus de PGN doivent être utilisés.
Problèmes et réponses
- I: Je ne peux pas compiler cette bibliothèque. J'utilise
Keil Microvision .- R:
Keil Microvision ne peut pas gérer les numéros binaires tels que 0b010101 . Essayez à la place STM32CubeIDE car Open SAE J1939 est fabriqué dans STM32CubeIDE
- I: Pouvez-vous nous fournir quelques exemples matériels par exemple
STM32 ?- R: Oui! Il existe un exemple STM32 comment obtenir la connexion avec CAN-BUS, y compris un écouteur d'interruption pour les messages. Allez dans
Examples -> Hardware sur CAN_STM32.txt . Il existe également un exemple USB également pour QT C++ .