硬汉嵌入式论坛

 找回密码
 立即注册
查看: 10308|回复: 9
收起左侧

[CAN/FDCAN] STM32H7 CAN1 CAN2 同时使用教程

  [复制链接]

10

主题

19

回帖

49

积分

初级会员

积分
49
发表于 2020-1-9 20:16:26 | 显示全部楼层 |阅读模式
STM32H7是一款相对来说比较新的MCU,很多例程上面都是只给了一个can口的例子,对于两个can口同时使用没有明确的说明。本文主要针对同时使用CAN1 CAN2 做一个教学。

1.对于CAN口配置分为以下几点:

    1.波特率配置,不细说,按照官方例程配置。

    2.CANRAM配置

消息RAM的宽度为32位,总共大小10k,一个宽度为1个字,总共32个字。

其中主要分为4部分,

1。滤波器配置

2.输入数据缓冲区配置

3.输出数据缓冲区配置

4.can配置的起始地址的配置。

针对于234做一个主要的讲解。

2.3都类似,配置一个缓冲区 每个元素的长度len和所有元素的个数num,则该缓冲区的长度为  len * num

4.非常重要,CANRAM的起始地址配置。举个例子,比如上述的参数占用的RAM字节数为800字节,这块配置为CAN1的配置,RAM的起始地址为0x0400AC00,

那么结束地址就要加800字节。那么如果要配置CAN2,CAN2参数MessageRAMOffset就必须至少从800开始计算起。CAN1的MessageRAMOffset为0。这样的话CAN1和CAN2才可以同时使用。记住:CAN1和CAN2的RAM配置并不是并行配置的,是串行配置的,每个CAN的配置都占用独立的一块RAM。

贴上代码供大家参考:
  1. CAN_PARA_CFG can_cfg[ODO_CAN_END] =
  2. {
  3.         {
  4.                 .Instance = FDCAN1,
  5.                 .Mode=FDCAN_MODE_NORMAL,
  6.                 .NominalPrescaler=10,
  7.                 .NominalSyncJumpWidth=8,
  8.                 .NominalTimeSeg1=31,
  9.                 .NominalTimeSeg2=8,
  10.                 .TxBuffersNbr = 0,
  11.                 .TxFifoQueueElmtsNbr = 32,
  12.           .MessageRAMOffset = 0,
  13.                 .filtertype = 1,
  14.                 .filterID1 = 0,
  15.                 .filterID2 = 0xFFFF
  16.         },
  17.         {
  18.                 .Instance = FDCAN2,
  19.                 .Mode=FDCAN_MODE_NORMAL,
  20.                 .NominalPrescaler=10,
  21.                 .NominalSyncJumpWidth=8,
  22.                 .NominalTimeSeg1=31,
  23.                 .NominalTimeSeg2=8,
  24.                 .TxBuffersNbr=0,
  25.                 .TxFifoQueueElmtsNbr = 32,
  26.                 .MessageRAMOffset = 500,
  27.                 .filtertype = 1,
  28.                 .filterID1 = 0,
  29.                 .filterID2 = 0xFFFF
  30.         }
  31. };

  32. void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
  33. {
  34.         if (hfdcan->Instance == FDCAN1)
  35.         {
  36.                 HAL_FDCAN1_MspInit(hfdcan);
  37.         }
  38.         else if(hfdcan->Instance == FDCAN2)
  39.         {
  40.                 HAL_FDCAN2_MspInit(hfdcan);
  41.         }
  42. }

  43. void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan)
  44. {
  45.         if (hfdcan->Instance == FDCAN1)
  46.         {
  47.                 HAL_FDCAN1_MspDeInit(hfdcan);
  48.         }
  49.         else if (hfdcan->Instance == FDCAN2)
  50.         {
  51.                 HAL_FDCAN2_MspDeInit(hfdcan);
  52.         }
  53. }


  54. u4 board_can_init(CAN_NAME canname)
  55. {
  56.                 FDCAN_FilterTypeDef FDCANRxFilterType;

  57.     HAL_FDCAN_DeInit(&can_cfg[canname].FDCANHalHandler);

  58.     can_cfg[canname].FDCANHalHandler.Instance=can_cfg[canname].Instance;
  59.     can_cfg[canname].FDCANHalHandler.Init.FrameFormat=FDCAN_FRAME_CLASSIC;            //传统模式
  60.     can_cfg[canname].FDCANHalHandler.Init.Mode=can_cfg[canname].Mode;               
  61.     can_cfg[canname].FDCANHalHandler.Init.AutoRetransmission=DISABLE;                 //关闭自动重传
  62.     can_cfg[canname].FDCANHalHandler.Init.TransmitPause=DISABLE;                      //关闭传输暂停
  63.     can_cfg[canname].FDCANHalHandler.Init.ProtocolException=DISABLE;                  //关闭协议异常处理
  64.     can_cfg[canname].FDCANHalHandler.Init.NominalPrescaler=can_cfg[canname].NominalPrescaler;                    //分频系数
  65.     can_cfg[canname].FDCANHalHandler.Init.NominalSyncJumpWidth=can_cfg[canname].NominalSyncJumpWidth;            //重新同步跳跃宽度
  66.     can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg1=can_cfg[canname].NominalTimeSeg1;                      //tsg1范围:2~256
  67.     can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg2=can_cfg[canname].NominalTimeSeg2;                      //tsg2范围:2~128
  68.                 can_cfg[canname].FDCANHalHandler.Init.MessageRAMOffset=can_cfg[canname].MessageRAMOffset;      
  69.     can_cfg[canname].FDCANHalHandler.Init.StdFiltersNbr=1;                            //标准信息滤波器个数
  70.     can_cfg[canname].FDCANHalHandler.Init.ExtFiltersNbr=0;                            //扩展信息滤波器个数
  71.     can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtsNbr=32;                          //接收FIFO0元素编号
  72.     can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8;         //接收FIFO0元素大小:8字节
  73.           can_cfg[canname].FDCANHalHandler.Init.RxFifo1ElmtsNbr=0;                          //接收FIFO1元素编号
  74.     can_cfg[canname].FDCANHalHandler.Init.RxBuffersNbr=0;                             //接收缓冲编号
  75.                
  76.     can_cfg[canname].FDCANHalHandler.Init.TxEventsNbr=0;                              //发送事件编号
  77.                 can_cfg[canname].FDCANHalHandler.Init.TxBuffersNbr=can_cfg[canname].TxBuffersNbr;                             //发送缓冲编号
  78.                 can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueElmtsNbr=can_cfg[canname].TxFifoQueueElmtsNbr;               //发送FIFO序列元素编号
  79.     can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION;    //发送FIFO序列模式
  80.     can_cfg[canname].FDCANHalHandler.Init.TxElmtSize=FDCAN_DATA_BYTES_8;              //发送大小:8字节
  81.     if(HAL_FDCAN_Init(&can_cfg[canname].FDCANHalHandler)!=HAL_OK) return 1;           //初始化FDCAN
  82.                
  83.                 /*fifo 0 设置为覆盖写*/
  84.                 HAL_FDCAN_ConfigRxFifoOverwrite(&can_cfg[canname].FDCANHalHandler,FDCAN_RX_FIFO0,FDCAN_RX_FIFO_OVERWRITE);
  85.   
  86.                 FDCANRxFilterType.IdType=FDCAN_STANDARD_ID;                       //标准ID
  87.                 FDCANRxFilterType.FilterIndex=can_cfg[canname].filtertype;        //滤波器索引                  
  88.                 FDCANRxFilterType.FilterType=FDCAN_FILTER_MASK;                   //滤波器类型
  89.                 FDCANRxFilterType.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
  90.                 FDCANRxFilterType.FilterID1=can_cfg[canname].filterID1;                               //>ID1
  91.                 FDCANRxFilterType.FilterID2=can_cfg[canname].filterID2;                               //<ID2
  92.                 if(HAL_FDCAN_ConfigFilter(&can_cfg[canname].FDCANHalHandler,&FDCANRxFilterType)!=HAL_OK)
  93.                 {       
  94.                         return 2;//滤波器初始化
  95.                 }
  96.                
  97.                 if (HAL_FDCAN_ConfigGlobalFilter(&can_cfg[canname].FDCANHalHandler, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, ENABLE, ENABLE) != HAL_OK)
  98.                 {
  99.                         return 2;
  100.                 }

  101.                 HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
  102.                 HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_TX_FIFO_EMPTY,0);
  103.                
  104.                 can_cfg[canname].FDCAN_TxHeader.IdType = FDCAN_STANDARD_ID;                  
  105.     can_cfg[canname].FDCAN_TxHeader.TxFrameType = FDCAN_DATA_FRAME;              
  106.     can_cfg[canname].FDCAN_TxHeader.DataLength = FDCAN_DLC_BYTES_8;              
  107.     can_cfg[canname].FDCAN_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;      
  108.     can_cfg[canname].FDCAN_TxHeader.BitRateSwitch = FDCAN_BRS_OFF;               
  109.     can_cfg[canname].FDCAN_TxHeader.FDFormat = FDCAN_CLASSIC_CAN;               
  110.     can_cfg[canname].FDCAN_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;     
  111.     can_cfg[canname].FDCAN_TxHeader.MessageMarker = 0;   
  112.                
  113.                 HAL_FDCAN_Start(&can_cfg[canname].FDCANHalHandler);                               //开启FDCAN
  114.                
  115.     return success;               
  116. }

  117. /*can1 初始化*/
  118. void can1_init(void)
  119. {
  120.         board_can_init(ODO_CAN1);        
  121. }

  122. /*can 初始化*/
  123. void can2_init(void)
  124. {
  125.         board_can_init(ODO_CAN2);      
  126. }

复制代码

下面给大家奉上一个排查硬件连接的一个小技巧:

进入调试模式:

1.查看can协议状态寄存器,刚初始化完毕并且没有接上CAN总线,则LEC位是状态7,表示未检测到任何CAN总线事件。当你把设置连接上CAN总线,如果程序和硬件没什么问题,那么,LEC状态变为0.表示未发生任何错误。 如果没有连接上CAN总线,而你发送了数据给外面,则LEC会变为状态5,bit0ERR,表示在消息发送过程中,器件希望发送显性电平,但受监控的宗闲置为隐形。

可以参考我的博客:https://my.oschina.net/u/2252538/blog/3155525

评分

参与人数 1金币 +50 收起 理由
eric2013 + 50 赞一个!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107023
QQ
发表于 2020-1-9 20:48:46 | 显示全部楼层
非常感谢楼主分享。
回复

使用道具 举报

0

主题

84

回帖

84

积分

初级会员

积分
84
发表于 2020-1-10 09:13:48 | 显示全部楼层
感谢,,学习,学习。
回复

使用道具 举报

0

主题

12

回帖

12

积分

新手上路

积分
12
发表于 2020-2-25 11:14:38 | 显示全部楼层
感谢,我也正在调试这一块,弄的一头雾水~~~~~~
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2020-3-19 12:19:57 | 显示全部楼层
yoyotansa 发表于 2020-2-25 11:14
感谢,我也正在调试这一块,弄的一头雾水~~~~~~

兄弟 你调好了吗  我现在也一头雾水 能给个例程吗
回复

使用道具 举报

1

主题

3

回帖

6

积分

新手上路

积分
6
发表于 2020-9-1 10:14:29 | 显示全部楼层
楼主,请问STM32H7 CAN1 CAN2同时使用还有什么需要注意的吗?我按照你的方法配置出来,CAN2接收中断一直进不来
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2020-9-10 11:54:31 | 显示全部楼层
only 发表于 2020-3-19 12:19
兄弟 你调好了吗  我现在也一头雾水 能给个例程吗

兄弟,你调好了吗H7的FDCAN
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2020-9-10 11:55:22 | 显示全部楼层
chongnew 发表于 2020-9-1 10:14
楼主,请问STM32H7 CAN1 CAN2同时使用还有什么需要注意的吗?我按照你的方法配置出来,CAN2接收中断一直进 ...

兄弟,我CAN1都不可以接收中断?开启中断需要注意什么吗
回复

使用道具 举报

8

主题

28

回帖

52

积分

初级会员

积分
52
发表于 2020-12-3 09:27:34 | 显示全部楼层
MessageRAMOffset直接定500(0x1F4)的话,会有问题吧???

hfdcan2.Init.MessageRAMOffset = hfdcan1.msgRam.EndAddress - SRAMCAN_BASE;     //这样才能正确解决问题。

评分

参与人数 1金币 +20 收起 理由
kevin_yf + 20 非常感谢,楼主的贴子配合你这个临门一脚。.

查看全部评分

回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2021-11-12 11:26:58 | 显示全部楼层
你好楼主,我在can接入了两个设备,偶尔会出现BIT 0 ERR,我都是通过重新初始化对应的can口解决的,请问出现这种情况怎么比较完美的解决呢。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 11:40 , Processed in 0.293912 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表