เปิด 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 ++ GUI ที่ใช้ Open SAE J1939 ผ่าน USB หรือไม่? https://github.com/danielmartensson/goobysoft
กำลังมองหาโครงการ C STM32 พร้อม Open SAE J1939 หรือไม่? https://github.com/danielmartensson/stm32-plc
เริ่มต้น
สิ่งแรกที่คุณต้องรู้คือการอ่านเอกสาร PDF ของฉันเองของ Open SAE J1939 ภายในโฟลเดอร์ Documentation เรียนรู้โครงสร้างของโครงการมิฉะนั้นคุณจะไม่สามารถเข้าใจ SAE J1939 ได้ หลังจากที่คุณมีความเข้าใจพื้นฐานเกี่ยวกับโครงการคุณสามารถสร้างมันได้ ทำให้มันง่ายและทำตามมาตรฐาน SAE J1939!
หลังจากที่คุณเข้าใจโครงสร้างของโครงการแล้วเลือกตัวเลือกโปรเซสเซอร์ใน Hardware -> Hardware.h ที่นี่คุณสามารถเลือกตัวอย่าง 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_IDIGITION ( J1939 * J1939 , UINT8_T DA ) { |
| ส่งคืน SAE_J1939_SEND_REQUEST ( J1939 , DA , PGN_ECU_IDENTIFICITION ); |
| - |
- ขั้นตอนที่ 2:
ECU Y กำลังอ่านข้อความ PGN จาก ECU X | bool is_new_message = can_read_message ( & id , data ); |
| if ( is_new_message ) { |
| / * บันทึกล่าสุด */ |
| J1939 -> id = id ; |
| MEMCPY ( J1939 -> ข้อมูล , ข้อมูล , 8 ); |
| j1939 -> id_and_data_is_updated = true; |
| |
| uint8_t id0 = id >> 24 ; |
| uint8_t id1 = id >> 16 ; |
| uint8_t da = id >> 8 ; /* ที่อยู่ปลายทางซึ่งเป็น ECU นี้ ถ้า da = 0xff = ออกอากาศไปยัง ECU ทั้งหมด บางครั้ง DA อาจเป็นหมายเลขประจำตัวได้เช่นกัน */ |
| UINT8_T SA = ID ; / * ที่อยู่แหล่งที่มาของ ECU ที่เราได้รับข้อความจาก */ |
| |
| / * อ่านคำขอจาก ECU อื่น ๆ */ |
| if ( id0 == 0x18 && id1 == 0xea && ( da == j1939 -> information_this_ecu . this_ecu_address || da == 0xff )) { |
| SAE_J1939_READ_REQUEST ( J1939 , SA , ข้อมูล ); |
- ขั้นตอนที่ 3: รหัสฟังก์ชัน
PGN จะถูกตีความโดย ECU Y | เป็นโมฆะ SAE_J1939_READ_REQUEST ( J1939 * J1939 , UINT8_T SA , ข้อมูล UINT8_T []) { |
| uint32_t pgn = ( ข้อมูล [ 2 ] << 16 ) | ( ข้อมูล [ 1 ] << 8 ) | ข้อมูล [ 0 ]; |
| if ( pgn == pgn_acknowledGement ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( pgn == pgn_address_claimed ) { |
| SAE_J1939_RESPONSE_REQUEST_ADDRESS_CLAIMED ( J1939 ); |
| } อื่น ถ้า ( pgn == pgn_commanded_address ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( pgn == pgn_address_delete ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); / * ไม่ใช่ SAE J1939 มาตรฐาน */ |
| } อื่น ถ้า ( pgn == pgn_dm1 ) { |
| SAE_J1939_RESPONSE_REQUEST_DM1 ( J1939 , SA ); |
| } อื่น ถ้า ( pgn == pgn_dm2 ) { |
| SAE_J1939_RESPONSE_REQUEST_DM2 ( J1939 , SA ); |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( pgn == pgn_dm3 ) { |
| SAE_J1939_RESPONSE_REQUEST_DM3 ( J1939 , SA ); |
| } อื่น ถ้า ( pgn == pgn_request ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( pgn == pgn_tp_cm ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( pgn == pgn_tp_dt ) { |
| SAE_J1939_SEND_ACKNOWLEDGEMENT ( J1939 , SA , Control_BYTE_ACKNOWLEDGEMENT_PGN_SUPPORTED , Group_function_value_normal , PGN ); |
| } อื่น ถ้า ( 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 */ |
| } อื่น ถ้า ( pgn == pgn_general_purpose_valve_estimated_flow ) { |
| ISO_11783_RESPONSE_REQUEST_GENERAL_PURPOSE_VALVE_ESTIMATED_FLOW ( J1939 , SA ); |
| } อื่น ถ้า ( 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 */ |
| } อื่น ถ้า ( pgn == pgn_software_identification ) { |
| SAE_J1939_RESPONSE_REQUEST_SOFTWARE_IDIGITION ( J1939 , SA ); |
| } อื่น ถ้า ( 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_IDIGITION |
| / * ค้นหาความยาวของฟิลด์อาร์เรย์ */ |
| uint8_t length_of_each_field = j1939 -> information_this_ecu this_identifications ecu_identification ความยาว _of_each_field ; |
| if ( length_of_each_field < 2 ) { |
| / * หากแต่ละฟิลด์มีความยาว 1 เราสามารถส่งการระบุ ECU เนื่องจากเป็นข้อความปกติ *// |
| uint32_t id = ( 0x18fdc5 << 8 ) | J1939 -> ข้อมูล _this_ecu this_ecu_address ; |
| ข้อมูล UINT8_T [ 8 ]; |
| ข้อมูล [ 0 ] = J1939 -> ข้อมูล _THIS_ECU this_identifications ecu_identification ecu_part_number [ 0 ]; |
| ข้อมูล [ 1 ] = J1939 -> ข้อมูล _this_ecu this_identifications ecu_identification ecu_serial_number [ 0 ]; |
| ข้อมูล [ 2 ] = J1939 -> ข้อมูล _this_ecu this_identifications ecu_identification ecu_location [ 0 ]; |
| ข้อมูล [ 3 ] = J1939 -> ข้อมูล _THIS_ECU this_identifications ecu_identification 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 นั้นออกอากาศ | } อื่น ถ้า ( id0 == 0x18 && id1 == 0xfd && da == 0xc5 ) { |
| SAE_J1939_READ_RESPONSE_REQUEST_ECU_IDIGITION ( J1939 , SA , ข้อมูล ); |
- ขั้นตอนที่ 4.2.1: สำหรับข้อความหลายแพ็คเกจไบต์ควบคุมสามารถเป็น BAM หรือ RTS ได้ BAM ใช้เฉพาะเมื่อคุณส่งไปยังที่อยู่
ECUs ทั้งหมด EG ทั้งหมด 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 ; |
| สำหรับ ( i = 0 ; i < length_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 data [ length_of_each_field + i ] = j1939 -> information_this_ecu this_identifications ecu_identification ecu_serial_number [ i ]; |
| J1939 -> this_ecu_tp_dt data [ length_of_each_field * 2 + i ] = j1939 -> information_this_ecu this_identifications ecu_identification ecu_location [ i ]; |
| J1939 -> this_ecu_tp_dt data [ length_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 ; |
| - |
| |
| / * ส่ง 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 Control Byte */ |
| enum_j1939_status_codes สถานะ = SAE_J1939_SEND_TRANSPORT_PROTOCOL_CONNECTION_MANAGUTION ( 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_MANAGUTION ( 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 ) | ( ดา << 8 ) | J1939 -> ข้อมูล _this_ecu this_ecu_address ; |
| uint8_t i , j , แพ็คเกจ [ 8 ]; |
| uint16_t bytes_sent = 0 ; |
| ENUM_J1939_STATUS_CODES สถานะ = STATE_SEND_OK ; |
| สำหรับ ( i = 1 ; i <= j1939 -> this_ecu_tp_cm . number_of_packages ; i ++ ) { |
| แพ็คเกจ [ 0 ] = i ; / * จำนวนแพ็คเกจ */ |
| สำหรับ ( j = 0 ; j < 7 ; j ++ ) { |
| if ( bytes_sent < J1939 -> this_ecu_tp_cm . total_message_size ) { |
| แพ็คเกจ [ j + 1 ] = j1939 -> this_ecu_tp_dt ข้อมูล [ bytes_sent ++ ]; / * ข้อมูลที่เรารวบรวม */ |
| } อื่น { |
| แพ็คเกจ [ j + 1 ] = 0xff ; /* ที่สงวนไว้ */ |
| - |
| - |
| สถานะ = CAN_SEND_MESSAGE ( ID , แพ็คเกจ ); |
| can_delay ( 100 ); / * สำคัญสามารถล่าช้าตามมาตรฐาน */ |
| if ( สถานะ ! = status_send_ok ) { |
| สถานะ การส่งคืน ; |
| - |
| - |
| สถานะ การส่งคืน ; |
| - |
- ขั้นตอนที่ 4.2.4: จากนั้น
ECU X จะได้รับแต่ละแพ็คเกจและสร้างข้อความโดยรู้รหัสฟังก์ชั่น PNG | Void SAE_J1939_READ_TRANSPORT_PROTOCOL_DATA_TRANSFER ( J1939 * J1939 , UINT8_T SA , ข้อมูล UINT8_T []) { |
| / * บันทึกข้อมูลลำดับ */ |
| 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 ; |
| สำหรับ ( i = 1 ; i < 8 ; i ++ ) { |
| j1939 -> from_other_ecu_tp_dt ข้อมูล [ ดัชนี * 7 + i - 1 ] = ข้อมูล [ 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 ) |
| กลับ ; |
| - |
| |
| / * ข้อความของเราเสร็จสมบูรณ์ - สร้างและเรียกว่า Complete_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 Complete_data [ max_tp_dt ]; |
| UINT16_T แทรก _Bytes = 0 ; |
| สำหรับ ( i = 0 ; i < j1939 -> from_other_ecu_tp_dt . sequence_number ; i ++ ) { |
| สำหรับ ( j = 0 ; j < 7 ; j ++ ) { |
| if ( inserted_bytes < total_message_size ) { |
| Complete_data [ inserted_bytes ++ ] = j1939 -> from_other_ecu_tp_dt ข้อมูล [ i * 7 + j ]; |
| - |
| - |
| - |
| |
| / * ส่งข้อความจบข้อความกลับ */ |
| 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 ); |
| - |
และในที่สุดก็ใช้ข้อความ | กรณี pgn_ecu_identification : |
| SAE_J1939_READ_RESPONSE_REQUEST_ECU_IDIGITION ( J1939 , SA , Complete_data ); |
| หยุดพัก ; |
ฟังก์ชั่น SAE J1939
- SAE J1939: 21 การขนส่งเลเยอร์
- การรับทราบ
- ขอ
- การจัดการการเชื่อมต่อโปรโตคอลการขนส่งด้วย BAM, CTS, RTS และ EOM
- การถ่ายโอนข้อมูลโปรโตคอลการขนส่ง
- SAE J1939: 71 แอปพลิเคชันเลเยอร์
- ขอการระบุส่วนประกอบ
- ขอบัตรประจำตัว ECU
- ขอการระบุซอฟต์แวร์
- ขอกรรมกร
- ขอกรรมสิทธิ์ B
- SAE J1939: 73 การวินิจฉัยเลเยอร์
- DM1
- DM2
- DM3
- DM14
- DM15
- DM16
- SAE J1939: 81 เลเยอร์การจัดการเครือข่าย
- ที่อยู่ที่อ้างสิทธิ์
- ที่อยู่สั่ง
- ที่อยู่ไม่ได้อ้างสิทธิ์
- ลบที่อยู่
ฟังก์ชั่นพิเศษ
- ISO 11783 รถแทรกเตอร์และเครื่องจักรเพื่อการเกษตรและป่าไม้
- ISO 11783-7 ใช้เลเยอร์แอปพลิเคชันข้อความ
- คำสั่งวาล์วเสริม
- การไหลของวาล์วเสริม
- ตำแหน่งวาล์วเสริม
- คำสั่งวาล์ววัตถุประสงค์ทั่วไป
- การไหลโดยประมาณวาล์ววัตถุประสงค์ทั่วไป
คำถามและคำตอบ
- ถาม: ห้องสมุดนี้สามารถใช้กับ
C++ ได้หรือไม่?- ตอบ: ใช่มันสามารถใช้กับ
C++
- ถาม: ฉันต้องการสร้างห้องสมุดนี้ฉันควรทำอย่างไร?
- ตอบ: ก่อนอื่นคุณต้องรู้
ANSI C (C89) และการดำเนินการ bitwise จากนั้นคุณต้องเข้าใจโครงสร้าง SAE J1939:21 Transport Layer อย่าลืมอัปเดต PDF ด้วยฟังก์ชั่นใหม่ของคุณ
- ถาม: ฉันสามารถใช้สิ่งนี้กับ Arduino ได้หรือไม่?
- ตอบ: ใช่รหัส
C นี้เป็นรหัส C บริสุทธิ์ 100% และใช้เฉพาะไลบรารีมาตรฐาน C และรหัสไม่ได้คำนึงถึงฮาร์ดแวร์ที่คุณใช้
- ถาม: ฉันจำเป็นต้องติดตั้งไลบรารีเพื่อใช้ห้องสมุดหรือไม่?
- ตอบ: ไม่เพียงแค่คัดลอกไฟล์
.c และ .h ไปยังโครงการของคุณและรวบรวม ฉันใช้สิ่งนี้กับกรอบ QT
- ถาม: โครงการนี้ค่อนข้างเก่าแล้วและไม่ได้รับการอัปเดตมากนักยังคงคุ้มค่าที่จะใช้งานหรือไม่?
- ตอบ: ใช่ห้องสมุดนี้จะอัปเดตเฉพาะเมื่อฉันหรืออื่น ๆ มีฟังก์ชั่นเพิ่มเติมจาก SAE J1939 เหตุผลที่ฉันเขียนสิ่งนี้ใน
ANSI C (C89) เป็นเพราะมันเป็นมาตรฐานอุตสาหกรรมและคุณจะสามารถรวบรวมไลบรารีนี้และใช้มันกับทุกระบบ
- ถาม: แผนการของคุณกับห้องสมุดคืออะไร?
- ตอบ: เพื่อให้ SAE J1939 พร้อมใช้งานสำหรับทุกคน
- ถาม: ฉันไม่มีบัส แต่ฉันสามารถใช้ห้องสมุดนี้กับ UART, USB, WiFi ฯลฯ ได้หรือไม่?
- ก. ใช่. นี่เป็นเพียงวิธีการกำหนดรูปแบบข้อความในลักษณะที่เฉพาะเจาะจง
- ถาม: ฉันสามารถส่งข้อมูลกับไลบรารีนี้ได้แม้ว่าฉันจะไม่มีบัสได้หรือไม่?
- ก. ใช่. มีบางสิ่งที่เรียกว่าคำขอส่ง DM14, การตอบสนองสถานะ DM15 และการถ่ายโอนไบนารี DM16 ใช้สิ่งนั้นหากคุณต้องการถ่ายโอนข้อมูลในทางอุตสาหกรรม
- ถาม: ฉันสามารถส่งข้อความหลายแพ็คเกจจากหลาย ECU ไปยัง ECU หนึ่งรายการในเวลาเดียวกันได้หรือไม่?
- ตอบ: ไม่ถ้าคุณเริ่มส่งหลายแพคเกจจากหลาย ECU ไปยัง ECU อื่น ECU นั้น ECU ไม่สามารถเข้าใจข้อความได้ ส่งเฉพาะข้อความหลายแพคเกจหนึ่งข้อความในเวลานั้นหากที่อยู่ปลายทางเหมือนกัน
- ถาม: ฉันไม่ต้องการใช้
ANSI C (C89) กับ Open SAE J1939 ฉันสามารถใช้มาตรฐาน C ล่าสุดกับ Open SAE J1939 ได้หรือไม่?- ใช่คุณสามารถใช้มาตรฐาน C ล่าสุดกับไลบรารีนี้
- ถาม: เป็นไปได้ไหมที่จะรวบรวมไลบรารีนี้ลงในเครื่อง Windows MS-DOS หรือ Windows 95?
- คอมไพเลอร์ที่เข้ากันได้กับ C89 และ IDE และไม่ควรมีปัญหาใด ๆ
- ถาม: ฉันสามารถปรับหน่วยความจำที่ครอบครองโดยโปรแกรมได้หรือไม่?
- ตอบ: ใช่คุณสามารถปรับการกำหนด
MAX_PROPRIETARY_A , MAX_PROPRIETARY_B และ MAX_PROPRIETARY_B_PGNS ในไฟล์ Structs.h ตามกรณีการใช้งานของคุณ มีค่าเริ่มต้น 'มีสติ' แต่คุณสามารถตั้งค่าให้เป็นค่าต่ำสุดหากไม่จำเป็นต้องมีการสนับสนุน PGNS ที่เป็นกรรมสิทธิ์หรือเพิ่มขึ้นหากจำเป็นต้องใช้ PGNs มากขึ้น
ปัญหาและคำตอบ
- ฉัน: ฉันไม่สามารถรวบรวมไลบรารีนี้ได้ ฉันใช้
Keil Microvision- ตอบ:
Keil Microvision ไม่สามารถจัดการหมายเลขไบนารีเช่น 0b010101 ลอง STM32CubeIDE แทนเพราะ Open SAE J1939 ทำใน STM32CubeIDE
- ฉัน: คุณสามารถให้ตัวอย่างฮาร์ดแวร์บางอย่างแก่เราเช่น
STM32 ได้หรือไม่?- ก. ใช่! มีตัวอย่าง STM32 วิธีการเชื่อมต่อกับ CAN-BUS รวมถึงผู้ฟังขัดจังหวะสำหรับข้อความ ไปที่
Examples -> Hardware ที่ค้นหา CAN_STM32.txt นอกจากนี้ยังมีตัวอย่าง USB เช่นกันสำหรับ QT C++