CAN 五: CAN编程实践

news2024/9/20 20:00:20

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.coloradmin.cn/o/1316835.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【linux】(ubuntu)下 QT 出现的问题

错误一&#xff1a;Make 运行QT程序以后出现这样的错误。 【解决方法】 我的ubuntu版本是18.04.4&#xff0c; 原因1&#xff1a;没有更换软件源 原因2&#xff1a;没安装相关 软件包 注意&#xff1a;这一步很有可能卡死这一步&#xff0c;所以如果一直卡在这并且进度…

黑马点评01

基础篇-07.Redis命令-数据结构介绍_哔哩哔哩_bilibili 1.NoSQL 非结构化数据库&#xff0c;和sql的区别在于没有数据库表之间的关系&#xff08;主键外键&#xff09;&#xff0c;一般的存储形式是JSON。每个json里面都存储了该记录的所有数据&#xff0c;所以有一定重复性。 …

总结一些vue3小知识2

1.el-tree-select和el-tree组件报错&#xff08;有的下拉选项选择不了&#xff0c;一点击就报错&#xff0c;但是有的却能选择&#xff0c;不会报错&#xff09; 原因:就如同v-for一样&#xff0c;需要添加key才不会出现渲染错误&#xff0c;而el-tree-select和el-tree组件需要…

MySQL数据库 DCL

目录 DCL概述 管理用户 权限控制 DCL概述 DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访 问权限。 管理用户 (1) 查询用户 select * from mysql.user; 查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localh…

计算机组成原理-指令系统CISC和RISC

文章目录 总览CISC和RISC 总览 CISC和RISC 存储程序就是用一个电路再加上存储部件构成 可访存指令不同 RISC更自由&#xff0c;因为很多函数没有固定&#xff0c;是自己写的 由于CISC各个指令执行时间不一样&#xff0c;要实现指令流水线比较困难 由于CISC可访存指令没有限制…

LVS负载均衡群集,熟悉LVS的工作模式,了解LVS的调度策略以及ipvsadm工具的命令格式

目录 一、什么是群集 群集的作用&#xff1a; 群集的目的是什么 根据群集所针对的目标差异&#xff0c;可分为三种类型 负载均衡群集&#xff08;LBC&#xff09;load balance cluster 高可用群集&#xff08;HAC&#xff09;high availability cluster 高性能运算群集&a…

【Docker】5. Dockerfile 构建和管理容器化应用程序

▒ 目录 ▒ &#x1f6eb; 导读开发环境 1️⃣ Dockerfile介绍 基本语法 指令 2️⃣ 实战&#xff1a;Python 的 Flask Web 代码 编译运行 发布到服务器 &#x1f6ec; 文章小结&#x1f4d6; 参考资料 &#x1f6eb; 导读 开发环境 版本号描述文章日期2023-12-15操作系统…

Dagger2基本使用2之子组件

一&#xff0c;基本使用&#xff0c;完成一个注入 1&#xff0c;创建作用域 //自定义作用域&#xff0c;作用域只是一个名称&#xff0c;随便起啥名字都可以&#xff0c;这里取一个全局单利的名字 Scope Documented Retention(RUNTIME) public interface GlobalSingleton { }…

LVS负载均衡器(DR模式)+nginx七层代理+tomcat多实例+php+mysql 实现负载均衡以及动静分离、数据库的调用!!!

目录 前言 一、nfs共享存储&#xff0c;为两个节点服务器提供静态网页共享 二、nginx作为lvs的后端节点服务器&#xff0c;完成lo:0网卡配置&#xff0c;以及内核参数设置&#xff0c;还有设置路由表 步骤一&#xff1a;先完成nfs共享存储挂载 步骤二&#xff1a;完成lo:0网…

QT----第三天,Visio stdio自定义封装控件,鼠标事件,定时器,事件分发器过滤器,绘图事件

目录 第三天1 自定义控件封装2 QT鼠标事件3 定时器4 event事件分发器5 事件过滤器6 绘图事件Qpainter 源码&#xff1a;CPP学习代码 第三天 1 自定义控件封装 新建一个QT widgetclass&#xff0c;同时生成ui,h,cpp文件 在smallWidget.ui里添加上你想要的控件并调试大小 回到…

Linux下MySQL的安装部署

MySQL数据库存在多种版本&#xff0c;不同的版本在不同的平台上&#xff08;OS&#xff0c;也就是操作系统上&#xff09;安装方式可能有所不同&#xff0c;因此安装时一定要参数官方文档进行安装。 MySQL :: MySQL Documentation 选择需要的MySQL官方提供的不同版本&#xff0…

【谭浩强C语言】导言-C知识点汇总

一、初衷 C语言基本是各大院校工科必修课&#xff0c;C语言也是单片机、嵌入式系统的基础开发语言&#xff0c;很多老师们都各显神通的把C语言精讲地很到位&#xff0c;咱们CSDN的技能树也提供了很棒的学习平台。那么&#xff0c;为什么还是打算开个专栏再整理整理呢&#xff…

Kubernetes实战(十四)-k8s高可用集群扩容master节点

1 单master集群和多master节点集群方案 1.1 单Master集群 k8s 集群是由一组运行 k8s 的节点组成的&#xff0c;节点可以是物理机、虚拟机或者云服务器。k8s 集群中的节点分为两种角色&#xff1a;master 和 node。 master 节点&#xff1a;master 节点负责控制和管理整个集群…

对自己的博客网站进行DOS攻击

对自己的博客网站进行DOS攻击 先说明一点,别对别人的网站进行ddos/dos攻击(dos攻击一般短时间攻击不下来),这是违法的,很多都有自动报警机制,本篇博客仅用于学习,请勿用于非法用途 安装kaili Linux 进入KALI官网,下载iso镜像文件 vmware新建虚拟机,选择自定义 点击下一步 …

LeetCode2961双模幂运算(相关话题:快速幂)

题目描述 给你一个下标从 0 开始的二维数组 variables &#xff0c;其中 variables[i] [ai, bi, ci, mi]&#xff0c;以及一个整数 target 。 如果满足以下公式&#xff0c;则下标 i 是 好下标&#xff1a; 返回一个由 好下标 组成的数组&#xff0c;顺序不限 。 示例 &…

《面向机器学习的数据标注规程》摘录

说明&#xff1a;本文使用的标准是2019年的团体标准&#xff0c;最新的国家标准已在2023年发布。 3 术语和定义 3.2 标签 label 标识数据的特征、类别和属性等。 3.4 数据标注员 data labeler 对待标注数据进行整理、纠错、标记和批注等操作的工作人员。 【批注】按照定义…

加权准确率WA,未加权平均召回率UAR和未加权UF1

加权准确率WA&#xff0c;未加权平均召回率UAR和未加权UF1 1.加权准确率WA&#xff0c;未加权平均召回率UAR和未加权UF12.参考链接 1.加权准确率WA&#xff0c;未加权平均召回率UAR和未加权UF1 from sklearn.metrics import classification_report from sklearn.metrics impor…

响应者链概述

响应者链 iOS事件的3大类型 Touch Events(触摸事件)Motion Events(运动事件&#xff0c;比如重力感应和摇一摇等)Remote Events(远程事件&#xff0c;比如用耳机上得按键来控制手机) 触摸事件 处理触摸事件的两个步骤 寻找事件的最佳响应者事件的响应在响应链中的传递 寻…

MAC上配置esp32的开发环境

1、安装Thonny. 2、你需要一块ESP32开发板。MicroPython支持ESP32芯片本身&#xff0c;从而可运行于任何一块搭载ESP32 芯片的开发板上。改板子的主要特征在于GPIO针脚是连接外界的&#xff0c;并且它包含了一个内置的 USB串口转换器&#xff0c;该转换器可以使你的电脑通过UAR…

springboot——定时任务、异步任务

springboot——定时任务、异步任务 一、定时任务1、创建一个定时任务、时间配置文件2、springboot主程序开启定时任务 EnableScheduling3、使用 Scheduled 注解 二、定时任务、异步执行。1、springboot主程序开启异步任务 EnableAsync2、方法上增加 Async 注解&#xff0c;标识…