Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av DanielM »

Ja. Det står i databladet :)
Jag kipper ut 16 sidor av databladet. Där kan ni se hur J1939 hanterar olika adresser och EEPROM.
TCI SENSE 42 Version 3.0-50-68.pdf
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av DanielM »

Nu fick jag det fungera! PointerType skall vara 0, inte 1!

Nu kan jag läsa utav meddelanden, men jag tror att jag har tolkat vad "Pointer" egentligen betyder.

Här har jag valt adresserna
const uint32_t pointers_eeprom_address[2] = {736, 647};
Och som ni ser i databladet så betyder det att 736 och 647 har antingen 0 eller 1. Men det svar jag får är att 736 har värdet 10 = 0x2 och 647 har värdet 0. Detta stämmer inte då 647 ska ha värdet 1 och 736 skall ha värdet 1
Markering_089.png
Markering_090.png

Kod: Markera allt

// Send a memory request for access EEPROM
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) | (0 << 4) | (command << 1) | 1; // Length MSB, Pointer Type(Diagnostic message = 0), 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] = {736, 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 - We expecting DM15_Proceed
		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){
				// Read the EEPROM values of ECU and give them to the EEPROM_values array
				memset(j1939->DM16_data, 0, 8); // j1939->DM16_data[0] will become between 1 and 7 only!
				while(j1939->DM16_data[0] == 0){
					read_1939_message(j1939); // As long DM16_data[0], then we have not receive our DM16 data yet
				}
				for(uint8_t j = 1; j <= j1939->DM16_data[0]; j++){
					j1939->EEPROM_values[i] |= j1939->DM16_data[j] << 8*(j-1); // EEPROM_values are uint16_t
				}

			}else if (command == DM14_Write){
				// Write the EEPROM_values to data and send it to the ECU EEPROM
				memset(j1939->DM16_data, 0, 8);
				j1939->DM16_data[0] = length_eeprom_values[i]; // Between 1 and 7 only!
				for(uint8_t j = 1; j <= j1939->DM16_data[0]; j++){
					j1939->DM16_data[j] = j1939->EEPROM_values[i] >> 8*(j-1); // EEPROM_values are uint16_t
				}
				write_CAN_message(ID, j1939->DM16_data);
			}
		}

		// Read until we got a DM15 message response - We expecting DM15_Operation_Completed
		j1939->DM15_Status = DM15_Reserved;
		while(j1939->DM15_Status == DM15_Reserved){
			read_1939_message(j1939); // Will update j1939->DM15_Status
		}

		// 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
		}
	}
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av DanielM »

If Pointer Type 0 is used, this 24-bit parameter, which has a value of 0 to 16,777,215 (0 to FFFFFF16) with no reserved ranges, is concatenated with the 8-bit Pointer Extension to form a direct memory address. The address thus formed represents the first address to be accessed within the memory in units of bytes. If Pointer Type 1 is used, the Pointer is to provide the identification of the specific OBJECT within whatever particular SPACE is being identified by the Pointer Extension. The direct memory address should be parsed as outlined below, 5.7.14.3.1, if the device memory width is other than 1 byte.
Jag använder alltså Pointer Type = 0 och det betyder att Pointer Extension = 1 kommer alltså vara en del utav adresseringen?
For all memory widths the starting address is simply the pointer extension concatenated with the pointer (the pointer being the lower 24 bits and the extension the upper 8). For memory widths of one byte there is a one-to-one mapping between data and the memory. Hence the first data byte goes into the memory at the starting address, while the second data byte corresponds to the memory at the starting address plus 1. For widths other than 1 byte, the data cannot map directly to the memory, but must be used to assemble the necessary width. Hence it will take as many data bytes per address as seven plus the memory width in bits all divided by 8 ((memory width + 7)/8). To maintain consistency with the rest of this standard the first data byte should be used for the byte containing bits 1 to 8 at the starting address. The second data byte should be used for bits 9 to 16. This should continue for the number of bytes required; then the address should be incremented and those bytes filled. When the memory width is less than 1 byte (as might happen when addressing a 2-bit parameter through the SPN space), a whole byte is used to contain each object's data (in other words no packing is to occur). The two bits will be placed in the least significant bits of the byte. For systems where the memory width is not an integer number of bytes, some bits in the highest byte are unused, reducing transfer efficiency, but enabling all memory widths to be handled. Examples of address calculation and byte association (see also section 5.7.16.2)
Eller hur ska man tolka detta?
8-bit-wide memory, Pointer Extension = 1016, Pointer = 36780016 then the starting memory address is 1036780016and the first byte of Raw Binary Data would map directly into the memory at 1036780016, the second byte of Raw Binary Data would then map into memory 1036780116, and so on until completed. 16-bit-wide memory, Pointer Extension = 1016, Pointer = 36780016 then the starting memory address is 1036780016and the first byte of Raw Binary Data would map into bits 1 to 8 of the memory at 1036780016, while the second byte of Raw Binary Data would map into bits 9 to 16 of the same memory. The third byte of Raw Binary Data would then map into bits 1 to 8 of the memory at 1036780116, while the fourth byte of Raw Binary Data would map into bits 9 to 16 of the memory at 1036780116.32-bit-wide memory, Pointer Extension = 1016, Pointer = 36780016 then the starting memory address is 1036780016and the first byte of Raw Binary Data would map into bits 1 to 8 of the memory at 1036780016, while the second byte of Raw Binary Data would map into bits 9 to 16 of the memory at 1036780016, the third byte of Raw Binary Data would then map into bits 17 to 24 of the same memory and the fourth byte of Raw Binary Data would map bits 25 to 32. The fifth byte of Raw Binary Data would then map bits 1 to 8 of 1036780116, while the sixth byte of Raw Binary Data would map into bits 9 to 16 of 1036780116, the seventh byte of Raw Binary Data then mapping bits 17 to 24 and the eight byte of Raw Binary Data mapping to bits 25 to 32 of the memory. 12-bit-wide memory, Pointer Extension = 1016, Pointer = 36780016 then the starting memory address is 1036780016and the first byte of Raw Binary Data would map into bits 1 to 8 there, while bits 9 to 12 of the second byte of Raw Binary Data would map into bits 9 to 12 of 1036780016 (bits 13 to 16 are simply unused). The third byte of Raw Binary Data would then map into bits 1 to 8 of 1036780116, while bits 9 to 12 of the fourth byte of Raw Binary Data would map into bits 9 to 12 of 1036780116.
Sida 57
WP29-140-06e.pdf
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av DanielM »

Okej! Nu har jag hittat ett sätt som styrker min teori på att Address[DEC] = pointer

Om jag tog Pointer Extension = 2 och sedan Address[DEC] = 1 = Pointer så kunde jag läsa utav temperaturen på motorn. Detta betyder att jag har hela tiden kunna läsa utav EEPROM. Men det jag inte kan göra, är att skriva till EEPROM. Jag får statusen: Busy

Kod: Markera allt

// Send a memory request for access EEPROM
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) | (0 << 4) | (command << 1) | 1; // Length MSB, Pointer Type(Diagnostic message = 0), 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);
}
Markering_101.png
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av Rick81 »

Temperatur ligger knappast i EEPROM. Testa läsa någon känd information ifrån EEPROM. Funkar det kan du testa skriva.

Sen brukar det vara fördröjningar på EEPROM på ett tiotal ms så skriva du flera ggr skulle du nog kunna få busy om du inte har delay i mellan.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Transport protokoll i J1939-21 - Hur gör man för skicka 9 bytes?

Inlägg av DanielM »

Pointer Extension = 0x02 är variabla parametrar, typ ADC. :)

Jag har talat med Sonceboz och dom säger att mitt protokoll som jag har, är för nytt jämfört med serienummret på den ACU som jag har hemma. Så därför får jag Busy tydligen. Med andra ord, adress 646 och 647 finns inte på min Sonceboz.

Jag inväntar en ny Sonceboz :) Återkommer.
Skriv svar