3523|1

208

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【国民技术车规MCU N32A455开发板】02.熟悉CAN通讯(邮箱、ID过滤等),与PC通讯测试 [复制链接]

本帖最后由 xld0932 于 2024-2-19 11:32 编辑

1.概述

当前CAN通讯应用越来越广泛、汽车电子、工业控制,到近些年的电动车,都开始使用CAN组网通讯了,这都得益于CAN的高效、稳定和规范。国民技术N32A455系列MCU带有2组CAN通讯接口,最高波特率可达到1Mbit/s,支持CAN协议2.0A和2.0B,支持时间触发通讯功能;每个CAN都有两个3级深度的接收FIFO、共有14个过滤器组、3个发送邮箱,通过接收FIFO和过滤机制,降低了CAN消息的实时响应要求,减少MCU不必要的消耗,同时也提升了MCU的利用率。

 

2.熟悉CAN模块

2.1.工作模式

初始化、正常和睡眠模式是CAN的三种主要工作模式。软件只有在CAN处于初始化模式时才能进行初始化配置、在初始化完成后,软件配置CAN进入正常模式、通过配置寄存器相应位可以使CAN进入睡眠模式,在进入睡眠模式后,可以通过硬件自动唤醒(检测到CAN总线的活动),也可以通过软件唤醒(操作寄存器位),需要注意的是在进入正常模式之前,CAN必须与CAN总线同步。另外还有测试模式(回环模式、静默模式、回环静默模式)、调试模式。

2.2.发送邮箱

应用程序可以通过三个发送邮箱发送消息,发送三个邮箱消息的顺序是由发送调度器根据消息的优先级决定的,优先级可以由消息的标识符决定,也可以由发送请求的顺序决定。

2.3.接收过滤器

每个 CAN 有 14 个可配置的标识符过滤器组。应用配置标识符过滤器组后,接收邮箱会自动接收需要的邮件,丢弃其他邮件。

2.4.接收FIFO

每个 CAN 有两个接收 FIFO,每个 FIFO 可以存储三个完整的报文。无需应用程序管理,由硬件管理。
 

3.CAN通讯示例

3.1.GPIO初始化配置

/* PD8_CAN1_RX  */
#define CAN1_RX_RCC     RCC_APB2_PERIPH_GPIOD
#define CAN1_RX_GPIO    GPIOD
#define CAN1_RX_PIN     GPIO_PIN_8

/* PD9_CAN1_TX  */
#define CAN1_TX_RCC     RCC_APB2_PERIPH_GPIOD
#define CAN1_TX_GPIO    GPIOD
#define CAN1_TX_PIN     GPIO_PIN_9

/* PE0_CAN1_STB */
#define CAN1_STB_RCC    RCC_APB2_PERIPH_GPIOE
#define CAN1_STB_GPIO   GPIOE
#define CAN1_STB_PIN    GPIO_PIN_0

void CAN_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(CAN1_RX_RCC | RCC_APB2_PERIPH_AFIO, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin       = CAN1_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitPeripheral(CAN1_RX_GPIO, &GPIO_InitStructure);

    RCC_EnableAPB2PeriphClk(CAN1_TX_RCC | RCC_APB2_PERIPH_AFIO, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = CAN1_TX_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitPeripheral(CAN1_TX_GPIO, &GPIO_InitStructure);

    RCC_EnableAPB2PeriphClk(CAN1_STB_RCC, ENABLE);

    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = CAN1_STB_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(CAN1_STB_GPIO, &GPIO_InitStructure);

    GPIO_WriteBit(CAN1_STB_GPIO, CAN1_STB_PIN, Bit_RESET);

    GPIO_ConfigPinRemap(GPIO_RMP1_CAN1, ENABLE);

    ......
}

3.2.CAN通讯参数配置

void CAN_Configuration(void)
{
    ......

    CAN_InitType CAN_InitStructure;

    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN1, ENABLE);

    CAN_DeInit(CAN1);

    CAN_InitStruct(&CAN_InitStructure);
    CAN_InitStructure.TTCM              = DISABLE;
    CAN_InitStructure.ABOM              = DISABLE;
    CAN_InitStructure.AWKUM             = DISABLE;
    CAN_InitStructure.NART              = DISABLE;
    CAN_InitStructure.RFLM              = DISABLE;
    CAN_InitStructure.TXFP              = ENABLE;
    CAN_InitStructure.OperatingMode     = CAN_Normal_Mode;
    CAN_InitStructure.RSJW              = CAN_RSJW_1tq;
    CAN_InitStructure.TBS1              = CAN_TBS1_14tq;
    CAN_InitStructure.TBS2              = CAN_TBS2_3tq;
    CAN_InitStructure.BaudRatePrescaler = 4;
    CAN_Init(CAN1, &CAN_InitStructure);

    ......
}

3.3.CAN过滤器配置

#define  CAN_FILTER_STDID(STDID)        ((STDID & 0x7FF) << 5)

#define  CAN_FILTER_EXTID_H(EXTID)      ((uint16_t)(((EXTID <<3) | 0x04) >> 16))
#define  CAN_FILTER_EXTID_L(EXTID)      ((uint16_t)(( EXTID <<3) | 0x04))

#define  CAN_STD_ID_H_MASK_CARE         (0xFFE0)
#define  CAN_STD_ID_L_MASK_CARE         (0x0000)
#define  CAN_STD_ID_H_MASK_DONT_CARE    (0x0000)
#define  CAN_STD_ID_L_MASK_DONT_CARE    (0x0000)

#define  CAN_EXT_ID_H_MASK_CARE         (0xFFFF)
#define  CAN_EXT_ID_L_MASK_CARE         (0xFFF8)
#define  CAN_EXT_ID_H_MASK_DONT_CARE    (0x0000)
#define  CAN_EXT_ID_L_MASK_DONT_CARE    (0x0000)

void CAN_Configuration(void)
{
    ......

    CAN_FilterInitType CAN_FilterInitStructure;

    CAN_FilterInitStructure.Filter_Num            = 0;
    CAN_FilterInitStructure.Filter_Mode           = CAN_Filter_IdMaskMode;
    CAN_FilterInitStructure.Filter_Scale          = CAN_Filter_32bitScale;
    CAN_FilterInitStructure.Filter_HighId         = CAN_FILTER_STDID(0x400);
    CAN_FilterInitStructure.Filter_LowId          = CAN_FILTER_STDID(0x400);
    CAN_FilterInitStructure.FilterMask_HighId     = CAN_STD_ID_H_MASK_DONT_CARE;
    CAN_FilterInitStructure.FilterMask_LowId      = CAN_STD_ID_H_MASK_DONT_CARE;
    CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
    CAN_FilterInitStructure.Filter_Act            = ENABLE;
    CAN1_InitFilter(&CAN_FilterInitStructure);

    CAN_INTConfig(CAN1, CAN_INT_FMP0, ENABLE);

    ......
}

3.4.CAN中断配置及处理

CanRxMessage CAN_RxMessage[10];
uint8_t      CAN_RxMessage_WriteCursor = 0;
uint8_t      CAN_RxMessage_ReadCursor  = 0;

void CAN_Configuration(void)
{
    ......

    NVIC_InitType NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void CAN1_RX0_IRQHandler(void)
{
    CAN_ReceiveMessage(CAN1, CAN_FIFO0, &CAN_RxMessage[CAN_RxMessage_WriteCursor++]);

    if (CAN_RxMessage_WriteCursor > 10)
    {
        CAN_RxMessage_WriteCursor = 0;
    }
}

3.5.接收发送处理

void CAN_RxMessageHandler(void)
{
    uint8_t i = 0;

    if (CAN_RxMessage_ReadCursor != CAN_RxMessage_WriteCursor)
    {
        printf("\r\n");

        if (CAN_RxMessage[CAN_RxMessage_ReadCursor].IDE == CAN_Extended_Id)
        {
            printf("\r\nReceive Frame[0x%X, %d]:", CAN_RxMessage[CAN_RxMessage_ReadCursor].ExtId, CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC);
        }
        else
        {
            printf("\r\nReceive Frame[0x%X, %d]:", CAN_RxMessage[CAN_RxMessage_ReadCursor].StdId, CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC);
        }

        for (i = 0; i < CAN_RxMessage[CAN_RxMessage_ReadCursor].DLC; i++)
        {
            printf(" 0x%02X", CAN_RxMessage[CAN_RxMessage_ReadCursor].Data[i]);
        }

        CAN_RxMessage_ReadCursor++;

        if (CAN_RxMessage_ReadCursor > 10)
        {
            CAN_RxMessage_ReadCursor = 0;
        }

        printf("\r\n");
    }
}

void CAN_TxStdMessage(void)
{
    CanTxMessage CAN_TxMessage;
    uint8_t      TxMailbox = 0;
    uint8_t      i = 0;

    CAN_TxMessage.StdId = 0x0400;
    CAN_TxMessage.IDE   = CAN_ID_STD;
    CAN_TxMessage.RTR   = CAN_RTRQ_DATA;
    CAN_TxMessage.DLC   = 8;

    for (i = 0; i < CAN_TxMessage.DLC; i++)
    {
        CAN_TxMessage.Data[i] = i;
    }

    TxMailbox = CAN_TransmitMessage(CAN1, &CAN_TxMessage);

    if (TxMailbox != CAN_TxSTS_NoMailBox)
    {
        while (CAN_TransmitSTS(CAN1, TxMailbox) != CANTXSTSOK)
        {
            __ASM("nop");
        }
    }
    else
    {
        printf("\r\n%s CAN_TxSTS_NoMailBox!!!", __FUNCTION__);
    }
}

void CAN_TxExtMessage(void)
{
    CanTxMessage CAN_TxMessage;
    uint8_t      TxMailbox = 0;
    uint8_t      i = 0;

    CAN_TxMessage.ExtId = 0x12345678;
    CAN_TxMessage.IDE   = CAN_ID_EXT;
    CAN_TxMessage.RTR   = CAN_RTRQ_DATA;
    CAN_TxMessage.DLC   = 8;

    for (i = 0; i < CAN_TxMessage.DLC; i++)
    {
        CAN_TxMessage.Data[i] = i;
    }

    TxMailbox = CAN_TransmitMessage(CAN1, &CAN_TxMessage);

    if (TxMailbox != CAN_TxSTS_NoMailBox)
    {
        while (CAN_TransmitSTS(CAN1, TxMailbox) != CANTXSTSOK)
        {
            __ASM("nop");
        }
    }
    else
    {
        printf("\r\n%s CAN_TxSTS_NoMailBox!!!", __FUNCTION__);
    }
}

 

4.测试结果

4.1.PC端使用PCAN工具收发数据

4.2.MCU在接收到CAN数据后,通过串口打印输出

4.3.硬件连接

需要注意的是我们使用的是CAN1,需要将J10这两个跳帽给短接上!!!

 

5.附件程序

N32A455VEL7-EVB V1.1.zip (7.12 MB, 下载次数: 7)
此帖出自汽车电子论坛

最新回复

非常详细的CAN分享技术帖,CAN大有替代传统的UART的趋势呀。  详情 回复 发表于 2024-2-22 06:43
点赞 关注
个人签名We are a team and we work as a team !

回复
举报

7059

帖子

11

TA的资源

版主

沙发
 
非常详细的CAN分享技术帖,CAN大有替代传统的UART的趋势呀。
此帖出自汽车电子论坛
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表