STM32 CAN通讯实验程序

目录

STM32 CAN通讯实验

CAN硬件原理图

CAN外设原理图

TJA1050T硬件描述

实验线路图

回环实验

CAN头文件配置

 CAN_GPIO_Config初始化

CAN初始化结构体

CAN筛选器结构体

 接收中断优先级配置

接收中断函数

main文件

实验现象

补充


STM32 CAN通讯实验

CAN硬件原理图

CAN外设原理图

野火STM32F103ZET6霸道板载原理图

我们的开发板没有使用GPIO外设的复用功能PA11和PA12,而使用了重定义(重映射)功能PB8和PB9

TJA1050T硬件描述

实验线路图

图中为两个霸道开发板,如果使用指南针开发板需要外接CAN收发器和电阻。

        是否使用RX和TX引脚是根据实际情况来确认是否使用的。如果我们使用回环模式时,在STM32芯片内部的CAN控制器的发送端和接收端就已经通过硬件逻辑连接起来了,比如回环静默模式,根本不用使用STM32的发送和接收引脚。甚至使用回环测试的时候,CAN收发器就算不供电都可以工作。

回环实验

我们配置外设的GPIO功能时,可以参考手册的外设GPIO功能配置

CAN头文件配置

#ifndef __BSP_CAN_H
#define __BSP_CAN_H#include "stm32f10x.h"#define PASS_ID   ((uint32_t)0x1314)#define CAN_TX_GPIO_PROT          GPIOB
#define CAN_TX_GPIO_PIN           GPIO_Pin_9#define  CAN_RX_GPIO_PORT     GPIOB
#define  CAN_RX_GPIO_PIN      GPIO_Pin_8#define CAN_GPIO_CLK                    RCC_APB2Periph_GPIOB/*信息输出*/
#define CAN_DEBUG_ON         1#define CAN_INFO(fmt,arg...)           printf("<<-CAN-INFO->> "fmt"\n",##arg)
#define CAN_ERROR(fmt,arg...)          printf("<<-CAN-ERROR->> "fmt"\n",##arg)
#define CAN_DEBUG(fmt,arg...)          do{\if(CAN_DEBUG_ON)\printf("<<-CAN-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);void CAN_Config(void)    ;     #endif /* __BSP_CAN_H */

 CAN_GPIO_Config初始化

void CAN_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* 使能CAN时钟 */RCC_APB1PeriphClockCmd (RCC_APB1Periph_CAN1 , ENABLE );/* 使能CAN引脚相关的时钟 */RCC_APB2PeriphClockCmd ( CAN_GPIO_CLK|RCC_APB2Periph_AFIO, ENABLE );//使用PA8 9引脚的第二功能GPIO_PinRemapConfig (GPIO_Remap1_CAN1 ,ENABLE);/* 配置CAN的 引脚,普通IO即可 */GPIO_InitStructure.GPIO_Pin = CAN_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(CAN_TX_GPIO_PROT, &GPIO_InitStructure);/* 配置CAN的 引脚,普通IO即可 */GPIO_InitStructure.GPIO_Pin = CAN_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);}

PB8和PB9使用重映射功能

我们要使用GPIO_PinRemapConfig函数来使能PA8 9引脚的第二功能,此外一定要记得开启相应的AFIO时钟,否则第二功能是无法使用的。

CAN初始化结构体

void CAN_Mode_Config(void)    
{CAN_InitTypeDef CAN_InitTypeStruct;CAN_InitTypeStruct.CAN_ABOM = ENABLE;CAN_InitTypeStruct.CAN_AWUM = ENABLE;CAN_InitTypeStruct.CAN_Mode = CAN_Mode_LoopBack;//CAN_Mode_Normal;//调试时建议使用回环模式,调试完再改成NORMALCAN_InitTypeStruct.CAN_NART = ENABLE; //错误重传CAN_InitTypeStruct.CAN_RFLM = ENABLE;CAN_InitTypeStruct.CAN_TTCM = DISABLE;CAN_InitTypeStruct.CAN_TXFP = DISABLE; //按ID优先级发送//配置成1MbpsCAN_InitTypeStruct.CAN_BS1 = CAN_BS1_5tq;CAN_InitTypeStruct.CAN_BS2 = CAN_BS2_3tq;CAN_InitTypeStruct.CAN_SJW = CAN_SJW_2tq;CAN_InitTypeStruct.CAN_Prescaler = 4;CAN_Init(CAN1,&CAN_InitTypeStruct);}

其中位时序及波特率按照下表配置

CAN筛选器结构体

void CAN_Filter_Config(void)
{CAN_FilterInitTypeDef CAN_FilterInitTypeStruct;CAN_FilterInitTypeStruct.CAN_FilterActivation = ENABLE;CAN_FilterInitTypeStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0  ;CAN_FilterInitTypeStruct.CAN_FilterNumber = 0;CAN_FilterInitTypeStruct.CAN_FilterScale = CAN_FilterScale_32bit;CAN_FilterInitTypeStruct.CAN_FilterMode = CAN_FilterMode_IdMask  ;CAN_FilterInitTypeStruct.CAN_FilterIdHigh = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF0000)>>16;CAN_FilterInitTypeStruct.CAN_FilterIdLow = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF);CAN_FilterInitTypeStruct.CAN_FilterMaskIdHigh = 0xFFFF;CAN_FilterInitTypeStruct.CAN_FilterMaskIdLow =0xFFFF;    CAN_FilterInit(&CAN_FilterInitTypeStruct);CAN_ITConfig (CAN1,CAN_IT_FMP0,ENABLE);}    

其中假如我们要过滤的ID为0x1314

使用stm32f10x_can.h文件末尾定义的相关宏

由于使用的是32位筛选器且标识符掩码,所以其中CAN_FilterIdHigh和CAN_FilterIdLow为我们过滤ID格式的高16位和低16位,首先将ID号左移三位,然后或上IDE、RTR位

CAN_FilterInitTypeStruct.CAN_FilterIdHigh = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF0000)>>16;
CAN_FilterInitTypeStruct.CAN_FilterIdLow = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF);

而CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow为要过滤的ID掩码,全为1,表示完全过滤

CAN_FilterInitTypeStruct.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitTypeStruct.CAN_FilterMaskIdLow =0xFFFF;    

 接收中断优先级配置

void CAN_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 配置NVIC为优先级组1 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;/* 配置抢占优先级 */NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 配置子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断通道 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}

在标准库头文件中找到CAN接收数据中断源,我们使用的是接收邮箱0,所以选择USB_LP_CAN1_RX0_IRQn

使能中断放在CAN筛选器结构体配置中

接收中断函数

extern CanRxMsg  CAN_Rece_Data;
extern uint8_t flag;void USB_LP_CAN1_RX0_IRQHandler(void)    
{CAN_Receive(CAN1,CAN_FIFO0, &CAN_Rece_Data); flag = 1;}

要注意的是在CAN里,我们设置完CAN_Receive(CAN1,CAN_FIFO0, &CAN_Rece_Data);之后不需要手动清除接收标志,该函数会自动清除。

flag用于在main函数中判断是否接收到数据,从而做相应的应用处理

我们也可以再加个判断进一步确认接收数据的准确性

main文件

#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./led/bsp_led.h"
#include "./can/bsp_can.h"
#include "./key/bsp_key.h"  CanRxMsg  CAN_Rece_Data;
CanTxMsg  CAN_Tran_Data;uint8_t flag = 0;void Delay(__IO uint32_t nCount); /** 函数名:main* 描述  :主函数* 输入  :无* 输出  :无*/
int main(void)
{     LED_GPIO_Config();LED_BLUE;/* 配置串口为:115200 8-N-1 */USART_Config();printf("\r\n 这是一个CAN通讯实验 \r\n");CAN_Config()    ;   Key_GPIO_Config();printf("\r\n 按KEY1按键发送数据\r\n");while(1){if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  ){uint8_t box;CAN_Tran_Data.StdId = 0;CAN_Tran_Data.ExtId = PASS_ID;CAN_Tran_Data.RTR = CAN_RTR_Data;//使用数据帧CAN_Tran_Data.IDE = CAN_Id_Extended ; //使用扩展帧CAN_Tran_Data.DLC = 1;CAN_Tran_Data.Data[0] = 10;box = CAN_Transmit(CAN1,&CAN_Tran_Data);while(CAN_TransmitStatus(CAN1,box) == CAN_TxStatus_Failed);printf("\r\n 数据包发送完成\r\n");            }         if(flag == 1){printf("\r\n接收到的数据:%d\r\n",CAN_Rece_Data.Data[0]);flag = 0;}else{}}
}void Delay(__IO uint32_t nCount)
{for(; nCount != 0; nCount--);
}

实验现象

补充

由于只有一个板子,无法演示双机实验,双机实验只需要将我们的回环实验中的回环模式换成正常模式,然后将程序分别下载到两个开发板即可。

学完基础的CAN通讯协议之后,如果想要今后从事CAN通讯相关工作,比如工业、汽车领域,我们还需要进一步学习一下CAN OPEN。

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

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

相关文章

【RabbitMQ】之高可用集群搭建

目录 一、RabbitMQ 集群原理 1、默认集群原理2、镜像集群原理3、负载均衡方案 二、RabbitMQ 高可用集群搭建 1、RabbitMQ 集群搭建2、配置镜像队列3、HAProxy 环境搭建4、Keepalived 环境搭建 一、RabbitMQ 集群简介 1、默认集群原理 3-1、RabbitMQ 集群简介 单台 RabbitM…

vue项目中对组件使用v-model绑定值,在vue3中如何更新数据

在el-form 中 el-form-item 绑定组件进行校验 想在表单下面爆红提示 可以对组件使用v-model绑定值 vue2 通过this.$emit(‘input’,value) 更新 v-model值 vue3 通过this.$emit(‘update:modelValue’ ,value) 更新 v-model值

腾讯云CVM内存型服务器MA3、M6、M6ce和M5处理器CPU说明

腾讯云内存型CVM服务器CPU处理器大全&#xff0c;CVM内存型MA3、内存型M6、安全增强内存型M6ce、内存型M6p、内存型M5、MA2、M4、M3、M2、M1处理器主频、CPU性能性能大全说明&#xff0c;腾讯云内存型云服务器具有大内存的特点&#xff0c;适合高性能数据库、分布式内存缓存等需…

Settings系列(三)根据需求动态添加删除一级菜单、二级菜单的设置项

一 、背景 当时遇到定制需求,需要根据实际需要隐藏Settings的菜单项,于是开始了寻找方法 二 、准备工作 在看了一下源码,经过尝试后,确认生效后,就简单说明一下Settings中布局中主要组成元素 Settings中的菜单项是由 PreferenceScreen 和Preference组成的。其中Prefer…

Day7 C++ 指针

目录 什么是指针 指针变量的定义 指针变量定义语法 注意 指针所占内存空间 空指针 野指针 函数指针 声明函数指针 初始化函数指针 使用函数指针调用函数 指针的使用 const修饰指针 const修饰指针 --- 指针常量&#xff08;constant pointer&#xff09; const修…

libuv库学习笔记-advanced-event-loops

Advanced event loops libuv提供了非常多的控制event-loop的方法&#xff0c;你能通过使用多loop来实现很多有趣的功能。你还可以将libuv的event loop嵌入到其它基于event-loop的库中。比如&#xff0c;想象着一个基于Qt的UI&#xff0c;然后Qt的event-loop是由libuv驱动的&am…

会议OA项目之会议发布(一)

目录 前言&#xff1a; 会议发布的产品原型图&#xff1a; 1.会议发布 1.1实现的特色功能&#xff1a; 1.2思路&#xff1a; 使用的数据库&#xff1a; 我们要实现多功能下拉框的形式选择可以参考原文档&#xff1a;https://hnzzmsf.github.io/example/example_v4.html#down…

Michael.W基于Foundry精读Openzeppelin第14期——SafeMath.sol

Michael.W基于Foundry精读Openzeppelin第14期——SafeMath.sol 0. 版本0.1 SafeMath.sol 1. 目标合约2. 代码精读2.1 tryAdd(uint256 a, uint256 b) && trySub(uint256 a, uint256 b) && tryMul(uint256 a, uint256 b) && tryDiv(uint256 a, uint256 b…

php的设计模式有哪些

1&#xff0c;创建设计模式&#xff08;Creational Patterns&#xff09;(5种)&#xff1a; 用于创建对象时的设计模式。更具体一点&#xff0c;初始化对象流程的设计模式。当程序日益复杂时&#xff0c;需要更加灵活地创建对象&#xff0c;同时减少创建时的依赖。而创建设计模…

LlaMA2微调实战

LLaMA2-SFT LLaMA2-SFT, Llama-2-7B微调(transformers)/LORA(peft)/推理 Gtihub地址 https://github.com/yongzhuo/Llama2-SFT prompt text_1 f"".join(["[INST] <<SYS>>\n ""You are a helpful, respectful and honest assista…

数组专题攻破新学习笔记

数组专题攻破新学习笔记 1.移除有序数组中的重复项和移除元素2.二分查找需注意3.在排序数组中查找元素的第一个和最后一个位置4.最长回文串5.区域和检索-数组不可变 1.移除有序数组中的重复项和移除元素 思想一样但是细节不一样 思想一样就是 设置快慢指针&#xff0c;快指针…

ubuntu远程控制小车 运行rviz时报错

我买的是wheeltec的小车&#xff0c;测试rgbd相机时想在ubuntu上的rviz中显示小车的姿态和看到的rgb和depth图&#xff0c;但是ubuntu中rostopic list和rviz都找不到小车发布的话题信息&#xff0c;运行rqt_image_view时可以显示图片信息。 最终wheeltec的技术人员lucas帮我找了…

nodejs+vue+elementui汽车销售网站

前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进行交互&#xff0c;从而使得用户在点击网页进行操作时能够正常。 可以设置中间件来响应 HTTP 请求。 Express …

游戏小记-全屏与无边框

“LoL” 是指英雄联盟&#xff08;League of Legends&#xff09;&#xff0c;一款非常流行的多人在线战术游戏。在游戏设置中&#xff0c;“全屏” 和 “无边框” 是两种不同的窗口模式&#xff0c;它们有以下区别&#xff1a; 全屏模式&#xff1a; 在全屏模式下&#xff0c;…

Kafka 入门到起飞 - Kafka怎么做到保障消息不会重复消费的? 消费者组是什么?

Kafka怎么做到避免消息重复消费的&#xff1f; 消费者组是什么&#xff1f; 消费者&#xff1a; 1、订阅Topic&#xff08;主题&#xff09; 2、从订阅的Topic消费&#xff08;pull&#xff09;消息&#xff0c; 3、将消费消息的offset&#xff08;偏移量&#xff09;保存在K…

西安电子科技大学

前言 本篇文章投稿与以下活动 【西安城市开发者社区】探索西安高校&#xff1a;展现历史与创新的魅力 资料参考与百度百科 学校简介 西安电子科技大学&#xff08;Xidian University&#xff09;&#xff0c;简称“西电”&#xff0c;位于陕西省西安市&#xff0c;是中央部…

浅析C++临时变量

在C/C中&#xff0c;临时变量&#xff08;也称为临时对象&#xff09;具有常量性质&#xff0c;是由编译器自动创建的&#xff0c;并在表达式求值期间临时存在。它们主要用于存储中间结果&#xff0c;使表达式的求值过程更加高效和简洁。临时变量的生命周期仅限于表达式的求值过…

14.Netty源码之模拟简单的HTTP服务器

highlight: arduino-light 简单的 HTTP 服务器 HTTP 服务器是我们平时最常用的工具之一。同传统 Web 容器 Tomcat、Jetty 一样&#xff0c;Netty 也可以方便地开发一个 HTTP 服务器。我从一个简单的 HTTP 服务器开始&#xff0c;通过程序示例为你展现 Netty 程序如何配置启动&a…

2023年全国程序员薪酬排行天梯榜

文章目录 ⭐️ 2023年全国程序员薪酬排行天梯榜 在过去很长的一段时间内&#xff0c;网上总有一个声音&#xff1a;“大厂裁员”、“程序员内卷严重”、“程序员人员过盛”、“35岁中年危机”、“码农吃的青春饭”、“互联网寒冬” 等等等等。 讲道理&#xff0c;我对这种人为的…

【通过改变压缩视频的分辨率实现高效的视频语义分割】CVPR2022论文精度

Efficient Semantic Segmentation by Altering Resolutions for Compressed Videos Efficient Semantic Segmentation by Altering Resolutions for Compressed VideosBasic Information:论文简要 :背景信息:a. 理论背景:b. 技术路线: 结果:a. 详细的实验设置:b. 详细的实验结果…