Setup
I am using an STM32F103C8T6 (aka Blue Pill). With the STM32Cube I set CAN_RX to PB8 and CAN_TX9 to PB9 (these are defaults/nonchangeable).
Circuit
simulate this circuit – Schematic created using CircuitLab
Components in above circuit:
- STM #1: STM32F103C8T6
- STM #2: STM32F103C8T6
- Transceiver #1: TJA1050 based transceiver (see TJA 1050)
- Transceiver #2: TJA1050 based transceiver (see TJA 1050)
I found out the TJA1050 works on 5V and the output VCCs from STM32 are 3.3V, so I used a breadboard power supply to give 5V to Transceiver 1 and 2 VCC. I assume the USB GNDs are coupled to the GNDs of the STM32s (probably internally since I didn't do any specific wiring), same as the USB +5V is coupled to the VCC of the STMs.
The transceivers already contain 120 ohm resistors so I assume I don't need any additional. The current distance between CANL and CANH of transceiver #1 and #2 is about 10 cm / 4" (simple wire). In my real application it will be about 2 meters.
Also I assume that the CAN TX needs to be connected to the Tranceiver's TX (and RX to RX).
Can Settings
The generated CAN settings are below. This executes ok.
/* CAN init function */
static void MX_CAN_Init(void)
{
static CanRxMsgTypeDef CanRX;
static CanTxMsgTypeDef CanTX;
CAN_FilterConfTypeDef sFilterConfig;
hcan.Instance = CAN1;
hcan.pRxMsg = &CanRX;
hcan.pTxMsg = &CanTX;
hcan.Init.Prescaler = 128;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SJW = CAN_SJW_1TQ;
hcan.Init.BS1 = CAN_BS1_12TQ;
hcan.Init.BS2 = CAN_BS2_5TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = DISABLE;
hcan.Init.AWUM = DISABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sFilterConfig.FilterNumber = 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_FILTER_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
Program
(removed STM generated comments blocks)
Transmitter:
int main(void)
{
..
/* USER CODE BEGIN 2 */
hcan.pTxMsg->StdId = 0x100;
hcan.pTxMsg->ExtId = 0x01;
hcan.pTxMsg->RTR = CAN_RTR_DATA;
hcan.pTxMsg->IDE = CAN_ID_STD;
hcan.pTxMsg->DLC = 2;
while (1)
{
hcan.pTxMsg->Data[0] = 0x10;
hcan.pTxMsg->Data[1] = 0x1;
if (HAL_CAN_Transmit(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(1000);
}
}
Receiver (interrupt code is never called):
void RxIntEnable(CAN_HandleTypeDef *CanHandle)
{
if (CanHandle->State == HAL_CAN_STATE_BUSY_TX)
{
CanHandle->State = HAL_CAN_STATE_BUSY_TX_RX0;
}
else
{
CanHandle->ErrorCode = HAL_CAN_ERROR_NONE;
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EWG); // Error warning interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_EPV); // Error passive interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_BOF); // Bus-off interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_LEC); // Last error code interrupt
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_ERR); // Error interrupt
}
__HAL_CAN_ENABLE_IT(CanHandle, CAN_IT_FMP0); // FIFO0 message pending interrupt
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
if ((CanHandle->pRxMsg->StdId == 0x100) &&
(CanHandle->pRxMsg->IDE == CAN_ID_STD) &&
(CanHandle->pRxMsg->DLC == 2))
{
printf("1");
}
RxIntEnable(CanHandle);
}
within main:
if (HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) != HAL_OK)
{
Error_Handler();
}
Loopback mode
When I use loopback mode:
hcan.Init.Mode = CAN_MODE_LOOPBACK
instead of Normal mode, I can transmit and receive messages (and the hcan shows the correct data in the received message).
Problem
However, in Normal mode (as shown in the code fragment above) I always get a timeout in the next command:
if (HAL_CAN_Transmit(&hcan, 10) != HAL_OK)
The function returns: HAL_CAN_STATE_TIMEOUT within this fragment (default HAL code):
/* Check End of transmission flag */
while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
{
hcan->State = HAL_CAN_STATE_TIMEOUT;
/* Cancel transmission */
__HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);
/* Process unlocked */
__HAL_UNLOCK(hcan);
return HAL_TIMEOUT;
}
}
}
All initialization seems to be ok (all functions return HAL_OK).
Analysis
What I tried/checked was:
- Using another STM32: no difference
- Using another transceiver: no difference
- Played a bit with the SJW/BS1/BS2 time quantities: no difference
- Making sure the time quantities were equal
- Playing with different data values and filters: no difference
- Checked the output of PB9 (CAN transmit): it seems not to change at all (so this is a problem): no difference
- Removing the wire from GPIO PB9 (CAN Tx) to the TX of my CAN transceiver : no difference.
- Checking the Transmit is cancelled (which is needed and was an old bug, but has already been fixed by the HAL library I'm using).
- Checking the resistance between CANL and CANH which moves between 63 and 70 ohms.
- Checking the voltage between CANL and CANH (while not sending after the error). 0 Voltage; I wouldn't expect this.
Questions
- Why do I get a timeout? I'm having a hard time trying to find more to check what I already did.
Related question:
Update
This is an old question, but trying again to get CAN working with same bad result (timeout). I changed some settings and updated the information above accordingly.
No comments:
Post a Comment