CAN&CANFD

目录

简介


  • 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引脚的配置。

FUNCTIONGPIOx_SFRPIN
CANFD_TXGPIOA_SFRGPIO_PIN_MASK_3
CANFD_RXGPIOE_SFRGPIO_PIN_MASK_7
STBGPIOG_SFRGPIO_PIN_MASK_9
ENGPIOC_SFRGPIO_PIN_MASK_6
/**
 *  @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);
}

结束

End