STM32 CAN通讯实验程序

news2024/11/17 3:27:21

目录

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;//调试时建议使用回环模式,调试完再改成NORMAL
    CAN_InitTypeStruct.CAN_NART = ENABLE; //错误重传
    CAN_InitTypeStruct.CAN_RFLM = ENABLE;
    CAN_InitTypeStruct.CAN_TTCM = DISABLE;
    CAN_InitTypeStruct.CAN_TXFP = DISABLE; //按ID优先级发送
    
    //配置成1Mbps
    CAN_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.coloradmin.cn/o/800452.html

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

相关文章

JavaScript的函数中this的指向

JavaScript的函数中this的指向 JavaScript 语言之所以有 this 的设计&#xff0c;跟内存里面的数据结构有关系。 以下例子来简单描述this在不同情况下所指向的对象。 var obj {aa: function(){console.log(this.num)},num: 5 };var aa obj.aa; var num 10;obj.aa(); // …

简要介绍 | 走向自然的身份认证:步态识别技术简介

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对步态识别进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 走向自然的身份认证&#xff1a;步态识别技术简介 Gait Recognition Based on Deep Learning: A Survey | ACM Computing Surveys 背景…

一文谈谈Git

"And if forever lasts till now Alright" 为什么要有git&#xff1f; 想象一下&#xff0c;现如今你的老师同时叫你和张三&#xff0c;各自写一份下半年的学习计划交给他。 可是你的老师是一个极其"较真"的人&#xff0c;发现你俩写的学习计划太"水&…

【弹力设计篇】聊聊异步通讯设计

为什么需要异步设计 刚开始参加工作&#xff0c;发现有一些API设计中回落数据之后&#xff0c;然后将数据写入到消息队列中&#xff0c;当时很是不理解为什么要这么做&#xff0c;直到后边系统学习消息队列之后才发现原来这其实就是异步处理&#xff0c;当流量很多的时候&…

一张表中几列字段以不同的条件规则去统计计数展示实现思路设计

今天在写一个业务的时候&#xff0c;遇到这样一个需求 一、需求描述 一张表中其中几列字段需要以不同的条件规则去统计计数&#xff0c;求实现方式 因为项目业务涉及隐私&#xff0c;我就想了一个类似的情景 二、情景描述 有一张月考成绩表&#xff0c;包含学生和他的各科…

区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归多输入单输出区间预测

区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归多输入单输出区间预测 目录 区间预测 | MATLAB实现QRBiGRU双向门控循环单元分位数回归多输入单输出区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 MATLAB实现QRBiGRU双向门控循环单元分位数回归…

EXCEL,如何比较2个表里的数据差异(使用数据透视表)

目录 1 问题: 需要比较如下2个表的内容差异 1.1 原始数据喝问题 1.2 提前总结 2 使用EXCEL公式方法 2.1 新增辅助列&#xff1a; 辅助index 2.2 具体公式 配合条件格式 使用 3 数据透视表方法 3.1 新增辅助列&#xff1a; 辅助index 3.2 需要先打开 数据透视表向导 …

基于CNN卷积神经网络的调制信号识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 1. 卷积神经网络&#xff08;CNN&#xff09; 2. 调制信号识别 3.实现过程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心程序 % 构建调制类型…

支付宝短视频平台创作分成激励项目

没想到支付宝也开通了中视频计划&#xff0c;这波羊毛算是蒿定了&#xff0c;最近啊&#xff0c;马爸爸火速上线了支付宝创作分成计划&#xff0c;明显就是抄的抖音中视频计划&#xff0c;目前还在内测阶段&#xff0c;补贴的力度非常大&#xff0c;错过的话就只能拍大腿了&…

Prometheus 的应用服务发现及黑河部署等

目录 promtool检查语法 部署Prometheus Server 检查语法是否规范 部署node-exporter 部署Consul 直接请求API进行服务注册 使用register命令注册服务&#xff08;建议使用&#xff09; 单个和多个注册&#xff0c;多个后面多加了s 在Prometheus上做consul的服务发现 部署…

windows安装linux

https://www.cnblogs.com/liuqingzheng/p/16271895.html 咱们安装linux系统是centos7 准备工作&#xff1a; 安装软件&#xff1a;vmware -------虚拟机 官网下载地址&#xff1a;下载 VMware Workstation Pro | CN 也可以从这里面下载 链接&#xff1a;https://pan.bai…

MySQL优化(面试)

文章目录 通信优化查询缓存语法解析及查询优化器查询优化器的策略 性能优化建议数据类型优化索引优化 优化关联查询优化limit分页对于varchar end mysql查询过程: 客户端向MySQL服务器发送一条查询请求服务器首先检查查询缓存&#xff0c;如果命中缓存&#xff0c;则立刻返回存…

行车遥控接线图

这个一般只有电工才会用。 主要是 【共线和总电】让人疑惑。 这图实际就是PLC的梯形图。 共电&#xff1a;接主电源。【它串联10A保险丝&#xff0c;再到继电器】 总电&#xff1a;它是所有继电器的公共端。【共电的继电器吸合&#xff0c;共电和总电就直通了。】共电的继电器…

Io进、线程——进程的基础

进程的基础 进程是计算机中最基本的执行单位&#xff0c;是程序在操作系统中的一次执行过程。每个进程都有自己的地址空间、数据栈、程序计数器等&#xff0c;相互之间独立运行&#xff0c;互不干扰。进程间的通信通过特定的机制来实现&#xff0c;进程的创建和撤销由操作系统…

详解Mybatis之动态sql问题

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 Mybatis版本&#xff1a;3.5.6 文章目录 一. 在sql映射文件中如何写注释&#xff1f;二. 什么是动态sql&#xff1f;三. 动态sql常用标签有…

Vue项目如何生成树形目录结构

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、有兴趣的可以关注一手。 前言 项目的目录结构清晰、可以帮助我们更快理顺项目的整体构成。在写文档之类的时候也比较方便。生成树形目录的方式有多种&#xff0c;我这里简单介绍其中一种较为简单的实现 过…

CSP 2021入门级 第一轮 题目讲解

A: a进栈&#xff0c;直接出栈&#xff1b;b进栈&#xff0c;直接出栈&#xff1b;c进栈&#xff0c;直接出栈&#xff1b;d进栈&#xff0c;直接出栈&#xff1b;e进栈&#xff0c;直接出栈。 B&#xff1a;全进栈后全出栈。 C&#xff1a;a和b先进栈&#xff0c;然后直接出…

【雕爷学编程】MicroPython动手做(09)——零基础学MaixPy之人脸识别2

自己打包kfpkg&#xff0c;试着整了好几次&#xff0c;都是无法烧录&#xff0c;只好不做第七步了&#xff0c;直接把前面获得的人脸识别模型烧录了 烧录完成后&#xff0c;打开IDE串口&#xff0c;确认开发板Maixpy固件的版本&#xff0c;好像是前期的稳定版本V0.4.0 第九步&a…

idea中创建请求基本操作

文章目录 说明效果创建GET请求没有参数带有参数带有环境变量带有动态参数 说明 首先通过###三个井号键来分开每个请求体&#xff0c;然后请求url和header参数是紧紧挨着的&#xff0c;请求参数不管是POST的body传参还是GET的parameter传参&#xff0c;都是要换行的&#xff0c;…

Java版本spring cloud + spring boot 电子招标采购系统源码

营造全面规范安全的电子招投标环境&#xff0c;促进招投标市场健康可持续发展 传统采购模式面临的挑战 一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标…