2023-07-31 03:21 PM
Hello staff,
I'm trying can bus interface on dev board nucleo-f103RB. I immediately pass the self-loop test mode and move on to build a minimal CAN with 2 nodes(2 f103RB, one as transmitter and the other as listener). I'm using normal communication mode for this test and two simple tja1050 breakouts as transceivers. On the breadboard, I use two 120 ohm resistor on each end of the bus to close it, and I power the whole on one of the nucleo-f103RB. The connection between controller and transceiver is Tx to Tx, Rx to Rx.
The problem I encountered is that, I always get RQCP0 and TERR0 reported 1 after sending the tranmission request. I tried to look deeper at the error reported, calling function HAL_CAN_GetError to take a look at the error status register (CAN_ESR) but it would always be cleared and left with 0x1000 with 0b000 on the Last Error Code part. This makes me really confused.
To summarize my questions:
1. what are the pre-requisite for the normal mode to functioning? Does it require external hardware connections? or as long as the code is doing the right thing, the sending would be successful?
2. how to make sure we activate the callback functions in CAN, I've set the callback by calling the function HAL_CAN_ActivateNotification and change the NVIC settings accordingly, but only HAL_CAN_RxFifo0MsgPendingCallback could work as expected and all others like
HAL_CAN_TxMailbox0CompleteCallback() and HAL_CAN_ErrorCallback() are not triggered even I've activated the notification.
I paste most important code snippets for reference here and the hardware connection is in attachment, thanks for your help!
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
// Step 3 of loop-back test of CAN-bus
CAN_TxHeaderTypeDef myHeaderTx;
CAN_RxHeaderTypeDef myHeaderRx;
HAL_CAN_StateTypeDef canPossibleError;
uint32_t canTxMailboxStatus;
static uint32_t mailboxTx;
static uint8_t dataBufferTx;
static uint8_t dataBufferRx;
uint32_t canErrorCode;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
/**
* Helper function for sending message to rbt6 1
*/
HAL_StatusTypeDef canTransmitMsg(void) {
/* setting headers for transmission */
// sprintf((char *) dataBufferTx, "Cody the most FarSeeing guy with id 0x1\n");
//
// myHeaderTx.DLC = strlen((const char *) dataBufferTx); // assigning data length according to requirement
dataBufferTx = 0b11111111;
myHeaderTx.DLC = 1;
myHeaderTx.ExtId = 0; // extended ID not in use
myHeaderTx.IDE = CAN_ID_STD; // declaring using standard ID not extended ones
myHeaderTx.RTR = CAN_RTR_DATA; // declaring data frame instead of remote frame
myHeaderTx.StdId = 0x001; // DIYed second highest priority stdid
myHeaderTx.TransmitGlobalTime = DISABLE; // no need to tx the time
return HAL_CAN_AddTxMessage(&hcan, &myHeaderTx, dataBufferTx, &mailboxTx);
}
/**
* @brief CAN Initialization Function
* @PAram None
* @retval None
*/
static void MX_CAN_Init(void)
{
/* USER CODE BEGIN CAN_Init 0 */
/* USER CODE END CAN_Init 0 */
/* USER CODE BEGIN CAN_Init 1 */
/* USER CODE END CAN_Init 1 */
hcan.Instance = CAN1;
hcan.Init.Prescaler = 16;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_2TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN_Init 2 */
canPossibleError = HAL_CAN_GetState(&hcan);
// attach filter objects to the CAN object
/*
// let the C8T6 keeps sending the message "Cody the most handsome guy with id 0x1" with stdID 0x1
// let the C8T6 keeps sending the message "Cody the most resilient guy with id 0x0" with stdID 0x0
// let one RBT6's can1 Rx Mailbox own filter with mask 0x0000'0001
// and with filterID as 0x0000'0001 for accepting messages with last digit as 1
// let another one's mask as 0x0000'0001 (filter on last digit)
// with filterID as 0x0000'0000 accepting messages with last digit as 0
*/
CAN_FilterTypeDef myNaiiveFilter;
myNaiiveFilter.FilterActivation = CAN_FILTER_ENABLE;
myNaiiveFilter.FilterBank = 10;
myNaiiveFilter.FilterFIFOAssignment = CAN_RX_FIFO0;
myNaiiveFilter.FilterIdHigh = 0x0000;
myNaiiveFilter.FilterIdLow = 0x0001;
myNaiiveFilter.FilterMaskIdHigh = 0x0000;
myNaiiveFilter.FilterMaskIdLow = 0x0001;
myNaiiveFilter.FilterMode = CAN_FILTERMODE_IDMASK;
myNaiiveFilter.FilterScale = CAN_FILTERSCALE_32BIT;
myNaiiveFilter.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan, &myNaiiveFilter);
canPossibleError = HAL_CAN_GetState(&hcan);
/* USER CODE END CAN_Init 2 */
}
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_CAN_StateTypeDef canStatusPriorStart = HAL_CAN_GetState(&hcan);
// starts the CAN bus controller
HAL_StatusTypeDef canStartStatus = HAL_CAN_Start(&hcan);
canErrorCode = HAL_CAN_GetError(&hcan);
if (canErrorCode & HAL_CAN_ERROR_TIMEOUT) {
__NOP();
__NOP();
}
// activate the callback function for listening on incoming messages
// HAL_StatusTypeDef canInterruptSetStatus = HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
// // activate the callback function for monitoring on emptying TxEmailbox
HAL_CAN_ActivateNotification(&hcan, CAN_IT_TX_MAILBOX_EMPTY);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_ERROR);
//// get the can module state prior to transmission
HAL_CAN_StateTypeDef canCurState = HAL_CAN_GetState(&hcan);
//
// dataBufferTx[0] = 0xff;
// HAL_StatusTypeDef canTransmitStatus = HAL_CAN_AddTxMessage(&hcan, &myHeaderTx, dataBufferTx, &mailboxTx);
// get the can module state after the trial transmission
// print error code if any
uint32_t errorCodeIfAny = HAL_CAN_GetError(&hcan);
__NOP();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
canTxMailboxStatus = HAL_CAN_IsTxMessagePending(&hcan, mailboxTx);
__NOP();
// send the message to the first RBT6
HAL_StatusTypeDef firstTxResult = canTransmitMsg();
canErrorCode = HAL_CAN_GetError(&hcan);
canTxMailboxStatus = HAL_CAN_IsTxMessagePending(&hcan, mailboxTx);
// check for error and error handling
if (__HAL_CAN_GET_FLAG(&hcan, CAN_FLAG_TERR0) ||
__HAL_CAN_GET_FLAG(&hcan, CAN_FLAG_TERR1) ||
__HAL_CAN_GET_FLAG(&hcan, CAN_FLAG_TERR2)) {
Error_Handler();
}
canCurState = HAL_CAN_GetState(&hcan);
// each loop do the delay for clearer data transmission
// intermittent transmission => better for checking
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2023-07-31 03:46 PM
@CWang.14 wrote:Hello staff,
(I wouldn't use Staff this way in a forum, forum staff are not my employees
2023-07-31 03:55 PM
Ok for sure I'll use friends lol, if that's more suitable