配置流程
1.芯片选型
芯片我选择的是:stm32f103c8t6
2.时钟使能
3.调试器选择
4.时钟树配置
5.CAN参数和中断设置
波特率计算公式:时钟频率/(预分频 x (TQ1+TQ2+SJW)) = 波特率;
参数设置要点:tq1 / (tq1 + tq2) 最好在0.8左右,小于0.5会导致不能通信,调试时能看到寄存器有发出数据,但用示波器却打不到信号;当然,也不能接收信号。
6.过滤器设置(CubeIDE不会自动生成需手动添加)
CubeIDE不会自动生成需手动添加!!!
按照上面的步骤执行后,能进行正常发送,但是还需要对邮箱进行配置才能接收数据,且要调用HAL_CAN_Start()和HAL_CAN_ActivateNotification()函数才能开始接收;
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.发送接收函数(按个人需求编写)
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.接收回调函数(中断服务函数)
/*************************************************
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);
}
}