Sida 2 av 3
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 11:26:23
av DanielM
mrfrenzy skrev: ↑13 augusti 2020, 07:16:32
Det är lite förvirrande språk.
Den texten betyder att dom förutsätter att din ECU har adress 0x22.
ACU tar emot meddelanden FRÅN alla adresser
ACU skickar bara TILL adress 0x22 även om frågan kom från en annan adress.
Om du ska skicka ett meddelande från ECU till ACU blir SA=0x22 och DA=0x80.
När ACU skickar ett meddelande til ECU blir SA=0x80 och DA=0x22
Om din ECU skulle ha adress 0x11 så kommer ACU (felaktigt) ta emot ett meddelande med SA=0x11 och DA=0x80
Svaret kommer den skicka med SA=0x80 och DA=0x22 så du kommer aldrig se det.
Jag sätter att min ECU har 0x22 som adress. Hur jag sätter det? Jag bara skriver in 22 som SA för ECU i ID-meddelandet.
Än fast ACU skickar endast till 0x22 så kan jag läsa exakt alla meddelanden på CAN-bus linan.
Med tanke på att jag kan göra Flow Control i J1939 så betyder det att jag kan faktiskt skicka meddelanden till ACU med 0x22. Men jag kunde även skicka meddelanden till ACU när jag satte ACU adressen till 0x8D av misstag.
Jag använder detta STM32 bibliotek. Fungerar utmärkt!
https://github.com/eziya/STM32_SPI_MCP2515
Så här ser ett mottagande och sändande för mig
https://github.com/eziya/STM32_SPI_MCP2 ... Src/main.c
Jag läser den där CAN-bus C koden du länkande till. Jag finner att min CAN-bus kod, mottar meddelanden olika. Jag skickar alltså inte med någon prioritet.
Kod: Markera allt
uCAN_MSG txMessage;
uCAN_MSG rxMessage;
CANSPI_Initialize();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(CANSPI_Receive(&rxMessage))
{
txMessage.frame.idType = rxMessage.frame.idType;
txMessage.frame.id = rxMessage.frame.id;
txMessage.frame.dlc = rxMessage.frame.dlc;
txMessage.frame.data0++;
txMessage.frame.data1 = rxMessage.frame.data1;
txMessage.frame.data2 = rxMessage.frame.data2;
txMessage.frame.data3 = rxMessage.frame.data3;
txMessage.frame.data4 = rxMessage.frame.data4;
txMessage.frame.data5 = rxMessage.frame.data5;
txMessage.frame.data6 = rxMessage.frame.data6;
txMessage.frame.data7 = rxMessage.frame.data7;
CANSPI_Transmit(&txMessage);
}
txMessage.frame.idType = dSTANDARD_CAN_MSG_ID_2_0B;
txMessage.frame.id = 0x0A;
txMessage.frame.dlc = 8;
txMessage.frame.data0 = 0;
txMessage.frame.data1 = 1;
txMessage.frame.data2 = 2;
txMessage.frame.data3 = 3;
txMessage.frame.data4 = 4;
txMessage.frame.data5 = 5;
txMessage.frame.data6 = 6;
txMessage.frame.data7 = 7;
CANSPI_Transmit(&txMessage);
HAL_Delay(1000);
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 11:30:10
av DanielM
sodjan skrev: ↑13 augusti 2020, 09:55:45
Ah, OK... Så den DA som man anger i en ACU är inte ACU'ns egen DA, utan en förväntad adress för ECU'n.
Ja det förklarar ju allt. Sen så står det även att denna DA ändå inte används, i och för sig. ACU'n accepterar
meddelanden från vilken avsändare som helst i alla fall, men svarar alltid till 0x22 (eller sannolikt den
konfigurerade DA'n i ACU'n). Hade kanske varit tydligare om denna parameter hade kallats "ECU address"...
Men det betyder att man, rent teoretiskt, kan ändra DA i ACU och ha en annan adress än 0x22 på ECU (?).
Inte bara teoretiskt. Även praktiskt också via EEPROM.
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 12:12:00
av DanielM
Tror ni jag ska ändra CA NAME något? Eller är det förprogrammerat och skall alltid vara så?
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 12:20:27
av sodjan
> Men jag kunde även skicka meddelanden till ACU när jag satte ACU adressen till 0x8D av misstag.
Beror inte det på att ACU'n annonserar sin adress efter ett byte?
Så ECU'n vet att din ACU nu har adress 0x8D.
Som jag fattar det så är det enbart ECU som är fördefinierad till 0x22.
Resterande ACU'er annonserar sina adresser vid inkoppling (och reder
ut eventuella adress konflikter sinsemellan).
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 12:52:09
av DanielM
Beror inte det på att ACU'n annonserar sin adress efter ett byte?
Så ECU'n vet att din ACU nu har adress 0x8D.
Vid start så blir det Claim Address. Då kan jag läsa utav denna kod här:
Kod: Markera allt
// Check what message we got
if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 != 0xFE) {
// Address claimed
sbz->SA_ACU = id3;
memcpy(sbz->CA, data, 8);
Min ECU är ju min STM32 och jag tror inte den vet att den har ECU addressen 0x22. Jag bara sätter 0x22 som adress när jag skriver ID meddelanden. Det kanske är förväntat från ACU att den ska få meddelanden från ECU som innehåller SA = 0x22.
Som jag fattar det så är det enbart ECU som är fördefinierad till 0x22.
Resterande ACU'er annonserar sina adresser vid inkoppling (och reder
ut eventuella adress konflikter sinsemellan).
Ja. Med tanke på att det är J1939 Function 0x81 (129d) i CA NAME, vilket betyder Auxiliary valve command 0...15. Detta betyder att om jag har 3 ACU, så numreras dom efter adresserna 0x30, 0x31, 0x32 osv. Jag behöver alltså inte sätta destinationsaddress i ID meddelandet. Jag tror detta du pratar om hela tiden. Lowest name?
Markering_071.png
Hela koden.
Kod: Markera allt
void read_sonceboz_status(SBZ* sbz) {
// Check if we have connected the CAN
if(CAN_connected == false){
memset(sbz->CA, 0, 8);
memset(sbz->errormessages_binary, 0, 12);
sbz->SA_ACU = 0;
CAN_connected = CANSPI_Initialize();
}
uint32_t ID;
uint8_t data[8];
if (read_j1939_message(&ID, data)) {
uint8_t id0 = ID >> 24;
uint8_t id1 = ID >> 16;
uint8_t id2 = ID >> 8;
uint8_t id3 = ID;
// Check what message we got
if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 != 0xFE) {
// Address claimed
sbz->SA_ACU = id3;
memcpy(sbz->CA, data, 8);
} else if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 == 0xFE) {
// Address not claimed
sbz->SA_ACU = 0;
sbz->errormessages_binary[0] = true;
memcpy(sbz->CA, data, 8);
} else if (id0 == 0x18 && id1 == 0xFE && id2 == 0xCA && id3 == sbz->SA_ACU) {
// DM1 message
if (data[0] == 0x00 && data[1] == 0xFF && data[2] == 0x00 && data[3] == 0x00 && data[4] == 0x00 && data[5] == 0x00 && data[6] == 0xFF && data[7] == 0xFF) {
// No error
} else {
// Error - Check only SPN and J1939 FMI:s - The rest are reserved
uint8_t SPN_byte_3 = data[2];
uint8_t SPN_byte_4 = data[3];
uint8_t SPN_byte_5 = data[4] >> 5;
uint8_t FMI_byte = data[4] & ~(0b11100000);
if(SPN_byte_3 == 0x3F && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x13){
// Inconsistent CAN Control message
sbz->errormessages_binary[1] = true;
}else if(SPN_byte_3 == 0x3F && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x9){
// No CAN Control message received = TIME OUT
sbz->errormessages_binary[2] = true;
}else if(SPN_byte_3 == 0x74 && SPN_byte_4 == 0x2 && SPN_byte_5 == 0x0 && FMI_byte == 0x2){
// EEPROM parameter write/read error
sbz->errormessages_binary[3] = true;
}else if(SPN_byte_3 == 0x40 && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x0){
// Stepper motor stall detected
sbz->errormessages_binary[4] = true;
}else if(SPN_byte_3 == 0x9E && SPN_byte_4 == 0x0 && SPN_byte_5 == 0x0 && FMI_byte == 0x12){
// Undervoltage SONCEBOZ value (VDC<U_MINOFF)
sbz->errormessages_binary[5] = true;
}else if(SPN_byte_3 == 0x9E && SPN_byte_4 == 0x0 && SPN_byte_5 == 0x0 && FMI_byte == 0x10){
// Overvoltage SONCEBOZ value (VDC>U_MAXOFF)
sbz->errormessages_binary[6] = true;
}else if(SPN_byte_3 == 0x42 && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x0){
// SCU temperature higher than T_MAXOFF
sbz->errormessages_binary[7] = true;
}else if(SPN_byte_3 == 0x42 && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x1){
// SCU temperature below T_MINOFF
sbz->errormessages_binary[8] = true;
}else if(SPN_byte_3 == 0x44 && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x0){
// Current exceeds upper limit I_MAX
sbz->errormessages_binary[9] = true;
}else if(SPN_byte_3 == 0x43 && SPN_byte_4 == 0xF0 && SPN_byte_5 == 0x7 && FMI_byte == 0x2){
// Error position in IDLE Mode
sbz->errormessages_binary[10] = true;
}else if(SPN_byte_3 == 0x76 && SPN_byte_4 == 0x2 && SPN_byte_5 == 0x0 && FMI_byte == 0x2){
// Range error for Linearization parameter in EEPROM
sbz->errormessages_binary[11] = true;
}
}
}
}
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 14:00:22
av sodjan
> Min ECU är ju min STM32 och jag tror inte den vet att den har ECU addressen 0x22. Jag bara sätter 0x22 som adress när jag skriver ID meddelanden.
Det som din ECU "vet" är ju exakt detsamma som det din kod gör. Det är ju samma sak.
Du sätter alltså 0x22 som "source address" då du skriver meddelanden. OK.
> Det kanske är förväntat från ACU att den ska få meddelanden från ECU som innehåller SA = 0x22.
Det sas tidigare att en ACU accepterar meddelanden från vilken adress som helst.
Men den svarar bara till 0x22.
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 14:26:18
av DanielM
sodjan skrev: ↑13 augusti 2020, 14:00:22
Det som din ECU "vet" är ju exakt detsamma som det din kod gör. Det är ju samma sak.
Du sätter alltså 0x22 som "source address" då du skriver meddelanden. OK.
När jag skickar från ECU till ACU. Ja.
Det sas tidigare att en ACU accepterar meddelanden från vilken adress som helst.
Men den svarar bara till 0x22.
Jag har kollat igenom denna kod och den skickar korrekt data med korrekt indexering. Men jag tror att jag har glömt två saker. ACK + Request.
Tittar vi på denna hemsida.
https://copperhilltech.com/blog/sae-j19 ... s-claimed/
Då ser vi att jag har glömt någon av dessa.
- Request Message (PGN 59904)
Address Claimed / Cannot Claim (PGN 60928)
Cannot Claim Source Address (PGN 60928)
Commanded Address (PGN 65240)
Idag utför jag inget Request Message eller ACK. Tror du jag måste göra detta?
Kod: Markera allt
static bool CAN_connected = false;
static uCAN_MSG txMessage;
static uCAN_MSG rxMessage;
// Write an extended CAN message
static void write_CAN_message(uint32_t ID, uint8_t data[]) {
txMessage.frame.idType = dEXTENDED_CAN_MSG_ID_2_0B;
txMessage.frame.id = ID;
txMessage.frame.dlc = 8;
txMessage.frame.data0 = data[0];
txMessage.frame.data1 = data[1];
txMessage.frame.data2 = data[2];
txMessage.frame.data3 = data[3];
txMessage.frame.data4 = data[4];
txMessage.frame.data5 = data[5];
txMessage.frame.data6 = data[6];
txMessage.frame.data7 = data[7];
CANSPI_Transmit(&txMessage);
}
// Read the extended CAN message
static bool read_CAN_message(uint32_t* ID, uint8_t data[]){
bool available = CANSPI_Receive(&rxMessage);
if(available){
//uint8_t idType = rxMessage.frame.idType; // Extended ID type
*ID = rxMessage.frame.id;
data[0] = rxMessage.frame.data0;
data[1] = rxMessage.frame.data1;
data[2] = rxMessage.frame.data2;
data[3] = rxMessage.frame.data3;
data[4] = rxMessage.frame.data4;
data[5] = rxMessage.frame.data5;
data[6] = rxMessage.frame.data6;
data[7] = rxMessage.frame.data7;
return available;
}
return available;
}
// Transport Protocol Connexion Management Broadcast Announce Message
static void send_j1939_TP_CM_BAM(SBZ* sbz, uint16_t message_size, uint8_t packages_to_send, uint32_t PGN){
// ID
uint32_t ID = (0x1CECFF << 8) | sbz->SA_ECU;
// Fill the data
uint8_t data[8];
data[0] = 0x20; // Control byte - Standard
data[1] = message_size; // Message size LSB. Total message size is 9 to 1785 bytes
data[2] = message_size >> 8; // Message size MSB
data[3] = packages_to_send; // Packages to send is 2 to 255 packages
data[4] = 0xFF; // Reserved
data[5] = PGN; // PGN LSB
data[6] = PGN >> 8; // PGN
data[7] = PGN >> 16; // PGN MSB
// Write and wait 100 ms
write_CAN_message(ID, data);
HAL_Delay(100);
}
//Transport Protocol Data Transfer
static void send_j1939_TP_DT(SBZ* sbz, uint8_t data[], uint16_t message_size, uint8_t packages_to_send){
uint32_t ID = (0x1CEBFF << 8) | sbz->SA_ECU;
uint8_t package[8];
uint16_t sended_bytes = 0;
for(uint8_t i = 1; i <= packages_to_send; i++){
// Number of package
package[0] = i;
// Data
for(uint8_t j = 0; j < 7; j++){
if(sended_bytes < message_size)
package[j+1] = data[sended_bytes++];
else
package[j+1] = 0xFF; // No data
}
// Send wait 100 ms
write_CAN_message(ID, package);
HAL_Delay(100);
}
}
// Write the new CA and SA
void write_1939_CA_names_and_source_address(SBZ* sbz){
// Begin first to send BAM
send_j1939_TP_CM_BAM(sbz, 0x9, 0x2, 0x00FED8); // 0x00FED8 = Commanded Address PGN
// Send packages
uint8_t data[9];
memcpy(data, sbz->CA, 8); // Fill all CA to data
data[8] = sbz->SA_ACU; // New address
send_j1939_TP_DT(sbz, data, 0x9, 0x2);
}
// Write flow between -250 and 250. CA NAME need to have 0x81 (129d) Function code
void write_1939_auxiliary_valve_command(uint8_t DA, SBZ* sbz, float flow){
uint8_t state;
if (flow > 0) {
state = 0x1; // Extend
} else if (flow < 0) {
state = 0x2; // Retract
} else {
state = 0x0; // Neutral
}
uint32_t ID = (0x0CFE << 16) | (DA << 8) | sbz->SA_ECU;
uint8_t data[8] = {fabsf(flow), 0xFF, state, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
write_CAN_message(ID, data);
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 15:06:11
av DanielM
Jag har lyckats skapa kod för att anropa PGN 00EE00 (60928) (Address Claimed), alltså jag anropar den och då får jag CA NAMES tillbaka. Så det verkar som att det fungerar riktigt bra att anropa med Request PGN.
Tror ni att jag måste ta någon PGN request när jag ska ändra SA på ACU?
Kod:
Kod: Markera allt
// Connect can-bus, if we are not connected
static void connect_can_bus(J1939* j1939){
if(CAN_connected == false){
memset(j1939->CA, 0, 8);
memset(j1939->errormessages_binary, 0, 12);
j1939->SA_ACU = 0;
CAN_connected = CANSPI_Initialize();
}
}
// Special case for sending a request in J1939 of 3 bytes of PNG
static void write_CAN_PGN_request(uint8_t ID, uint8_t data[]){
txMessage.frame.idType = dEXTENDED_CAN_MSG_ID_2_0B;
txMessage.frame.id = ID;
txMessage.frame.dlc = 3;
txMessage.frame.data0 = data[0];
txMessage.frame.data1 = data[1];
txMessage.frame.data2 = data[2];
CANSPI_Transmit(&txMessage);
}
void write_1939_request_for_claim_address(J1939* j1939){
connect_can_bus(j1939);
uint8_t data[3] = {0x0, 0xEE, 0x00};
uint32_t ID = 0x18EAFFFE; // FE = 254 = No SA address known
write_CAN_PGN_request(ID, data);
HAL_Delay(100);
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 17:05:59
av sodjan
> Idag utför jag inget Request Message eller ACK. Tror du jag måste göra detta?
Frågar du mig?
Inte en susning...
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 17:34:26
av DanielM
Nu fungerar det att sätta adressen!
Vad glad jag blir!
Jag kan berätta lite kort hur jag gjorde så kanske du kan förklara med lite CPU språk.
För att få meddelanden från ACU till ECU så börjar ECU först ansluta MCP2515.
Detta görs vid denna lilla fina C-kod där CAN_connected är statiska och
CA är en 8 uint8_t array och
SA_ACU är uint8_t variabel samt
j1939 är en struktur.
Kod: Markera allt
// Connect can-bus, if we are not connected
static void connect_can_bus(J1939* j1939){
if(CAN_connected == false){
memset(j1939->CA, 0, 8);
memset(j1939->errormessages_binary, 0, 12);
j1939->SA_ACU = 0;
CAN_connected = CANSPI_Initialize();
}
}
Så fort jag får anslutning så skickar ACU sina CA NAME + SA_ACU adress.
Kod: Markera allt
// Read the 1939 message
void read_1939_message(J1939* j1939) {
// Check if we have connected the CAN
connect_can_bus(j1939);
uint32_t ID;
uint8_t data[8];
if (read_CAN_message(&ID, data) && CAN_connected) {
uint8_t id0 = ID >> 24;
uint8_t id1 = ID >> 16;
uint8_t id2 = ID >> 8;
uint8_t id3 = ID;
// Check what message we got
if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 != 0xFE) {
// Address claimed
j1939->SA_ACU = id3;
memcpy(j1939->CA, data, 8);
} else if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 == 0xFE) {
// Address not claimed
j1939->SA_ACU = 0;
j1939->errormessages_binary[0] = true;
memcpy(j1939->CA, data, 8);
} else if (id0 == 0x18 && id1 == 0xFE && id2 == 0xCA && id3 == j1939->SA_ACU) {
Vid denna koddel så ändrade jag från detta.
Kod: Markera allt
if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 != 0xFE) {
// Address claimed
j1939->SA_ACU = id3;
memcpy(j1939->CA, data, 8);
Till detta
Kod: Markera allt
if (id0 == 0x18 && id1 == 0xEE && id2 == 0xFF && id3 != 0xFE) {
// Address claimed
j1939->SA_ACU = 0x80; // Min nya adress
memcpy(j1939->CA, data, 8);
write_1939_CA_names_and_source_address(j1939);
Då fungerar det! Alltså detta är alltså det absolut första som görs så fort vi har fått anslutning med MCP2515.
Slutsats:
Innan man skickar TP BAM så MÅSTE man vänta minst 750 ms. Så jag väntar 1000 ms och detta löse problemet!
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 13 augusti 2020, 19:52:55
av DanielM
Någon som känner igen DM14, DM15 och DM16 i J1939?
Jag tänkte bara fråga vad pointer betyder?
Markering_077.png
Markering_078.png
Markering_079.png
Kan pointer betyda
Address[DEC]?
Markering_080.png
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 14 augusti 2020, 10:56:27
av Rick81
Pointer är väl bara minnesadressen du vill läsa ifrån?
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 14 augusti 2020, 11:13:22
av DanielM
Okej! Nu har jag grottat i lite saker nu. Nu ska ni få höra!
DM14 är bara en förfrågan till minnet om man vill skriva eller läsa. Man kan välja Flash-minnet eller EEPROM eller variabel-minnet, vet ej vad variabelminnet betyder dock.
Här är en procedur hur man anropar minnet.
- 1. Length betyder längden på datat du vill ändra eller läsa.
2. Pointer Type säts antingen till 1 eller 0. Om det är 0 så får du ingen återkoppling om det är OK att läsa eller skriva. Sätter du den till 1 så får du ett så kallat DM15 meddelande som beskriver statusen
3. Command är om du vill läsa eller skriva
4. Pointer är själva adresssnummret till just den variabeln eller värdet du vill ändra.
5. Pointer extension skall vara 1 om du vill läsa eller skriva från EEPROM
6. Key/User level är som ett lås där man kan hindra andra användare från att läsa eller skriva till EEPROM. För att läsa så skriver vi key = 0xFFFF. För att skriva så väljer vi key = 0x2505
Efter man har skickat sitt DM14 så får man ett DM15.
Markering_082.png
Här behöver vi bara läsa utav status då det är just status som bestämmer om vi kan läsa eller inte.
Markering_083.png
Men då kommer jag till frågan. Låt oss säga att vi har fått grönt ljus av DM15 att läsa eller skriva. Hur ska jag då tolka DM16?
Markering_084.png
Jag har hittat ett dokument här
http://www.unece.org/fileadmin/DAM/tran ... 40-06e.pdf
Som beskriver lite om DM16 men jag kan inte tolka vad "Number of occurrences" betyder.
Markering_085.png
Jag har lite C-kod som beskriver kontrollflödet. Men jag har ingen aning hur jag skall tolka DM16. Kommer det direkt från ACU till ECU efter jag har fått DM15?
Kod: Markera allt
// Send a memory request for access EEPROM and ask for a diagnostic message DM15
static void DM14_Memory_access_request(uint32_t ID, uint16_t length, uint8_t command, uint32_t pointer, uint16_t key){
uint8_t data[8];
data[0] = length; // Length LSB
data[1] = (length >> 3) | (1 << 4) | (command << 1) | 1; // Length MSB, Pointer Type(Diagnostic message), Command, 1 (Always)
data[2] = pointer; // Pointer LSB
data[3] = pointer >> 8;
data[4] = pointer >> 16; // Pointer MSB
data[5] = 0x1; // Pointer extension 1 for access EEPROM
data[6] = key; // Key LSB
data[7] = key >> 8; // Key MSB
write_CAN_message(ID, data);
}
// Request configuration parameters
void write_1939_configuration_request(J1939* j1939, uint8_t command){
uint32_t ID = (0x18D9 << 16) | (j1939->SA_ACU << 8) | j1939->SA_ECU;
HAL_Delay(1000);
/*
* Pointers:
* 646 = Sensor_Stall_Neutral_Enable
* 647 = Sensor_Stall_Normal_Enable
*
* Length:
* 1 = Sensor_Stall_Neutral_Enable
* 1 = Sensor_Stall_Normal_Enable
*/
uint8_t length_eeprom_values[2] = {1, 1};
uint8_t pointers_eeprom_address[2] = {646, 647};
// DM14(Ask) -> DM15(Status) -> DM16(Read/Write) -> DM14(Close)
for(uint8_t i = 0; i < 2; i++){
// Send a DM14 request
if(command == DM14_Read)
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Read, pointers_eeprom_address[i], 0xFFFF); // 0xFFFF = No key
else if (command == DM14_Write)
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Write, pointers_eeprom_address[i], 0x2505); // 0xFFFF = Write key
// Read until we got a DM15 message response
j1939->DM15_Status = DM15_Reserved;
while(j1939->DM15_Status == DM15_Reserved){
read_1939_message(j1939); // Will update j1939->DM15_Status
}
// What does it say
if(j1939->DM15_Status == DM15_Proceed){
if(command == DM14_Read)
readDM16();
else if (command == DM14_Write)
writeDM16();
// Close the read operation of DM14
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Operation_Completed, pointers_eeprom_address[i], 0xFFFF);
}else if(j1939->DM15_Status == DM15_Busy){
return; // One single Busy status, then we cannot do anything yet
}
}
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 14 augusti 2020, 15:21:53
av DanielM
Okej! Framsteg nu!
Jag börjar med att anropa DM14 (memory request) med denna typ av data. Se till höger där jag har en array uint8_t av 8 bytes.
Markering_086.png
Hittar vi på databladet så betyder det att jag väljer
Kod: Markera allt
byte1 = 0b00000001 (Längd på EEPROM värdet är 1 som vi vill ha tillåtelse till)
byte2 = 0b00010011 (Pointer Type = 1(Vi vill ha DM15 meddelande som respons), Command = 1 (Read). Sista 1:an är fixerad
byte3 = 0b10000110 (Sista bits för adressen 646)
byte4 = 0b00000010 (Första bits för adressen 646)
byte5 = 0b00000000 (Med tanke på att 646 är inte mer än 16-bit så blir denna noll)
byte6 = 0b00000001 (Pointer Extension = 1 betyder att läser eller skriver till EEPROM)
byte7 = 0b11111111 (Key LSB 0xFF = 255 = Vi vill läsa)
byte8 = 0b11111111 (Key MSB 0xFF = 255 = Vi vill läsa)
Men då kommer mitt DM15 svar.
Markering_087.png
Kod: Markera allt
byte1 = 0b00000000 ( Detta betyder att det finns inget EEPROM som vi har valt, som är tillåtet att läsa eller skriva. I detta fall läsa)
byte2 = 0b00000011 (Status = Busy = Upptagen)
byte3 -> byte8 = 0b1111111 ( Enligt databaldet är alla 0xFF på byte3 till byte8)
Så något gör så att jag kan ej läsa EEPROM.
Kod: Markera allt
// Send a memory request for access EEPROM and ask for a diagnostic message DM15
static void DM14_Memory_access_request(uint32_t ID, uint16_t length, uint8_t command, uint32_t pointer, uint16_t key){
uint8_t data[8];
data[0] = length; // Length LSB
data[1] = (length >> 3) | (1 << 4) | (command << 1) | 1; // Length MSB, Pointer Type(Diagnostic message), Command, 1 (Always)
data[2] = pointer; // Pointer LSB
data[3] = pointer >> 8;
data[4] = pointer >> 16; // Pointer MSB
data[5] = 0x1; // Pointer extension 1 for access EEPROM
data[6] = key; // Key LSB
data[7] = key >> 8; // Key MSB
write_CAN_message(ID, data);
}
// Request configuration parameters
void write_1939_configuration_request(J1939* j1939, uint8_t command){
uint32_t ID = (0x18D9 << 16) | (j1939->SA_ACU << 8) | j1939->SA_ECU;
HAL_Delay(1000);
/*
* Pointers:
* 646 = Sensor_Stall_Neutral_Enable
* 647 = Sensor_Stall_Normal_Enable
*
* Length:
* 1 = Sensor_Stall_Neutral_Enable
* 1 = Sensor_Stall_Normal_Enable
*/
const uint8_t length_eeprom_values[2] = {1, 1}; // Between 1 and 7 only!
const uint32_t pointers_eeprom_address[2] = {646, 647}; // Same indexing for j1939->EEPROM_values
// DM14(Ask) -> DM15(Status) -> DM16(Read/Write) -> DM14(Close)
for(uint8_t i = 0; i < 2; i++){
// Send a DM14 request
if(command == DM14_Read)
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Read, pointers_eeprom_address[i], 0xFFFF); // 0xFFFF = No key
else if (command == DM14_Write)
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Write, pointers_eeprom_address[i], 0x2505); // 0x2505 = Write key
// Read until we got a DM15 message response
j1939->DM15_Status = DM15_Reserved;
while(j1939->DM15_Status == DM15_Reserved){
read_1939_message(j1939); // Will update j1939->DM15_Status
}
// What does it say
if(j1939->DM15_Status == DM15_Proceed){
if(command == DM14_Read){
j1939->DM16_data[0] = 0;
while(j1939->DM16_data[0] == 0){
read_1939_message(j1939); // As long DM16_data[0], then we have not receive our DM16 data yet
}
}else if (command == DM14_Write){
uint8_t data[8];
memset(data, 0, 8);
data[0] = length_eeprom_values[i]; // Between 1 and 7 only!
for(uint8_t j = 1; j < data[0]; j++){
data[j] = j1939->EEPROM_values[i] >> 8*(j-1); // EEPROM_values are uint16_t
}
write_CAN_message(ID, data);
}
}
// Close the read operation of DM14
DM14_Memory_access_request(ID, length_eeprom_values[i], DM14_Operation_Completed, pointers_eeprom_address[i], 0xFFFF);
// Break the for-loop and return
if(j1939->DM15_Status == DM15_Busy){
break; // One single Busy status, then we cannot do anything yet
}
}
}
Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?
Postat: 14 augusti 2020, 16:15:05
av Rick81
Du är säker på att motorn har ett EEPROM?