打印

STM32H7 CAN1 CAN2 同时使用教程

[复制链接]
295|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
3月的尾巴|  楼主 | 2018-8-1 20:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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。

贴上代码供大家参考:
CAN_PARA_CFG can_cfg[ODO_CAN_END] =
{
        {
                .Instance = FDCAN1,
                .Mode=FDCAN_MODE_NORMAL,
                .NominalPrescaler=10,
                .NominalSyncJumpWidth=8,
                .NominalTimeSeg1=31,
                .NominalTimeSeg2=8,
                .TxBuffersNbr = 0,
                .TxFifoQueueElmtsNbr = 32,
          .MessageRAMOffset = 0,
                .filtertype = 1,
                .filterID1 = 0,
                .filterID2 = 0xFFFF
        },
        {
                .Instance = FDCAN2,
                .Mode=FDCAN_MODE_NORMAL,
                .NominalPrescaler=10,
                .NominalSyncJumpWidth=8,
                .NominalTimeSeg1=31,
                .NominalTimeSeg2=8,
                .TxBuffersNbr=0,
                .TxFifoQueueElmtsNbr = 32,
                .MessageRAMOffset = 500,
                .filtertype = 1,
                .filterID1 = 0,
                .filterID2 = 0xFFFF
        }
};

void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
        if (hfdcan->Instance == FDCAN1)
        {
                HAL_FDCAN1_MspInit(hfdcan);
        }
        else if(hfdcan->Instance == FDCAN2)
        {
                HAL_FDCAN2_MspInit(hfdcan);
        }
}

void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan)
{
        if (hfdcan->Instance == FDCAN1)
        {
                HAL_FDCAN1_MspDeInit(hfdcan);
        }
        else if (hfdcan->Instance == FDCAN2)
        {
                HAL_FDCAN2_MspDeInit(hfdcan);
        }
}


u4 board_can_init(CAN_NAME canname)
{
                FDCAN_FilterTypeDef FDCANRxFilterType;

    HAL_FDCAN_DeInit(&can_cfg[canname].FDCANHalHandler);

    can_cfg[canname].FDCANHalHandler.Instance=can_cfg[canname].Instance;
    can_cfg[canname].FDCANHalHandler.Init.FrameFormat=FDCAN_FRAME_CLASSIC;            //传统模式
    can_cfg[canname].FDCANHalHandler.Init.Mode=can_cfg[canname].Mode;               
    can_cfg[canname].FDCANHalHandler.Init.AutoRetransmission=DISABLE;                 //关闭自动重传
    can_cfg[canname].FDCANHalHandler.Init.TransmitPause=DISABLE;                      //关闭传输暂停
    can_cfg[canname].FDCANHalHandler.Init.ProtocolException=DISABLE;                  //关闭协议异常处理
    can_cfg[canname].FDCANHalHandler.Init.NominalPrescaler=can_cfg[canname].NominalPrescaler;                    //分频系数
    can_cfg[canname].FDCANHalHandler.Init.NominalSyncJumpWidth=can_cfg[canname].NominalSyncJumpWidth;            //重新同步跳跃宽度
    can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg1=can_cfg[canname].NominalTimeSeg1;                      //tsg1范围:2~256
    can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg2=can_cfg[canname].NominalTimeSeg2;                      //tsg2范围:2~128
                can_cfg[canname].FDCANHalHandler.Init.MessageRAMOffset=can_cfg[canname].MessageRAMOffset;      
    can_cfg[canname].FDCANHalHandler.Init.StdFiltersNbr=1;                            //标准信息滤波器个数
    can_cfg[canname].FDCANHalHandler.Init.ExtFiltersNbr=0;                            //扩展信息滤波器个数
    can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtsNbr=32;                          //接收FIFO0元素编号
    can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8;         //接收FIFO0元素大小:8字节
          can_cfg[canname].FDCANHalHandler.Init.RxFifo1ElmtsNbr=0;                          //接收FIFO1元素编号
    can_cfg[canname].FDCANHalHandler.Init.RxBuffersNbr=0;                             //接收缓冲编号
               
    can_cfg[canname].FDCANHalHandler.Init.TxEventsNbr=0;                              //发送事件编号
                can_cfg[canname].FDCANHalHandler.Init.TxBuffersNbr=can_cfg[canname].TxBuffersNbr;                             //发送缓冲编号
                can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueElmtsNbr=can_cfg[canname].TxFifoQueueElmtsNbr;               //发送FIFO序列元素编号
    can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION;    //发送FIFO序列模式
    can_cfg[canname].FDCANHalHandler.Init.TxElmtSize=FDCAN_DATA_BYTES_8;              //发送大小:8字节
    if(HAL_FDCAN_Init(&can_cfg[canname].FDCANHalHandler)!=HAL_OK) return 1;           //初始化FDCAN
               
                /*fifo 0 设置为覆盖写*/
                HAL_FDCAN_ConfigRxFifoOverwrite(&can_cfg[canname].FDCANHalHandler,FDCAN_RX_FIFO0,FDCAN_RX_FIFO_OVERWRITE);
  
                FDCANRxFilterType.IdType=FDCAN_STANDARD_ID;                       //标准ID
                FDCANRxFilterType.FilterIndex=can_cfg[canname].filtertype;        //滤波器索引                  
                FDCANRxFilterType.FilterType=FDCAN_FILTER_MASK;                   //滤波器类型
                FDCANRxFilterType.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
                FDCANRxFilterType.FilterID1=can_cfg[canname].filterID1;                               //>ID1
                FDCANRxFilterType.FilterID2=can_cfg[canname].filterID2;                               //<ID2
                if(HAL_FDCAN_ConfigFilter(&can_cfg[canname].FDCANHalHandler,&FDCANRxFilterType)!=HAL_OK)
                {        
                        return 2;//滤波器初始化
                }
               
                if (HAL_FDCAN_ConfigGlobalFilter(&can_cfg[canname].FDCANHalHandler, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, ENABLE, ENABLE) != HAL_OK)
                {
                        return 2;
                }

                HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
                HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_TX_FIFO_EMPTY,0);
               
                can_cfg[canname].FDCAN_TxHeader.IdType = FDCAN_STANDARD_ID;                  
    can_cfg[canname].FDCAN_TxHeader.TxFrameType = FDCAN_DATA_FRAME;              
    can_cfg[canname].FDCAN_TxHeader.DataLength = FDCAN_DLC_BYTES_8;              
    can_cfg[canname].FDCAN_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;      
    can_cfg[canname].FDCAN_TxHeader.BitRateSwitch = FDCAN_BRS_OFF;               
    can_cfg[canname].FDCAN_TxHeader.FDFormat = FDCAN_CLASSIC_CAN;               
    can_cfg[canname].FDCAN_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;     
    can_cfg[canname].FDCAN_TxHeader.MessageMarker = 0;   
               
                HAL_FDCAN_Start(&can_cfg[canname].FDCANHalHandler);                               //开启FDCAN
               
    return success;               
}

/*can1 初始化*/
void can1_init(void)
{
        board_can_init(ODO_CAN1);        
}

/*can 初始化*/
void can2_init(void)
{
        board_can_init(ODO_CAN2);      
}

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

进入调试模式:

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

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

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

433

主题

433

帖子

0

粉丝