stm32HAL库之can操作

基于STM32CubeMx的CAN配置信息

volatile

1.系统时钟APB1=36MHZ

stm32HAL库之can操作_第1张图片

 2.CAN计算通信率计算公式,参考数据手册, CAN bit timing register (CAN_BTR) 寄存器
 

NominalBitTime计算公式: NominalBitTime =1 t × q +  tBS1 + tBS2

 

stm32HAL库之can操作_第2张图片

 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

stm32HAL库之can操作_第3张图片

 

4.CAN.c
 

/**
  ******************************************************************************
  * File Name          : CAN.c
  * Description        : This file provides code for the configuration
  *                      of the CAN instances.
  ******************************************************************************
  * @attention
  *
  * 

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * 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
  *
  * 

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * 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 >>>


// can1 配置
// can1 速率个数 <17-20>
// DeFault:20
#define CAN_BAUD_NUM		17

// CAN1 映射
// 	使能映射
#define CAN1Remap
// 

// 

// can2 配置
// can2 配置 <9600-1111111>
// DeFault:9600
#define USART2_BaudRate		115200

// can2 映射
// 	使能 映射
#define CAN2Remap
// 

// 串口2 中断接收
// 	usart2 RX enable
#define USART2_RX_ENABLE
// 

// 

//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);  /* 清除挂起中断 */	
}

 

你可能感兴趣的:(stm32)