STM32 CAN通讯实验程序

这篇具有很好参考价值的文章主要介绍了STM32 CAN通讯实验程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

STM32 CAN通讯实验

CAN硬件原理图

CAN外设原理图

TJA1050T硬件描述

实验线路图

回环实验

CAN头文件配置

 CAN_GPIO_Config初始化

CAN初始化结构体

CAN筛选器结构体

 接收中断优先级配置

接收中断函数

main文件

实验现象

补充


STM32 CAN通讯实验

CAN硬件原理图

CAN外设原理图

野火STM32F103ZET6霸道板载原理图

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

TJA1050T硬件描述

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

实验线路图

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

回环实验

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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时钟,否则第二功能是无法使用的。

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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);

}

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

由于使用的是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;    

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

 接收中断优先级配置

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,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函数中判断是否接收到数据,从而做相应的应用处理

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

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--);
}

实验现象

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

补充

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

STM32 CAN通讯实验程序,CAN通讯,stm32,单片机,嵌入式硬件,CAN通讯

学完基础的CAN通讯协议之后,如果想要今后从事CAN通讯相关工作,比如工业、汽车领域,我们还需要进一步学习一下CAN OPEN。文章来源地址https://www.toymoban.com/news/detail-614707.html

到了这里,关于STM32 CAN通讯实验程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库,STM32F103

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月07日
    浏览(58)
  • 【单片机】STM32单片机,RTC实时时钟,STM32F103C8T6,程序,万年历,数字时钟

    我以STM32F103C8T6为例,但STM32F103的RTC是通用的,STM32F103C8T6有一个原理图: https://qq742971636.blog.csdn.net/article/details/131288390 用纽扣电池给VBAT供电(要共地),即可实现掉电后依旧走时的能力。 主要特性(来源于STM32中文参考手册V10.pdf): 记得加标准库文件: 串口接收:

    2024年02月11日
    浏览(56)
  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月11日
    浏览(53)
  • CH340进行STM32单片机程序烧录

    目录 代码: 接法: 结束: 刚写完32点灯程序,接下来打算用CH340进行烧录 一个main.c实现点灯,即PA2出低电位 放个仿真图  接下来就是烧录了 用的是CH340进行烧录 CH340usb转ttl CH340 STM32 TXD RXD RXD TXD 3V3 3V3 GND GND 注意这里TXD和RXD是反接的 然后打开flymcu进行配置 port看设备管理器选

    2024年02月05日
    浏览(50)
  • STM32G0+EMW3080+阿里云实现单片机WiFi智能联网功能(一)EMW3080实现和PC之间的串口通讯

    项目描述:该系列记录了STM32G0+EMW3080实现单片机智能联网功能项目的从零开始一步步的实现过程; 硬件环境:单片机为STM32G030C8T6;物联网模块为EMW3080V2-P;网联网模块的开发板为MXKit开发套件,具体型号为XCHIP MXKit-Base V2.2; 软件环境:STM32需要的软件有STM32CubeMX和STM32CubeIDE;

    2024年02月10日
    浏览(68)
  • 基于STM32单片机的密码锁(Proteus仿真、程序)

    由STM32F103单片机最小系统+ 4*4矩阵键盘+LCD1602液晶显示+蜂鸣器+继电器模块 1、采用STM32F103为主控芯片 2、通过4*4矩阵键盘实现密码输入、功能键等排列如下 1     2    3     删除 4     5    6     修改密码 7     8    9     重新输入 返回  0   确认   紧急开锁键 3、每按下一次

    2024年02月07日
    浏览(63)
  • 基于STM32单片机的电子钟(Proteus仿真+程序)

    本设计由STM32单片机+液晶1602+按键+RTC时钟组成。 1、采用STM32F103最小系统板。 2、利用STM32内部自带RTC时钟提供时钟信号 3、液晶1602实时显示年月日、时分秒、星期等信息。 4、三个按键可实现年月日、时分秒的设定。 由于在仿真中运行CPU占用率较高,运行时,时间会变慢许多

    2024年02月12日
    浏览(61)
  • 基于STM32单片机的密码锁(Proteus仿真+程序+报告)

    3-基于STM32单片机的密码锁 功能描述如下:          由STM32F103单片机最小系统+ 4*4矩阵键盘+LCD1602液晶显示+蜂鸣器+继电器模块; 1、采用STM32F103为主控芯片。 2、通过4*4矩阵键盘实现密码输入、功能键等排列如下 1     2    3     删除 4     5    6     修改密码 7   

    2024年02月08日
    浏览(59)
  • 【单片机】STM32单片机读取旋转编码器,TIM定时器编码器模式捕获,程序

    旋转编码器简单来说,就是会输出2个PWM,依据相位可以知道旋转方向,依据脉冲个数可以知道旋转的角度。一般旋转一圈有一个固定数值的脉冲个数。 旋转编码器广泛用于电机、或者角度传感器,STM32的定时器可以直接接入这两个波形获取到信息。 前两个引脚(接地和Vcc)

    2024年02月13日
    浏览(50)
  • C语言-单片机:STM32程序烧录的几种方法

    STM32微控制器提供了多种程序烧录(也称为编程或固件更新)方式,这些方法允许用户将编译后的程序代码(通常为HEX或BIN格式)下载到MCU的闪存中。以下是几种常见的STM32程序烧录方式: ST-LINK : ST-LINK/V2 : 这是最常用的官方开发工具之一,可以直接通过USB接口与PC连接。S

    2024年04月26日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包