2021-07-21 08:13 AM
Hi!
I have recently written an SAE J1939 library and it works great to read CAN-bus signals. Check it out.
https://github.com/DanielMartensson/Open-SAE-J1939
I have copy->paste the library into my STM32 and it works great to read the SAE J1939 signals from the ECU unit. But when I'm going to write to the ECU unit, then nothing happens. It's not the librarys fault. It's the CAN-bus settings in STM32CubeIDE.
This is how I have done:
Step 1: I KNOW that the ECU has 250 kb/s baudrate. So I tune that in inside STM32CubeIDE
Step 2: Then I create my CAN-bus layer code. It's for STM32F3 if you wonder.
/*
* CAN.c
*
* Created on: Jun 14, 2021
* Author: Daniel Mårtensson
*/
#include "Functions.h"
static CAN_HandleTypeDef *can_handler;
static uint32_t CAN_ID = 0;
static uint8_t RxData[8] = {0};
static bool new_message = false;
static void Create_CAN_Filter(CAN_HandleTypeDef *hcan);
static void Create_CAN_Interrupt(CAN_HandleTypeDef *hcan);
void STM32_PLC_Start_CAN(CAN_HandleTypeDef *hcan) {
can_handler = hcan;
Create_CAN_Filter(hcan);
if (HAL_CAN_Start(hcan) != HAL_OK)
Error_Handler();
Create_CAN_Interrupt(hcan);
}
HAL_StatusTypeDef STM32_PLC_CAN_Transmit(uint8_t TxData[], CAN_TxHeaderTypeDef *TxHeader) {
uint32_t TxMailbox;
return HAL_CAN_AddTxMessage(can_handler, TxHeader, TxData, &TxMailbox);
}
/* Returns true if the message data is new */
void STM32_PLC_CAN_Get_ID_Data(uint32_t* ID, uint8_t data[], bool* is_new_message) {
*ID = CAN_ID;
memcpy(data, RxData, 8);
*is_new_message = new_message;
new_message = false;
}
/* Interrupt handler that read message */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
CAN_RxHeaderTypeDef RxHeader;
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
Error_Handler();
/* Read ID */
if(RxHeader.IDE == CAN_ID_STD){
CAN_ID = RxHeader.StdId;
}else{
CAN_ID = RxHeader.ExtId;
}
new_message = true;
}
static void Create_CAN_Interrupt(CAN_HandleTypeDef *hcan) {
if (HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
Error_Handler();
}
static void Create_CAN_Filter(CAN_HandleTypeDef *hcan) {
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(hcan, &sFilterConfig) != HAL_OK)
Error_Handler();
}
Step 3: I init the CAN-bus layer.
STM32_PLC_Start_CAN(&hcan);
Step 4: I'm reading the SAE J1939 can bus signals..
Open_SAE_J1939_Listen_For_Messages(&j1939); /* Examples are available in the GitHub repository */
Step 5: Im suing TCAN334 IC chip for transmitt CAN-data.
https://www.ti.com/lit/ds/symlink/tcan334.pdf
All this above works great! I can read messages.
But then when I'm writing to the ECU unit. In this case, the ECU unit have the address 0x80 = 128. Nothing happens.
SAE_J1939_Send_Request_Address_Claimed(&j1939, 0x80);
I hook up an oscilloscope and analysing the signals.
Settings:
1V divider
20 uS sweep time
CAN+ from my STM32 board:
This is a request ID for Address Claimed = 0x00EE00
ID = 0x18EA8022 = 0b00011000 11101010 10000000 00100010
DLC = 3 bytes
DATA = 0x00EE00 = 0b00000000 11101110 00000000
CAN+ from the ECU:
Question:
Judging by the CAN+ signals, how different they are. Can it be that I have seleted wrong baudrate?
Why can I read the signals from the ECU, but not write to the ECU?
Edit:
Here is more pictures. The same settings as above.
CAN+ and CAN- from ECU
CAN+ and CAN- from STM32F3:
2021-07-21 09:45 AM
Is the STM32 flagging any error/status?
The CAN+/- look Ok
Have you tried a pair of STM32 talking to each other, or CAN1 to CAN2 out-n-back test?
Perhaps look at what the transceiver is doing.
2021-07-21 10:31 AM
I'm only having CAN1 and only one STM32 board.
The transmitt function gives HAL_OK.
Also from the ECU, I get a DM1 message.
FMI = 0 is it. I don't understand it.
"Data Valid But Above Normal Operational Range (Most Severe Level): The signal communicating information is within a defined acceptable and valid range, but the real world condition is above what would be considered normal as determined by the predefined most severe level limits for that particular measure of the real world condition (Region e of the signal range definition). Broadcast of data values is continued as normal."
https://product-help.schneider-electric.com/Machine%20Expert/V1.1/en/IoDrvJ1939/topics/fmi.htm
2021-07-21 10:53 AM
By the way! I notice something weir.d
This code runs, even if TransmitGlobalTime is DISABLE
/* Set up the Transmit Global Time mode */
if (pHeader->TransmitGlobalTime == ENABLE)
{
SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT);
}
Have a look
2021-07-21 11:51 AM
Is there any way I can put CAN- constant low and CAN+ constant high in STM32CubeIDE?
I want to measure the voltage between CAN+ and CAN-. Perhaps the voltage is to low?
Thank you.