打印
[KungFu32位 MCU]

KF32146/156学习笔记之CAN&CANFD模块

[复制链接]
488|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wowu|  楼主 | 2024-9-7 10:21 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
简介
CAN模块是CAN总线通信模块,CANFD模块是CAN扩展协议模块,CAN模块和CANFD模块是互斥的,只能同时使用一个,但是CANFD可兼容CAN。
CAN:适用于数据速率要求较低、数据负载较小的应用,如传统的车辆ECU通信和简单的工业自动化网络。
CAN FD:适用于需要更高数据速率和更大数据负载的现代应用,如高级驾驶辅助系统(ADAS)、自动驾驶、车载娱乐系统以及复杂的工业自动化控制系统。
基于CANFD实现CAN和CANFD数据的发送和接收(波特率为500K,采样点为81.3%数据段波特率2M,采样点为80.0%).
引脚配置
MCU的CANFD_TX和RX引脚以及收发器STB和EN引脚的配置。



/**
*  @brief :Canfd Gpio Init,PTA3:CANFD6_TX , PTE7:CANFD6_RX
*  @param in :None
*  @param out :None
*  @retval :None
*/
void Canfd_Gpio_Init(void)
{
    GPIO_Pull_Up_Enable(GPIOA_SFR, GPIO_PIN_MASK_3, TRUE);
    GPIO_Write_Mode_Bits(GPIOA_SFR, GPIO_PIN_MASK_3, GPIO_MODE_RMP);

    GPIO_Pull_Up_Enable(GPIOE_SFR, GPIO_PIN_MASK_7, TRUE);
    GPIO_Write_Mode_Bits(GPIOE_SFR, GPIO_PIN_MASK_7, GPIO_MODE_RMP);

    GPIO_Pin_RMP_Config(GPIOA_SFR, GPIO_Pin_Num_3, GPIO_RMP_AF6);
    GPIO_Pin_RMP_Config(GPIOE_SFR, GPIO_Pin_Num_7, GPIO_RMP_AF6);
}


/**
* @brief: GPIOx output initialization configuration
*
* @param GPIOx Gpio port pointer
* @param GpioPin Pin number
* @retval: None
*/
void GPIOInit_Output_Config(GPIO_SFRmap *GPIOx, uint16_t GpioPin)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_Struct_Init(&GPIO_InitStructure);
    GPIO_InitStructure.m_Pin      = GpioPin;
    GPIO_InitStructure.m_Speed    = GPIO_LOW_SPEED;
    GPIO_InitStructure.m_Mode     = GPIO_MODE_OUT;
    GPIO_InitStructure.m_PullUp   = GPIO_NOPULL;
    GPIO_InitStructure.m_PullDown = GPIO_NOPULL;
    GPIO_Configuration(GPIOx, &GPIO_InitStructure);

    GPIO_Set_Output_Data_Bits(GPIOx, GpioPin, Bit_SET);
}

void Canfd_Stb_En_Init(void)
{
    GPIOInit_Output_Config(GPIOG_SFR, GPIO_PIN_MASK_9);
    GPIOInit_Output_Config(GPIOC_SFR, GPIO_PIN_MASK_6);   
}



波特率配置
波特率为500K,采样点为81.3%
数据段波特率2M,采样点为80.0%

const Can_BDRConfigType Canfd_Controller_AllClockAndBDRConfig[1] = {
    /* Default 500k hz*/
    /* Clock and baudrate config 0 : Index 0 */
    { .PreScale = 1U, .Sjw = 1U, .TSeg1 = 11U, .TSeg2 = 2U, .SampleTimes = CAN_SAMPLE_ONCE }
};


const Can_FdBDRConfigType Canfd_Controller_ALLFdBDRConfig[1] = {
    /* Default 2M hz */
    /* High Speed Clock and bandrate config 0 : Index 0 */
    {
     .BrsPrescale = 0U,
     .HtSeg1      = 5U,
     .HtSeg2      = 0U,
     },
};




相关函数及变量
#define BODY_CAN_CTRL_INDEX CANfd6

typedef struct
{
    Can_MailboxNumType MailBox;
    Canfd_MailboxHeaderType *AttrStruct;
}CAN_MailboxConfig_t;

volatile uint32_t Writewrong_Flag = 0;
volatile uint8_t ArbLose_Flag = 0;

Canfd_MailboxHeaderType ClassicCAN_TxAttr = {
    { {
          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
          0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
          0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
          0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
          0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
      }, Data_Length_8 },
    0x111,
    0x000,
    CANFD_BRS_ENABLE,
    CAN_FRAME_CLASSICAL,
    CAN_DATA_STANDARD,
    MAIL_TRANSMIT,
};
Canfd_MailboxHeaderType CANFD_TxAttr = {
    { {
          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
          0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
          0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
          0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
          0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
      }, Data_Length_64 },
    0x222,
    0x000,
    CANFD_BRS_ENABLE,
    CAN_FRAME_FD,
    CAN_DATA_STANDARD,
    MAIL_TRANSMIT,
};

Canfd_MailboxHeaderType CANFD_RxAttr = {
    { {
          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
          0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
          0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
          0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
          0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
      }, Data_Length_64 },
    0x444,
    0x000,
    CANFD_BRS_ENABLE,
    CAN_FRAME_CLASSICAL,
    CAN_DATA_STANDARD,
    CAN_RECEIVE,
};

static CAN_MailboxConfig_t ClassicCan_TxConfig =
{
    Mailbox_0,
    &ClassicCAN_TxAttr
};
static CAN_MailboxConfig_t Canfd_TxConfig =
{
    Mailbox_0,
    &CANFD_TxAttr
};
static CAN_MailboxConfig_t Canfd_RxConfig =
{
    Mailbox_1,
    &CANFD_RxAttr
};

Can_ControllerConfigType Canfd_Controller_AllConfig[1] = {
    /* Can 0 Config */
    {
     /* Can controller Mode set
        Value Range :
        CANFD_NORMAL_MODE
        CANFD_LOOP_INTERNAL_MODE
        CNAFD_LOOP_EXTERNAL_MODE
        CANFD_SILENT_MODE */
        CANFD_NORMAL_MODE, /* Can controller Mode set
                Value Range :
                DISABLE
                ENABLE */
        ENABLE,
/* Can controller clock source set
        Value Range :
                CAN_CLOCKSOURCE_SCLK
                CAN_CLOCKSOURCE_HFCLK
                CAN_CLOCKSOURCE_LFCLK */
     CAN_CLOCKSOURCE_HFCLK,
     /* Can controller Arbitrate clock source set
        Value Range :
        CAN_CLOCKSOURCE_SCLK
        CAN_CLOCKSOURCE_HFCLK
        CAN_CLOCKSOURCE_LFCLK */
        CAN_CLOCKSOURCE_HFCLK, /* Mailbox block size config
             Value Range :
                CAN_8_BYTE_DATALENGTH :
                CAN_16_BYTE_DATALENGTH :
                CAN_32_BYTE_DATALENGTH :
                CAN_64_BYTE_DATALENGTH : */
        CAN_8_BYTE_DATALENGTH, /* Iso mode or non-iso mode config
            Value Range :
                CAN_FD_NON_ISOMODE :
                CAN_FD_ISOMODE : */
        CAN_FD_ISOMODE,
/* Global Mask Set */
#if(HARDWARE_FILTER == STD_ON)
     0x00000000,
#else
        0xFFFFFFFF,
#endif
     /* Enable/disable mailbox full receive config
       Value Range :
            CAN_MBFULLRECEIVE_DISABLE
            CAN_MBFULLRECEIVE_ENABLE */
        CAN_MBFULLRECEIVE_DISABLE, /* Interrupt config  */
        &Can_Controller_InterruptConfig[0],
#if(HARDWARE_FILTER == STD_ON)
     /* Hardware Filter config  */
        &Can_HwFilter,
#endif
     /* Arbitrate Segment Baudrate Config */
        &Canfd_Controller_AllClockAndBDRConfig[0],
     /* Data Segment Baudrate Config */
        &Canfd_Controller_ALLFdBDRConfig[0],
     },
    /* end */
};

//接收邮箱的初始化
void Receive_Mailboxinit(const uint8_t Can_Controller_Index)
{
    Can_m_FdMailBox_Write(Can_Controller_Index, Canfd_RxConfig.MailBox,Canfd_RxConfig.AttrStruct);   
}

//数据发送函数
void CANFD_Send(const CAN_MailboxConfig_t * config)
{
        volatile Kf32a_Canfd_Reg* ControllerRegPtr = (Kf32a_Canfd_Reg*)Can_m_ControllersInfo[BODY_CAN_CTRL_INDEX].BaseAddress;        
    uint8_t delay_num = 0x0;

    /* Wait tx complete & tx state idle, or arb lose,we need to resend the data */
        if (((ControllerRegPtr->CANFD_CTLR0.B.TCSTA == 0x01) && (ControllerRegPtr->CANFD_CTLR0.B.TXSTA == 0x00)) || (ArbLose_Flag == 1))
        {
                if(CAN_OK == Can_m_FdMailBox_Write(BODY_CAN_CTRL_INDEX, config->MailBox, config->AttrStruct))
                {
                        Can_m_FdTransmit(BODY_CAN_CTRL_INDEX);
                        delay_num = 0xFF;
                        while((ControllerRegPtr->CANFD_CTLR0.B.TXSTA == 0x01) && (delay_num--));
                        if(Writewrong_Flag > 0)
                        {
                            Writewrong_Flag--;
                        }
                        else
                        {
                                Writewrong_Flag = 0;
                        }
                }
                else
                {
                        Can_m_FdTransmit(BODY_CAN_CTRL_INDEX);
                }
                if(ArbLose_Flag == 1)
                {
                        ArbLose_Flag = 0;
                }
        }
        else
        {
                Can_m_FdTransmit(BODY_CAN_CTRL_INDEX);
                Writewrong_Flag++;
                if(Writewrong_Flag == 128)
                {
            can_init();
                }
        }   
}

//初始化函数
void can_init(void)
{
    /* CANFD initialized */
    Canfd_Gpio_Init();
    Can_m_FdControllerDeInit(BODY_CAN_CTRL_INDEX);
    Can_m_FdControllerInit(BODY_CAN_CTRL_INDEX, Canfd_Controller_AllConfig, Initindex_0);
    /* CANFD Receive messages structure initialized */
    Receive_Mailboxinit(BODY_CAN_CTRL_INDEX);
}

//然后调用下边这两个函数即可成功发送数据
void canfd_send()
{
    CANFD_Send(&Canfd_TxConfig);
}

void can_send()
{
    CANFD_Send(&ClassicCan_TxConfig);
}




结束



————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/xiaohuanxiong_/article/details/141065083

使用特权

评论回复
沙发
chenjun89| | 2024-9-9 07:54 | 只看该作者
CANFD主要是数据域是可变速率的

使用特权

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

本版积分规则

85

主题

4022

帖子

1

粉丝