CAN总线实战项目:使用STM32和PCAN-View实现数据采集与监控系统(附完整代码)

摘要: 本文深入浅出地介绍CAN(Controller Area Network,控制器局域网络)总线协议,涵盖其基础概念、报文帧格式、仲裁机制、错误处理等关键知识。同时,文章结合STM32平台,从硬件设计、软件开发到实战案例,全面讲解CAN总线应用开发,并提供详细的代码示例和注释,帮助读者快速掌握CAN总线技术。

关键词: CAN总线, STM32, 嵌入式系统, 汽车电子, 工业控制, 物联网


一、 项目概述

1.1 项目背景

CAN总线作为一种高可靠性、实时性强的串行通信协议,广泛应用于汽车电子、工业自动化、医疗设备等领域。 掌握CAN总线技术,对于嵌入式工程师和物联网开发者至关重要。

1.2 项目目标
  • 深入理解CAN总线协议的原理和特点
  • 掌握基于STM32平台的CAN总线应用开发
  • 通过实战项目,提升CAN总线应用开发能力

二、 CAN总线基础

2.1 CAN总线简介

CAN总线是一种多主站的串行通信协议,其特点包括:

  • 高可靠性: 具有强大的错误检测和纠错机制。
  • 实时性: 采用非破坏性总线仲裁技术,保证高优先级报文优先传输。
  • 灵活性: 支持多主站通信,易于扩展。
  • 成本效益: 硬件结构简单,成本较低。
2.2 CAN 标准与报文帧格式

常见的CAN标准包括CAN 2.0A、CAN 2.0B和CAN FD。 其中,CAN FD (Flexible Data-Rate) 支持更高的数据速率和更长的数据长度。

CAN总线数据以报文帧的形式传输,常见的报文帧格式包括:

  • 数据帧 (Data Frame): 用于传输数据。
  • 远程帧 (Remote Frame): 请求其他节点发送数据。
  • 错误帧 (Error Frame): 节点检测到错误时发送。
  • 过载帧 (Overload Frame): 节点需要延迟发送数据时发送。
2.3 仲裁机制与标识符

CAN总线采用基于标识符的非破坏性仲裁机制,保证高优先级报文优先传输。 标识符越小,优先级越高。

2.4 错误检测与处理

CAN总线具有多种错误检测机制,例如CRC校验、位填充等,并支持错误恢复机制,确保通信的可靠性。

三、 系统设计

3.1 硬件设计

本项目基于STM32F103C8T6微控制器和STM32CubeMX进行开发。

  • MCU: STM32F103C8T6
  • CAN收发器: TJA1050
  • CAN连接器: DB9

连接示意图:

3.2 软件设计
  • 开发环境: Keil MDK
  • HAL库: STM32 HAL库
  • 功能模块:
    • CAN初始化
    • CAN报文发送
    • CAN报文接收
    • 中断处理

四、 代码实现

4.1 CAN初始化
/* CAN 初始化 */
void CAN_Init(void)
{
  /* CAN 时钟使能 */
  __HAL_RCC_CAN1_CLK_ENABLE();

  /* 初始化 CAN 句柄 */
  hcan1.Instance = CAN1;
  /* 设置 CAN 工作模式为普通模式 */
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  /* 设置波特率为 500Kbps */
  hcan1.Init.Prescaler = 6; 
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_13TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
  /* 设置自动离线管理模式 */
  hcan1.Init.AutoBusOff = ENABLE;
  /* 设置自动重传模式 */
  hcan1.Init.AutoRetransmission = ENABLE;
  /* 设置接收 FIFO 锁定模式 */
  hcan1.Init.ReceiveFifoLockedMode = ENABLE;
  /* 设置发送 FIFO 优先级模式 */
  hcan1.Init.TransmitFifoPriority = ENABLE;
  /* 初始化 CAN */
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

  /* 配置 CAN 过滤器 */
  CAN_FilterTypeDef can_filter_config;
  can_filter_config.FilterBank = 0;
  can_filter_config.FilterMode = CAN_FILTERMODE_IDMASK;
  can_filter_config.FilterScale = CAN_FILTERSCALE_32BIT;
  can_filter_config.FilterIdHigh = 0x0000;
  can_filter_config.FilterIdLow = 0x0000;
  can_filter_config.FilterMaskIdHigh = 0x0000;
  can_filter_config.FilterMaskIdLow = 0x0000;
  can_filter_config.FilterFIFOAssignment = CAN_RX_FIFO0;
  can_filter_config.FilterActivation = ENABLE;
  can_filter_config.SlaveStartFilterBank = 14;

  if (HAL_CAN_ConfigFilter(&hcan1, &can_filter_config) != HAL_OK)
  {
    Error_Handler();
  }

  /* 启动 CAN */
  if (HAL_CAN_Start(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

  /* 开启 CAN 接收中断 */
  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    Error_Handler();
  }
}

代码说明:

  • 首先,启用 CAN1 的时钟。
  • 然后,初始化 CAN 句柄 hcan1,并设置 CAN 的工作模式、波特率、自动离线管理、自动重传、接收 FIFO 锁定模式、发送 FIFO 优先级模式等参数。
  • 配置 CAN 过滤器,设置过滤器模式、标识符、掩码等参数。
  • 启动 CAN 模块。
  • 最后,开启 CAN 接收中断,以便在接收到数据时及时进行处理。
4.2 CAN 报文发送
/* CAN 报文发送 */
void CAN_Send_Msg(uint32_t std_id, uint8_t *data, uint8_t len)
{
  CAN_TxHeaderTypeDef tx_header;
  uint32_t mailbox;

  /* 设置报文 ID */
  tx_header.StdId = std_id;
  /* 设置报文类型为数据帧 */
  tx_header.RTR = CAN_RTR_DATA;
  /* 设置数据长度 */
  tx_header.DLC = len;

  /* 发送 CAN 报文 */
  if (HAL_CAN_AddTxMessage(&hcan1, &tx_header, data, &mailbox) != HAL_OK)
  {
    Error_Handler();
  }
}

 

代码说明:

  • 首先,定义一个 CAN_TxHeaderTypeDef 类型的变量 tx_header,用于设置 CAN 报文的 ID、类型、数据长度等信息。
  • 然后,调用 HAL_CAN_AddTxMessage() 函数将 CAN 报文添加到发送邮箱。其中,hcan1 是 CAN 句柄,tx_header 是报文头信息,data 是要发送的数据,mailbox 是发送邮箱的编号。
  • 如果发送成功,HAL_CAN_AddTxMessage() 函数返回 HAL_OK,否则返回错误码。
4.3 CAN 报文接收

/* CAN 报文接收 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  CAN_RxHeaderTypeDef rx_header;
  uint8_t rx_data[8];

  /* 接收 CAN 报文 */
  if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) != HAL_OK)
  {
    Error_Handler();
  }

  /* 处理接收到的数据 */
  if (rx_header.StdId == 0x100)  // 判断报文 ID
  {
    // 处理 ID 为 0x100 的报文
  }
}

代码说明:

  • HAL_CAN_RxFifo0MsgPendingCallback() 函数是 CAN 接收中断回调函数,当接收到 CAN 报文时,该函数会被调用。
  • 首先,定义一个 CAN_RxHeaderTypeDef 类型的变量 rx_header,用于存储接收到的 CAN 报文头信息,以及一个 uint8_t 类型的数组 rx_data,用于存储接收到的数据。
  • 然后,调用 HAL_CAN_GetRxMessage() 函数从接收 FIFO 中读取 CAN 报文。
  • 根据接收到的报文 ID 进行相应处理。
4.4 中断处理

在 STM32CubeMX 中,可以图形化地配置 CAN 中断。 在代码中,需要实现 HAL_CAN_RxFifo0MsgPendingCallback() 函数来处理接收到的 CAN 报文。

五、 项目总结

本项目介绍了 CAN 总线的基本概念、帧格式、仲裁机制和错误处理等关键知识,并结合 STM32 平台,详细讲解了 CAN 总线的硬件设计、软件开发和实战案例。 通过学习本项目,读者可以快速掌握 CAN 总线技术,并将其应用到实际项目中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/792913.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【益起童行】为“来自星星的孩子”点亮希望之光

在未来的日子里, 我期望每一个孩子都能得到优质的干预治疗,让他们在未来能够过上正常、快乐的生活。 我也期望每一个家庭都能战胜困境,迎来美好。 作为社会的一份子,我愿意为这繁华人世贡献出自己微不足道但却真挚的力量&#xff…

24暑假计划

暑假计划: 1.从明天起开始将C语言的部分补充完整,这部分的预计在7月24日前完成 2.由于之前的文章内容冗余,接下来进行C语言数据结构的重新编写和后面内容的补充预计8月10号前完成 3.后续开始C的初级学习

新加坡很火的slots游戏代投Facebook广告新流量趋势

新加坡很火的slots游戏代投Facebook广告新流量趋势 在新加坡这片充满活力的土地上,Slots游戏以其独特的魅力和吸引力,迅速成为了许多玩家的心头好。而Facebook,作为全球最大的社交媒体平台之一,为Slots游戏的推广提供了得天独厚的…

element-plus 按需导入问题 404等问题

场景 新开一个项目,需要用element-plus这个ui库,使用按需引入。 这是我项目的一些版本号 "element-plus": "^2.7.6","vue": "^3.2.13","vue-router": "^4.0.3",过程(看解决方法…

【MySQL】常见的MySQL日志都有什么用?

MySQL日志的内容非常重要,面试中经常会被问到。同时,掌握日志相关的知识也有利于我们理解MySQL 底层原理,必要时帮助我们排查解决问题。 MySQL中常见的日志类型主要有下面几类(针对的是InnoDB 存储引擎): 错误日志(error log):对 MySQL 的启…

利用Python与uiautomator2实现【手机群控】

利用Python与uiautomator2实现多设备自动化测试 引言 在移动应用测试中,自动化测试是一种提高测试效率和覆盖率的有效手段。本文将介绍如何使用Python语言结合uiautomator2库来实现对多个设备的并行自动化测试。 老规矩先放实现的效果 环境准备 Python环境安装u…

评价妙笔生词智能写歌词软件:助力与局限并存

在音乐创作的领域,科技的发展催生了各种创新工具,妙笔生词智能写歌词软件便是其中引人注目的一项。对于这款软件,我们需要以客观和全面的视角来进行评估,因为它既带来了显著的助力,同时也存在不可忽视的局限。 妙笔生…

Iridient Developer:解锁Mac RAW图像处理的极致潜力,打造专业级色彩与细节

Iridient Developer for Mac是一款专为Mac用户设计的RAW图像调整软件,它以其卓越的性能和丰富的功能,赢得了众多摄影师的青睐。以下是对这款软件的详细介绍: 一、强大的RAW图像处理能力 Iridient Developer专为处理RAW图像而设计&#xff0…

JAVA毕业设计146—基于Java+Springboot+vue+uniapp的景区旅游购票小程序(源代码+数据库+9000字论文)

毕设所有选题: https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvueuniapp的景区旅游购票小程序(源代码数据库9000字论文)146 一、系统介绍 本项目前后端分离,分为用户、管理员两种角色 1、用户: 注册…

PHP充电桩小程序系统源码

绿色出行新伴侣!充电桩小程序,让充电不再烦恼✨ 🔋 开篇:告别电量焦虑,充电桩小程序来救场! 在这个电动车日益普及的时代,电量不足成了不少车主的“心头大患”。但别担心,充电桩小…

神器!3个免费PPT成品网站推荐+3款AIPPT工具盘点!

熬夜加班做PPT却没有头绪?别再自己憋着想了!现在凡事主打一个“抄作业”,想做ppt却没想法,可以去到ppt成品网站搜集PPT模板,或是使用时下流行的AI生成PPT工具,只需输入PPT主题,即可快速生成一份…

MongoDB教程(二):mongoDB引用shell

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 引言一、MongoD…

为企业提升销售工作效率的工作手机管理系统

在竞争日益激烈的市场环境中,企业的销售团队如同前线战士,其作战效率直接关乎企业的生存与发展。然而,传统销售管理模式下的信息孤岛、沟通不畅、数据混乱等问题,正悄然成为制约销售效率提升的瓶颈。今天,我们为您揭秘…

VR头显如何低延迟播放8K的RTSP|RTMP流

技术背景 我们在做Unity平台RTSP、RTMP播放器的时候,有公司提出来这样的技术需求,希望在头显播放全景的8K RTSP|RTMP直播流,8K的数据,对头显和播放器,都提出了新的要求,我们从几个方面,探讨下V…

mongo数据库迁移

前言 mongo数据库迁移的方式目前常见的有两种: 1,mongodump与mongorestore 2,mongoimport与mongoexport 二者主要区别有: 1、mongoexport 可以导出json和csv格式, mongodump导出的是bson可读性不如前者 2,…

智慧金融-数据可视化

智慧金融-数据可视化 导入所需的库 import numpy as np import numpy_financial as npf import matplotlib.pyplot as plt from pylab import mpl mpl.rcParams[font.sans-serif][FangSong] mpl.rcParams[axes.unicode_minus]False单图曲线图 r 0.05 # 贷款的年利率 n 30…

LeetCode LCR024.反转链表 经典题目 C写法

LeetCode LCR024.反转链表 经典题目C写法 第一种思路🧐: ​ 使用三个指针,n1,n2,n3,n1为空,n2为头结点,n3为头结点的next。开始反转后,n1赋值给n2的next,n2赋值给n1,n3赋…

深入理解FFmpeg--libavformat接口使用(一)

libavformat(lavf)是一个用于处理各种媒体容器格式的库。它的主要两个目的是去复用(即将媒体文件拆分为组件流)和复用的反向过程(以指定的容器格式写入提供的数据)。它还有一个I/O模块,支持多种…

推荐一个比 Jenkins 使用更简单的项目构建和部署工具

最近发现了一个比 Jenkins 使用更简单的项目构建和部署工具,完全可以满足个人以及一些小企业的需求,分享一下。 项目介绍 Jpom 是一款 Java 开发的简单轻量的低侵入式在线构建、自动部署、日常运维、项目监控软件。 日常开发中,Jpom 可以解…

[Linux]基本指令(二)

一些剩下的指令部分 mv指令(重要) mv 命令是 move 的缩写,可以用来移动文件或者将文件改名( move (rename) files ),是 Linux 系统下常用的命令, 经常用来备份文件或者目录。 语法 : mv [ 选项…