表不同模式下各结构体成员的内容
对这些结构体成员赋值的时候,还要注意寄存器位的映射,即注意哪部分代表 STID,哪部分代表 EXID 以及 IDE、RTR 位。
(5) FilterFIFOAssignment
本成员用于设置当报文通过筛选器的匹配后,该报文会被存储到哪一个接收 FIFO,它的可选值为 FIFO0 或 FIFO1(宏 CAN_FILTER_FIFO0/1)。
(6) FilterBank
本成员用于设置筛选器的编号,即本过滤器结构体配置的是哪一组筛选器,CAN 一共有 28 个筛选器,所以它的可输入参数范围为 0-27。
(7) FilterMode
本 成 员 用 于 设 置 筛 选 器 的 工 作 模 式, 可 以 设 置 为 列 表 模 式 (宏CAN_FILTERMODE_IDLIST) 及掩码模式 (宏 CAN_FILTERMODE_IDMASK)。
(8) FilterScale
本成员用于设置筛选器的尺度,可以设置为 32 位长 (宏 CAN_FILTERSCALE_32BIT)及 16 位长 (宏 CAN_FILTERSCALE_16BIT)。
(9) FilterActivation
本成员用于设置是否激活这个筛选器 (宏 ENABLE/DISABLE)。
三. CAN Cubemx配置
我们通过问题来熟悉下cubemx配置,你熟悉了这些问题基本就知道怎么配置了!
问题:Parameter Settings分别都是设置什么的?答案:如图问题:怎么配置波特率呢?
答案:用我上面贴的工具(CAN波特率计算 f103AHP1_36M f407AHP1_42M 采样点软件有说明.rar)直接配置,举两个个例子
例子1:我们要配置成500KHz,那么我们这样配置我们用采集点为80%,所以BS1为4tq,BS2为2tq,分频系数为12,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(4+2+1)/12=500kHz例子2:我们要配置成1M Hz,那么我们这样配置我们用采集点为75%,所以BS1为3tq,BS2为2tq,分频系数为7,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(3+2+1)/7=1MHz问题:Basic Parameter分别是啥意思呢?Timer Triggered Communication Mode:否使用时间触发功能 (ENABLE/DISABLE),时间触发功能在某些CAN 标准中会使用到。
Automatic Bus-Off Management:用于设置是否使用自动离线管理功能 (ENABLE/DISABLE),使用自动离线管理可以在出错时离线后适时自动恢复,不需要软件干预。
Automatic Wake-Up Mode:用于设置是否使用自动唤醒功能 (ENABLE/DISABLE),使能自动唤醒功能后它会在监测到总线活动后自动唤醒。
Automatic Retransmission:用于设置是否使用自动重传功能 (ENABLE/DISABLE),使用自动重传功能时,会一直发送报文直到成功为止。
Receive Fifo Locked Mode:用于设置是否使用锁定接收 FIFO(ENABLE/DISABLE),锁定接收 FIFO 后,若FIFO 溢出时会丢弃新数据,否则在 FIFO 溢出时以新数据覆盖旧数据。
Transmit Fifo Priority:用于设置发送报文的优先级判定方法 (ENABLE/DISABLE),使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文 ID 的优先级来发送。配置完这些结构体成员后,我们调用库函数 HAL_CAN_Init 即可把这些参数写入到 CAN 控制寄存器中,实现 CAN 的初始化
问题:为啥CAN分为RX0,RX1中断呢?
答案:STM32有2个3级深度的接收缓冲区:FIFO0和FIFO1,每个FIFO都可以存放3个完整的报文,它们完全由硬件来管理。如果是来自FIFO0的接收中断,则用CAN1_RX0_IRQn中断来处理。如果是来自FIFO1的接收中断,则用CAN1_RX1_IRQn中断来处理,如图:
问题:CAN SCE中断时什么?
答案:status chanege error,错误和状态变化中断!
四.CAN分析工具的使用
下面我们会用到CAN分析工具,还是比较好用的,此部分使用作为自己使用
https://www.zhcxgd.com/h-col-112.html
五. 实验
1.Normal模式测试500K 波特率(定时发送,轮询接收)
1.1 CubeMx配置
1.2 设置Filter过滤,我们只使能FIFO0,并且不过滤任何消息
uint8_tbsp_can1_filter_config(void){
CAN_FilterTypeDeffilter={0};
filter.FilterActivation=ENABLE;
filter.FilterMode=CAN_FILTERMODE_IDMASK;
filter.FilterScale=CAN_FILTERSCALE_32BIT;
filter.FilterBank=0;
filter.FilterFIFOAssignment=CAN_FILTER_FIFO0;
filter.FilterIdLow=0;
filter.FilterIdHigh=0;
filter.FilterMaskIdLow=0;
filter.FilterMaskIdHigh=0;
HAL_CAN_ConfigFilter(&hcan1,&filter);returnBSP_CAN_OK;
}
1.3 开启CAN(注意,默认Cubemx生成的代码并没有can start)
HAL_CAN_Start(&hcan1);
1.4 编写发送函数
我们开出了几个参数,id_type是扩展帧还是标准帧,basic_id标准帧ID(在标准帧中有效),ex_id扩展帧ID(在扩展帧中有效),data要发送的数据,data_len要发送的数据长度
uint8_tbsp_can1_send_msg(uint32_tid_type,uint32_tbasic_id,uint32_tex_id,uint8_t*data,uint32_tdata_len){uint8_tindex=0;uint32_t*msg_box;uint8_tsend_buf[8]={0};
CAN_TxHeaderTypeDefsend_msg_hdr;
send_msg_hdr.StdId=basic_id;
send_msg_hdr.ExtId=ex_id;
send_msg_hdr.IDE=id_type;
send_msg_hdr.RTR=CAN_RTR_DATA;
send_msg_hdr.DLC=data_len;
send_msg_hdr.TransmitGlobalTime=DISABLE;for(index=0;index< data_len; index++)
send_buf[index] = data[index];
HAL_CAN_AddTxMessage(&hcan1,&send_msg_hdr,send_buf,msg_box);
returnBSP_CAN_OK;
}
我们在main函数中1s发送一帧,标准帧跟扩展帧交叉调用,代码如下:
send_data[0]++;
send_data[1]++;
send_data[2]++;
send_data[3]++;
send_data[4]++;
send_data[5]++;
send_data[6]++;
send_data[7]++;if(id_type_std==1)
{
bsp_can1_send_msg(CAN_ID_STD,1,2,send_data,8);
id_type_std=0;
}else{
bsp_can1_send_msg(CAN_ID_EXT,1,2,send_data,8);
id_type_std=1;
}
HAL_Delay(1000);
我们通过CAN协议分析仪来抓下结果
1.5 编写轮询接收函数
uint8_tbsp_can1_polling_recv_msg(uint32_t*basic_id,uint32_t*ex_id,uint8_t*data,uint32_t*data_len){uint8_tindex=0;uint8_trecv_data[8];
CAN_RxHeaderTypeDefheader;while(HAL_CAN_GetRxFifoFillLevel(&hcan1,CAN_RX_FIFO0)!=0)
{if(__HAL_CAN_GET_FLAG(&hcan1,CAN_FLAG_FOV0)!=RESET)printf('[CAN]FIFO0overrun!
');
HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&header,recv_data);if(header.IDE==CAN_ID_STD)
{printf('StdIdID:%d
',header.StdId);
}else{printf('ExtIdID:%d
',header.ExtId);
}printf('CANIDE:0x%x
',header.IDE);printf('CANRTR:0x%x
',header.RTR);printf('CANDLC:0x%x
',header.DLC);printf('RECVDATA:');for(index=0;index< header.DLC; index++)
{
printf('0x%x',recv_data[index]);
}printf('
');
}
}
实验一总结:
1.没用调用HAL_CAN_Start(&hcan1);使能CAN
2.没有编写Filter函数,我开始自认为不设置就默认不过滤,现在看来是我想多了,其实想想也合理,你如果不过滤分配FIFO,STM32怎么决定把收到的放到哪个FIFO中
待提升:
1.目前只用到FIFO0,待把FIFO1使用起来2.Normal模式测试500K 波特率(定时发送,中断接收)
2.1 CubeMx配置
步骤2,3,4跟polling完全一致,我们来直接说下中断怎么用(主要是使能notifity就行了)
staticvoidMX_CAN1_Init(void){/*USERCODEBEGINCAN1_Init0*//*USERCODEENDCAN1_Init0*//*USERCODEBEGINCAN1_Init1*//*USERCODEENDCAN1_Init1*/hcan1.Instance=CAN1;
hcan1.Init.Prescaler=12;
hcan1.Init.Mode=CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth=CAN_SJW_1TQ;
hcan1.Init.TimeSeg1=CAN_BS1_4TQ;
hcan1.Init.TimeSeg2=CAN_BS2_2TQ;
hcan1.Init.TimeTriggeredMode=DISABLE;
hcan1.Init.AutoBusOff=ENABLE;
hcan1.Init.AutoWakeUp=ENABLE;
hcan1.Init.AutoRetransmission=DISABLE;
hcan1.Init.ReceiveFifoLocked=DISABLE;
hcan1.Init.TransmitFifoPriority=DISABLE;if(HAL_CAN_Init(&hcan1)!=HAL_OK)
{
Error_Handler();
}/*USERCODEBEGINCAN1_Init2*/bsp_can1_filter_config();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);/*USERCODEENDCAN1_Init2*/}
下面我们来编写下中断函数
voidHAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef*hcan){uint8_tindex=0;uint8_trecv_data[8];
CAN_RxHeaderTypeDefheader;
HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&header,recv_data);if(header.IDE==CAN_ID_STD)
{printf('StdIdID:%d
',header.StdId);
}else{printf('ExtIdID:%d
',header.ExtId);
}printf('CANIDE:0x%x
',header.IDE);printf('CANRTR:0x%x
',header.RTR);printf('CANDLC:0x%x
',header.DLC);printf('RECVDATA:');for(index=0;index< header.DLC; index++)
{
printf('0x%x',recv_data[index]);
}printf('
');
}
上一篇:基于ST32F103ZET6设计的小说阅读器详解
下一篇:利用RT-Thread与MQTT实现智慧班车管理系统的设计
推荐阅读最新更新时间:2024-11-13 18:18