CAN 五: CAN编程实践

1、CAN基本驱动步骤

(1)CAN参数初始化

  • 工作模式、波特率等
  • 函数:HAL_CAN_Init

(2)使能CAN时钟和初始化相关引脚

  • GPIO模式设为复用功能模式
  • 函数:HAL_CAN_MspInit(CAN的初始化回调函数)

(3)设置过滤器

  • 过滤器的配置
  • 函数:HAL_CAN_ConfigFilter

(4)CAN数据的接收和发送

  • HAL_CAN_AddTxMessage  发送消息
  • HAL_CAN_GetRxMessage  接收数据

(5)使能CAN相关中断/设置NVIC/编写中断服务函数

  • NVIC:中断控制器
  • __HAL_CAN_ENABLE_IT (可选)

2、开发环境

(1)KeilMDK:V5.38.0.0

(2)STM32CubeMX:V6.8.1

(3)MCU:STM32F407ZGT6

3、实验目的

(1)使用回环模式实现自发自收。

(2)CAN发送数据,然后接收数据,将接收到的数据通过串口发送出去。

4、原理图

(1)CAN芯片选择TJA1040。

(2)CAN_TX接PA12,CAN_RX接PA11。

5、STM32CubeMX创建工程及配置

5.1、补充内容

(1)查阅数据手册,CAN外设接在总线APB1上,时钟频率此处配置为36MHz。

(2)CubeMX创建工程、配置时钟、串口不做详细介绍。

5.2、CubeMX中CAN的配置

(1)使能CAN外设。

(2)配置CAN的参数

  • Bit Timings Parameters:位时序参数
    • Prescaler:分频系数
    • Time Quanta in Bit Segment 1:时间段1(配置为9标识9个时间单元)
    • Time Quanta in Bit Segment 2:时间段2
    • ReSynchronization Jump Width:重新同步跳跃宽度
    • TS1=8、TS2=7、BRP=3,波特率 = 36000 / [( 9 + 8 + 1 ) * 4] = 500Kbps
  • Basic Parameters:基本参数
    • Time Triggered Communication Mode:时间触发通信方式
    • Automatic Bus-Off Management:总线自动离线管理
    • Automatic Wake-Up Mode:自动唤醒模式
    • Automatic Retransmission:自动重发
    • Receive Fifo Locked Mode:接收Fifo锁定模式
    • Transmit Fifo Priority:发送Fifo优先级
  • Advanced Parameters:先进的参数
    • Operating Mode:操作模式

6、KeilMDK软件编写

6.1、CAN相关函数

CAN_TxHeaderTypeDef g_can1_txheader;    /* CAN发送结构体 */
CAN_RxHeaderTypeDef g_can1_rxheader;    /* CAN接收结构体 */
CAN_HandleTypeDef hcan1;     // CAN控制句柄

/* CAN1 init function */
void MX_CAN1_Init(void)
{
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 4;                  /* 分频系数 */            
  hcan1.Init.Mode = CAN_MODE_LOOPBACK;       /* 工作模式设置 环回模式:自发自收 */
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;    /* 重新同步跳跃宽度 */
  hcan1.Init.TimeSeg1 = CAN_BS1_9TQ;         /* 时间段1 */
  hcan1.Init.TimeSeg2 = CAN_BS2_8TQ;         /* 时间段2 */
  hcan1.Init.TimeTriggeredMode = DISABLE;    /* 禁止时间触发通信模式 */
  hcan1.Init.AutoBusOff = DISABLE;           /* 禁止自动离线管理 */
  hcan1.Init.AutoWakeUp = DISABLE;           /* 禁止自动唤醒 */
  hcan1.Init.AutoRetransmission = DISABLE;   /* 禁止自动重发 */
  hcan1.Init.ReceiveFifoLocked = DISABLE;    /* 禁止接收FIFO锁定 */
  hcan1.Init.TransmitFifoPriority = DISABLE; /* 禁止发送FIFO优先级 */
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

}

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_GPIOA_CLK_ENABLE();
    /**CAN1 GPIO Configuration
    PA11     ------> CAN1_RX
    PA12     ------> CAN1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    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(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}


/*
**功能:CAN过滤器配置
**参数:无
**返回值:无
 */
void can_filter_config(void)
{
	CAN_FilterTypeDef can_filterconfig;
    /* 过滤器是接收所有报文,不筛选 */
    can_filterconfig.FilterMode = CAN_FILTERMODE_IDMASK;   /* 过滤器模式:标识符掩码模式(屏蔽位模式)*/
    can_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;  /* 过滤器位宽:32位位宽 */
   
	//STID[10:3] STID[2:0] EXID[17:13]         EXID[12:5] EXID[4:0] IDE RTR 0
	can_filterconfig.FilterIdHigh = 0;        /* ID高字节 */               
    can_filterconfig.FilterIdLow  = 0;        /* ID低字节 */
    can_filterconfig.FilterMaskIdHigh = 0;    /* 掩码高字节 */
    can_filterconfig.FilterMaskIdLow  = 0;    /* 掩码低字节 */
	
    can_filterconfig.FilterBank = 0;                         /* 选择过滤器组 */
    can_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0; /* 过滤器关联FIFO */
    can_filterconfig.FilterActivation = CAN_FILTER_ENABLE;   /* 过滤器使能 */
    can_filterconfig.SlaveStartFilterBank = 14;
    HAL_CAN_ConfigFilter(&hcan1, &can_filterconfig);
    
}

/* 发送消息数据函数 */
void can_send_message(uint32_t id, uint8_t *buf, uint8_t len)
{

    uint32_t tx_mail = CAN_TX_MAILBOX0;  /* 发送邮箱 */
    
    g_can1_txheader.ExtId = id;          /* 扩展标识符 */
    g_can1_txheader.DLC = len;           /* 数据长度 */
    g_can1_txheader.IDE = CAN_ID_EXT;    /* 帧格式(标准帧或扩展帧) */
    g_can1_txheader.RTR = CAN_RTR_DATA;  /* 帧类型(数据帧或远程帧) */
    
    HAL_CAN_AddTxMessage(&hcan1, &g_can1_txheader, buf, &tx_mail);
    // 等待发送完成
    while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3);
}

/* 接收数据函数 */
uint8_t can_receive_message(uint8_t *buf)
{
    if (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) == 0)
    {
        return 0;
    }
    
    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &g_can1_rxheader, buf);
    
		// 返回接收数据长度
    return g_can1_rxheader.DLC;
}

6.2、main.c部分代码

#include "can.h"


int main(void)
{
    /* USER CODE BEGIN 1 */
    uint8_t can_sen_buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};  // can发送数据
    uint8_t can_rec_len = 0;                            // can接收数据长度
    uint8_t can_rec_buf[8] = {0};                       // can接收数据缓冲区
   

    MX_CAN1_Init();
    /* USER CODE BEGIN 2 */
	// 1、已经使能CAN时钟和初始化CAN
	// 2、配置CAN接收过滤器
	can_filter_config();
	// 3、启动CAN设备
	HAL_CAN_Start(&hcan1);
    while (1)
    {
	    printf("hello world\r\n");
	    can_send_message(0xF0000000, can_sen_buf, 8);
	    can_rec_len = can_receive_message(can_rec_buf);
        
        if (can_rec_len)
	    {
		    for (uint8_t i = 0; i < can_rec_len; i++)
		    {
			    printf("%x ",can_rec_buf[i]);
		    }
		    printf("\r\n");
	    }
    }
}

6.3、完整工程下载地址

(1)完整工程存储再码云。

(2)STM32_CSDN: CSDN中STM32专栏的所有示例代码

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

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

相关文章

客户端SDK测试是什么?如何测?

01、是什么 客户端SDK是为第三方开发者提供的软件开发工具包&#xff0c;包括SDK接口、开发文档和Demo示例等。SDK和应用之间是什么关系呢&#xff1f;以云信即时消息服务为例&#xff0c;如下图所示&#xff0c;应用客户端通过调用云信SDK接口&#xff0c;进行消息等数据查询…

用EnumSet代替位域

在Java中&#xff0c;可以使用EnumSet来代替位域&#xff0c;以提高代码的可读性和类型安全性。下面是一个简单的例子&#xff0c;演示如何使用EnumSet来管理一组枚举值&#xff1a; import java.util.EnumSet;// 定义一个枚举类型表示权限 enum Permission {READ, WRITE, EXE…

【Java】使用递归的方法获取层级关系数据demo

使用递归来完善各种业务数据的层级关系的获取 引言&#xff1a;在Java开发中&#xff0c;我们通常会遇到层层递进的关系型数据的获取问题&#xff0c;有时是树状解构&#xff0c;或金字塔结构&#xff0c;怎么描述都行&#xff0c;错综复杂的关系在程序中还是可以理清的。 这…

【MySQL】SQL通用语法 、介绍SQL分类

SQL通用语法 1.SQL语句可以单行或多行书写&#xff0c;以分号结尾 2.MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写。 3.注释&#xff1a; 单行注释&#xff1a; -- 或 # 多行注释: /* */ SQL分类 SQL分类主要分为4类 分别是 DDL DML DQL DCL

向华为学习:基于BLM模型的战略规划研讨会实操的详细说明,含研讨表单(一)

前面&#xff0c;华研荟用了三篇文章介绍华为战略规划的时候使用的其中一个工具&#xff1a;五看三定。一句话来说&#xff0c;五看三定是通过“五看”来知己知彼&#xff0c;然后设计业务&#xff0c;在选定的业务领域&#xff08;方向&#xff09;确定战略控制点&#xff0c;…

libp2p 快速开始

文章目录 第一部分&#xff1a;libp2p 快速入门一、什么是libp2plibp2p 发展历程libp2p的特性p2p 网络和我们熟悉的 client/server 网络的区别&#xff1a; 二、Libp2p的实现目标三、Libp2p的用途四、运行 Libp2p 协议流程libp2p 分为三层libp2p 还有一个局域网节点发现协议 mD…

新能源汽车的“一池春水”,或许不再由价格战掀起波澜?

2005年12月15日&#xff0c;丰田普锐斯混合动力车进入中国&#xff0c;拉开了国内新能源汽车发展的序幕。18年后的今天&#xff0c;国产及进口的新能源汽车已经渗透我国超三分之一的乘用车市场&#xff0c;与油车二分天下的愿景渐趋实现。 今年11月&#xff0c;随着购车需求进…

Mac专用投屏工具AirServer 7 .27 for Mac破解版2024最新免费下载及 2024激活码进行详细解析

AirServer是一款多平台无线屏幕镜像推送软件&#xff0c;能够将iPhone、iPad等移动设备的画面投射到电视、投影仪等大屏幕设备上。而对于尝试使用AirServer的用户来说&#xff0c;激活码是不可或缺的一部分&#xff0c;本文将从多个方面对AirServer 2024激活码进行详细解析。 一…

管理类联考——数学——真题篇——按知识分类——几何——解析几何

文章目录 解析几何2023真题&#xff08;2023-07&#xff09;-几何-解析几何-最值-画图求最值-两线相减求最大-联想三角形的“两边差小于第三边”&#xff0c;当为第三边为最大真题&#xff08;2023-19&#xff09;-几何-解析几何-最值-画图求最值-圆方程画出圆的形状-两点间距离…

TranslatePress Pro 2.6.8 + Addons – WordPress 多语言插件说明介绍

关于TranslatePress Pro 2.6.8 Addons – WordPress多语言插件 TranslatePress Pro Nulled 直接从前端翻译您的 WordPress 网站的更好方式&#xff0c;完全支持 WooCommerce、复杂主题和网站构建器。TranslatePress Pro WordPress 翻译插件&#xff0c;易于使用进行更改。 T…

智能优化算法应用:基于海洋捕食者算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于海洋捕食者算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于海洋捕食者算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.海洋捕食者算法4.实验参数设定5.算法…

了解 Flutter 3.16 功能更新

作者 / Kevin Chisholm 我们在季度 Flutter 稳定版发布会上带来了 Flutter 3.16&#xff0c;此版本包含诸多更新: Material 3 成为新的默认主题、为 Android 带来 Impeller 的预览版、允许添加适用于 DevTools 的扩展程序等等&#xff0c;以及同步推出 Flutter 休闲游戏工具包重…

北京陪诊小程序|陪诊系统功能改善医疗体验

作为领先的医疗科技公司&#xff0c;我们致力于提供创新的解决方案来改善医疗陪诊体验。我们的陪诊软件不仅具备基本的陪诊功能&#xff0c;更融入了先进的技术和个性定制的功能&#xff0c;以满足不同用户的需求&#xff0c;让陪诊变得更加智能、高效和贴心。 1、个性化隐私保…

git代码管理学习文档

1.版本控制 每一版本都会发生变化 更新版本&#xff0c;回退版本 版本控制实际就是控制文件的变化 服务器端和每个人的电脑上都会记录版本的变化&#xff0c;也就是说整个团队都记录了版本的变化。 不需要连网&#xff0c;他是分布式的&#xff0c;在自己电脑上也可以操作。 …

优质全套SpringMVC教程

三、SpringMVC 在SSM整合中&#xff0c;MyBatis担任的角色是持久层框架&#xff0c;它能帮我们访问数据库&#xff0c;操作数据库 Spring能利用它的两大核心IOC、AOP整合框架 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff08;不是设计模式-思想就是我们…

过滤器和监听器及应用

Filter及应用 Filter有什么用?一、Filter处理中文乱码二、监听器&#xff0c;统计网站在线人数1.监听器引入2.统计网站在线人数 三、Filter实现权限拦截 Filter有什么用? Filter:过滤器&#xff0c;可以用来过滤网站的数据。 比如处理中文乱码&#xff0c;每次写servlet&…

[Verilog] Verilog 基本格式和语法

主页&#xff1a; 元存储博客 全文 3000 字 文章目录 1. 声明格式1.1 模块声明1.2 输入输出声明1.3 内部信号声明1.4 内部逻辑声明1.5 连接声明1.6 数据类型声明1.7 运算符和表达式1.8 控制结构 2. 书写格式2.1 大小写2.2 换行2.3 语句结束符2.4 注释2.5 标识符2.6 关键字 1. 声…

VM虚拟机打不开原来保存的虚拟机文件夹ubuntu

VMWare虚拟机打不开原来保存的虚拟机文件夹ubuntu 换了电脑把之前的虚拟机克隆的文件夹直接拿来用 报这个错&#xff1a; 指定的文件不是虚拟磁盘 打不开磁盘“D:\ubuntu_iso\ubuntu_location\Ubuntu 64 位-s002.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未…

图像生成算法评估指标

IS P(y|x)分布越尖越好&#xff0c;说明他质量好&#xff0c;能够被模型很好的识别&#xff1b;P&#xff08;y&#xff09;表示生成n张图片的概率的均值&#xff0c;越平说明每个类别生成越平均&#xff0c;说明多样性好&#xff1b;IS越大说明这两个分布差别越大&#xff0c;…

php查询数据库,并通过表格展示

第一步&#xff1a;创建数据库 创建一个数据库php-crud 第二步&#xff1a;创建数据库表 在数据库php-crud下创建一个歌曲表song /*Navicat Premium Data TransferSource Server : MariaDBSource Server Type : MariaDBSource Server Version : 100605 (10.6.5-M…