首页 > 其他分享 >STM32 CAN的HAL库简单使用

STM32 CAN的HAL库简单使用

时间:2024-11-24 16:59:17浏览次数:11  
标签:HAL 简单 hcan1 STM32 Init CAN1 GPIO ID

一、CAN的基本知识

1. 物理层

  1. 差分信号
  2. ISO11898标准:高速、短距离“闭环网络”,它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个“120欧”的电阻。
  3. ISO11519-2标准:低速、远距离“开环网络”它的最大传输距离为1km,最高通讯速率为125kbps,两根总线是独立的、不形成闭环,要求每根总线上各串联有一个“2.2千欧”的电阻。
  4. 逻辑1时(隐性电平):CAN_High和CAN_Low线上的电压均为2.5v,即它们的电压差VH-VL=0V;
  5. 逻辑0时(显性电平):CAN_High的电平为3.5V,CAN_Low线的电平为1.5V,即它们的电压差为VH-VL=2V。

请添加图片描述
假如有两个CAN通讯节点,在同一时间,一个输出隐性电平,另一个输出显性电平,类似I2C总线的“线与”特性将使它处于显性电平状态,显性电平的名字就是这样来的。

2. 协议层

① 数据位格式
  1. CAN时钟的最小周期称为最小时间单元Time Quantum(Tq)
  2. 同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)和相位缓冲段2(PBS2)。每个段都占有数量不同的Tq,一个完整的bit,由8~25个Tq组成,除了SS段是固定的1Tq之外,其他的段占有Tq的数量都是可调的。
  3. 通过确定一个数据位的总Tq,可以计算波特率:
    例如:而每个数据位由19个Tq组成,波特率可得
    1 x 1 0 6 / 19 = 52631.6 ( b p s ) 1x10^6/19 = 52631.6 (bps) 1x106/19=52631.6(bps)
② STM32数据位格式

STM32的CAN外设,数据位格式与标准的略有不同,分为三段:
在这里插入图片描述
在STM32CubemX中波特率的计算,
Time Quanta in Bit Segment 1是位段1
Time Quanta in Bit Segment 2是位段2
在这里插入图片描述
按上图的配置计算波特率:
CAN总线在时钟树的APB1总线上,当前的总线频率为30MHz
经过10分频后,CAN的1Tq为大概为333.33ns
BS1段设置为1Tq,BS2段设置为4Tq,可得1bit的总时间为
SYNC(1)+ BS1(1) + BS2(4) = 6Tq
波特率为:
B a u d r a t e = 1 / 6 T q = 1 / ( 333.33 ∗ 6 ) = 1 / ( 1999 ) ≈ 499.99 K b i t / s Baudrate = 1/6Tq = 1/(333.33*6) = 1/(1999)≈499.99K bit/s Baudrate=1/6Tq=1/(333.33∗6)=1/(1999)≈499.99Kbit/s

3. CAN 通信帧

  1. 帧种类
帧格式含义
数据帧用于节点向外传送数据
遥控帧用于向远端节点请求数据
错误帧用于向远端节点通知校验错误,请求重新发送上一个数据
过载帧用于通知远端节点:本节点尚未做好接收准备
帧间隔用于将数据帧及遥控帧与前面的帧分离开来
  1. 数据帧格式为:帧起始(SOF段一个显性位(逻辑0))、 仲裁段、控制段、数据段、CRC段、ACK段和帧结束(EOF段以7个连续的隐性位(逻辑1)结束)
    在这里插入图片描述3. 仲裁段: 内容为数据帧的CAN ID(标识符),数据帧具有标准格式和扩展格式两种
    标准格式的CAN的ID为11位、扩展帧格式为29位。
    当两个节点同时发送报文时,若首先出现隐性电平,则会失去对总线的占有权,进入接收状态,在CAN通信中0是显性电平,所以CAN的ID越小,其优先级越高。

二、STM的CAN使用

1. CAN 过滤器

参考链接:https://blog.csdn.net/qq_35480173/article/details/98878309

①两种过滤模式
模式优点缺点
列表模式能精确地过滤每个指定的CAN ID有数量限制
掩码模式取决于屏蔽码,有时无法完全精确到每一个CAN ID,部分不期望的CAN ID有时也会收到数量取决于屏蔽码,最多无上限
②过滤寄存器
  1. CAN_FM1R寄存器中的FBMx位:”0”表示掩码模式,”1”表示列表模式。
    下图的每一个位对应地表示这28个过滤器的工作模式
    在这里插入图片描述
  2. CAN_FS1R寄存器表示CAN ID的位宽:0:16位宽 1:32位宽
    在这里插入图片描述
  3. CAN_FxR1和CAN_FxR2 两个寄存器
    列表模式-16位宽模式下: 写入4个标准CAN ID
    列表模式-32位宽模式下: 写入2个CAN ID
    掩码模式-16位宽模式: 2对验证码+屏蔽码组合来用,但它只能对标准CAN ID进行过滤
    掩码模式-32位宽模式: CAN_FxR1用做32位宽的验证码,而CAN_FxR2则用作32位宽的屏蔽码
    注意:下面STID表示标准ID有11位,EXID为扩展ID有18位(扩展帧ID总共29位).
    然后是RTR,表示是否为远程帧(遥控帧)。IDE,表示扩展帧标识。

    在这里插入图片描述

2. CAN 初始化和配置

下面以常用的32位掩码模式为例解释CAN的初始化配置和过滤器配置

1. CAN初始化

在这里插入图片描述在这里插入图片描述

/* CAN1 init function */
void MX_CAN1_Init(void)
{

  /* USER CODE BEGIN CAN1_Init 0 */

  /* USER CODE END CAN1_Init 0 */

  /* USER CODE BEGIN CAN1_Init 1 */

  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 14;
  hcan1.Init.Mode = CAN_MODE_NORMAL;            //正常模式
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;       
  hcan1.Init.TimeSeg1 = CAN_BS1_4TQ;            //BS1时间段
  hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;            //BS2时间段
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;      //自动重发
  hcan1.Init.ReceiveFifoLocked = DISABLE;       
  hcan1.Init.TransmitFifoPriority = ENABLE;     //发送使用FIFO
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

  // 过滤只接收0x000018xx的CAN ID
  uint32_t mask = 0xffffff00;
	mask <<= 3;
	mask |= 0x02;   //设置只接受数据帧
  /* USER CODE BEGIN CAN1_Init 2 */
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  //掩码模式
  sFilterConfig.FilterIdHigh = ((0x00001871 << 3) >> 16) & 0xffff;   //配置ID        
  sFilterConfig.FilterIdLow = ((0x00001871 << 3) & 0xffff) | CAN_ID_EXT;  //配置扩展帧
  sFilterConfig.FilterMaskIdHigh = (mask >> 16) & 0xffff;
  sFilterConfig.FilterMaskIdLow = (mask & 0xffff);         //配置掩码
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;      //32位宽度
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;  //FIFO0
  sFilterConfig.FilterBank = 0;                           //过滤器0
  sFilterConfig.SlaveStartFilterBank = 14;            //从属CAN2实例的起始过滤器库,单CAN没有用,
                                                      //过滤器Min_Data = 0 和最大值 Max_Data = 27 
  sFilterConfig.FilterActivation = ENABLE;
  if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
	  Error_Handler();
  }
  //使能FIFO接收中断
  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
	  Error_Handler();
  }
  /* USER CODE END CAN1_Init 2 */

}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**CAN1 GPIO Configuration
    PB8     ------> CAN1_RX
    PB9     ------> CAN1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* CAN1 interrupt Init */
    HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

2. CAN接收和发送
//CAN 接收回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == CAN1)
	{
		HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxdata);
	}
}
//CAN 发送函数
HAL_StatusTypeDef UserCan_Transmit(uint32_t Id, uint32_t IDE, uint32_t RTR, uint32_t DLC, uint8_t *data)
{
	CAN_TxHeaderTypeDef txHeader;
	txHeader.StdId = Id;	 
	txHeader.ExtId = Id;	 
	txHeader.IDE = IDE;//CAN_ID_STD;
	txHeader.RTR = RTR;//CAN_RTR_DATA;
	txHeader.DLC = DLC;//8;
	txHeader.TransmitGlobalTime = DISABLE;
	return HAL_CAN_AddTxMessage(&hcan1, &txHeader, data, &TxMailboxNumber);
}

标签:HAL,简单,hcan1,STM32,Init,CAN1,GPIO,ID
From: https://blog.csdn.net/TANG3223/article/details/144006863

相关文章

  • 基于Java+SpringBoot+Mysql在线简单拍卖竞价拍卖竞拍系统功能设计与实现六
    一、前言介绍:免费学习:猿来入此1.1项目摘要主要源于互联网技术的快速发展和电子商务的普及。随着网络技术的不断进步,人们越来越依赖于互联网进行购物、交易和沟通。电子商务的兴起为在线拍卖提供了广阔的市场和便利的条件。在线拍卖系统通过搭建一个虚拟的拍卖平台,将传统的拍卖......
  • 基于Java+SpringBoot+Mysql在线简单拍卖竞价拍卖竞拍系统功能设计与实现五
    一、前言介绍:免费学习:猿来入此1.1项目摘要主要源于互联网技术的快速发展和电子商务的普及。随着网络技术的不断进步,人们越来越依赖于互联网进行购物、交易和沟通。电子商务的兴起为在线拍卖提供了广阔的市场和便利的条件。在线拍卖系统通过搭建一个虚拟的拍卖平台,将传统的拍卖......
  • HTML学生个人网站作业设计:动漫网站设计——樱桃小丸子(6页) HTML+CSS+JavaScript 简单
    一、......
  • 第54篇 Redis简单介绍
    前言Redis,作为一种开源的、基于内存且支持持久化的键值存储系统,以其卓越的性能、丰富灵活的数据结构和高度可扩展性在全球范围内广受欢迎。Redis不仅提供了一种简单直观的方式来存储和检索数据,更因其支持数据结构如字符串、哈希、列表、集合、有序集合等多种类型,使得其在众多场景......
  • 简单好用!营销活动A/B测试 - 智能短链接
    在如今竞争白热化的市场中,活动营销是否有效直接关乎企业成败。AB测试作为有力工具,能助力企业优化活动营销策略,增强营销成效。AB测试关键在于打造多个活动方案版本,同时推送给不同用户群,对比优劣。其一,先明确测试目标,究竟是提升参与度、促进销售额,还是拔高品牌知名度等。设计......
  • STM32 通过按键方式触发中断的处理流程
    需求:通过按键方式触发中断中断处理流程整体流程图片首先中断处理源有三个方向方向:1:内核其他控件(灰色的图2)有可以配置的,配置优先级也有固定的,优先级最高,数越小优先级越高2:片上外设:位于CPU外部,STM32芯片内部(白色的图3)3:片上外设,EXTI专门管理外部中断  通过需求......
  • STM32 系统滴答定时器和时间换算问题
    ARMCPU内部存在定时器SysTick可以称为系统滴答定时器,需要查看Cortex-M3->STK_CRTL控制和状态寄存器:32位寄存器:reserved保留0位:ENABLE:使能位,写1开始计时16位:COUNTFALG:标志位,计数完成自动置1。1位:TICKINT:中断使能,定时完成是否发生中断,0是默认关闭2位:CLKSOURCE:时钟源......
  • STM32 通过STM32cubemx软件进行代码生成(led灯闪烁)并最后封装点亮、熄灭以及翻转灯函数
    第一步生成代码对hal生成的文件进行解释Core:核心->Inc:各种头文件->Src:各种源文件Drivers:驱动文件MDK:可以看到个keil各种文件项目路径hail.ioc,可以用来修改配置,工作日志和配置文件 第二步点击MDK-ARM可以看到keil文件,双击打开keil文件对其配置自动复位功......
  • MySQL中的ROW_NUMBER窗口函数简单了解下
    ROW_NUMBER()是MySQL8引入的窗口函数之一,它为查询结果集中的每一行分配一个唯一的顺序号(行号)。这个顺序号是基于窗口函数的ORDERBY子句进行排序的,可以根据指定的排序顺序生成连续的整数值。ROW_NUMBER()在分页、去重、分组内排序等场景中非常有用。本文涉及到的脚本测试请......
  • Vue.js基础——贼简单易懂!!(响应式 ref 和 reactive、v-on、v-show 和 v-if、v-for、v-b
     Vue.js是一个渐进式JavaScript框架,用于构建用户界面。它专门设计用于Web应用程序,并专注于视图层。Vue允许开发人员创建可重用的组件,并轻松管理状态和数据绑定。它还提供了一个虚拟DOM系统,用于高效地渲染和重新渲染组件。Vue以其简单易用的特点而闻名,使其成为初学者和有经验的......