1.系统时钟APB1=36MHZ
2.CAN计算通信率计算公式,参考数据手册, CAN bit timing register (CAN_BTR) 寄存器
NominalBitTime计算公式: NominalBitTime =1 t × q + tBS1 + tBS2
3.STM32CubeMx设置的Prescaler为8->对应BRP=7,TimeSeg1=6->对应TS1=5,TimeSeg2=2->对应TB2=2,STM32F103ZE对应APB1设置为36M,即Time for one Bit的时间为(1 + TimeSeg1+ TimeSeg2)* Prescaler/36M,--->(1+6+2)*8/36M=2us,即2000ns,500K bps
4.CAN.c
/** ****************************************************************************** * File Name : CAN.c * Description : This file provides code for the configuration * of the CAN instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2019 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "can.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ CAN_HandleTypeDef hcan; CAN_TxHeaderTypeDef TxHeader; CAN_RxHeaderTypeDef RxHeader; uint8_t TxData[8]; uint8_t RxData[8]; uint32_t TxMailbox; /* CAN init function */ void MX_CAN_Init(void) { CAN_FilterTypeDef sFilterConfig; hcan.Instance = CAN1; hcan.Init.Prescaler = 8; hcan.Init.Mode = CAN_MODE_NORMAL; hcan.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan.Init.TimeSeg1 = CAN_BS1_6TQ; hcan.Init.TimeSeg2 = CAN_BS2_2TQ; hcan.Init.TimeTriggeredMode = DISABLE; hcan.Init.AutoBusOff = DISABLE; hcan.Init.AutoWakeUp = DISABLE; hcan.Init.AutoRetransmission = DISABLE; hcan.Init.ReceiveFifoLocked = ENABLE; hcan.Init.TransmitFifoPriority = ENABLE; if (HAL_CAN_Init(&hcan) != HAL_OK) { Error_Handler(); } /* Configure the CAN Filter */ 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(&hcan, &sFilterConfig) != HAL_OK) { /* Filter configuration Error */ Error_Handler(); } /* Start the CAN peripheral */ if (HAL_CAN_Start(&hcan) != HAL_OK) { /* Start Error */ Error_Handler(); } /* Activate CAN RX notification */ if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { /* Notification Error */ Error_Handler(); } /* Activate CAN TX notification */ if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK) { /* Notification Error */ Error_Handler(); } /* Configure Transmission process */ TxHeader.StdId = 0x321; TxHeader.ExtId = 0x01; TxHeader.RTR = CAN_RTR_DATA; TxHeader.IDE = CAN_ID_STD; TxHeader.DLC = 8; TxHeader.TransmitGlobalTime = DISABLE; } void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(canHandle->Instance==CAN1) { /* USER CODE BEGIN CAN1_MspInit 0 */ /* USER CODE END CAN1_MspInit 0 */ /* CAN1 clock enable */ __HAL_RCC_CAN1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**CAN GPIO Configuration PA11 ------> CAN_RX PA12 ------> CAN_TX */ GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* CAN1 interrupt Init */ HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 7, 0); HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspInit 1 */ HAL_NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); /* USER CODE END CAN1_MspInit 1 */ } } void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle) { if(canHandle->Instance==CAN1) { /* USER CODE BEGIN CAN1_MspDeInit 0 */ /* USER CODE END CAN1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_CAN1_CLK_DISABLE(); /**CAN GPIO Configuration PA11 ------> CAN_RX PA12 ------> CAN_TX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); /* CAN1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); /* USER CODE BEGIN CAN1_MspDeInit 1 */ /* USER CODE END CAN1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ void USER_CAN_Send() { HAL_Delay(1000); HAL_CAN_ActivateNotification(&hcan, CAN_IT_TX_MAILBOX_EMPTY);//开启中断 if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox) != HAL_OK) { /* Transmission request Error */ Error_Handler(); } HAL_Delay(100); TxData[0]++; } /** * @brief Rx Fifo 0 message pending callback in non blocking mode * @param CanHandle: pointer to a CAN_HandleTypeDef structure that contains * the configuration information for the specified CAN. * @retval None */ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle) { /* Get RX message */ if (HAL_CAN_GetRxMessage(CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK) { /* Reception Error */ Error_Handler(); } /* Display LEDx */ if ((RxHeader.StdId == 0x321) && (RxHeader.IDE == CAN_ID_STD) && (RxHeader.DLC == 2)) { RxData[0] = RxData[0]; } } /* USER CODE END 1 */ /** * @brief Transmission Mailbox 0 complete callback. * @param hcan pointer to a CAN_HandleTypeDef structure that contains * the configuration information for the specified CAN. * @retval None */ void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { static uint8_t num = 0; /* Prevent unused argument(s) compilation warning */ UNUSED(hcan); /* NOTE : This function Should not be modified, when the callback is needed, the HAL_CAN_TxMailbox0CompleteCallback could be implemented in the user file */ /* if() 数据 要到 */ HAL_CAN_DeactivateNotification(hcan, CAN_IT_TX_MAILBOX_EMPTY); HAL_CAN_AddTxMessage(hcan, &TxHeader, TxData, &TxMailbox); TxData[1] = TxData[1]+ 1; } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/can.h
/** ****************************************************************************** * File Name : CAN.h * Description : This file provides code for the configuration * of the CAN instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2019 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __can_H #define __can_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ extern CAN_HandleTypeDef hcan; extern CAN_TxHeaderTypeDef TxHeader; extern CAN_RxHeaderTypeDef RxHeader; extern uint8_t TxData[8]; extern uint8_t RxData[8]; extern uint32_t TxMailbox; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void MX_CAN_Init(void); /* USER CODE BEGIN Prototypes */ void USER_CAN_Send(void); /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /*__ can_H */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/RTR : CAN_RTR_DATA 数据帧 CAN_RTR_REMOTE 远程帧 IDE : CAN_ID_STD 标准帧 0-0x7FF -->11bit CAN_ID_EXT 扩展帧 0-0x1FFFFFFF -->29bit DLC : 数据长度 0-8
FIFO0对应CAN1_RX0_IRQHandler,FIFO1对应CAN1_RX1_IRQHandler
/* ********************************************************************************************************* * * 模块名称 : can代码模块 * 文件名称 : bsp_can.c * 版 本 : V1.0 * 说 明 : F107 初始化 * 修改记录 : * 版本号 日期 作者 说明 * V1.0 2019-06-04 LLF 正式发布 * * ********************************************************************************************************* */ #include "bsp_can.h" // <<< Use Configuration Wizard in Context Menu >>> // <h>can1 配置 // <o>can1 速率个数 <17-20> // <i>DeFault:20 #define CAN_BAUD_NUM 17 // <c1>CAN1 映射 // <i>使能映射 #define CAN1Remap // </c> // </h> // <h>can2 配置 // <o>can2 配置 <9600-1111111> // <i>DeFault:9600 #define USART2_BaudRate 115200 // <c1>can2 映射 // <i>使能 映射 #define CAN2Remap // </c> // <c1>串口2 中断接收 // <i>usart2 RX enable #define USART2_RX_ENABLE // </c> // </h> //USART 映射 #ifdef CAN1Remap #define RCC_APB2Periph_GPIO_CAN1 RCC_APB2Periph_GPIOD #define GPIO_Remapping_CAN1 GPIO_Remap2_CAN1 #define GPIO_CAN1 GPIOD #define GPIO_Pin_CAN1_RX GPIO_Pin_0 #define GPIO_Pin_CAN1_TX GPIO_Pin_1 #else #define RCC_APB2Periph_GPIO_CAN1 RCC_APB2Periph_GPIOD #define GPIO_Remapping_CAN1 GPIO_Remap2_CAN1 #define GPIO_CAN1 GPIOD #define GPIO_Pin_CAN1_RX GPIO_Pin_0 #define GPIO_Pin_CAN1_TX GPIO_Pin_1 #endif #ifdef CAN2Remap #define RCC_APB2Periph_GPIO_CAN2 RCC_APB2Periph_GPIOB #define GPIO_Remapping_CAN2 GPIO_Remap_CAN2 #define GPIO_CAN2 GPIOB #define GPIO_Pin_CAN2_RX GPIO_Pin_5 #define GPIO_Pin_CAN2_TX GPIO_Pin_6 #else #define RCC_APB2Periph_GPIO_CAN2 RCC_APB2Periph_GPIOB #define GPIO_Remapping_CAN2 GPIO_Remap_CAN2 #define GPIO_CAN2 GPIOB #define GPIO_Pin_CAN2_RX GPIO_Pin_5 #define GPIO_Pin_CAN2_TX GPIO_Pin_6 #endif // <<< end of configuration section >>> //格式: 波特率 CAN_SJW CAN_BS1 CAN_BS2 CAN_Prescaler const unsigned int CAN_baud_table[CAN_BAUD_NUM][5] = { //波特率, CAN_SJW, CAN_BS1, CAN_BS2,CAN_Prescaler {5, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,450}, //未通 {10, CAN_SJW_1tq,CAN_BS1_6tq,CAN_BS2_2tq, 400}, //未通 {15, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,150}, //15K {20, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,200}, //20k {25, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,90}, //25k {40, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,100}, //40k {50, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,45}, //50k {62, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,36}, //62.5k {80, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,50}, //80k {100, CAN_SJW_1tq,CAN_BS1_5tq, CAN_BS2_2tq,45}, //100K {125, CAN_SJW_1tq,CAN_BS1_13tq, CAN_BS2_2tq,18}, //125K {200, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,20}, //200K {250, CAN_SJW_1tq,CAN_BS1_13tq,CAN_BS2_2tq,9}, //250k {400, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,10}, //400K {500, CAN_SJW_1tq,CAN_BS1_5tq, CAN_BS2_2tq,9}, //500K {800, CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,5}, //800K {1000,CAN_SJW_1tq,CAN_BS1_6tq, CAN_BS2_2tq,4}, //1000K }; static void CAN_Baud_Process(unsigned int Baud,CAN_InitTypeDef *CAN_InitStructure); /* ********************************************************************************************************* * 函 数 名: CAN_Baud_Process * 功能说明: 计算波特率,返回 * 创 建 人:LLF * 日 期:2019-06-04 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void CAN_Baud_Process(unsigned int Baud,CAN_InitTypeDef *CAN_InitStructure) { unsigned int i = 0; for(i = 0;i < CAN_BAUD_NUM;i ++) { if(Baud == CAN_baud_table[i][0]) { CAN_InitStructure->CAN_SJW = CAN_baud_table[i][1]; CAN_InitStructure->CAN_BS1 = CAN_baud_table[i][2]; CAN_InitStructure->CAN_BS2 = CAN_baud_table[i][3]; CAN_InitStructure->CAN_Prescaler = CAN_baud_table[i][4]; break; } } } /* ********************************************************************************************************* * 函 数 名: bsp_can * 功能说明: can初始化 * 形 参: void * 返 回 值: 无 ********************************************************************************************************* */ void bsp_can_init(void) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; /* 打开GPIO时钟 */ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIO_CAN1, ENABLE); /* 打开CAN时钟 */ RCC_APB1PeriphClockCmd( RCC_APB1Periph_CAN1, ENABLE); #ifdef CAN1Remap GPIO_PinRemapConfig(GPIO_Remapping_CAN1, ENABLE); #endif /* Configure CAN1 pin: RX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CAN1_RX; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIO_CAN1, &GPIO_InitStructure); /* Configure CAN1 pin: TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CAN1_TX; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIO_CAN1, &GPIO_InitStructure); /* 复位CAN1的寄存器值 */ CAN_DeInit(CAN1); /* 复位CAN 结构体 */ CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.CAN_TTCM = DISABLE; /* 时间触发禁止, 时间触发:CAN硬件的内部定时器被激活,并且被用于产生时间戳 */ CAN_InitStructure.CAN_ABOM = DISABLE; /* 自动离线禁止,自动离线:一旦硬件监控到128次11个隐性位,就自动退出离线状态。在这里要软件设定后才能退出 */ CAN_InitStructure.CAN_AWUM = DISABLE; /* 自动唤醒禁止,有报文来的时候自动退出休眠 */ CAN_InitStructure.CAN_NART = DISABLE; /* 报文重传, 如果错误一直传到成功止,否则只传一次 */ CAN_InitStructure.CAN_RFLM = DISABLE; /* 接收FIFO锁定, 1--锁定后接收到新的报文摘不要,0--接收到新的报文则覆盖前一报文 */ CAN_InitStructure.CAN_TXFP = ENABLE; /* 发送优先级 0---由标识符决定 1---由发送请求顺序决定 */ CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 模式 */ CAN_Baud_Process(100,&CAN_InitStructure);//波特率500K if (CAN_Init(CAN1,&CAN_InitStructure) == CANINITFAILED) { /* 初始化时先设置CAN_MCR的初始化位 */ /* 然后查看硬件是否真的设置了CAN_MSR的初始化位来确认是否进入了初始化模式 */ } //CAN1滤波器设置 CAN_FilterInitStructure.CAN_FilterNumber = 17; ///* 过滤器组 */ CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;//CAN_FilterMode_IdList;//CAN_FilterMode_IdMask; /* 屏敝模式 */ CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; ///* 32位 */ CAN_FilterInitStructure.CAN_FilterIdHigh = 0; CAN_FilterInitStructure.CAN_FilterIdLow = 0; CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0; CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0; CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO1; ///* 能够通过该过滤器的报文存到fifo0中 */ CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); CAN_ITConfig(CAN1,CAN_IT_FMP1, ENABLE); /* 挂号中断, 进入中断后读fifo的报文函数释放报文清中断标志 */ } //CAN1中断程序 FIFO0 void CAN1_RX0_IRQHandler(void) { CanRxMsg RxMessage; RxMessage.StdId=0x00; RxMessage.ExtId=0x00; RxMessage.IDE=0; RxMessage.DLC=0; RxMessage.FMI=0; RxMessage.Data[0]=0x00; CAN_Receive(CAN1,CAN_FIFO0, &RxMessage); /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */ CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0); /* 清除挂起中断 */ // SEI();//打开总中断 } //CAN1中断程序 FIFO1 void CAN1_RX1_IRQHandler(void) { CanRxMsg RxMessage; RxMessage.StdId=0x00; RxMessage.ExtId=0x00; RxMessage.IDE=0; RxMessage.DLC=0; RxMessage.FMI=0; RxMessage.Data[0]=0x00; CAN_Receive(CAN1,CAN_FIFO1, &RxMessage); /* 此函数包含释放提出报文了的,在非必要时,不需要自己释放 */ CAN_ClearITPendingBit(CAN1,CAN_IT_FMP1); /* 清除挂起中断 */ }