历史上的今天
返回首页

历史上的今天

今天是:2026年03月20日(星期五)

正在发生

2023年03月20日 | CAN总线学习笔记 | CAN盒测试STM32的CAN中断接收CAN总线学习笔记 | CAN盒测试STM32的CAN中断接收

2023-03-20 来源:zhihu

CAN基础知识介绍文中介绍了CAN协议相关的基础知识,以及STM32F4芯片的CAN控制器相关知识,下面将通过实例,利用STM32CubeMX图形化配置工具,并配合CAN盒,来实现CAN通讯的中断收发测试


1. STM32CubeMX配置

⏩ CAN是挂载在APB1总线上,设置PCLK1时钟频率到最大45MHz

⏩ 激活CAN1,配置位时序参数,其他基本参数以及工作模式(此处设置为Normal普通模式)

CAN波特率的计算公式:只需要知道BS1和BS2的设置,以及APB1的时钟频率,就可以方便的计算出波特率。比如设置TS1=8、TS2=6和BRP=6,在APB1频率为45Mhz的条件下,即可得到CAN通信的波特率=45000/6/(8+6+1)=500Kbps


⏩ 激活USART1作为调试串口,配置相关LED对应的GPIO引脚作为指示灯


2. MDK-ARM编程

2.1 几个重要的结构体

⏩ CAN 初始化结构体:此结构体内容,可由STM32CubeMX工具进行配置


typedef struct

{

  uint32_t Prescaler;       /* 配置 CAN 外设的时钟分频,可设置为 1-1024*/

  uint32_t Mode;            /* 配置 CAN 的工作模式,回环或正常模式 */

  uint32_t SyncJumpWidth;   /* 配置 SJW 极限值 */

  uint32_t TimeSeg1;        /* 配置 BS1 段长度 */

  uint32_t TimeSeg2;        /* 配置 BS2 段长度 */

  FunctionalState TimeTriggeredMode;    /* 是否使能 TTCM 时间触发功能 */

  FunctionalState AutoBusOff;           /* 是否使能 ABOM 自动离线管理功能 */

  FunctionalState AutoWakeUp;           /* 是否使能 AWUM 自动唤醒功能 */

  FunctionalState AutoRetransmission;   /* 是否使能 NART 自动重传功能 */

  FunctionalState ReceiveFifoLocked;    /* 是否使能 RFLM 锁定 FIFO 功能 */

  FunctionalState TransmitFifoPriority; /* 配置 TXFP 报文优先级的判定方法 */

} CAN_InitTypeDef;

⏩ 发送及接收头结构体:主要用于构造发送报文,以及接收报文。收发发文时,需要自定义头结构体变量


typedef struct

{

  uint32_t StdId;      /* 存储报文的标准标识符 11 位,0-0x7FF */

  uint32_t ExtId;      /* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF */

  uint32_t IDE;        /* 存储 IDE 扩展标志 */

  uint32_t RTR;        /* 存储 RTR 远程帧标志 */

  uint32_t DLC;        /* 存储报文数据段的长度,0-8 */

  FunctionalState TransmitGlobalTime; 

} CAN_TxHeaderTypeDef;


typedef struct

{

  uint32_t StdId;      /* 存储报文的标准标识符 11 位,0-0x7FF. */

  uint32_t ExtId;      /* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF */

  uint32_t IDE;        /* 存储 IDE 扩展标志 */

  uint32_t RTR;        /* 存储 RTR 远程帧标志 */

  uint32_t DLC;        /* 存储报文数据段的长度,0-8 */

  uint32_t Timestamp; 

  uint32_t FilterMatchIndex; 

} CAN_RxHeaderTypeDef;

⏩ 过滤器结构体:STM32CubeMX不会初始化过滤器的相关内容,需要自己添加


typedef struct

{

  uint32_t FilterIdHigh;         /*CAN_FxR1 寄存器的高 16 位 */

  uint32_t FilterIdLow;          /*CAN_FxR1 寄存器的低 16 位 */

  uint32_t FilterMaskIdHigh;     /*CAN_FxR2 寄存器的高 16 位 */

  uint32_t FilterMaskIdLow;      /*CAN_FxR2 寄存器的低 16 位 */

  uint32_t FilterFIFOAssignment; /* 设置经过筛选后数据存储到哪个接收 FIFO */

  uint32_t FilterBank;           /* 筛选器编号,范围0-27,CAN1是0-13,CAN2是14-27 */

  uint32_t FilterMode;           /* 筛选器模式 */

  uint32_t FilterScale;          /* 设置筛选器的尺度 */

  uint32_t FilterActivation;     /* 是否使能本筛选器 */

  uint32_t SlaveStartFilterBank; /* CAN2起始过滤器组 */

} CAN_FilterTypeDef;

2.2 程序编写

⏩ 生成工程后,打开can.c文件,可见STM32CubeMX已经对位时序参数、其他基本参数以及工作模式进行了初始化。但是并没有初始化过滤器的相关内容,因此需要我们自己添加,并在CAN初始化时调用


//下面的设置只使能了FIFO0,并不过滤任何消息

void CAN_Filter_Config(){

  CAN_FilterTypeDef sFilterConfig;

 

  sFilterConfig.FilterBank = 0;      //筛选器编号, CAN1是0-13, CAN2是14-27

  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //采用掩码模式

  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //设置筛选器的尺度, 采用32位

  sFilterConfig.FilterIdHigh = 0X0000;    //过滤器ID高16位,即CAN_FxR1寄存器的高16位

  sFilterConfig.FilterIdLow = 0X0000;     //过滤器ID低16位,即CAN_FxR1寄存器的低16位

  sFilterConfig.FilterMaskIdHigh = 0X0000;   //过滤器掩码高16位,即CAN_FxR2寄存器的高16位

  sFilterConfig.FilterMaskIdLow = 0X0000;    //过滤器掩码低16位,即CAN_FxR2寄存器的低16位

  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; //设置经过筛选后数据存储到哪个接收FIFO

  sFilterConfig.FilterActivation = ENABLE;   //是否使能本筛选器

  sFilterConfig.SlaveStartFilterBank = 14;   //指定为CAN1分配多少个滤波器组

 

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)

  {

    Error_Handler();

  }

}

⏩ 编写发送和接收数据函数:此处将格式固定为标准数据帧,ID为12


uint8_t CAN1_Send_Msg(uint8_t *msg, uint8_t len){

  uint16_t i = 0;

  uint32_t txMailBox;

  uint8_t send_buf[8];

 

  txHeader.StdId = 12;

  txHeader.ExtId = 12;

  txHeader.IDE = CAN_ID_STD;

  txHeader.RTR = CAN_RTR_DATA;

  txHeader.DLC = len;

 

  for(i = 0; i < len; i++)

    send_buf[i] = msg[i];

 

  if(HAL_CAN_AddTxMessage(&hcan1, &txHeader, send_buf, &txMailBox) != HAL_OK)

    return 1; 

  return 0;

}


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){

  uint16_t i = 0;

  uint8_t buf[8] = {0};

 

  if(hcan->Instance == CAN1){

    printf("*******************************rn");

    printf("Recv via STM32F429 Interruptrn");

 

    HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rxHeader, buf);

 

    if(rxHeader.IDE == CAN_ID_STD)

      printf("StdId ID: %dn", rxHeader.StdId);

    else

      printf("ExtId ID: %dn", rxHeader.ExtId);

    printf("rn");

    printf("CAN IDE: %dn", rxHeader.IDE);printf("rn");

    printf("CAN RTR: %dn", rxHeader.RTR);printf("rn");

    printf("CAN DLC: %dn", rxHeader.DLC);printf("rn");

    printf("Recv Data: ");

 

    for(i = 0; i < rxHeader.DLC; i++)

      printf("%c ",buf[i]);

 

    printf("rn");

    printf("*******************************rn");

  }

}

⏩ 默认Cubemx生成的代码并没有can start,没有调用HAL_CAN_Start(&hcan1) 来使能CAN,因此需要在CAN初始化代码中添加


void MX_CAN1_Init(void){

  ......

  /* USER CODE BEGIN CAN1_Init 2 */

  CAN_Filter_Config();

  HAL_CAN_Start(&hcan1); 

  HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);

  /* USER CODE END CAN1_Init 2 */

}

⏩ 主函数main.c中,代码如下


int main(void){

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  MX_CAN1_Init();

  MX_USART1_UART_Init();

   /* USER CODE BEGIN 2 */

  uint8_t ret;

  printf("CAN Testing....!rn");

  uint8_t txdata[8] = {78, 79, 82, 77, 65, 76, 33, 32};

  /* USER CODE END 2 */

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);

    printf("Start Send data...rn");

  

    ret = CAN1_Send_Msg(txdata, 8);

    if(ret == 0)

      printf("STM32F429 CAN Send success!rn");

    else 

      printf("STM32F429 CAN Send failed!rn");

  

    HAL_Delay(3000);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}


3. 下载测试

将CAN盒与STM32的CAN接口连接起来,CAN盒连接电脑,使用CAN调试软件接收和发送数据,如下图示

STM32工程编译无误后,下载到开发板,可以看到系统运行时D1指示灯不断闪烁,串口不断的打印STM32发送CAN消息成功的信息。使用CAN调试软件,可以看到CAN盒接收到了STM32发出的数据。使用调试软件,发送CAN数据给STM32

串口调试助手中可以看到,STM32通过中断接收到了CAN盒发来的数据

推荐阅读

史海拾趣

Greatbatch-Sierra Inc公司的发展小趣事

机顶盒,全称为数字视频变换盒,是连接电视机与外部信号源的重要设备,其专业性与科普性并重。从广义上讲,机顶盒泛指一切与电视机连接的网络终端设备,能够接收并转换多种信号源,包括有线电缆、卫星天线、宽带网络及地面广播等,为观众提供丰富多样的视听体验。

在数字电视时代,机顶盒扮演了至关重要的角色。它不仅能够接收并解码高清乃至4K超高清的数字电视信号,将其转换为电视机可识别的视频和音频流,还具备网络交互功能,使用户能够享受在线购物、观看网络视频、玩游戏等多元化服务。此外,机顶盒还提供了电子节目指南、因特网网页浏览等增值服务,极大地丰富了用户的娱乐生活。

从技术分类上看,机顶盒可分为多种类型,如DVB-S(数字卫星机顶盒)、DVB-T(数字地面机顶盒)、DVB-C(有线电视数字机顶盒)以及IPTV机顶盒等。每种类型在信号接收和解码方面各有特点,但共同之处在于它们都是连接电视机与外部世界的桥梁,为用户带来更加便捷、丰富的视听享受。

随着智能电视的快速发展,机顶盒的形态也在不断变化。一些智能电视已经内置了机顶盒的功能,实现了电视机与机顶盒的一体化。然而,机顶盒作为独立的设备,在灵活性、扩展性等方面仍具有独特的优势,将继续在数字电视领域发挥重要作用。

安谱隆(Ampleon)公司的发展小趣事

在安谱隆的发展历程中,资本市场对其一直保持着高度的关注。然而,其“安家”之路却并不平坦。2017年,奥瑞德曾有意收购安谱隆,但由于资金问题,这桩收购最终未能成行。2018年,旋极信息也计划收购安谱隆,但同样未能成功。这些波折反映了资本市场对安谱隆价值的认可,但也暴露出安谱隆在寻找合适买家方面所面临的挑战。

Electronic公司的发展小趣事

小米,作为一家年轻的科技公司,在电子行业的发展中展现了惊人的成长速度。小米凭借出色的产品设计和创新的营销策略,迅速在手机市场获得了巨大成功。随着业务的不断拓展,小米还涉足了智能家居、物联网和互联网金融等领域,形成了完整的生态布局。小米通过提供高性价比的产品和优质的服务,赢得了大量年轻用户的喜爱和支持。

福斯特(FIRST)公司的发展小趣事
确保信号在传输过程中不受噪声和干扰的影响。例如,轮速传感器的接口电路设计可能包括两级滤波和整形电路。
Defense Logistics Agency公司的发展小趣事

面对日益复杂的军事需求和快速发展的技术环境,DLA积极推进技术创新和数字化转型。通过引入云计算、大数据、人工智能等先进技术,DLA实现了对全球供应链的实时监控和智能调度,大大提高了后勤保障的效率和准确性。同时,DLA还加强了对新型军事装备的研发和保障能力,确保美军在现代化战争中保持领先地位。

AUK Contractors Co Ltd公司的发展小趣事

AUK Contractors Co Ltd深知人才是企业发展的核心。因此,公司一直注重人才培养和团队建设。通过定期的培训、交流以及激励机制,公司吸引并留住了一批批优秀的电子工程师和技术人才。这些人才为公司的发展提供了源源不断的动力。

问答坊 | AI 解惑

LED灯具致命缺陷问题-浪涌电压

本帖最后由 jameswangsynnex 于 2015-3-3 19:56 编辑 现象描述:最常见的问题,就是做一个工程,几百台灯,经常会无缘无故的损坏,常见的就象一条街上装的LED路灯,时不时不亮,经常坏,修了又坏,坏了再修.还有LED日光灯,很多用非隔离电源,量产时经常发现 ...…

查看全部问答>

紧急求助:代码有个错误 与语音识别的方案

在做一个毕业设计,遇到几个问题,请高手帮助,谢谢! 1、目前的程序主要是用SPCE061实现下语音播放,不论怎么修改都一直有个错误: Error L0080: The external symbol \"T_SACM_S480_SpeechTable\" has not a public definition. 请高手帮忙啊 ...…

查看全部问答>

招聘WinCE嵌入式工程师,PCB硬件工程师

招聘WinCE嵌入式工程师 职位:WinCE嵌入式工程师 岗位要求:   1、本科及以上,电子,通讯,计算机相关专业;   2、1年以上工作经验;   3、熟悉ARM体系或MIPS体系;   4、熟悉wince等操作系统  ...…

查看全部问答>

关于arm jflash的问题

1、jflash是什么?给个定义说明; 2、jflash有什么作用?能详细介绍吗? 3、jflash主要跟那些硬件有关?有什么样的关系? 谢谢…

查看全部问答>

FPGA芯片RAM分割问题(在线等)

小弟在用xilinx 的XC3S400芯片做LDPC,需要很多个小块RAM(30个字节左右)用来存储数据。而XC3S400利用IP核最多只能生成16个block RAM(与大小无关),而我又不能用Distributed RAM,因为需要的小块RAM很多,会占用很多逻辑资源。      ...…

查看全部问答>

求助高手

                                 小弟用到st72f561做毕业设计,是关于can总线的汽车车门控制系统。那位高手可以指点一下。我的qq278387881…

查看全部问答>

请教版主,STM32运行途中,可不可以修改PLL?

版主: 你好! 请教STM32运行路途,可不可以修改PLL?  比方开机时主频先设置为72MHz,然后再修改成36MHz?…

查看全部问答>

2007年国赛高频方向题目解析——无识别线装置

本帖最后由 paulhyde 于 2014-9-15 03:33 编辑 终于把07年高频题目解析完成了,从上一篇写完就开始写这篇了, 最近两个月项目比较紧,所以每天往前只能推进一点点。 基本都是抽午饭后的时间写的,语言方面没有刻意的组织,写的很随便,请大家见 ...…

查看全部问答>

关于ADXL345在硬件设计的问题

请教大家一个问题,ADXL345在硬件设计和PCB画图时,需要注意哪些问题? \0\0\0eeworldpostqq…

查看全部问答>