赞
踩
起因:
库版本不一致,网上找到的都是早期的函数调用,一些函数接口都不一样,现在重新写一份调试文档
条件:
Mcu:stm32f103c8t6
Cube调用的库:STM32Cube_FW_F1_V1.8.1
Can的配置流程(先大致说一遍):stm32使用maibox(邮箱)的方式进行数据的收发,需要先配置can的pinmux,波特率,中断函数(其中mailbox的fifo也需要中断使能,否则虽然可以采用查询的方式读取数据,但是无法进入中断函数),滤波参数配置;之后需要跟另外一个can模块相连接通讯,否则调试会报错(这里使用了PC端的usbcan模块Ecantools软件);
详细配置:
Cube配置:
Can.c中,代码需要进行修改和添加:
Can波特率的配置有一定的公式,可以寻找对应的公式来设置下面红色的三个参数
在这里插void MX_CAN_Init(void) { CAN_FilterTypeDef sFilterConfig; hcan1.Instance = CAN1; hcan1.Init.Prescaler = 18; //pclk0=36Mhz /18=2Mhz hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.TimeSeg1 = CAN_BS1_2TQ; //CAN_BS1_1TQ hcan1.Init.TimeSeg2 = CAN_BS2_1TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = DISABLE; hcan1.Init.AutoWakeUp = DISABLE; hcan1.Init.AutoRetransmission = DISABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; switch(g_board_dev.tboard_cfg.can_rate){ case 0: hcan1.Init.Prescaler = 36; //250k break; case 1: hcan1.Init.Prescaler = 18; //500khz break; case 2: hcan1.Init.Prescaler = 9; //1Mhz break; default: hcan1.Init.Prescaler = 18; break; } if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterBank = 0; //过滤器0 sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //过滤器0关联到FIFO0 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterActivation = ENABLE; //激活过滤器0 HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig); __HAL_CAN_ENABLE_IT(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);//使能can中断 // CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. //CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE); //buffer init Can_FifoBuf_Init(&gpmag_rx, mag_rxbuffer, MAG_RXBUFFER_SIZE); } 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, 6, 0); HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 6, 0); HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn); /* USER CODE BEGIN CAN1_MspInit 1 */ /* USER CODE END CAN1_MspInit 1 */ } } 中断接收函数: void USB_LP_CAN1_RX0_IRQHandler(void) { /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ HAL_CAN_IRQHandler(&hcan1); /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ } //uint8_t byData[8]; //CAN_RxHeaderTypeDef RxMsg; //CanRxMsgTypeDefPriv tRxMsgPriv; /*can中断回调函数*/ 这里的一帧can数据,帧头和数据进行了分离,不像早先的库都放在了一个结构体里面 void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { uint8_t byData[8]; CAN_RxHeaderTypeDef RxMsg; CanRxMsgTypeDefPriv tRxMsgPriv; HAL_StatusTypeDef HAL_RetVal; if(hcan ==&hcan1){ HAL_RetVal = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMsg, byData); if ( HAL_OK==HAL_RetVal){ //在这里接收数据 memcpy(&tRxMsgPriv.RxMsg, &RxMsg, sizeof(CAN_RxHeaderTypeDef)); memcpy(&tRxMsgPriv.Data, &byData, sizeof(byData)); //压入队列中去 Can_FifoBuf_PutByte(&gpmag_rx, tRxMsgPriv); } } }
上述这样配置ok以后,可以使用下面的发送函数来进行发送
CAN_TxHeaderTypeDef TxMeg; //发送数据函数 uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len) { HAL_StatusTypeDef HAL_RetVal; uint16_t SendTimes,SendCNT=0; uint8_t FreeTxNum=0; TxMeg.StdId=ID; if(!hcan || ! pData ||!Len) return 1; SendTimes=Len/8+(Len%8?1:0); FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(hcan); TxMeg.DLC=8; while(SendTimes--){ if(0==SendTimes){ if(Len%8) TxMeg.DLC=Len%8; } while(0==FreeTxNum){ FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(hcan); } HAL_Delay(1); //没有延时很有可能会发送失败 HAL_RetVal=HAL_CAN_AddTxMessage(hcan,&TxMeg,pData+SendCNT,(uint32_t*)CAN_TX_MAILBOX0); if(HAL_RetVal!=HAL_OK) { return 2; } SendCNT+=8; } return 0; } 这个发送函数会报错,进入hardfault函数中去,只因HAL_CAN_AddTxMessage这个函数里面的一条语句需要屏蔽掉 /* Check transmit mailbox value */ if (transmitmailbox > 2U) { /* Update error code */ hcan->ErrorCode |= HAL_CAN_ERROR_INTERNAL; return HAL_ERROR; } /* Store the Tx mailbox */ //*pTxMailbox = (uint32_t)1 << transmitmailbox; 如果不使用中断的方式接收can数据,也可以在主循环中采用查询的方式进行读取数据 HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &recv_test1, can_recv_data);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。