文章目录

目录

文章目录

前言

一、LIN总线是什么?

1.LIN总线的标准

2.LIN总线形式

3、帧的构成

二、UART模拟LIN从机的实现

1.方案概述

2.串口中断处理

3、同步间隔断中断处理

4、接收中断处理

验证测试

1、CANoe IG发送帧头

2、示波器观测波形

总结



前言

在汽车领域,CAN总线和LIN总线是应用比较多的总线,因此需要对LIN总线有深入的了解。

本文主要梳理关键知识点,帮助大家建立整体的概念,重点在于知识体系的构建。


一、LIN总线是什么?

1.LIN总线的标准

目前各大主机厂广泛会用的是LIN2.1,波特率采用19200。

2.LIN总线形式

LIN在总线上的展现形式,主机发帧头(对比CAN的ID),从机响应数据(对比CAN的8字节数据)

3、帧的构成

同步段为  0x55

ID段为     帧ID+校验

数据段为  帧的数据内容

校验和    数据段字节和ID的校验和

二、UART模拟LIN从机的实现

1.方案概述

用接收中断进行同步段验证、数据接收

用发送中断进行数据和校验的发送

2.串口中断处理

在中断中处理

同步间隔中断

接收中断

发送中断

void UartLIN_Handler(void *device, uint32_t wpara, uint32_t lpara)
{// Receive break fieldif (0 != (lpara & UART_LSR1_FBRK_Msk)){LIN_IfcAux();UART_LIN->LSR1 |= UART_LSR1_FBRK_Msk;   ///<write 1 to clear break status}// Receive dataif (0 != (wpara & UART_LSR0_DR_Msk)){LIN_IfcRx();}// Transmit data doneif (0 != (wpara & UART_LSR0_THRE_Msk)){LIN_IfcTx();}
}

3、同步间隔断中断处理

void LIN_IfcAux(void)
{if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_IDLE){g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;USART_TXE_INT_Enable(USART1_SFR, FALSE);}else{//fprintf("Frame err\r\n");g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;USART_TXE_INT_Enable(USART1_SFR, FALSE);}}
}

4、接收中断处理

void LIN_IfcRx(void)
{uint8_t data = 0, id = 0, index = 0, checksum = 0, frameNum = 0;FRAME_ID_TBL  *frameTable = 0, *frameInfo = 0;data = USART_ReceiveData(USART1_SFR);//fprintf("%02x ", data);if (g_direction == DIR_TX){
#if 0if (data != g_buffer[g_rxCount]){// Send error//fprintf("bit err\r\n");}g_rxCount++;// transmit doneif (g_rxCount == g_tranByte){frameInfo = &g_scheduleTable[g_schTblIdx].schedule[g_frameIdx];if (g_state == LIN_STATE_SEND_SYNC){// Start transmit or receive dataif (frameInfo->dir == DIR_TX){g_state = LIN_STATE_SEND_DATA;g_direction = DIR_TX;g_tranByte = frameInfo->dtl + 1;memcpy((void *)g_buffer, (const void *)frameInfo->data, (unsigned int)g_tranByte - 1);checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,frameInfo->dtl, frameInfo->data);g_buffer[g_tranByte - 1] = checksum;g_txCount = 0;g_rxCount = 0;//UART_SetTXEInterrupt(UART_LIN, ENABLE);USART_Send(USART1_SFR, g_buffer, g_tranByte);}else{g_state = LIN_STATE_RECEIVE_DATA;g_direction = DIR_RX;g_recvByte = frameInfo->dtl + 1;g_rxCount = 0;}}else if (g_state == LIN_STATE_SEND_DATA){// Transmit frame doneg_state = LIN_STATE_IDLE;}}
#endif}else{if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_RECEIVE_SYNC){// Check sync fieldif (data == 0x55){g_state = LIN_STATE_RECEIVE_IDENTIFIER;}else{g_state = LIN_STATE_IDLE;//fprintf("Sync err\r\n");}}else if (g_state == LIN_STATE_RECEIVE_IDENTIFIER){// Check protect idid = data & 0x3F;if (data == LIN_MakeProtId(id)){frameTable = g_scheduleTable[g_schTblIdx].schedule;frameNum = g_scheduleTable[g_schTblIdx].frameNum;for (index = 0; index < frameNum; index++){frameInfo = &frameTable[index];// Find needed idif (id == frameInfo->id){g_frameIdx = index;g_protectId = data;//fprintf("%d\r\n", id);// Start transmit or receive dataif (frameInfo->dir == DIR_TX){g_state = LIN_STATE_SEND_DATA;g_direction = DIR_TX;g_tranByte = frameInfo->dtl + 1;memcpy((void *)g_buffer, (const void *)frameInfo->data, g_tranByte - 1);checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,frameInfo->dtl, frameInfo->data);g_buffer[g_tranByte - 1] = checksum;g_txCount = 0;g_rxCount = 0;//UART_SetTXEInterrupt(UART_LIN, ENABLE);//USART_Send(USART1_SFR, g_buffer, g_tranByte);USART_TXE_INT_Enable(USART1_SFR, TRUE);//delay_us(2);//g_state = LIN_STATE_IDLE;//g_direction = DIR_RX;//g_txCount = 0;//g_rxCount = 0;}else{g_state = LIN_STATE_RECEIVE_DATA;g_direction = DIR_RX;g_recvByte = frameInfo->dtl + 1;g_rxCount = 0;}break;}}// Not needed idif (index == frameNum){g_state = LIN_STATE_IDLE;//fprintf("Err Id:0x%x\r\n", data);}}else{g_state = LIN_STATE_IDLE;//fprintf("Pid:0x%x err\r\n", data);}}else if (g_state == LIN_STATE_RECEIVE_DATA){if (g_rxCount < g_recvByte){g_buffer[g_rxCount] = data;g_rxCount++;}// Receive frame doneif (g_rxCount == g_recvByte){frameInfo = &g_scheduleTable[g_schTblIdx].schedule[g_frameIdx];checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,g_recvByte - 1, g_buffer);if (checksum == g_buffer[g_rxCount - 1]){// Checksum is successful.// Save datamemcpy((void *)frameInfo->data, (const void *)g_buffer, g_rxCount - 1);}else{// Checksum is failed.//fprintf("Cs err\r\n");}g_state = LIN_STATE_IDLE;}}else{}}}
}

发送中断处理

void LIN_IfcTx(void)
{if (g_direction == DIR_TX){if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_SEND_DATA){// Send dataif (g_txCount < g_tranByte){//UART_SendData(UART_LIN, g_buffer[g_txCount]);USART_SendData(USART1_SFR, g_buffer[g_txCount]);g_txCount++;if (g_txCount == g_tranByte){//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);}}else{//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;}}else{//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);}}}
}

数据结构和变量


typedef enum
{LIN_STATE_IDLE,                  ///< Idle stateLIN_STATE_SEND_BREAK,            ///< Send break stateLIN_STATE_RECEIVE_BREAK,         ///< Receive break stateLIN_STATE_SEND_SYNC,             ///< Send sync stateLIN_STATE_RECEIVE_SYNC,          ///< Receive sync stateLIN_STATE_SEND_IDENTIFIER,       ///< Send identifier stateLIN_STATE_RECEIVE_IDENTIFIER,    ///< Receive identifier stateLIN_STATE_SEND_DATA,             ///< Send data stateLIN_STATE_RECEIVE_DATA,          ///< Receive data stateLIN_STATE_SEND_CHECKSUM,         ///< Send checksum stateLIN_STATE_BUSSLEEP               ///< Bus sleep state
} lin_ifcState;typedef struct {uint8_t  id;               ///< LIN message frame ID for this frameuint8_t  dir;              ///< Name of the node that publishes the datauint8_t  cst;              ///< Type of checksum to be used (enhanced or classic)uint8_t  dtl;              ///< Number of bytes in the data fielduint16_t  delayTime;       ///< Actual slot time in ms for the frameuint8_t  *data;            ///< Address of the structure that lists the signals
} FRAME_ID_TBL;typedef struct {uint8_t  frameNum;         ///< Number of frame slots in the schedule tableFRAME_ID_TBL  *schedule;   ///< Address of the schedule table
} SCHEDULE_TBL;//#define UART_LIN        UART1// Checksum type
#define    ENHANCED_CHECKSUM    0    ///< Enhanced checksum type
#define    CLASSIC_CHECKSUM     1    ///< Classic checksum type// Direction
#define    DIR_RX               0    ///< receive direction
#define    DIR_TX               1    ///< transmit direction// Node mode
#define    MASTER_MODE          0    ///< master mode
#define    SLAVE_MODE           1    ///< slave modeextern void LIN_IfcRx(void);
extern void LIN_IfcAux(void);
extern void LIN_IfcTx(void);
extern void LinSlaveInit(void);void LinSlaveInit(void)
{}uint8_t g_LinData[4][8] =
{{0xA1,0xB2,0xC3,0xD4,0xE5,0xF6,0x97,0x88},{0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28},{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08},{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08},
};///< Master send header and receive data
FRAME_ID_TBL g_frameTable1[] =
{{0x23, 1, 0, 3, 60, g_LinData[0]},{0x21, 0, 0, 8, 60, g_LinData[1]}
};///< Schedule table
SCHEDULE_TBL g_scheduleTable[] =
{{2, &g_frameTable1[0]}
};uint32_t g_sendTimes = 0xFFFF; ///< Send frame timesuint8_t g_mode = SLAVE_MODE;          ///< Master or slave mode
uint8_t g_state = 0;         ///< Lin state
uint8_t g_schTblIdx = 0;     ///< Schedule table index
uint8_t g_frameIdx = 0;      ///< Frame index
uint8_t g_protectId = 0;     ///< Protect id
uint8_t g_firstFlag = 1;     ///< First time flaguint8_t g_direction = 0;     ///< Send direction
uint8_t g_tranByte = 0;      ///< Need transmit bytes
uint8_t g_recvByte = 0;      ///< Need receive bytes
uint8_t g_txCount = 0;       ///< Transmit data count
uint8_t g_rxCount = 0;       ///< Receive data count
uint8_t g_autoBaud = 0;      ///< Auto baud rate
uint8_t g_breakThre = 1;     ///< Break threshold
uint8_t g_buffer[20] = {0};  ///< Data bufferuint8_t LIN_MakeProtId(uint8_t idData)
{union {uint8_t  byte;struct {uint8_t  d0: 1;uint8_t  d1: 1;uint8_t  d2: 1;uint8_t  d3: 1;uint8_t  d4: 1;uint8_t  d5: 1;uint8_t  p0: 1;uint8_t  p1: 1;} bit;} buf;/* Load the desired message frame ID into the LSBits of the buffer.  */buf.byte = idData & (uint8_t)0x3F;/* Set the two parity bits.  */buf.bit.p1 = ~(buf.bit.d1 ^ buf.bit.d3 ^ buf.bit.d4 ^ buf.bit.d5);buf.bit.p0 = buf.bit.d0 ^ buf.bit.d1 ^ buf.bit.d2 ^ buf.bit.d4;return buf.byte;
}uint8_t LIN_MakeChecksum(uint8_t protectId, uint8_t length, uint8_t *data)
{uint8_t i = 0, checksum = 0;uint16_t sum = protectId;for (i = 0; i < length; i++){sum += data[i];if (sum >= 0x100){sum -= 0xFF;}}checksum = ~(uint8_t)sum;return checksum;
}

验证测试

1、CANoe IG发送帧头

2、示波器观测波形


总结

利用串口可以完美模拟从机,发送和接收采用中断的形式有利于提高程序的执行效率。

5.1的最后一天假,完美收官

LIN总线解析与UART模拟LIN从机实战相关推荐

  1. LIN总线uart形式实现lin通信

    LIN是Local Interconnect Network的缩写,是基于UART/SCI(Universal Asynchronous Receiver-Transmitter/Serial Com ...

  2. lin总线可以控制几个节点_LIN主从节点设计与实现

    LIN(LocalInterconnect Network)是一种低速汽车网络,采用单主多从.异步串行通信方式,定位于现有汽车网络(如CAN总线)的辅助和补充,目的是以低廉的价格联接车上的传感器.执行 ...

  3. 细说汽车电子通信总线之LIN总线协议详解

    内容提要 1. LIN总线概述 1.1 LIN总线特点及发展历史 1.2 LIN 总线协议的物理层(收发器) 2. LIN总线报文帧结构(Message Frame Structure)详解 2.1 ...

  4. lin通讯从节点同步间隔场_基于LIN总线的汽车分级制网络结构

    原标题:基于LIN总线的汽车分级制网络结构 1.引言 汽车总线中通讯节点和数据流量持续增加,节点日益复杂,使得汽车总线在重量.布置.成本.通信效率等方面面临困境,走出这一困境的出路在于实行汽车总线的网 ...

  5. 从应用角度了解下LIN总线

    导读 本文将介绍LIN(Local Interconnect Network,本地连接网络)协议的基本知识,包括LIN总线和CAN总线的对比.LIN总线的应用案例.LIN是如何运行的以及LIN中的6种 ...

  6. “保姆级”车载LIN总线教程(三)-堪称全网“最细”系列

    目录 1.无条件帧(Unconditional Frame) 2.事件触发帧(Event Triggered Frame) 3.零星帧/偶发帧(Sporadic Frame) 4.诊断帧(Diagno ...

  7. 车用技术总线 | 从应用角度了解下LIN总线

    注意:本文约4850字,完整阅读时间约13分钟. 主要内容 LIN总线概述 LIN总线的应用 示例:LIN总线和CAN总线的窗户控制 LIN总线的信号报文 记录LIN总线数据 LIN总线数据记录应用案 ...

  8. LIN总线入门到精通第一讲

    目录 1.车载LIN总线诞生背景和使用场景 2.LIN总线硬件接口 3.LIN总线协议 4.总结 ->返回总目录<- 1.车载LIN总线诞生背景和使用场景 LIN:Local Interc ...

  9. lin总线可以控制几个节点_[LIN].LIN总线详解

    花点时间看了一些关于LIN总线基础的内容,把其中的关键点提取了出来,在这里分享给大家.在这里你可能要问"不都有CAN总线了吗?这个LIN总线又是从哪里来的?"其实理由很简单,就是C ...

最新文章

  1. 装java 无法应用转换程序_应用程序崩溃“android.app.Application无法强制转换为”...
  2. 最通俗的机器学习介绍
  3. Keyboard驱动中button中断的处理机制
  4. Freebsd下如何安装配置ssh
  5. C4.5决策树 此博文包含图片 (2011-10-20 23:22:19)转载▼ 标签: 分类树
  6. centos7下安装低版本mysql_centos7下使用yum安装制定版本mysql
  7. mysql中的操作指令,MySQL中常用指令操作的介绍(代码示例)
  8. 商城系统php功能模块,yershop商城系统的支付模块问题
  9. 知识技能归档--CA-PKI体系-20210324
  10. Jawin –Java/Win32互动项目 可调用DLL及COM的调用项目
  11. 【Python】一句话 if else 简洁写法
  12. java分布式商城项目环境搭建1-CentOS7.6-安装JDK1.8
  13. 递增三元数组——第九届蓝桥杯C语言B组(省赛)第六题
  14. 离线服务器系统补丁如何打,Win系统补丁要不要打?如何打补丁才最适合?
  15. 老男孩python全栈3期_Python/Python3视频教程2017老男孩Python全栈工程师3期基础Python3.5...
  16. 02块级标签和内联标签的区别
  17. BMZCTF:insomniteaser_2019_l33t_hoster
  18. hazelcast java_Hazelcast入门教程
  19. c枚举类型enum例题_c语言之枚举类型(enum)
  20. 康耐视VisionPro工业标定

热门文章

  1. 农业物联网的六大应用场景
  2. Android App 优化之 Layout 怎么摆
  3. 如何监控Windows进程的句柄资源
  4. C++常用数据结构或技巧
  5. getTime()得到时间戳不一样
  6. 如何用java打印1-100_在java中使用10个线程打印1到100
  7. ai描边工具怎么打开_ai轮廓化描边在哪 轮廓化描边快捷键,需要技巧
  8. 让战略落地到运营的PMO实施经验分享——亚马逊全球新兴市场PMO负责人宋晓雪
  9. ICCV 2021 | 美团“LargeFineFoodAI“研讨会开幕在即,互动有奖
  10. GD32F4xx uIP协议栈移植记录