Configuration process
1. Chip selection
The chip I chose is: stm32f103c8t6
2. Clock enable
3. Debugger selection
4. Clock tree configuration
5.CAN parameters and interrupt settings
Baud rate calculation formula: clock frequency/(prescaler x (TQ1+TQ2+SJW)) = baud rate;
Parameter setting points: tq1 / (tq1 + tq2) It is best to be around 0.8. If it is less than 0.5, communication will not be possible. During debugging, you can see that the register is sending data, but you can’t get a signal with an oscilloscope; of course, you can’t receive a signal either.
6. Filter settings (CubeIDE will not automatically generate them and need to be added manually)
CubeIDE will not automatically generate it and needs to be added manually! ! !
After following the above steps, normal sending can be carried out, but the mailbox needs to be configured to receive data, and the HAL_CAN_Start() and HAL_CAN_ActivateNotification() functions must be called to start receiving;
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 = 12;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_10TQ;
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 */
CAN_FilterTypeDef CAN_FilterInitStructure0;
CAN_FilterInitStructure0.FilterActivation = ENABLE;//使能过滤�?
CAN_FilterInitStructure0.FilterBank = 0;//指定过滤器为0
CAN_FilterInitStructure0.FilterMode = CAN_FILTERMODE_IDMASK;//指定过滤器为标识符屏蔽位模式
CAN_FilterInitStructure0.FilterScale = CAN_FILTERSCALE_32BIT;//过滤器位宽为32�?
CAN_FilterInitStructure0.FilterFIFOAssignment = CAN_FILTER_FIFO0;//设定了指向过滤器的FIFO
CAN_FilterInitStructure0.FilterIdHigh =0x0000 ;//要过滤的ID高位
CAN_FilterInitStructure0.FilterIdLow = 0x0000;//要过滤的ID低位
CAN_FilterInitStructure0.FilterMaskIdHigh = 0x0000;//过滤器屏蔽标识符的高16位�??
CAN_FilterInitStructure0.FilterMaskIdLow = 0x0000; //过滤器屏蔽标识符的低16位�??
HAL_CAN_ConfigFilter(&hcan,&CAN_FilterInitStructure0);
if ( HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING)!= HAL_OK)//选择fifo0中断
{
/* Notification Error */
Error_Handler();//开启CAN总线挂起中断失败的处理程序
}
HAL_CAN_Start(&hcan); /* 开启CAN的接收 */
/* USER CODE END CAN_Init 2 */
}
7. Send and receive functions (written according to personal needs)
typedef struct
{
uint32_t id; /* 发送ID */
uint8_t data[8]; /* 数据包 */
uint8_t lenth; /* 数据长度 */
}CAN_MSG_pHandler;
CAN_MSG_pHandler Rx_pHandler;
/*************************************************
Function: CAN接收函数
Description:
Input: rxheader,接收数据结构体
Output: None
Return: None
Others: None
*************************************************/
void CAN_Msg_RX(CAN_MSG_pHandler *rxheader)
{
CAN_RxHeaderTypeDef Rx_pHeader;
HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &Rx_pHeader, rxheader->data);
rxheader->id = Rx_pHeader.StdId;
rxheader->lenth =Rx_pHeader.DLC;
}
/*************************************************
Function: CAN发送函数
Description:
Input: txheader,发送数据结构体
Output: None
Return: None
Others: None
*************************************************/
void ADC_Samp::CAN_Msg_TX(CAN_MSG_pHandler *txheader)
{
uint32_t TxMailboxNumber = 0x00000000U; // 存储本次发送所使用邮箱的邮箱号
CAN_TxHeaderTypeDef Tx_pHeader;
Tx_pHeader.StdId = txheader->id; // 以此ID发送
Tx_pHeader.ExtId = 0x0000; // 扩展ID(此处无用)
Tx_pHeader.IDE = CAN_ID_STD; // 标准帧
Tx_pHeader.RTR = CAN_RTR_DATA; // 数据帧
Tx_pHeader.DLC = txheader->lenth; // 发送数据的长度
Tx_pHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan, &Tx_pHeader, txheader->data, &TxMailboxNumber);
}
8. Receive callback function (interrupt service function)
/*************************************************
Function: CAN接收邮箱0回调函数
Description:
Input: None
Output: None
Return: None
Others: None
*************************************************/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance == CAN1)
{
CAN_Msg_RX(&Rx_pHandler);
}
}