I'm trying to learn about microcontrollers in general and at this point I'm trying to learn about the CAN bus standard by using it with an STM32 MCU in a NUCLEO-F767ZI board.
For that end I want to send a message from an STM32 in the board to an Arduino Uno with a CAN module, and have it reply something based on what I send.
The first step in this process was to achieve CAN bus communication between two Arduinos using two CAN MCP2515 modules that interface with the Arduino through SPI. It worked perfectly when I flashed one Arduino with transmitter code and the other with receiver code and exchanged messages as described above.
The second step was to replace the transmitter Arduino with the STM32, which is where things stopped working. First I realized I needed a CAN transceiver, so I got a MCP2551 transciver and connected the VCC to STM32 5 V, GND to STM32 GND, CANTX and CANRX to CANTX and CANRX. The CANH lines and CANL lines I connected to the CANH and CANH on the arduino's MCP2515 module. I then flashed the STM32 with the following code:
MX_CAN1_Init();
CAN_FilterTypeDef canfilterconfig;
canfilterconfig.FilterActivation = CAN_FILTER_ENABLE;
canfilterconfig.FilterBank = 18; // which filter bank to use from the assigned ones
canfilterconfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
canfilterconfig.FilterIdHigh = 0x446<<5;
canfilterconfig.FilterIdLow = 0;
canfilterconfig.FilterMaskIdHigh = 0x446<<5;
canfilterconfig.FilterMaskIdLow = 0x0000;
canfilterconfig.FilterMode = CAN_FILTERMODE_IDMASK;
canfilterconfig.FilterScale = CAN_FILTERSCALE_32BIT;
canfilterconfig.SlaveStartFilterBank = 20;
CAN_TxHeaderTypeDef TxHeader;
uint8_t TxData;
uint32_t TxMailbox = 1;
TxHeader.IDE = CAN_ID_STD;
TxHeader.StdId = 0x0F6;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.DLC = 1;
TxData = 0x11;
HAL_CAN_ConfigFilter(&hcan1, &canfilterconfig);
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
while (1)
{
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, &TxData, &TxMailbox) ;
delay(500);
}
static void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 9;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK) //Edit: I had ommitted this section
{
Error_Handler();
}
}
I then attempted to receive the commands on the Arduino but, I couldn't. I couldn't figure out why, so I bought a logic analyzer. I tested it on the CANRX line by analyzing that signal when the transceiver is connected to a transmitting Arduino, so everything is working, but what I cannot understand is why when I try to analyze the CANTX line (going out of the STM32) the line is idle as high. I have not been so able to analyze this signal and I suspect the STM32 isn't outputting anything, but I don't know why. Does anyone know?
I don't know if at this stage (just looking at CANTX) this is required, but I hooked up the CAN connection between STM32 and the Arduino again and put 120 Ω resistors between the CANH and CANL lines at both ends, but still nothing is shown.
When interfacing an STM32 and an Arduino for other protocols I needed to use a level shifter, since the STM32 operates at 3.3 V and the Arduino at 5 V, but I think that shouldn't be an issue if I'm only trying to get something on the CANTX.
I don't believe there is anything wrong with my code since it seems to be pretty standard in all implementations I've seen, so that means the problem must be in the hardware, but I've run out of ideas, so if someone could help I would really appreciate it.