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