Abrir SAE J1939
SAE J1939 es un protocolo para dar forma al mensaje de los bus de canales de una manera específica que se adapta a vehículos industriales como tractores, maquinaria, camiones y más.
SAE J1939 es un protocolo muy fácil de usar, pero hay una falta de información sobre SAE J1939, debido al costo del documento de protocolo, disponible sobre cómo dar forma a un mensaje de bus de canales SAE J1939. Por lo tanto, estoy escribiendo un protocolo SAE J1939 disponible de forma gratuita en cualquier sistema integrado como STM32, Arduino, AVR, PIC, etc. o PC.
Para aprender a construir sobre este proyecto, primero debe comprender SAE J1939. He escrito este proyecto en el lenguaje C porque C es un estándar de la industria. El dialecto del lenguaje C que he elegido es ANSI C (C89) y no uso la asignación de memoria dinámica en esta biblioteca. Entonces funcionará con el estándar MISRA C
Con esta biblioteca, puede comunicarse con válvulas, motores, actuadores, maquinaria, hardware y todas las demás cosas que son adecuadas para aplicaciones móviles industriales pesadas. He construido una estructura básica del proyecto y espero que otros usuarios envíen una solicitud de extracción de su código C para una funcionalidad adicional al estándar SAE J1939 porque SAE J1939 es un gran estándar.
¿Busca la biblioteca C Canopen para sistemas integrados? https://github.com/danielmartensson/easy-canopen
¿Busca un marco GUI C ++ que use SAE J1939 abierto sobre el USB? https://github.com/danielmartensson/goobysoft
¿Busca un proyecto C STM32 con Open SAE J1939? https://github.com/danielmartensson/stm32-plc
Empezando
Lo primero que debe saber es leer mi propio documento PDF de Open SAE J1939 dentro de la carpeta Documentation . Aprenda la estructura del proyecto, de lo contrario, no podrá entender SAE J1939. Después de tener una comprensión básica del proyecto, puede aprovecharlo. ¡Manténgalo simple y siga el estándar SAE J1939!
Después de que haya entendido la estructura del proyecto, seleccione la elección del procesador en el archivo Hardware -> Hardware.h . Aquí puede seleccionar, por ejemplo, STM32 , Arduino , PIC , AVR , etc. o si desea ejecutarlo primero en PC, luego seleccione PROCESSOR_CHOICE 0 y ejecute algunos ejemplos. Ese es el modo de depuración para la retroalimentación de lata interna.
Cómo usar el proyecto
- Paso 1: Descargue este repositorio
- Paso 2: Vaya a
Hardware -> Hardware.h y seleccione su procesador, si no está disponible, escriba el código y envíeme una solicitud de extracción - Paso 3: Copie a través de la carpeta
Src a la carpeta de su proyecto dentro de su IDE. Cambie el nombre de Src para, por ejemplo, Open SAE J1939 . Ese es un buen nombre. - Paso 4: Use los
Examples -> Open SAE J1939 -> Main.txt como su código inicial inicial para un proyecto 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 ;
} Consulte los ejemplos en Examples -> SAE J1939 Cómo cambiar la dirección, el nombre o las identificaciones para su ECU.
La estructura del proyecto
Un ejemplo de trabajo cómo se realiza la estructura de SAE J1939 abierto
Este diagrama de flujo en código cómo está funcionando la biblioteca SAE J1939 abierta. Este ejemplo demuestra cómo enviar una solicitud y obtener una respuesta.
- Paso 1:
ECU X va a enviar un PGN a ECU Y . Interpreta PGN como un código de función. | Enum_j1939_status_codes sae_j1939_send_request_ecu_identification ( j1939 * j1939 , uint8_t da ) { |
| return sae_j1939_send_request ( j1939 , da , pgn_ecu_ididentification ); |
| } |
- Paso 2:
ECU Y va a leer ese mensaje PGN de ECU X . | bool is_new_message = can_read_message ( & id , data ); |
| if ( is_new_message ) { |
| / * Guardar último */ |
| J1939 -> id = id ; |
| MEMCPY ( J1939 -> Datos , datos , 8 ); |
| J1939 -> id_and_data_is_updated = true; |
| |
| uint8_t id0 = id >> 24 ; |
| uint8_t id1 = id >> 16 ; |
| uint8_t da = id >> 8 ; /* Dirección de destino que es esta ECU. Si da = 0xff = transmitido a toda ECU. A veces, DA también puede ser un número de identificación */ |
| uint8_t sa = id ; / * Dirección fuente de la ECU que recibimos el mensaje de */ |
| |
| / * Leer solicitud de otra ECU */ |
| if ( id0 == 0x18 && id1 == 0xea && ( da == J1939 -> Information_this_ecu . this_ecu_address || da == 0xff )) { |
| Sae_j1939_read_request ( j1939 , sa , datos ); |
- Paso 3: El código de función
PGN será interpretado por ECU Y | void sae_j1939_read_request ( j1939 * j1939 , uint8_t sa , uint8_t data []) { |
| uint32_t pgn = ( datos [ 2 ] << 16 ) | ( datos [ 1 ] << 8 ) | datos [ 0 ]; |
| if ( pgn == pgn_acknowledgement ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn == pgn_address_claimed ) { |
| Sae_j1939_esponse_request_address_claimed ( J1939 ); |
| } else if ( pgn == pgn_commanded_address ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn == pgn_address_delete ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); / * No SAE J1939 estándar */ |
| } else if ( pgn == pgn_dm1 ) { |
| Sae_j1939_esponse_request_dm1 ( j1939 , sa ); |
| } else if ( pgn == pgn_dm2 ) { |
| Sae_j1939_esponse_request_dm2 ( J1939 , sa ); |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn == pgn_dm3 ) { |
| Sae_j1939_esponse_request_dm3 ( j1939 , sa ); |
| } else if ( pgn == pgn_request ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn == pgn_tp_cm ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn == pgn_tp_dt ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_Byte_acknowledgement_pgn_supported , group_function_value_normal , pgn ); |
| } else if ( pgn > = pgn_auxiliary_valve_estimated_flow_0 && pgn <= pgn_auxiliar_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_auxiliar_valve_measured_position_0 && pgn <= pgn_auxiliar_valve_measured_position_15 ) { |
| ISO_11783_RESPONSE_REQUEST_AUXILIARY_VALVE_MAASED_POSITION ( J1939 , PGN & 0XF ); / * PGN & 0xf = Valve_Number */ |
| } else if ( pgn == pgn_software_identification ) { |
| Sae_j1939_esponse_request_software_identification ( J1939 , SA ); |
| } else if ( pgn == PGN_ECU_IENTIFICE ) { |
| SAE_J1939_RESPONSE_REQUEST_ECU_IDENTIFICATION ( J1939 , SA ); |
- Paso 4: El código de función
PGN ahora se interpreta como ECU Identification por ECU Y . Entonces ECU Y va a transmitir la ECU Identification a todas ECUs .- Paso 4.1.1: para un mensaje de 1 paquete,
ECU Y va a transmitir la ECU Identification . | Enum_j1939_status_codes sae_j1939_esponse_request_ecu_ididentification ( j1939 * j1939 , uint8_t da ) { |
| / * Encuentra la longitud de los campos de matriz */ |
| uint8_t longitud_of_each_field = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . longitud_of_each_field ; |
| if ( longitud_of_each_field < 2 ) { |
| / * Si cada campo tiene la longitud 1, entonces podemos enviar la identificación de la ECU, ya que era un mensaje normal */ |
| uint32_t id = ( 0x18fdc5 << 8 ) | J1939 -> Information_this_ecu . this_ecu_address ; |
| datos uint8_t [ 8 ]; |
| Datos [ 0 ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_part_Number [ 0 ]; |
| Datos [ 1 ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_Serial_Number [ 0 ]; |
| Datos [ 2 ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_Location [ 0 ]; |
| Datos [ 3 ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_TYPE [ 0 ]; |
| datos [ 4 ] = 0xff ; / * Reservado */ |
| datos [ 5 ] = 0xff ; / * Reservado */ |
| datos [ 6 ] = 0xff ; / * Reservado */ |
| datos [ 7 ] = 0xff ; / * Reservado */ |
| return can_send_message ( id , datos ); |
| } demás { |
- Paso 4.1.2:
ECU X Lea la respuesta de ECU Y porque se transmite la ECU Identification . | } else if ( id0 == 0x18 && id1 == 0xfd && da == 0xc5 ) { |
| Sae_j1939_read_esponse_request_ecu_identification ( j1939 , sa , data ); |
- Paso 4.2.1: Para el mensaje de paquete múltiple, el byte de control puede ser BAM o RTS. BAM solo se usa si envía a toda
ECUs por ejemplo, dirección 0xFF = 255 . Pero si el byte de control es RTS, por ejemplo, la dirección no es 0xFF , entonces ECU Y enviará un RTS y escuchará una respuesta CTS por ECU X . RTS es una pregunta para "avísame cuándo puedo transmitir el mensaje?" Y CTS es respuesta Now you can transmit the message to me . | J1939 -> this_ecu_tp_cm . Total_message_size = 0 ; |
| uint8_t i ; |
| para ( i = 0 ; i < long_of_each_field ; i ++ ) { |
| J1939 -> this_ecu_tp_dt . Datos [ i ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_part_Number [ i ]; |
| J1939 -> this_ecu_tp_dt . datos [ long_of_each_field + i ] = j1939 -> información_this_ecu . this_identifications . Ecu_identificación . ECU_Serial_Number [ i ]; |
| J1939 -> this_ecu_tp_dt . datos [ long_of_each_field * 2 + i ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_Location [ i ]; |
| J1939 -> this_ecu_tp_dt . datos [ long_of_each_field * 3 + i ] = J1939 -> Information_this_ecu . this_identifications . Ecu_identificación . ECU_TYPE [ i ]; |
| J1939 -> this_ecu_tp_cm . Total_message_size += 4 ; |
| } |
| |
| / * Enviar 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 ; / * Redondeando */ |
| 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 ; / * Si se transmite, entonces use Bam Control Byte */ |
| Enum_j1939_status_codes status = sae_j1939_send_transport_protocol_connection_management ( J1939 , da ); |
- Paso 4.2.2: Si
ECU Y está enviando un RTS, entonces ECU X leerá el RTS y la respuesta con CTS de regreso a 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 ; / * Copiar: necesitamos tener los mismos datos */ |
| J1939 -> this_ecu_tp_cm . control_byte = control_byte_tp_cm_cts ; / * Solo necesitamos cambiar el byte de control de RTS a CTS */ |
| Sae_j1939_send_transport_protocol_connection_management ( J1939 , SA ); |
| } |
- Paso 4.2.3: Una vez que
ECU Y haya recibido el CTS, luego transmitirá los datos, en este caso, ECU Identification , de regreso a 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 ); |
| } |
- Paso 4.2.3: Una vez que
ECU Y envíe un paquete después del paquete ... | 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 , paquete [ 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 ++ ) { |
| paquete [ 0 ] = i ; / * Número de paquete */ |
| para ( j = 0 ; j < 7 ; j ++ ) { |
| if ( bytes_sent < j1939 -> this_ecu_tp_cm . Total_message_size ) { |
| paquete [ j + 1 ] = J1939 -> this_ecu_tp_dt . datos [ bytes_sent ++ ]; / * Datos que hemos recopilado */ |
| } demás { |
| paquete [ j + 1 ] = 0xff ; / * Reservado */ |
| } |
| } |
| status = can_send_message ( id , paquete ); |
| Can_delay ( 100 ); / * Importante puede retrasar según el estándar */ |
| if ( status ! = status_send_ok ) { |
| estado de retorno ; |
| } |
| } |
| estado de retorno ; |
| } |
- Paso 4.2.4: Entonces
ECU X recibe cada paquete y está construyendo el mensaje conociendo el código de función PNG . | void sae_j1939_read_transport_protocol_data_transfer ( J1939 * J1939 , uint8_t sa , uint8_t data []) { |
| / * Guardar los datos de la secuencia */ |
| J1939 -> from_other_ecu_tp_dt . secuence_number = data [ 0 ]; |
| J1939 -> from_other_ecu_tp_dt . from_ecu_address = sa ; |
| uint8_t i , j , index = data [ 0 ] - 1 ; |
| para ( i = 1 ; i < 8 ; i ++ ) { |
| J1939 -> from_other_ecu_tp_dt . datos [ índice * 7 + i - 1 ] = data [ i ]; / * Para cada paquete, enviamos 7 bytes de datos donde los primeros datos de bytes [0] es el número de secuencia */ |
| } |
| / * Compruebe si hemos completado nuestro mensaje - return = no completado */ |
| if ( j1939 -> from_other_ecu_tp_cm . number_of_packages ! = j1939 -> from_other_ecu_tp_dt . secuence_number || j1939 -> from_other_ecu_tp_cm . number_of_packages == 0 ) { |
| devolver ; |
| } |
| |
| / * Nuestro mensaje está completo: construirlo y llamarlo completo_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 completo_data [ max_tp_dt ]; |
| uint16_t inserted_bytes = 0 ; |
| for ( i = 0 ; i < j1939 -> from_other_ecu_tp_dt . secuence_number ; i ++ ) { |
| para ( j = 0 ; j < 7 ; j ++ ) { |
| if ( inserted_bytes < total_message_size ) { |
| complete_data [ inserted_bytes ++ ] = j1939 -> from_other_ecu_tp_dt . datos [ i * 7 + j ]; |
| } |
| } |
| } |
| |
| / * Enviar un final del mensaje ACK Atrás */ |
| 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_function_value_normal , pgn ); |
| } |
Y finalmente implementa el mensaje. | Caso PGN_ECU_IDENTIFICACIÓN : |
| Sae_j1939_read_esponse_request_ecu_identification ( j1939 , sa , complete_data ); |
| romper ; |
Funcionalidad SAE J1939
- SAE J1939: 21 Capa de transporte
- Reconocimiento
- Pedido
- Gestión de la conexión del protocolo de transporte con BAM, CTS, RTS y EOM
- Transferencia de datos del protocolo de transporte
- SAE J1939: 71 Capa de aplicación
- Solicitar identificación de componentes
- Solicitar identificación de ECU
- Solicitar identificación de software
- Solicitar propietario a
- Solicitar propietarios b
- SAE J1939: 73 Capa de diagnóstico
- DM1
- DM2
- DM3
- DM14
- DM15
- DM16
- SAE J1939: 81 Capa de gestión de redes
- Dirección reclamada
- Dirección ordenada
- Dirección no reclamada
- Eliminar dirección
Funcionalidad extra
- Tractores y maquinaria ISO 11783 para la agricultura y la silvicultura
- ISO 11783-7 Implementar la capa de aplicación de mensajes
- Comando de válvula auxiliar
- Flujo estimado de válvula auxiliar
- Posición de válvula auxiliar medida
- Comando de válvula de propósito general
- Flujo estimado de válvula de propósito general
Preguntas y respuestas
- P: ¿Se puede usar esta biblioteca con
C++ ?- R: Sí, se puede usar con
C++
- P: Quiero construir en esta biblioteca, ¿qué debo hacer?
- R: Primero debe conocer las operaciones
ANSI C (C89) y Bitwise. Luego debe comprender la estructura SAE J1939:21 Transport Layer . No olvide actualizar el PDF con su nueva funcionalidad.
- P: ¿Puedo usar esto en mi Arduino?
- R: Sí, este código
C es 100% puro código C y solo usa la biblioteca estándar C y también el código no tiene en cuenta el hardware que está utilizando.
- P: ¿Necesito instalar la biblioteca para usar la biblioteca?
- R: No, simplemente copie sobre los archivos
.c y .h a su proyecto y compile. He usado esto con el marco QT.
- P: Este proyecto es bastante antiguo ahora y no tantas actualizaciones, ¿todavía vale la pena usarlo?
- R: Sí, esta biblioteca solo se actualiza cuando yo u otra incluye más funcionalidad de SAE J1939. La razón por la que escribí esto en
ANSI C (C89) es porque es un estándar de la industria y siempre podrá compilar esta biblioteca y usarla en todos los sistemas.
- P: ¿Cuál es su plan con la biblioteca?
- R: Para hacer que SAE J1939 esté disponible para todos
- P: No tengo canales, pero ¿puedo usar esta biblioteca de todos modos con UART, USB, WiFi, etc.?
- A: Sí. Esta es solo una forma de dar forma a un mensaje de manera específica.
- P: ¿Puedo enviar datos con esta biblioteca, incluso si no tengo cay-bus?
- A: Sí. Hay algo llamado solicitud de transmisión DM14, respuesta de estado DM15 y transferencia binaria DM16. Úselo si desea transferir datos de manera industrial.
- P: ¿Puedo enviar mensajes de paquetes múltiples de múltiples ECU a una ECU al mismo tiempo?
- R: No. Si comienza a enviar múltiples empacaciones de múltiples ECU a otra ECU, entonces esa ECU no puede entender el mensaje. Transmita solo los mensajes multipackage uno en el momento si la dirección de destino es la misma.
- P: No quiero usar
ANSI C (C89) con SAE Open J1939. ¿Puedo usar el último estándar C con Open SAE J1939?- Sí, puede usar el último estándar C con esta biblioteca.
- P: ¿Es posible compilar esta biblioteca en una máquina Windows MS-DOS o Windows 95?
- Un compilador compatible con C89 y un IDE y no debe ser ningún problema
- P: ¿Puedo ajustar la memoria ocupada por el programa?
- R: Sí, puede ajustar las define
MAX_PROPRIETARY_A , MAX_PROPRIETARY_B y MAX_PROPRIETARY_B_PGNS en el archivo Structs.h según su caso de uso. Se proporciona un valor predeterminado 'sano', pero puede establecerlos al mínimo si no se necesita soporte de PGNS patentado o aumentarlo si se necesitan más PGN.
Problemas y respuestas
- I: No puedo compilar esta biblioteca. Estoy usando
Keil Microvision .- R:
Keil Microvision no puede manejar números binarios como 0b010101 . Pruebe STM32CubeIDE en su lugar porque Open SAE J1939 está hecho en STM32CubeIDE
- I: ¿Puede proporcionarnos algunos ejemplos de hardware, por ejemplo,
STM32 ?- A: ¡Sí! Hay un ejemplo de STM32 sobre cómo obtener conexión con Can-Bus, incluido un oyente de interrupción para los mensajes. Vaya a
Examples -> Hardware para buscar CAN_STM32.txt . También hay un ejemplo USB también para QT C++ .