[STM32CubeIDE]CAN调试详细解
发送报文定义结构体(CAN_TxHeaderTypeDef)/*!标准ID。参数值只能是 0 到 0x7FF(二进制的11位1) *//*!扩展ID。参数值只能是 0 到 0x1FFFFFFF(二进制的29位1)*//*!IDE。HAL库编程时,标准帧填写CAN_ID_STD,扩展帧填写CAN_ID_EXT *//*!RTR。HAL库编程时,数据帧填写CAN_RTR_DATA,遥控帧填写CAN_R
1、CAN概念
全称Controller Area Network,是一种半双工,异步通讯。
1.1物理层
闭环:允许总线最长40m,最高速1Mbps,规定总线两端各有一个120Ω电阻,闭环
开环:最大传输距离1Km,最高速125Kbps,规定每根线串联一个2.2kΩ的电阻,开环

显性电平对应“0”,隐性电平对应“1”。隐性电平(1)两条线电压都是2.5V,即压差为0;显性电平(0)CAN_High和CAN_Low分别为3.5V和1.5V,压差为2V。
总线上,只要有一个节点输出显性,则总线上为显性电平;只有所有节点都是隐性电平,总线才为隐性电平
电压值:
| 信号 | 闭环总线ISO11898协议(高速) | 开环总线ISO11519-2协议(低速) | ||||||||||
| 隐形(逻辑1) | 显形(逻辑0) | 隐形(逻辑1) | 显形(逻辑0) | |||||||||
| min | typ | max | min | typ | max | min | typ | max | min | typ | max | |
| CAN_High | 2.0 | 2.5 | 3.0 | 2.75 | 3.5 | 4.5 | 1.6 | 1.75 | 1.9 | 3.85 | 4.0 | 5.0 |
| CAN_Low | 2.0 | 2.5 | 3.0 | 0.5 | 1.5 | 2.25 | 3.10 | 3.25 | 3.4 | 0 | 1.0 | 1.15 |
| High-Low | -0.5 | 0 | 0.05 | 1.5 | 2.0 | 3.0 | -0.3 | -1.5 | - | 0.3 | 3.0 | - |
1.2 协议层
1.3 过滤机制
2、STM32 HAL_CAN详解
在此以STM32F4 为例,作详细介绍
2.1、STM32CubeIDE图形化配置
以STM32F4xx为例,配置CAN1

一般通信都会打开接收中断,在这里打开CAN1 RX0的中断,优先级可以通过NVIC进行更改。 
2.2、STM32 HAL库程序编写
2.2.1、STM32 can结构体介绍
发送报文定义结构体(CAN_TxHeaderTypeDef)
typedef struct
{
uint32_t StdId; /*!标准ID。参数值只能是 0 到 0x7FF(二进制的11位1) */
uint32_t ExtId; /*!扩展ID。参数值只能是 0 到 0x1FFFFFFF(二进制的29位1)*/
uint32_t IDE; /*!IDE。HAL库编程时,标准帧填写CAN_ID_STD,扩展帧填写CAN_ID_EXT */
uint32_t RTR; /*!RTR。HAL库编程时,数据帧填写CAN_RTR_DATA,遥控帧填写CAN_RTR_REMOTE */
uint32_t DLC; /*!DLC。数据长度,参数值只能是 0 到 8 */
FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
@note: Time Triggered Communication Mode must be enabled.
@note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
This parameter can be set to ENABLE or DISABLE. */
} CAN_TxHeaderTypeDef;
接收报文定义结构体(CAN_RxHeaderTypeDef)
typedef struct
{
uint32_t StdId; /*!标准ID。参数值只能是 0 到 0x7FF(二进制的11位1) */
uint32_t ExtId; /*!扩展ID。参数值只能是 0 到 0x1FFFFFFF(二进制的29位1)*/
uint32_t IDE; /*!IDE。HAL库编程时,标准帧填写CAN_ID_STD,扩展帧填写CAN_ID_EXT */
uint32_t RTR; /*!RTR。HAL库编程时,数据帧填写CAN_RTR_DATA,遥控帧填写CAN_RTR_REMOTE */
uint32_t DLC; /*!DLC。数据长度,参数值只能是 0 到 8 */
FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
@note: Time Triggered Communication Mode must be enabled.
@note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
This parameter can be set to ENABLE or DISABLE. */
} CAN_TxHeaderTypeDef;
接收过滤器类型定义结构体(CAN_FilterTypeDef)
typedef struct
{
uint32_t FilterIdHigh; /*!过滤器验证码ID高16位,只能填0到0xFFFF 中间的数值 */
uint32_t FilterIdLow; /*!过滤器ID低16位,只能填0到0xFFFF 中间的数值*/
uint32_t FilterMaskIdHigh; /*!过滤器掩码ID高16位,只能填0到0xFFFF中间的数值 */
uint32_t FilterMaskIdLow; /*!过滤器掩码ID低16位,只能填0到0xFFFF中间的数值 */
uint32_t FilterFIF(x)Assignment; /*!将通过的报文放入哪个FIFOx中,填写FIFO(x) */
uint32_t FilterBank; /*!使用过滤器编号。使用一个CAN,则可选 0~13;使用两个CAN可选 0~27 */
uint32_t FilterMode; /*!过滤器模式选择。掩码模式填写 CAN_FILTERMODE_IDMASK,列表模
式填写 CAN_FILTERMODE_IDLIST */
uint32_t FilterScale; /*!过滤器位宽,32位是CAN_FILTERSCALE_32BIT,
16位是CAN_FILTERSCALE_16BIT */
uint32_t FilterActivation; /*!是否使能过滤器,DISABLE 或 ENABLE */
uint32_t SlaveStartFilterBank; /*!< Select the start filter bank for the slave CAN instance.
For single CAN instances, this parameter is meaningless.
For dual CAN instances, all filter banks with lower index are assigned to master
CAN instance, whereas all filter banks with greater index are assigned to slave
CAN instance.
This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
} CAN_FilterTypeDef;
2.2.2 CAN基本函数
| 函数 | 功能 |
| HAL_CAN_Start | 开启CAN通讯 |
| HAL_CAN_Stop | 关闭CAN通讯 |
| HAL_CAN_RequestSleep | 使CAN模块完成当前操作后尝试进入休眠模式 |
| HAL_CAN_WakeUp | 从休眠模式中唤醒 |
| HAL_CAN_IsSleepActive | 检查是否成功处于休眠模式 |
| HAL_CAN_AddTxMessage | 向 Tx 邮箱中增加一个消息,并且激活对应的传输请求 |
| HAL_CAN_AbortTxRequest | 请求中断传输 |
| HAL_CAN_GetTxMailboxesFreeLevel | 查询空闲的发送邮箱个数 |
| HAL_CAN_IsTxMessagePending | 检查是否有传输请求在指定的 Tx 邮箱上等待 |
| HAL_CAN_GetRxMessage | 从Rx FIFO 收取一个 CAN 帧 |
| HAL_CAN_GetRxFifoFillLevel | 查询接收邮箱未读邮箱的个数 |
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)**
功能:开启CAN,一般一开始就要打开
参数:CAN句柄指针,&hcan1 或 &hcan2
返回值:返回值:HAL状态
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)
功能:配置CAN过滤器
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,CAN配置结构体的指针
返回值:返回值:HAL状态
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)
功能:使能中断
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,使能哪个中断,在stm32f4xx_HAL_Driver.h中,搜索Receive Interrupts可以查到各宏定义
返回值:返回值:HAL状态
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)(根据使用0可能替换成1)
功能:接收回调函数,CAN回调后进行的操作。一般在此接收数据
参数:第一个,CAN句柄指针
返回值:void
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)**
功能:增加一个消息到第一个空闲的 Tx 邮箱,并且激活对应的传输请求
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,发送报文定义结构体的指针
第三个,数据帧数组的内容,长度不能超过定义的长度
第四个,Tx邮箱,可填 (uint32_t*)CAN_TX_MAILBOX0 ,CAN_TX_MAILBOX1 , CAN_TX_MAILBOX3
返回值:HAL状态
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
功能:从Rx FIFO收取一个 CAN 帧
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,Rx FIFO,可填 CAN_RX_FIFO0, CAN_RX_FIFO1
第三个,接收报文定义结构体的指针
第四个,接受数据数组
返回值:HAL状态
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)
功能:设置接收过滤器
参数:第一个,CAN句柄指针,&hcan1 或 &hcan2
第二个,过滤器类型定义结构体指针
返回值:HAL状态
2.3 编写完整代码函数
在 can.c 中
/* USER CODE BEGIN 0 */
uint8_t TxData[8];//CAN发送数据缓存
uint8_t RxData[8];//CAN接收数据缓存
CAN_FilterTypeDef sFilterConfig;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
/* USER CODE END 0 */
在 can.c 的 void MX_CAN1_Init(void) 函数里
/* USER CODE BEGIN CAN1_Init 2 */
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;//验证码
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;//屏蔽码
sFilterConfig.FilterMaskIdLow = 0x0006;//0x0006
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan1) != HAL_OK)//启动CAN外围设备
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END CAN1_Init 2 */
在最后编写回调函数已经发送函数
/* USER CODE BEGIN 1 */
uint8_t CAN_Send_Msg(uint8_t* msg, uint8_t len, uint32_t std_id)
{
TxHeader.StdId = std_id;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.TransmitGlobalTime = ENABLE;
TxHeader.DLC = len;
//MailboxesFreeLevel = HAL_CAN_GetTxMailboxesFreeLevel(&hcan);
//while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan)==0);
if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, msg,CAN_TX_MAILBOX0 ) != HAL_OK)//发???
{
return 1;
}
return 0;
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance == CAN1)//CAN鎺ユ敹涓柇澶勭悊鍑芥暟
{
HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RxHeader,RxData);
CAN_Send_Msg(TxData,8,0x55);
}
}
/* USER CODE END 1 */
在 can.h 中编写
/* USER CODE BEGIN Private defines */
extern uint8_t TxData[8];//CAN发送数据缓存
extern uint8_t RxData[8];//CAN接收数据缓存
extern CAN_TxHeaderTypeDef TxHeader;
extern CAN_RxHeaderTypeDef RxHeader;
/* USER CODE END Private defines */
void MX_CAN1_Init(void);
/* USER CODE BEGIN Prototypes */
uint8_t CAN_Send_Msg(uint8_t* msg, uint8_t len, uint32_t std_id);
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan);
/* USER CODE END Prototypes */
至此,完成代码编写,代码可以完美运行。
更多推荐


所有评论(0)