2022-02-08 02:36 AM
I have two STM32 based development boards and would like to get CAN example (slightly modified) to work with a simple data packet of 2 bytes sent from one board to the other. But I detect no valid CAN frame on the bus.
The setup is taken from here:
STM32F756 NUCLEO as CAN network master using HAL:
Code Source:
STM32F407 as CAN network slave using SPL:
Code from example projects of STSW-STM32065
Transceiver used : TJA1051
The source code used in projects are attached to this thread.
Please let me know where the issue could be, and it would be a great help.
Thanks in advance.
2022-02-18 01:08 AM
Following is the code source for the above-mentioned issue:
/************************** MASTER CODE ********************/
#define CANx CAN1
#define CANx_CLK_ENABLE() __HAL_RCC_CAN1_CLK_ENABLE()
#define CANx_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define CANx_FORCE_RESET() __HAL_RCC_CAN1_FORCE_RESET()
#define CANx_RELEASE_RESET() __HAL_RCC_CAN1_RELEASE_RESET()
/* Definition for CANx Pins */
#define CANx_TX_PIN GPIO_PIN_1
#define CANx_TX_GPIO_PORT GPIOD
#define CANx_TX_AF GPIO_AF9_CAN1
#define CANx_RX_PIN GPIO_PIN_0
#define CANx_RX_GPIO_PORT GPIOD
#define CANx_RX_AF GPIO_AF9_CAN1
/* Definition for CAN's NVIC */
#define CANx_RX_IRQn CAN1_RX0_IRQn
#define CANx_RX_IRQHandler CAN1_RX0_IRQHandler
static void MPU_Config(void);
void SystemClock_Config(void);
static void Error_Handler(void);
static void CPU_CACHE_Enable(void);
static void CAN_Config(void);
uint8_t TxData[8];
uint8_t RxData[8];
uint32_t TxMailbox;
uint8_t ubKeyNumber = 0x0;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
uint8_t count=0;
CAN_HandleTypeDef Can1Handle;
void main(void){
MPU_Config();
CPU_CACHE_Enable();
HAL_Init();
SystemClock_Config();
while (1)
{
/* Set the data to be transmitted */
TxData[0] = count++;
HAL_StatusTypeDef status;
/* Start the Transmission process */
status = HAL_CAN_AddTxMessage(&Can1Handle, &TxHeader, TxData, &TxMailbox);
if ( status!= HAL_OK){
//Debug code
}
else if(status ==HAL_OK){
//Debug code
}
HAL_Delay(10);
}
}
static void CAN_Config(void){
GPIO_InitTypeDef GPIO_InitStruct;
CANx_CLK_ENABLE();
CANx_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = CANx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Alternate = CANx_TX_AF;
HAL_GPIO_Init(CANx_TX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = CANx_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Alternate = CANx_RX_AF;
HAL_GPIO_Init(CANx_RX_GPIO_PORT, &GPIO_InitStruct);
/******************* CAN **********************/
CAN_FilterTypeDef sFilterConfig;
Can1Handle.Instance = CANx;
Can1Handle.Init.TimeTriggeredMode = DISABLE;
Can1Handle.Init.AutoBusOff = DISABLE;
Can1Handle.Init.AutoWakeUp = DISABLE;
Can1Handle.Init.AutoRetransmission = ENABLE;
Can1Handle.Init.ReceiveFifoLocked = DISABLE;
Can1Handle.Init.TransmitFifoPriority = DISABLE;
Can1Handle.Init.Mode = CAN_MODE_NORMAL;
Can1Handle.Init.SyncJumpWidth = CAN_SJW_1TQ;
Can1Handle.Init.TimeSeg1 = CAN_BS1_6TQ;
Can1Handle.Init.TimeSeg2 = CAN_BS2_2TQ;
Can1Handle.Init.Prescaler = 6;
if (HAL_CAN_Init(&Can1Handle) != HAL_OK){
Error_Handler();
}
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(&Can1Handle, &sFilterConfig) != HAL_OK){
Error_Handler();
}
if (HAL_CAN_Start(&Can1Handle) != HAL_OK){
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&Can1Handle, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK){
Error_Handler();
}
TxHeader.StdId = 0x321;
TxHeader.ExtId = 0x01;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.IDE = CAN_ID_STD;
TxHeader.DLC = 1;
TxHeader.TransmitGlobalTime = DISABLE;
}
/************* SLAVE CODE ***************/
#define CANx CAN1
#define CAN_CLK RCC_APB1Periph_CAN1
#define CAN_RX_PIN GPIO_Pin_0
#define CAN_TX_PIN GPIO_Pin_1
#define CAN_GPIO_PORT GPIOD
#define CAN_GPIO_CLK RCC_AHB1Periph_GPIOD
#define CAN_AF_PORT GPIO_AF_CAN1
#define CAN_RX_SOURCE GPIO_PinSource0
#define CAN_TX_SOURCE GPIO_PinSource1
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint8_t ubKeyNumber = 0x0;
static void CAN_Config(void);
void main(void){
CAN_Config();
/* Infinite loop */
while (1){
}
}
static void CAN_Config(void){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
GPIO_InitTypeDef GPIO_InitStructure;
/* CAN GPIOs configuration **************************************************/
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK, ENABLE);
/* Connect CAN pins to AF9 */
GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT);
/* Configure CAN RX and TX pins */
GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN | CAN_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
/* CAN configuration ********************************************************/
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
/* CAN register init */
CAN_DeInit(CANx);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
/* CAN Baudrate = 1 MBps (CAN clocked at 30 MHz) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 2;
CAN_Init(CANx, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
/* Enable FIFO 0 message pending Interrupt */
CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}
void CAN1_RX0_IRQHandler(void){
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
if ((RxMessage.StdId == 0x321)&&(RxMessage.IDE == CAN_ID_STD) && (RxMessage.DLC == 2))
{
ubKeyNumber = RxMessage.Data[0];
}
}
I have tried analyzing the bus using MICROCHIP's CAN ANALYZER tool, but it doesn't see any valid frame. Also the F756's HAL code returns hcan->ErrorCode:HAL_CAN_ERROR_TIMEOUT and hcan->State: HAL_CAN_STATE_ERROR by the function HAL_CAN_Start(&CanHandle). This occurs only when HAL based CAN code tries communicating with SPL based CAN code.
2022-02-18 01:47 AM
Get the data rates consistent, ie via APB clock and prescaler and then via bit quanta.
2022-02-18 11:33 PM
Hi Tesla DeLorean,
The time quanta for both the master and slave were wrong in the previous code snippet and are corrected to the following values,
F407 Dicovery Board (SLAVE)
SYS-CLK : 168MHz
APB1 CLK : 42MHz
CAN Prescalar : 2
TImeSeg1 : CAN_BS1_15TQ
TImeSeg2 : CAN_BS2_5TQ
SyncJumpWidth : CAN_SJW_1TQ
Sampling Point : 75%
BAUDRATE : 1MBps
CALCULATION:
tq = 1/(42MHz/2) = 47.619 nS
tBS1 = 15 x tq = 714.29 nS
tBS1 = 5 x tq = 238.1 nS
NominalBitTime = 1 tq + tBS1 + tBS2 = 1uS
Baudrate = 1/NominalBitTime = 1Mbps
samplingpoint (%) = tBS1/(tBS1 + tBS2)*100
(15/20)*100= 75%
F756 Nucleo Board (MASTER)
SYS-CLK : 216MHz
APB1 CLK : 54MHz
CAN Prescalar : 6
TImeSeg1 : CAN_BS1_6TQ
TImeSeg2 : CAN_BS2_2TQ
SyncJumpWidth : CAN_SJW_1TQ
Sampling Point : 75%
BAUDRATE : 1MBps
CALCULATION:
tq = 1/(54MHz/6) = 111.111 nS
tBS1 = 6 x tq = 666.667 nS
tBS1 = 2 x tq = 222.222 nS
NominalBitTime = 1 tq + tBS1 + tBS2 = 1uS
Baudrate = 1/NominalBitTime = 1Mbps
samplingpoint (%) = tBS1/(tBS1 + tBS2)*100
(6/8)*100= 75%
Based on the return status from the function HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, TxData, &TxMailbox) (in master code), the status seems to be OK for the first three times (the three mailboxes getting filled) then the status becomes HAL_ERROR.
During the entire operation, no valid or no CAN message frames are seen on the bus.
Please help me out in solving this issue.