使用芯片:STM32F103C8T6
cube软件版本:5.10
软件包版本为:STM32Cube FW_F1 V1.7.0
一、配置时钟为使用外部晶振,并配置为72M
二、使能 can,并配置参数
设置can波特率为500k,并设置为loopback模式,波特率计算方式为(systime/(pre*(bs1+bs2+sjw))),can时钟为36M,则36/(12*(1+2+3))=500k。
三、开启can接收中断
四、设置生成代码,在生成的can.c函数中增加过滤器配置代码如下
CAN_FilterIdHigh和CAN_FilterIdLow组合成一个32位寄存器,用来存储将要过滤的ID
CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow组合成一个32位寄存器,用来表示这个ID的哪些位必须符合(置1),哪些位不关心(置0).
例如要过滤的ID为0x1e000000,则CAN_FilterIdHigh、CAN_FilterIdLow、CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow配置为
- uint32_t EXTID = 0x1e000000;
- CAN_FilterType.FilterIdHigh=(EXTID<<3)>>16;
- CAN_FilterType.FilterIdLow=((EXTID<<3)&0xffff)|CAN_ID_EXT;//只关心扩展帧,标准帧为CAN_ID_STD
- CAN_FilterType.FilterMaskIdHigh=0xffff;
- CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT;//每一位都必须一致,只关心扩展帧,标准帧为CAN_ID_STD
复制代码
以下配置代码,有列表模式和掩码模式,二选一
- /* 列表模式只接受0x02200000和0x1e000000 */
- void CAN1_IDLISTConfig(void)
- {
- uint32_t EXTID = 0x02200000;
- uint32_t EXTID1 = 0x1e000000;
- CAN_FilterTypeDef CAN_FilterType;
- CAN_FilterType.FilterBank=0;
- CAN_FilterType.FilterIdHigh=(EXTID<<3)>>16;
- CAN_FilterType.FilterIdLow=((EXTID<<3)&0xffff)|CAN_ID_EXT;
- CAN_FilterType.FilterMaskIdHigh=0xffff;
- CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT;
- CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDLIST;
- CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;
- CAN_FilterType.FilterActivation=ENABLE;
- CAN_FilterType.SlaveStartFilterBank=14;
- if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)
- {
- Error_Handler();
- }
- CAN_FilterType.FilterBank=1;
- CAN_FilterType.FilterIdHigh=(EXTID1<<3)>>16;
- CAN_FilterType.FilterIdLow=((EXTID1<<3)&0xffff)|CAN_ID_EXT;
- CAN_FilterType.FilterMaskIdHigh=0xffff;
- CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT;
- CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDLIST;//列表模式
- CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;
- CAN_FilterType.FilterActivation=ENABLE;
- CAN_FilterType.SlaveStartFilterBank=14;
- if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)
- {
- Error_Handler();
- }
- if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)
- {
- Error_Handler();
- }
- if(HAL_CAN_Start(&hcan)!=HAL_OK)
- {
- Error_Handler();
- }
- }
- /* 掩码模式全部接收 */
- void CAN1_IDMASKConfig(void)
- {
- CAN_FilterTypeDef CAN_FilterType;
- CAN_FilterType.FilterBank=0;
- CAN_FilterType.FilterIdHigh=0x0000;
- CAN_FilterType.FilterIdLow=0x0000;
- CAN_FilterType.FilterMaskIdHigh=0x0000;
- CAN_FilterType.FilterMaskIdLow=0x0000;
- CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDMASK;//掩码模式
- CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;
- CAN_FilterType.FilterActivation=ENABLE;
- CAN_FilterType.SlaveStartFilterBank=14;
- if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)
- {
- Error_Handler();
- }
- if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)
- {
- Error_Handler();
- }
- if(HAL_CAN_Start(&hcan)!=HAL_OK)
- {
- Error_Handler();
- }
- }
复制代码
五、增加can发送函数
- /***********************************************
- 函数功能:can发送数据
- 入口参数:
- ide: 0:标准帧
- 1:扩展帧
- id: 帧ID
- len: 数据长度
- data: 数据
- 返回值:0:成功。1:失败
- ************************************************/
- uint8_t Can_TxMessage(uint8_t ide,uint32_t id,uint8_t len,uint8_t *data)
- {
- uint32_t TxMailbox;
- CAN_TxHeaderTypeDef CAN_TxHeader;
- HAL_StatusTypeDef HAL_RetVal;
- uint16_t i=0;
- if(ide == 0)
- {
- CAN_TxHeader.IDE = CAN_ID_STD; //标准帧
- CAN_TxHeader.StdId = id;
- }
- else
- {
- CAN_TxHeader.IDE = CAN_ID_EXT; //扩展帧
- CAN_TxHeader.ExtId = id;
- }
- CAN_TxHeader.DLC = len;
- CAN_TxHeader.RTR = CAN_RTR_DATA;//数据帧,CAN_RTR_REMOTE遥控帧
- CAN_TxHeader.TransmitGlobalTime = DISABLE;
- while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0)
- {
- i++;
- if(i>0xfffe)
- return 1;
- }
- HAL_Delay(500);
- HAL_RetVal = HAL_CAN_AddTxMessage(&hcan,&CAN_TxHeader,data,&TxMailbox);
- if(HAL_RetVal != HAL_OK)
- return 1;
- return 0;
- }
复制代码
六、增加接收中断回调函数
- void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
- {
- CAN_RxHeaderTypeDef CAN_RxHeader;
- HAL_StatusTypeDef HAL_Retval;
- uint8_t Rx_Data[8];
- uint8_t Data_Len=0;
- uint32_t ID=0;
- uint8_t i;
- HAL_Retval = HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&CAN_RxHeader,Rx_Data);
- if(HAL_Retval == HAL_OK)
- {
- Data_Len = CAN_RxHeader.DLC;
- if(CAN_RxHeader.IDE)
- ID = CAN_RxHeader.ExtId;
- else
- ID = CAN_RxHeader.StdId;
- printf("id:%x\r\n",ID);
- printf("Data_Len:%d\r\n",Data_Len);
- for(i=0;i<8;i++)
- printf("Rx_Data[%d]=%x\r\n",i,Rx_Data<i>);
- }
- }</i>
复制代码
七,在main.c函数中增加函数,最终如下:
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- uint8_t data[8]={1,2,3,4,5,6,7,8};
- /* 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 */
- CAN1_IDMASKConfig();//过滤器配置
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- Can_TxMessage(0,0x222,8,data);//CAN发送
- HAL_Delay(1000);
- }
- /* USER CODE END 3 */
- }
复制代码
每隔1S,通过can向标识符为0x222的设备发送一次数据,因为本例程设置的为loopback模式,所以不需要接任何外设即可,通过串口调试助手查看接收到的数据,与发送数据相符
|