在线时间352 小时
UID2053419
注册时间2014-11-27
NXP金币0
TA的每日心情 | 衰 2016-10-20 09:45 |
---|
签到天数: 1 天 [LV.1]初来乍到
版主
- 积分
- 2223
- 最后登录
- 2023-11-20
|
本帖最后由 花溪村长 于 2015-12-15 09:39 编辑
很早之前就想发LIN的东西了,一直没空,今天事情忙完了,把最近学习的LIN协议整理归纳下,Make一下,公司折腾S12,没办法就先用S12实验,后面再上KEA系列的!其中可能有些地方有些问题,欢迎各位大神拍砖~
下面开始纯手打!可能会写得比较乱!
先来LIN的基础知识
一、帧的结构
帧包括帧头和应答两部分,主机发送帧头,从机接收帧头并解析内容,然后确认发送应答或者是接收应答还是不做处理。帧的传输如下图
帧头包括同步间隔断、同步段、受保护PID段;应答包括数据段和校验和段。总线实行线与关系,显性覆盖隐形.帧的结构如下:
1同步间隔段
[size=10.5000pt]同步间隔段由同步间隔和同步间隔段间隔符组成,同步间隔至少持续13位的显性电平。从机检测到总线上出现持续11位的显性电平则认为是帧开始!
2 同步段
同步段以下降沿为判断标志,采用0x55为标志
3 受保护ID段
受保护ID段由前6位的帧ID和后两位奇偶校验位组成
帧ID范围一般为0x00~0x3F之间,奇偶校验由异或和取非运算帧ID得到,计算公式如下,由公式可知PID不会全0或全1
不同车企对帧的的类型有不同的定义,一般的分类如下:
4 数据段
数据段包含1-8个字节,先发送编号最低的字节,编号依次增加。
数据段包括信号和诊断消息
5 校验和段
检验和段是对帧中所传内容进行校验
检验和分为标准型和增强型,标准型只需要校验数据段,而增强型需要校验PID和数据段
检验方法是将检验对象的各个字节进行带进位二进制加法,当结果大于0xFF时,结果减去0xFF,并将最终结果取反。接收方对接收数据进行相同操作,结果不取反,然后和接收到的校验和相加,如果相加等于0xFF则校验无误。
来个总线波形
二、FSL HCS12 SCI用作LIN
下面以S12G128来进行LIN传输,由于感觉LIN的API函数太复杂了!只是简单的数据传输,不涉及到网络管理及诊断功能。
SCI主要设置波特率和间隔符
设置 SCISR2 BRK13 设置13位间隔符 用于LIN的帧间隔段
设置SCICR2的SBK发送间隔符
硬件电路如图使用的是NXP的TJA1020
工作模式
按照LIN的协议编写程序,然后下载调试,发送PID为0x30,数据8位 0~7,总线上的波形如下
(PS :安捷伦的示波器!以前还可以解析LIN的协议,30天试用!现在不能用了!需要License!坑爹啊!!!)
然后问同事接了个X宝淘的蓝宙的USB-LIN测试下
运行下软件:
最后附上部分源代码:
花样玩S12,灰常熟悉的代码有木有!直接写成自己熟悉的库来玩!
- /**
- * @brief LIN初始化
- * @param SCIx SCI通道 baud 波特率
- * @retval
- */
- void LIN_Init(SCI_Type *SCIx ,uint32 baud)
- {
- uint8 i ;
- GPIO_InitTypeDef GPIO_InitStruct;
-
- SCIx->SR2 &= 0x7f ; // 设置AMAP
- SCIx->BD = SystemBusClock/16/baud; //设置SCI波特率
- SCIx->CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验
- SCIx->CR2 = 0x2c; //允许接收和发送数据,允许接收中断功能
- SCIx->SR2 |=1<<2; //设置BRK13 13位间隔符
-
-
- //初始化接收结构体
- Frame_Receive.PID=0;
- Frame_Receive.State=IDLE;
- Frame_Receive.Error=0;
- Frame_Receive.Check=0;
- for (i=0;i<8;i++)
- Frame_Receive.Data[i]=0;
-
- //设置正常模式
- GPIO_InitStruct.GPIO_Pin =Pin5; //选择引脚
- GPIO_InitStruct.State =SET; //初始化状态
- GPIO_InitStruct.Mode = GPIO_Mode_OUT; //设置输出
- GPIO_Init(GPIOJ,&GPIO_InitStruct); //初始化
-
- }
复制代码- /**
- * @brief 发送同步间隔段
- * @param
- * @retval
- */
- void LIN_SendBreak(SCI_Type *SCIx)
- {
- while(!(SCIx->SR1&0x80)); //等待发送数据寄存器(缓冲器)为空
- SCIx->CR2 |= 0x01; //队列待发送的中止字符
- SCIx->CR2 &= 0xfe; //返回正常发送操作
- }
- /**
- * @brief LIN发送字节函数
- * @param
- * @retval
- */
- void LIN_SendChar(SCI_Type *SCIx,uint8 ch)
- {
- while(!(SCIx->SR1&0x80)); //等待发送数据寄存器(缓冲器)为空
- SCIx->DRL = ch;
- }
- /**
- * @brief LIN奇偶校验计算
- * @param
- * @retval
- */
- uint8 LIN_CalcParity(uint8 id)
- {
- uint8 parity, p0,p1;
- parity=id;
- p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6; //偶校验位
- p1=(!(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7; //奇校验位
- parity|=(p0|p1);
- return parity;
- }
- /**
- * @brief LIN校验和计算
- * @param
- * @retval
- */
- uint8 LIN_CalcChecksum(uint8 id,uint8 *data,uint8 length)
- {
- uint8 i;
- uint16 check_sum = 0;
- //0x3C 0x3D 使用标准型校验
- if(id != 0x3c && id != 0x7d) //使用增强型校验
- {
- check_sum = id ;
- }
- else //使用标准校验
- {
- check_sum = 0 ;
- }
- for (i = 0; i < length; i++)
- {
- check_sum += *(data++);
-
- if (check_sum > 0xFF) //进位
- {
- check_sum -= 0xFF;
- }
- }
- return (~check_sum); //取反
- }
- /**
- * @brief LIN发送函数
- * @param
- * @retval
- */
- Bool LIN_Send_Msg(SCI_Type *SCIx,LIN_Msg *SendMsg)
- {
- uint8 pid ,i ,check_sum;
- if(SendMsg->ID == 0xff||SendMsg->ID == 0x00)
- return (FALSE);
- //发送间隔同步段
- LIN_SendBreak(SCIx);
-
- //发送同步场
- LIN_SendChar(SCIx,0x55);
-
- //计算PID
- pid = LIN_CalcParity(SendMsg->ID);
- //发送PID
- LIN_SendChar(SCIx,pid);
-
- //发送数据场
- for(i=0; i <SendMsg->length ; i++) //SendMsg->length
- {
- // 发送数据场
- LIN_SendChar(SCIx,SendMsg->Data[i]); //SendMsg->Data[i]
- }
- //计算校验和 SendMsg->ID &SendMsg->Data SendMsg->length
- check_sum = LIN_CalcChecksum(pid,SendMsg->Data,SendMsg->length);
- LIN_SendChar(SCIx,check_sum);
- return(TRUE);
- }
复制代码- /**
- * @brief LIN接收中断
- * @param
- * @retval
- */
- #pragma CODE_SEG __NEAR_SEG NON_BANKED
- void interrupt VectorNumber_Vsci1 LINreceive(void)
- {
- if(!LIN_GetChar(SCI1))
- {
-
- Frame_Receive.Error = 1;
- Frame_Receive.State = IDLE;
- }
- }
- #pragma CODE_SEG DEFAULT
复制代码- LIN_Msg msg ;
- uint8 i ;
- msg.ID = 0x30;
- msg.length = 8 ;
- for(i = 0 ;i<msg.length;i++)
- msg.Data[i] = i ;
- for(;;)
- {
- LIN_Send_Msg(SCI1,&msg);
- GPIO_ToggleBits(GPIOT,Pin6);
- delay(400);
- }
复制代码 最后附上LIN文件:
LIN.rar
(2.4 KB, 下载次数: 833)
|
|