基于stm32cubeIDE学习can通信

can通信

TO DO
1
CAN_FilterTypeDef 中的SlaveStartFilterBank 为从过滤器配置,用来选择从过滤器的寄存器号
当选择双CAN模式的时候,这个参数要跟CAN2的filternumber 一致。
//filternumber 是啥
2
can在发送的时候怎么决定是送到FIFO0还是FIFO1?
3
看这个

WHY
发送信息的时候 邮箱是怎么选的。为什么我按照例程重新写句柄和发送函数的时候即使发第一个消息也会跳转到邮箱1,而且发送失败。。

 /* Select one empty transmit mailbox */
  if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
  {
    transmitmailbox = 0;
  }
  else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
  {
    transmitmailbox = 1;
  }

CAN 的硬件结构

CAN总线系列学习笔记
在这里插入图片描述
左边是高速CAN总线的拓扑结构,右边是低速CAN总线的拓扑结构。所以高速和低速的设备是不能混用的【吧】
在这里插入图片描述

CAN 的信息格式

太多了,拿一个典型的给大家康康
在这里插入图片描述
下面的描述也是简化版本,具体还有很多细节没提到。
ID 确定顺序用的【canopen里用来划分帧的功能和子设备号】
控制段 确定数据的长度用的 【canopen里的SDO还另外用数据段里的内容又指定一次数据长度,搁这套娃呢】
数据段 8字节,只能少不能多
CRC 校验
ACK 回应
帧结束 7个隐性位

Can总线何时是空闲的

当总线连续表现为11个位的隐形电平(高电平),则总线为空闲状态。但是Can总线不是说5个相同位后就会有一个反转位码,那是发生在发送数据时。总线空闲时没有发送数据,发送数据时不会出现这么多隐性位。

CAN消息的有效长度。uint8_t len

每一帧CAN消息能够传递最多8个无符号整形数据,或者说能够传递8*8的bool类型的数据。这里的len最大值为8,如果该帧CAN消息中有些位没有数据,这里的len就会小于8。

NOTE
1开发板上的两个 CAN 都分别拥有自己的发送邮箱和接收 FIFO,但是他们共用 28 个 滤波器
2CAN有两个接收FIFO ,每个滤波器要设定对应的FIFO // ‘FIFO’ ==先入先出

CAN总线有接收邮箱和发送邮箱:
”发送邮箱“是用于CAN总线数据发送的,总共有3个,并且存在优先级关系。优先级越高表示其里面的数据会被优先发送。数据在发送前都会被送到优先级最高且空闲的发送邮箱,然后依次发送。最后说明一点:“发送邮箱有3个,且每个邮箱只能装一个报文”。
”接收邮箱“是用于CAN总线数据接收用的,在接收数据端会有一个过滤器处于”接收邮箱“的前面,过滤器使用于删选”标识符“的,只有标识符符合的报文才会被放入到”接收邮箱“当中。注意:”接收邮箱不同于发送邮箱,接收邮箱只有2(FIFO0、FIFO1)个,但是每一个有三层,每层都可以存放一个报文,即每一个接收邮箱可以接收三个报文。但读取时只能读到最先收到的报文,等这个读完之后,才能读下一个报文”。

3滤波器初始化里的CAN1_FilerConf.BankNumber=14;用来设置CAN2 起始存储区。

FIFO溢出时的策略
STM32有两种策略来处理当FIFO溢出时的报文:

一:当FIFO溢出时,首先抛弃FIFO内最老的报文,然后再存入新接收到的报文,即滚动接收模式。
二:当FIFO溢出时,抛弃新接收到的报文,即FIFO锁定模式。

如何采用以上何种策略,取决于具体应用需求。
如何设置?CAN主控制器寄存器(CAN_MCR)设置RFLM位为0,则为FIFO滚动接收模式,设为1,则为FIFO锁定模式。

基础设施

指示灯,按键中断以及NVIC中断允许,can的引脚和波特率配置,SYS调试引脚选第一项S… W… 记不清了
在这里插入图片描述
文件管理把生成.c .h文件勾选上
在这里插入图片描述

一要设置波特率

【重要性类比串口的波特率】
在这里插入图片描述

首先知道自己的APB1是45M
在这里插入图片描述
后面的参数就是45M/5(1+5+3)=1Mbps 想换频率只要改Prescaler就好 //但是这个频率好像太高了,ioc那边有警报。 现在用45M/9(1+5+4)=0.5Mbps

二是设置过滤器

自己新建个结构体 设定参数,调用句柄。可以像我一样新建个函数来初始化,也可以直接写在can的init函数里。

列表模式:只能接收指定ID的消息。

消息发送时的ID为0x0-0x7FF 【0000 0111 1111 1111】因此只有11个位有效 而过滤器的4个16位数据的存储方式是顶格存储的 所以过滤器设置1000 0000 1000 0000 从前面开始取值是 100 0000 0100 0000 0 对应的是 ID 404 【即过滤器里的后5位是废弃的】。截图里的设置是我的测试方式,大家也试一遍想必印象会更深刻。在这里插入图片描述

当将消息的ID设置为0x0404时,过滤器列表应设为0x8080才能挑出ID为0404的消息。也就是说这个设置不能接收到ID为0201的消息,能接收到306的消息。另外我尝试了反向翻译一下过滤器设为0404的ID,ID是0020.开发板能接收。

【另外,我通信协议学的是canopen 这11个位里的前四位是报文的功能码,剩下的是从机编号(所以能有127个从机)】

屏蔽模式

举个简单的例子,我们设置过滤器组 0 工作在:1 个 32 位过滤器-标识符屏蔽模式,然后设置CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00。
其中存放到 CAN_F0R1 的值就是期望收到的ID,即我们希望收到的 ID(STID+EXTID+IDE+RTR)最好是:0XFFFF0000。而 0XFF00FF00就是设置我们需要必须关心的 ID,表示收到的 ID,其位[31:24]和位[15:8]这 16 个 位的必须和 CAN_F0R1 中对应的位一模一样,而另外的 16 个位则不关心,可以一样,也可以 不一样,都认为是正确的 ID,即收到的 ID 必须是0xFFxx00xx,才算是正确的(x 表示不关心)

三 通信中断使能

HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
开启中断,开的是CAN_IT_RX_FIFO0_MSG_PENDING 接收中断

四 打开can通信

HAL_CAN_Start(&hcan1);

五 发送

数据帧

数据帧中有两种模式,一种是标准帧,一种是扩展帧。区别就只有ID的长短,但是同样是发送0x601,只有标准帧能被canopen识别,我不清楚这是因为canopen只能识别标准帧还是说标准帧和扩展帧就算低位数相同也会被区分开。
在这里插入图片描述
在这里插入图片描述
上面是can通信的格式,基本上就只用管ID和实际数据内容,其他部分都给函数整好了【而且学数据帧就够用了,别的很少用的样子】

玩过过滤就会搞ID 其余的设置对应的就是帧的结构
在这里插入图片描述
在这里插入图片描述
发送扩展帧只是ID变多了。而且发送的时候上面那个Stdid作废,ExtId可以从0写到1fffffff。

CAN发送流程

程序选择 1 个空置的邮箱(TME=1)->设置标识符(ID),数据长度和 发送数据->设置CAN_TIxR的TXRQ位为 1,请求发送->邮箱挂号(等待成为最高优先级)->预定发送(等待总线空闲)->发送->邮箱空置

六 接收

在这里插入图片描述
FIFO 空->收到有效报文->挂号_1(存入 FIFO 的一个邮箱,这个由硬件控制,我们不需要理会)->收到有效报文->挂号_2->收到有效报文->挂号_3->收到有效报文-> 溢出。
这个流程里面,我们没有考虑从 FIFO 读出报文的情况,实际情况是:我们必须在 FIFO 溢出之前,读出至少 1 个报文,否则下个报文到来,将导致 FIFO 溢出,从而出现报文丢失。每读出 1 个报文,相应的挂号就减 1,直到 FIFO 空.
FIFO 接收到的报文数,我们可以通过查询 CAN_RFxR 的 FMP 寄存器来得到,只要 FMP 不为 0,我们就可以从 FIFO读出收到的报文

参考文献

微雪课堂
过滤器
理论讲解
运行200秒左右 can就不发数据了 3个发送邮箱都满了?哪的问题,怎么办?

void can_filter_init(CAN_HandleTypeDef *phcan)
{

CAN_FilterTypeDef  sFilterConfig;

  /* 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();
  }

}
void CAN_Send(CAN_HandleTypeDef* phcan)
{

//HAL_CAN_ActivateNotification(&hcan, CAN_IT_TX_MAILBOX_EMPTY);//开启中断
CAN_TxHeaderTypeDef TxHeader;
uint32_t TxMailbox=0;
uint8_t TxData[6] = {0x23, 0x81, 0x60, 0x00, 0x55, 0x55};

// HAL_Delay(1000);
TxHeader.StdId = 0x404; //标准帧ID �???�???11位,也就�???0x7FF
TxHeader.RTR = CAN_RTR_DATA; //帧类型是数据�??? 数据类型,由系统定义的,无需理会
TxHeader.IDE = CAN_ID_STD;//ID类型是标准帧 定义信息传输类型,系统内定,不予理会
TxHeader.DLC = 8;//指定即将传输的数据帧的长8字节长度
TxHeader.TransmitGlobalTime=DISABLE;

HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);

TxData[0]++;
// HAL_UART_Transmit(&huart1,TxData,8,0xffff);//79 0B 00 08 C1 09 00 08

}

  • 3
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Stm32CubeIDE是一款由ST微电子公司开发的集成开发环境(IDE),用于开发基于ST微电子的STM32单片机系列产品。该软件提供了丰富的工具和功能,方便开发人员进行嵌入式软件开发。 STM32CubeIDE 103 CAN是指在STM32CubeIDE软件中进行CAN总线相关开发。CAN(Controller Area Network)是一种常用的实时通信协议,广泛应用于汽车、工业控制以及其他需要高可靠性和实时性的领域。 在STM32CubeIDE 103 CAN中,开发人员可以使用软件提供的CAN相关库函数和API,快速编写CAN通信程序。通过这些库函数和API,开发人员可以方便地实现CAN消息的发送和接收,设置CAN帧的参数和标识符等。 在进行CAN开发时,需先在STM32CubeMX软件中进行硬件配置,选择要使用的CAN通道,并设置相应的参数。然后,在STM32CubeIDE中创建一个新的工程,并选择相应的板级支持包和库文件。 在编写代码时,可以使用STM32CubeIDE提供的Code Generator工具,自动生成CAN相关的初始化代码和处理函数。然后,根据实际需求,进行自定义的修改和编写。 在完成代码编写后,可以使用STM32CubeIDE提供的调试工具,如更断点、观察表等,对代码进行调试和测试。最后,将代码下载到目标设备上运行,进行实际的CAN通信测试和验证。 总之,通过STM32CubeIDE 103 CAN,开发人员可以在方便和高效的开发环境中进行CAN总线相关的开发,快速实现嵌入式CAN通信功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值