当前位置:   article > 正文

S32K3学习笔记---S32K3之CAN模块_s32k3 can

s32k3 can

S32K3学习笔记—S32K3之CAN模块

1.前言

CAN通信比较重要性,本文是基于S32K324 RTD3.0做的一个简单调试,在两个核分别注册一路CAN,会分别介绍中断和轮询两种方式,一般而言BT用轮询,APP里面一般用中断。其次也是介绍一下CANFD和CAN,主要记录整个过程。

2.原理

​ FlexCAN 模块是CAN协议的一个高完成度版本,带有CANFD协议和 CAN 2.0 B 版本协议,支持标准和拓展数据帧和长达 64 字节的数据传输,频率最大可达到 8Mbps。NXP的FLEXCAN个人感觉很复杂,要想全部了解就只能看芯片手册,下面只简单的介绍几个基本概念

image-20231126224702048

各模块功能如下:

​ 1.Bus Interface Unit (BIU):允许时钟、寻址、数据总线、中断、DMA和测试信号访问模块

​ 2.Controller Host Interface (CHI):消息缓存区仲裁和匹配算法。

​ 3.Protocol Engine (PE): 请求RAM访问、错误处理、验证接收帧、探测CAN FD帧。

一些关键功能:

​ 1.可配置长度(0,8,16,32,64 Bytes)的邮箱

​ 2.接收或者传输未使用的RAM可以用作通用的RAM

​ 3.CANFD的增强型FIFO可以储存20CANFD frames以及DMA支持

​ 4.优先级机制:最低的ID,缓存区数量最少,优先级最高

​ 5.CAN0最大96mbs, CAN1、CAN2最大64mbs

普通CAN和CANFD的区别:

image-20231202195838962

FlexCAN消息缓冲区结构

​ 1.CAN规范(版本2.0第B部分)中使用的扩展(29位标识符)和标准(11位标识符)帧都有表示。每个单独的消息缓冲 区是16、24、40或72个字节,这取决于为消息有效载荷分配的数据字节数量:分别为8、16、32或64个数据字节。

​ 2.存储区域80h–67Fh由消息缓冲器使用。启用CAN FD时,每个消息缓冲区的确切地址取决于其有效负载的大小

image-20231202203442011

​ EDL:拓展数据位。用来区分是普通 CAN 帧还是 CANFD 。当 CODE 字段为 0110 时,该位不能置1

​ BRS:位速率选择位。该位决定在 CANFD 模式下是否切换速率

​ ESI:错误状态位。该位指示发送节点是主动错误还是被动错误

​ CODE:报文缓冲区码。该字段可以被 MCU 和 FlexCAN 模块访问(读和写),作为报文缓冲区匹配与仲裁过程的一部 分

FlexCAN具有以下功能模式:

image-20231202204739974image-20231202204756918

​ 其他的像发送过程、接收过程、仲裁过程等看芯片手册

3.EB配置

​ 关于MCAL的配置,其可能依赖模块包括:Port、Platform、Mcu、Mcl、Can

​3.1 port

​ 主要是配置TX和RX,下图是将PTA6和PTA7复用为CAN0的RX和TX,其主要配置如下,具体Port和platform配置可参考之前文章 S32K3学习笔记—S32K3之Gpt、Dio、Platform

image-20231125230030259

image-20231125230639104

image-20231125230707881

3.2 paltform

​ 如果不是用的Interupt的方式,此处可以不配置, 此处主要是使能CAN的中断。

image-20231125230948945

3.3 Mcu

​ Mcu配置如下,具体的配置细节可以参考S32K3学习笔记—S32K3之MCU模块

image-20231126170602657

​ 此处配置两个用于不同硬件CAN的参考时钟就行。还有一点需要注意的,不要忘记在McuPeripheral中使能相应外设的时钟。

3.4 Mcl

​ 如果我们要用的FIFO+ DMA的形式,就需要在Mcl里面配置DMA的逻辑通道相关,此处由于自己没用过这种模式,所以暂不给出配置,如果后续有用到这种模式再回来补

注意:

​ 1.只有在使能FIFO的情况下,才能使用DMA来接收数据

​ 2.发送是不能使用DMA的

3.5 CAN

​ 首先先介绍一下polling或者Interuput的通用配置,相对比较简单。
image-20231125232722176

1.使能支持多核

2.成功接收到L-PDU后的回调函数,看需求使能

3、4.默认使能,芯片自身特定参数

5.使能修改波特率的API

image-20231125233216486

1.可以注册到两个核分区

image-20231125233247234

1.Can_MainFunction_Read或Can_MainFunction_Write的周期。单位是秒。用于polling模式

image-20231125233550714

1.在此处注册所需要的HRH和HOH

需要注意,此处一定是所有的receive之后才能注册transmit

image-20231202211938996

1.可以存储的最大L-PDU有效负载长度,CAN-8bytes,CANFD-64bytes

2.Can实现类型:basic 、full。一般诊断和网络管理报文选择basic ,其他的选择full

3.注意:对于接收邮箱的配置,如果设置成MIXED,那么程序则会将邮箱初始化成extended。

4.选择接收还是发送

5.如果前面选择的polling模式,需要使能5,选择对应的发送/接收的周期

6.增强型FIFO需要使能

接下来就是报文ID和掩码的配置,此处有两种组合

A.固定的ID报文

image-20231202213420484

​ 1.这种ID Filter+掩码的配置,只能接收0x110和0x120两条报文

B.范围ID报文

image-20231202213806308

​ 1.只有0x110 ~ 0x11f的ID报文才会被接收

​ 如下是CAN TX的object。对于发送的object配置相对简单,不需要配置CanHwFilter,只需要配置general

image-20231202213959913

​ 1.选择发送

​ 2.根据模式选择,polling需要使能该选项

接下来是CAN控制器配置

image-20231126165118856

1.使能CAN控制器

2、3、4.CAN rx tx busoff的方式,选择polling 或者 interrupt

5.是否在环回模式下运行,看需求

6.是否支持busoff自恢复

7.是否使用CANFD协议,如果只用普通CAN则不使能此选项

8.默认波特率配置参考,具体配置见后文

9.此路CAN注册到哪个核

10.CAN的时钟参考,在MCU模块配置,需要主要CAN0_2是一种时钟,CAN2_5是另外一种时钟

接下来就是CAN波特率的配置

image-20231126172307328

1.ENHANCE_CBT:提供更高的位定时分辨率,存储在ENCBT、EDCBT和EPRS寄存器中。

2.该5位字段指示从CAN总线上的CRC字段的第一位开始,Tx仲裁过程起始点可以延迟多少CAN位,默认12

3.预分频系数

4.CAN控制器的波特率 波特率 = 时钟频率(40M) / 3 /(5 + 6 + 7 + 8) 如:500K = 40M /1/(1+47+16+16)

​ 此外,采样点的公式 采样点 = 1 - 8 / (5 + 6 + 7 + 8) 如:采样点 = 1 - 16/(1+47+16+16)*100% = 0.8

5、6.同步段、传输段

7、8.相位段1 、相位段2

9.指定控制器的同步跳跃宽度

​ 如果不用CANFD,此配置可以不使能,对于CANFD 波特率和采样点的公式也是一样的,CANFD的配置如下:

image-20231126173654350

1.波特率 = 时钟 / 分频系数 / (2 + 3 + 4 + 5) 例如: 2000K = 40M / 1/ (1 + 7 + 6 + 6)

6.指定控制器的同步跳跃宽度

7.指定变送器延迟补偿偏移

8.指定传输是否应使用比特率切换

接下来就是使能FIFO

image-20231126180224835

1.Legacy FIFO是不支持CANFD的,Enhanced FIFO支持CANFD。

2.指定FIFO的过滤方案

3.使能使能DMA,此处不使能DMA,如果有需要可以使能

​ 至此,核0的CAN的配置完成了,同样,核1只需要做相同的操作就能注册一路CAN,最后只需要将EB生成的代码导入工程,进行调试就行

4.代码调试

1.polling

/*		main_c0		*/
uint8 CanIf_u8TxConfirmCnt = 0U;
boolean CanIf_bTxFlag = FALSE;
uint8 CanIf_u8RxIndicationCnt = 0U;
boolean CanIf_bRxFlag = FALSE;

void CanIf_ControllerBusOff(uint8 ControllerId)
{
    (void)ControllerId;
}

void CanIf_ControllerModeIndication(uint8 ControllerId, Can_ControllerStateType ControllerMode )
{
    (void)ControllerId;
    (void)ControllerMode;
}
void CanIf_TxConfirmation(PduIdType CanTxPduId)
{
    CanIf_u8TxConfirmCnt++;
    CanIf_bTxFlag = TRUE;
    (void)CanTxPduId;
}

void CanIf_RxIndication(const Can_HwType* Mailbox, const PduInfoType* PduInfoPtr )
{
    CanIf_u8RxIndicationCnt++;
    CanIf_bRxFlag = TRUE;
    (void)Mailbox;
    (void)PduInfoPtr;
}

void Can_DummyDelay(uint32 loops)
{
    VAR( volatile uint32, CAN_VAR) data = 0xAA55AA55;
    VAR( volatile uint32, CAN_VAR) contor1 = 0;
    VAR( volatile uint32, CAN_VAR) contor2 = loops;

    do
    {
        for (contor1 = 0; contor1 < 0x2FF; contor1++)
        {
            data ^= (1 << contor1) | (0xAAAAAA | contor2);
        }
        contor2--;
    } while( contor2 > 0);
}

Can_PduType Can_CreatePduInfo(Can_IdType id, PduIdType swPduHandle, uint8 length, uint8* sdu)
{
    Can_PduType PduInfo;
    
    PduInfo.id = id;
    PduInfo.swPduHandle = swPduHandle;
    PduInfo.length = length;
    PduInfo.sdu = sdu;
    
    return PduInfo;
}

int main_c0(void) 
{
    uint8 u8TimeOut = 100U;
    CanIf_bTxFlag = FALSE;
    CanIf_bRxFlag = FALSE;
    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */
    /* Initialize the clock tree and apply PLL as system clock */
    Mcu_InitClock(McuConf_McuModeSettingConf_McuModeSettingConf_0);

#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }

    Mcu_DistributePllClock();
#endif

    Mcu_SetMode(McuModeSettingConf_0);

    /* Initialize Platform driver */
    Platform_Init(NULL_PTR);  
    static Can_PduType Can_PduInfo;
    
    /* Can_CreatePduInfo(id, swPduHandle,length, sdu) */
    Can_PduInfo = Can_CreatePduInfo(0U, 0U, 8U, Can_au8Sdu8bytes);
    /* Initilize Can driver */
#if (CAN_43_FLEXCAN_PRECOMPILE_SUPPORT == STD_ON)
    Can_43_FLEXCAN_Init(NULL_PTR);
#else
    Can_43_FLEXCAN_Init(&Can_43_FLEXCAN_Config_VS_0);
#endif
    Can_43_FLEXCAN_SetControllerMode(CanController_0, CAN_CS_STARTED);
    if((Can_43_FLEXCAN_Write(CanHardwareObject_2, &Can_PduInfo) == E_OK))
    while((!CanIf_bTxFlag) && (u8TimeOut != 0U))
    {
        Can_43_FLEXCAN_MainFunction_Write();
        Can_DummyDelay(100U);
        u8TimeOut--;
    }
        
    u8TimeOut = 100U;
    while((!CanIf_bRxFlag) && (u8TimeOut != 0U))
    {
        Can_43_FLEXCAN_MainFunction_Read();
        Can_DummyDelay(100U);
        u8TimeOut--;
    }
    Can_43_FLEXCAN_SetControllerMode(CanController_0, CAN_CS_STOPPED);
    Can_43_FLEXCAN_DeInit();
    
    return (0U);
}


/*		main_c1		*/
int main_c1(void) 
{
    uint8 u8TimeOut = 100U;
    CanIf_bTxFlag = FALSE;
    CanIf_bRxFlag = FALSE;
    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */
    /* Initialize the clock tree and apply PLL as system clock */
    Mcu_InitClock(McuConf_McuModeSettingConf_McuModeSettingConf_0);

#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }

    Mcu_DistributePllClock();
#endif

    Mcu_SetMode(McuModeSettingConf_0);

    /* Initialize Platform driver */
    Platform_Init(NULL_PTR);  
    static Can_PduType Can_PduInfo;
    
    /* Can_CreatePduInfo(id, swPduHandle,length, sdu) */
    Can_PduInfo = Can_CreatePduInfo(0U, 0U, 8U, Can_au8Sdu8bytes);
    /* Initilize Can driver */
#if (CAN_43_FLEXCAN_PRECOMPILE_SUPPORT == STD_ON)
    Can_43_FLEXCAN_Init(NULL_PTR);
#else
    Can_43_FLEXCAN_Init(&Can_43_FLEXCAN_Config_VS_0);
#endif
    Can_43_FLEXCAN_SetControllerMode(CanController_1, CAN_CS_STARTED);
    if((Can_43_FLEXCAN_Write(CanHardwareObject_3, &Can_PduInfo) == E_OK))
    while((!CanIf_bTxFlag) && (u8TimeOut != 0U))
    {
        Can_43_FLEXCAN_MainFunction_Write();
        Can_DummyDelay(100U);
        u8TimeOut--;
    }
        
    u8TimeOut = 100U;
    while((!CanIf_bRxFlag) && (u8TimeOut != 0U))
    {
        Can_43_FLEXCAN_MainFunction_Read();
        Can_DummyDelay(100U);
        u8TimeOut--;
    }
    Can_43_FLEXCAN_SetControllerMode(CanController_1, CAN_CS_STOPPED);
    Can_43_FLEXCAN_DeInit();
    
    return (0U);
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181

2.interrupt

/*		main_c0		*/
int main_co(void) 
{
    uint8 u8TimeOut = 100U;
    CanIf_bTxFlag = FALSE;
    CanIf_bRxFlag = FALSE;
    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */
    /* Initialize the clock tree and apply PLL as system clock */
    Mcu_InitClock(McuConf_McuModeSettingConf_McuModeSettingConf_0);

#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }

    Mcu_DistributePllClock();
#endif

    Mcu_SetMode(McuModeSettingConf_0);

    /* Initialize Platform driver */
    Platform_Init(NULL_PTR);  
    static Can_PduType Can_PduInfo;
    
    /* Can_CreatePduInfo(id, swPduHandle,length, sdu) */
    Can_PduInfo = Can_CreatePduInfo(0U, 0U, 8U, Can_au8Sdu8bytes);
    /* Initilize Can driver */
#if (CAN_43_FLEXCAN_PRECOMPILE_SUPPORT == STD_ON)
    Can_43_FLEXCAN_Init(NULL_PTR);
#else
    Can_43_FLEXCAN_Init(&Can_43_FLEXCAN_Config_VS_0);
#endif
    Can_43_FLEXCAN_SetControllerMode(CanController_0, CAN_CS_STARTED);
	
	for(;;)
	{
		
	}
    return (0U);
}

/*		main_c1		*/
int main_c1(void) 
{
    uint8 u8TimeOut = 100U;
    CanIf_bTxFlag = FALSE;
    CanIf_bRxFlag = FALSE;
    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */
    /* Initialize the clock tree and apply PLL as system clock */
    Mcu_InitClock(McuConf_McuModeSettingConf_McuModeSettingConf_0);

#if (MCU_NO_PLL == STD_OFF)
    while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }

    Mcu_DistributePllClock();
#endif

    Mcu_SetMode(McuModeSettingConf_0);

    /* Initialize Platform driver */
    Platform_Init(NULL_PTR);  
    static Can_PduType Can_PduInfo;
    
    /* Can_CreatePduInfo(id, swPduHandle,length, sdu) */
    Can_PduInfo = Can_CreatePduInfo(0U, 0U, 8U, Can_au8Sdu8bytes);
    /* Initilize Can driver */
#if (CAN_43_FLEXCAN_PRECOMPILE_SUPPORT == STD_ON)
    Can_43_FLEXCAN_Init(NULL_PTR);
#else
    Can_43_FLEXCAN_Init(&Can_43_FLEXCAN_Config_VS_0);
#endif
    Can_43_FLEXCAN_SetControllerMode(CanController_1, CAN_CS_STARTED);

	for(;;)
	{
		
	}
    return (0U);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

5.展望

​ FIFO+DMA的形式没有用过,后续有时间将这个验证一下再补上,关于原理那块比较复杂,写的很简单,如果有时间后续将原理那块丰富一下。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
  

闽ICP备14008679号