概述
目录
一,基本原理部分
二,cubeMX配置
1. 配置波特率
2. 打开接收中断(本实验开个邮箱0(FIFO0)即可)
三. keil中代码
1. 配置过滤器
2. 数据帧的发送:
3. 数据帧的接收
4. 开启CAN
一,基本原理部分
参考:(12条消息) CAN通信知识梳理及在Stm32上的应用(HAL库)_冬瓜-CSDN博客
二,cubeMX配置
1. 配置波特率
由中文参考手册:
位时序如下:
2. 打开接收中断(本实验开个邮箱0(FIFO0)即可)
三. keil中代码
1. 配置过滤器
对于掩码模式的过程:
寄存器 CAN_TIxR 各位描述:
几种模式的过滤器配置:
//32位列表模式过滤器配置(这里配置R1用来过滤标准ID(StdId),R2用来过滤拓展ID(ExtId))
void CANFilterConfig_Scale32_IdList(CAN_HandleTypeDef * hcan,uint32_t StdId,uint32_t ExtId,uint8_t Filter_Number )
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; //设为列表模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //配置为32位宽
sFilterConfig.FilterIdHigh = StdId<<5; //如图基本ID左移5位,放入到STID中
sFilterConfig.FilterIdLow = 0|CAN_ID_STD; //设置IDE位为0
sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff; //拓展ID前部分存入R2高位中
sFilterConfig.FilterMaskIdLow = ((ExtId<<3)&0xffff)|CAN_ID_EXT;//拓展ID后部分存入R2低位并且设置IDE位为1
sFilterConfig.FilterFIFOAssignment = 0; //接收到的报文放入到FIFO0中
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterBank = Filter_Number; //选择使用第n个过滤器(to definition可知和以前用的can库中的FilterNumber相同)
HAL_CAN_ConfigFilter(hcan, &sFilterConfig) ;
}
//16位列表模式过滤器配置(可以写入四个标准ID)
void CANFilterConfig_Scale16_IdList(CAN_HandleTypeDef * hcan,uint32_t StdId1,uint32_t StdId2,uint32_t StdId3,uint32_t StdId4, uint8_t Filter_Number)
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; //设为列表模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; //位宽设置为16位
sFilterConfig.FilterIdHigh = StdId1<<5; //4个标准CAN ID分别放入到4个存储中
sFilterConfig.FilterIdLow = StdId2<<5;
sFilterConfig.FilterMaskIdHigh = StdId3<<5;
sFilterConfig.FilterMaskIdLow = StdId4<<5; //因为只能过滤标准ID故不需要配IDE位
sFilterConfig.FilterFIFOAssignment = 0; //接收到的报文放入到FIFO0中
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterBank = Filter_Number;
HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
}
//32位掩码模式过滤器配置(验证码(期望ID):ID,屏蔽码(哪些位必须一样):Mask)
void CANFilterConfig_Scale32_IdMask(CAN_HandleTypeDef * hcan,uint32_t ID,uint32_t Mask,uint8_t ID_Type, uint8_t Filter_Number)
{
if(ID_Type==0) //标准ID
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //配置为掩码模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //设置为32位宽
sFilterConfig.FilterIdHigh =ID<<5;
sFilterConfig.FilterIdLow =0; //设置IDE位为0
sFilterConfig.FilterMaskIdHigh =(Mask<<5);
sFilterConfig.FilterMaskIdLow =0|0x02; //置位RTR:只接收数据帧
sFilterConfig.FilterFIFOAssignment = 0; //设置通过的数据帧进入到FIFO0中
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterBank = Filter_Number;
HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
}
else //扩展ID
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //配置为掩码模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //设为32位宽
sFilterConfig.FilterIdHigh =((ID<<3) >>16) &0xffff;
sFilterConfig.FilterIdLow =((ID<<3)&0xffff) | CAN_ID_EXT; //设置IDE位为1
sFilterConfig.FilterMaskIdHigh = (Mask>>16)&0xffff;
sFilterConfig.FilterMaskIdLow = (Mask&0xffff)|0x02; //只接收数据帧
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterBank = Filter_Number;
HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
}
}
2. 数据帧的发送:
//发送标准ID数据帧(数据数组指针:pData)
uint8_t CANx_SendStdData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)
{
static CAN_TxHeaderTypeDef Tx_Header;
Tx_Header.StdId=ID; //标准数据帧ID
Tx_Header.ExtId=0;
Tx_Header.IDE=CAN_ID_STD; //标准帧,IDE设置为0
Tx_Header.RTR=CAN_RTR_DATA; //发送数据帧,RTR设置为0:CAN_RTR_DATA = 0x00000000U
Tx_Header.DLC=Len; //数据长度
//找到空的发送邮箱发送数据
if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK) //
{
if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX1) != HAL_OK)
{
HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX2);
}
}
}
//发送拓展ID数据帧
uint8_t CANx_SendExtData(CAN_HandleTypeDef* hcan,uint32_t ID,uint8_t *pData,uint16_t Len)
{
static CAN_TxHeaderTypeDef Tx_Header;
Tx_Header.StdId=0;
Tx_Header.ExtId=ID; //拓展数据帧ID
Tx_Header.IDE=CAN_ID_EXT;
Tx_Header.RTR=CAN_RTR_DATA;
Tx_Header.DLC=Len;
//找到空的发送邮箱发送数据
if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK)
{
if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX1) != HAL_OK)
{
HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX2);
}
}
}
3. 数据帧的接收
uint8_t date_CAN1[8]; //用于接收数据
//CAN接收(写在FIFO0接收中断回调里)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance ==CAN1)
{
CAN_RxHeaderTypeDef RxHeader; //接受句柄(不需要配置,只需要拿来接即可,内容已经配置在TxHeader)
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, date_CAN1); //接收,CAN邮箱为0
}
}
4. 开启CAN
void My_CAN_START(CAN_HandleTypeDef *hcan)
{
HAL_CAN_Start(hcan);
if(HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
四. 调试记录
最后
以上就是不安玫瑰为你收集整理的学习记录--CAN通信的全部内容,希望文章能够帮你解决学习记录--CAN通信所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复