S32K3学习笔记—S32K3之LIN模块
1.前言
LIN相对于CAN来说成本低、传输速率低,且LIN控制器相对简单。对于一些局部传输,用CAN比较浪费,并且很多传感器也是支持LIN通信的,所以就会选择用LIN。本文是记录在两个核分别注册一路lin,采用中断的形式,并基于MCAL代码进行调试,暂时不涉及协议栈内容。
2.原理
LIN规范里面有详细介绍,此处简单了解一下帧格式。 一个完整的LIN 总线报文帧“Message Frame”包含 报头“Header”和响应“Response”,主机任务负责发送帧头;从机任务接收帧头并对帧头所包含信息进行解析,然后决定是发送应答,还是接收应答,还是不作任何反应。 帧头包括同步间隔段、同步段以及PID(受保护ID)段,应答包括数据段和校验和段。
LIN Block diagram
LIN的时钟
注意:通道0和8是80M,其他的都是40M
LIN的波特率
特征
其他更细节的参考芯片手册和LIN规范文档。
3.EB配置
LIN依赖模块:Mcu、Port、Platform、Lin
Mcu主要是配置LIN的时钟和使能外设,具体配置如下,关于Mcu的详细配置,请参考S32K3学习笔记—S32K3之MCU模块
注意:此处勿忘使能
Port模块
1.选择PIN的模式 LPUART5_LPUART5_TX_OUT,其他的配置项请参考S32K3学习笔记—S32K3之Gpt、Dio、Platform
1.选择PIN的模式 LPUART5_LPUART5_RX_IN
至此,LIN收发器的TX、RX就配置完成,将这一组LIN的通道映射到对应的核就行。
platform模块
1.使能对应的中断并注册对应的回调,platform具体配置可参考S32K3学习笔记—S32K3之Gpt、Dio、Platform
Lin模块
1.是否支持多核
2.超时方式:如果选择了SystemTimer或CustomTimer,请确保在OsIf中启用了相应的计时器
3.如果LinTimeoutMethod是OSIF_COUNTER_SYSTEM或OSIF_COUTER_CUSTOM,则LinTimeoutDuration以微秒为单 位。如果LinTimeoutMethod是OSIF_COUNTER_DUMMY,则LinTimeoutDuration是等待循环的次数。
4.主帧将接受比TFrame_Maximum长的帧
1.LIN模式选择,主模式或者从模式
2.波特率设置,最大20K
3.LIN的硬件通道绑定
4.时钟参考
5.Lin通道映射到到核0分区
类似的,将另外一路Lin注册到核1
1.此处用到通道8,所以是在需要选择80M
2.Lin通道映射到到核1分区
至此,Lin配置完成,Lin的配置相对比较简单,
4.代码调试
测试代码是NXP官方demo,可以看一下中断是否能进,数据是否有发出。
#include "Mcu.h"
#include "Lin_43_LPUART_FLEXIO.h"
#include "Port.h"
#include "Platform.h"
#include "OsIf.h"
#include "Mcl.h"
/*==================================================================================================
* LOCAL MACROS
==================================================================================================*/
#define LIN_MASTER_RESPONSE LIN_FRAMERESPONSE_TX
#define T_LIN_TEST_NUM_CHANNELS ((uint8)2U)
#define T_LIN_TEST_FRM_NUM ((uint8)1U)
#define T_LIN_TIME_OUT 400000
/*==================================================================================================
* LOCAL CONSTANTS
==================================================================================================*/
uint8 T_Lin_Data[3] = {0x01, 0x02, 0x03};
const Lin_PduType T_Lin_Frame[T_LIN_TEST_FRM_NUM] =
{
{0x1A, LIN_ENHANCED_CS, LIN_MASTER_RESPONSE, 3u, T_Lin_Data}
};
int main(void)
{
static uint8 linSdu[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
volatile Lin_StatusType T_LinStatus;
volatile uint32 TimeOut;
uint8 Index_frame = 0;
Lin_PduType linFrame;
const uint8* linSduPtr = linSdu;
volatile uint8 T_result = 0;
uint8 Channel_Index = 0;
volatile Std_ReturnType wakeUpEvent;
/* Setup Clocks */
/* Initialize Mcu module */
Mcu_Init(NULL_PTR);
/* Initialize Mcu clock */
Mcu_InitClock(McuClockSettingConfig_0);
while (Mcu_GetPllStatus() != MCU_PLL_LOCKED){};
/* Use PLL clock */
Mcu_DistributePllClock();
Mcu_SetMode(McuModeSettingConf_0);
#if (LIN_43_LPUART_FLEXIO_FLEXIO_USED == STD_ON)
Mcl_Init(NULL_PTR);
#endif
/* Initialize all pins */
Port_Init(NULL_PTR);
/* Initialize Mcu module to enable interrupts and install handler */
Platform_Init(NULL_PTR);
/* Init osif */
OsIf_Init(NULL_PTR);
/* Initialize LIN module */
Lin_43_LPUART_FLEXIO_Init(NULL_PTR);
for (Channel_Index = 0; Channel_Index < T_LIN_TEST_NUM_CHANNELS; Channel_Index++)
{
/* Wakeup LIN channels for ASR 4.3.1 */
Lin_43_LPUART_FLEXIO_WakeupInternal(Channel_Index);
/* Check Lin channel wakeup */
wakeUpEvent = Lin_43_LPUART_FLEXIO_CheckWakeup(Channel_Index);
/* Get frame data */
linFrame = T_Lin_Frame[Index_frame];
/* Send LIN frame */
Lin_43_LPUART_FLEXIO_SendFrame(Channel_Index, &linFrame);
/* Wait for the transmission done */
TimeOut = 4*T_LIN_TIME_OUT;
do
{
T_LinStatus = Lin_43_LPUART_FLEXIO_GetStatus(Channel_Index, &linSduPtr);
} while (LIN_TX_OK != T_LinStatus && 0 != TimeOut--);
/* Verify that the LIN frame is sent successfully */
if (LIN_TX_OK == T_LinStatus)
{
T_result = T_result + 1;
}
}
return (0U);
}
5.展望
关于FLEXIO_IP目前没用到,后续研究一下再补上。