MM32F3270通讯板之LIN接口主从通讯分享

MM32F3270系列MCU的UART(通用异步收发器)支持全双工数据传输,可以通过分数波特率发生器,选择宽范围的通讯波特率,也可以通过波特率自适应功能来自动判别通讯波特率,其通讯速率的容忍度可以达到±3%;另外还支持5/6/7/8/9位数据通讯、支持数据奇/偶校验方式以及接收空闲中断等功能;还可以通过复用端口引脚CTS/RTS来实现数据收发的流控功能。除此之外MM32F3270系列MCU的UART还具备异步单向通讯和半双工单线通讯的功能、支持多机通讯、智能卡操作、IrDA红外通讯和LIN接口通讯的功能,可谓是功能相当的强大哈。

通过官网下载的MM32F3270资料中不管是DS手册还是UM手册对于LIN总线通讯的功能,仅仅限于在UART主要特征描述时告知我们MM32F3270是支持的,但具体怎么使用,如何配置,文中并没有找到;在UART所有的寄存器中也只有几个比特位是跟LIN相关的描述,致使在拿到这份手册想要使用LIN通讯功能时,都无从下手!官方的库程序以及示例程序中也没有找到LIN相关的范例。

BUT没关系,本文可以带领各位小伙伴玩转基于MM32F3270的LIN通讯功能,有正好需要使用到LIN通讯的小伙伴请坐坐好,准备开讲啦……

首先我们要知道什么是LIN?LIN的全称为Local Interconnect Network,它是基于UART/SCI(通讯异步收发器/串行通讯接口)接口的低成本串行通讯协议,所以说MM32F3270系列MCU的UART支持LIN功能也是合情合理了。LIN总线通讯多用于汽车、家电、办公设备等诸多领域。尤其是在汽车应用上,除了上篇讲述的CAN通讯,最多的就是LIN通讯了,比如前大灯控制、转向灯的控制、天窗的控制等等,这些都是作为LIN从机节点存在的,而汽车通讯网络中主干线还是CAN通讯的居多,所以这个时候在CAN和LIN总线之间就需要一个CAN-LIN网关来负责协调控制,而这个CAN-LIN网关一般也是作为LIN的主机节点存在的。

LIN的拓扑结构为单总线类型,采用了一主多从的通讯方式,总线电平一般使用12V的居多,数据传输的速率最高可达20Kbps。在LIN组网中,主机节点有且只有一个,从机节点可以有多个,因受到外围硬件的限制,一般从机节点在1到15个左右;对于主机节点来说包含主机任务和从机任务,而对于从机节点来说只包含从机任务。

LIN通讯时的数据帧结构包含帧头和应答这2部分,LIN主机任务负责发送帧头,LIN从机任务负责接收帧头并对帧头数据进行解析,然后通过判断决定接下来是发送应答操作,还是接收应答操作,又或者是不作任何反应。数据帧在LIN总线上的传输示意图如下所示:

LIN总线上传输数据帧的帧头是由同步间隔段、同步段和PID段这3部分组成;应答则是由数据段和校验和段这2部分组成,如下图所示:

在上图的帧结构中,电平值为0时我们称之为显性电平,电平值为1时我们称之为隐性电平;在LIN总线通讯上电平信号执行的是“线与”的标准,即当总线上有任意一个节点发送显性电平时,整个总线将呈显性电平状态,反之当总线上所有节点都发送隐性电平或者不发送任何信息时,整个总线将呈隐性电平状态。

帧头:同步间隔段

在LIN通讯中同步间隔段代表了一个数据帧的开始,同步间隔段由同步间隔和同步间隔段间隔符组成的,同步间隔是至少持续13位的显性电平,而同步间隔段的间隔符则是一个至少持续1位的隐性电平;这个对于MM32F3270的UART来说,可以通过操作UART_CCR寄存器中的LIN和BRK这两位来实现同步间隔段的产生;如下图所示:

帧头:同步间隔段实现代码:

void LIN_MASTER_Break(void)

{

    UART3->CCR |= UART_CCR_LIN;

    UART3->CCR |= UART_CCR_BRK;

    while(UART_GetITStatus(UART3, UART_IT_TXBRK) == RESET);

}

字节域

字节域包括1个起始位、8个数据位和1个停止位,数据传输是先发送LSB最后发送MSB,这是标准UART的通讯格式,通过这个描述我们可以得到对MM32F3270系列MCU的在实现LIN通讯时所需要的UART配置参数。在LIN通讯的一帧数据中,除了上面的同步间隔段外,后面跟随的各个段数据都是符合字节域的格式来传输的。如下图所示:


 

帧头:同步段

LIN通讯中规定同步段采用固定字节0x55表示,如下图所示:

帧头:同步段实现代码:

void LIN_MASTER_SyncByte(void)

{

    LIN_MASTER_SendData(0x55);

}

帧头:PID

PID段也称作受保护ID段,它的前6位是帧ID号,后2位校验位;所以帧ID的范围被限制在0x00~0x3F之间;而校验位中P0是由ID0\ID1\ID2\ID4这4个比特位进行异或运算的结果,P1是由ID1\ID3\ID4\ID5先进行异或运算后再取非的运算结果。如下图所示:

帧头:PID段实现代码:

uint8_t LIN_FrameIDToPID(uint8_t FrameID)

{

    uint8_t P0 = 0, P1 = 0, PID = 0xFF;

    uint8_t ID_BIT[6] = {0, 0, 0, 0, 0, 0};

    if(FrameID < 0x40)

    {

        PID = FrameID;

        for(uint8_t i = 0; i < 6; i++)

        {

            if(FrameID & (0x01 << i))

            {

                ID_BIT[i] = 1;

            }

            else

            {

                ID_BIT[i] = 0;

            }

        }

        P0 =  (ID_BIT[0] ^ ID_BIT[1] ^ ID_BIT[2] ^ ID_BIT[4]) & 0x01;

        P1 = ~(ID_BIT[1] ^ ID_BIT[3] ^ ID_BIT[4] ^ ID_BIT[5]) & 0x01;

        if(P0) PID |= 0x40;

        if(P1) PID |= 0x80;

    }

    printf("\r\nFrameID => PID : 0x%02x => 0x%02x\r\n", FrameID, PID);

    return PID;

}

uint8_t LIN_PIDToFrameID(uint8_t PID)

{

    uint8_t P0 = 0, P1 = 0, FrameID = 0xFF;

    uint8_t PID_BIT[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    for(uint8_t i = 0; i < 8; i++)

    {

        if(PID & (0x01 << i))

        {

            PID_BIT[i] = 1;

        }

        else

        {

            PID_BIT[i] = 0;

        }

    }

    P0 =  (PID_BIT[0] ^ PID_BIT[1] ^ PID_BIT[2] ^ PID_BIT[4]) & 0x01;

    P1 = ~(PID_BIT[1] ^ PID_BIT[3] ^ PID_BIT[4] ^ PID_BIT[5]) & 0x01;

    if((P0 == PID_BIT[6]) && (P1 == PID_BIT[7]))

    {

        FrameID = PID & 0x3F;

    }

    printf("\r\nPID => FrameID : 0x%02x => 0x%02x\r\n", PID, FrameID);

    return FrameID;

}

根据帧ID值的不同可以将帧进行如下分类:

应答:数据段

数据段可分为信号、诊断消息这2种数据类型。信号是由信号携带帧传递的,一个帧ID所对应的数据段可能包含一个或者多个信号。而一个信号通常是由一个固定的节点发送出来的,此节点被称为该信号的发布节点,LIN总线上的其余节点则被称之为接收节点;而诊断消息则是由诊断帧传递的,对消息内容的解析由数据自身和节点状态来决定。如下图所示:

应答:校验和段

校验和段是对帧中所传输的内容进行检验,分为标准型校验和和增强型校验和,对比如下表所示:

采用标准型校验和还是增强型校验和是由主机节点来决定的,发布节点和各接收节点根据帧ID来判断采用哪种校验和。校验和的计算方法也很简单:将校验对象挨个进行累加计算,每当计算结果大于等于265时就减去255,将得到的累加结果再进行逐位取反操作。

应答:校验和段实现代码:

uint8_t LIN_ClassicChecksum(uint8_t *Buffer, uint8_t Length)

{

    uint16_t Checksum = 0;

    for(uint8_t i = 0; i < Length; i++)

    {

        Checksum += Buffer[i];

        if(Checksum > 0xFF) Checksum %= 0xFF;

    }

    return ~(uint8_t)(Checksum & 0x00FF);

}

uint8_t LIN_EnhancedChecksum(uint8_t PID, uint8_t *Buffer, uint8_t Length)

{

    uint16_t Checksum = PID;

    for(uint8_t i = 0; i < Length; i++)

    {

        Checksum += Buffer[i];

        if(Checksum > 0xFF) Checksum %= 0xFF;

    }

    return ~(uint8_t)(Checksum & 0x00FF);

}

其它关于LIN通讯的相关知识点可以参考附件中的工程源代码和资料手册,这里就不一一展开介绍了。

通讯测试

接下来我们通过图莫斯的CAN&LIN Analyser工具来进行LIN主、从机的收发测试,通过外置的12V电源适配器对LIN总结进行供电。

  • 在测试LIN主机功能时,需要将CAN&LIN Analyser工要配置为从机工作模式,然后通过MobaXterm调试终端发送SHELL命令来调用测试功能函数,SHELL命令格式为:

LIN_M <FrameID> <Mode>

其中FrameID为帧ID,Mode为操作模式,Mode为0时执行LIN主机写操作,Mode为1时执行LIN主机读操作,如下图所示:

测试连接图

CAN&LIN Analyser配置

LIN主机(MM32)操作从机(PC)读写通讯

如上图所示,主机写入从机数据和主机读取从机数据,因为PC作为从机没有回复,所以数据为空。


 

  • 在测试LIN从机功能时,需要将CAN&LIN Analyser工要配置为主机工作模式,从机会根据收到的主机数据进行相应的应答回复

测试连接图

CAN&LIN Analyser配置

LIN主机(PC)写数据到从机(MM32)

LIN主机(PC)读取从机(MM32)数据

附件

软件工程源代码:  LIN.zip (2.82 MB)

参考资料:  瑞萨LIN入门.PDF (1.48 MB)

基于MM32F3270通讯板的所有接口功能至此就全部分享结束了,从画板、制板到后面的焊接调试都投入不少精力,在分享这些的同时自己也有很大收获。以连载的形式进行分享,是想把每个部分都尽量描述清楚,有条理些,方便大家理解、学习或者是掌握应用。虽然对于MM32芯片来说使用的外设并不是太多,仅仅用到UART、CAN和SPI接口,但其扩展出来的应用技术却是很广泛的,不能因为使用外设单一或者简单而否定其在实际项目中的应用价值体现,像FatFs的文件系统、Xmodem/Ymodem/Kermit串行通讯协议、以及后面被广泛应用在工业、汽车领域的CAN接口、LIN接口通讯等等,都是我们在项目中常用的技术点。本来还想进行CANopen、CANFestival、LIN的LDF应用等等这些应用层面的分享的,这些跟MM32本身的外设都不相关了,后面有机会再看吧。最后谢谢大伙的关注和支持了!感谢


---------------------
作者:xld0932
链接:https://bbs.21ic.com/icview-3221574-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值