学习CAN通信协议(下)--实例讲解

发布者:平凡的梦想最新更新时间:2024-06-18 来源: elecfans关键字:CAN  通信协议  STM32 手机看文章 扫描二维码
随时随地手机看文章

表不同模式下各结构体成员的内容

f165a678-68d6-11ee-939d-92fbcf53809c.png对这些结构体成员赋值的时候,还要注意寄存器位的映射,即注意哪部分代表 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分别都是设置什么的?答案:如图f171dd1c-68d6-11ee-939d-92fbcf53809c.png问题:怎么配置波特率呢?

答案:用我上面贴的工具(CAN波特率计算 f103AHP1_36M f407AHP1_42M 采样点软件有说明.rar)直接配置,举两个个例子

例子1:我们要配置成500KHz,那么我们这样配置f17d7460-68d6-11ee-939d-92fbcf53809c.pngf18f77b4-68d6-11ee-939d-92fbcf53809c.png我们用采集点为80%,所以BS1为4tq,BS2为2tq,分频系数为12,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(4+2+1)/12=500kHz例子2:我们要配置成1M Hz,那么我们这样配置f1a348b6-68d6-11ee-939d-92fbcf53809c.png我们用采集点为75%,所以BS1为3tq,BS2为2tq,分频系数为7,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(3+2+1)/7=1MHzf1ba3a94-68d6-11ee-939d-92fbcf53809c.png问题:Basic Parameter分别是啥意思呢?f1c247de-68d6-11ee-939d-92fbcf53809c.pngTimer 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中断呢?

f1c9476e-68d6-11ee-939d-92fbcf53809c.png

答案:STM32有2个3级深度的接收缓冲区:FIFO0和FIFO1,每个FIFO都可以存放3个完整的报文,它们完全由硬件来管理。如果是来自FIFO0的接收中断,则用CAN1_RX0_IRQn中断来处理。如果是来自FIFO1的接收中断,则用CAN1_RX1_IRQn中断来处理,如图:

f1d568d2-68d6-11ee-939d-92fbcf53809c.png

问题:CAN SCE中断时什么?

f1ee5dc4-68d6-11ee-939d-92fbcf53809c.png答案:status chanege error,错误和状态变化中断!

四.CAN分析工具的使用

下面我们会用到CAN分析工具,还是比较好用的,此部分使用作为自己使用

https://www.zhcxgd.com/h-col-112.html

五. 实验

1.Normal模式测试500K 波特率(定时发送,轮询接收)

1.1 CubeMx配置

f1f59620-68d6-11ee-939d-92fbcf53809c.pngf201f6f4-68d6-11ee-939d-92fbcf53809c.png

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协议分析仪来抓下结果

f21cf9ae-68d6-11ee-939d-92fbcf53809c.png

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配置

f22aa4b4-68d6-11ee-939d-92fbcf53809c.pngf232fc2c-68d6-11ee-939d-92fbcf53809c.png

步骤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('

');

}


[1] [2]
关键字:CAN  通信协议  STM32 引用地址:学习CAN通信协议(下)--实例讲解

上一篇:基于ST32F103ZET6设计的小说阅读器详解
下一篇:利用RT-Thread与MQTT实现智慧班车管理系统的设计

推荐阅读最新更新时间:2024-11-13 18:18

STM32蜂鸣器模拟播放歌曲
/********************************************************************** *函数名:BEEP_Init *功 能:蜂鸣器初始化 *参 数:无 *返 回:无 *备 注: 引脚 点蜂鸣器电平 模式 速度 PC3 高电平 通用推挽输出 50M **********************************************************************/ void BEEP_Init(void)
[单片机]
STM32入门之旅(第四天)-------位带操作、中断
一、位带操作 1.意义 回想以前写51代码 P0 = 0x10; //将P0端口设置为0x10 P1_0=1; //将P1端口1号引脚设置为高电平 a = P2_2; //获取P2端口2号引脚的电平 根据上述的方法,我们可以发现快速定位修改某个引脚的电平还有获取引脚的状态 GPIO_SetBits、GPIO_ResetBits操作IO口的性能没有达到极致,因为这些函数都需要进行现场保护和现场恢复的动作,比较耗时间,没有进行一步到位,使用位带操作则没有上述的烦恼,简单快速! //位带操作,实现51类似的GPIO控制功能 //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr
[单片机]
stm32快速学习4——串口发送字符
设定UART1时钟 设定发送脚功能 串口设置,使能 #include stm32f10x.h void RCC_Configuration(void); void GPIO_Configuration(void); void USART_Configuration(void); unsigned char str = A ; int main(void) { RCC_Configuration(); GPIO_Configuration(); USART_Configuration(); USART_SendData(USART1,str ); while(1); }
[单片机]
stm32程序升级SD卡读取hex文件写入flash
日期:2019,1,14 芯片:STM32F1ZET6 参考文献: 1、了解hex文件: https://wenku.baidu.com/view/930d6583ec3a87c24028c403.html 2、stm32SD卡hex文件升级:看这位博客的【MCU实战经验】+ 通过SD卡升级HEX格式程序(附源码): https://blog.csdn.net/niepangu/article/details/50683754 【MCU实战经验】+ 通过SD卡升级HEX格式程序(附源码) 3、boot与app的切换可以了解一下正点原子的教程: www.openedv.com/posts/list/11494.htm 4、st
[单片机]
STM32中断挂起和RTOS任务挂起的区别
中断挂起 可以理解为:将中断设置为就绪状态,一旦符合条件,立即执行中断并进入中断函数;比如A和B的抢占优先级相同,A的响应优先级高于B,那么当产生A和B中断的事件发生时,先执行A,并同时将B挂起,一旦A执行完毕,立即执行B。 RTOS的任务挂起 以FreeROTS为例,因为某些原因不能立即执行的任务,可以将其挂起,这个挂起使得任务暂时无法参与任务调度。只有将任务唤醒之后才能继续参与;
[单片机]
STM32 基础系列教程 22 - CAN
前言 CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。在汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议。此后,CAN 通过ISO11898 及ISO11519 进行了标准化,在欧洲已是汽车网络的标准协议。 CAN 的高性能和可靠性已被认同,并被广泛地应用于工业
[单片机]
<font color='red'>STM32</font> 基础系列教程 22 - <font color='red'>CAN</font>
STM32 IIC通信往24C02写数据、读数据
1、24C02模块的原理图:从图中可以看出,A0、A1、A2三个引脚全部接地,说明表示器件地址7位数据后三位全部是0 注:当上一个数据写完之后,若发送停止信号,则至少停下10ms时间后,才能再发送起始信号,这个时间就叫做写周期。 3、器件寻址: 4、字节写: 5、写页: (1)、用页写,CAT24WC01可一次写入8个字节的数据,CAT24C02/04/08/16可以一次写入16个字节的数据。 (2)、页写操作的启动和字节写一样,不同在于传送了一字节数据后并不产生停止信号,主器件还可以被允许额外再发送7或者15个字节。 (3)、每发送一个字节数据后CAT24WCxx产生一个
[单片机]
<font color='red'>STM32</font> IIC通信往24C02写数据、读数据
stm32学习1跑马灯程序之寄存器版本
1使能IO口时钟,配置相关寄存器RCC- AHB1ENR 2初始化IO口模式。配置四个寄存器GPIOX_MODER/GPIOX_OTYPER/OSPEEDER/PUPDR 3操作IO口,输出高低电平。配之寄存器GPIOX_ODR或BSRRL/BSRRH 1:RCC是一个结构体指针RCC- AHB1ENR使能寄存器AHB1,使能外部时钟第六位,位5,及设置这一位为1 ,c语言中利用或运算A|=B相当于A=A|B,32位及寄存器两种写法:1)RCC- AHB1ENR|=0x0020 2)RCC- AHB1ENR|=1 5;1左移5位比较直观 2:GPIOF- MODER= 32位寄存器,一组寄存器对应16个IO口,所以要配置9和10I
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved