找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6028|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

LIN協(xié)議驅(qū)動(dòng)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:51024 發(fā)表于 2014-8-3 00:49 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
/******************** (C) COPYRIGHT 2010 YongChen Co., Ltd *************

* File Name         : ycc_lin.c
* Author            : tangeping
* Version           : V1.0.0
* Date              : 07/09/2014
* Description       : LIN協(xié)議驅(qū)動(dòng)程序
************************************************************************/
#define  YCC_LIN_GLOBALS
#include "stm32f10x.h"
#include "main.h"
#include <stdio.h>
#include <string.h>
#define BIT(A,B)      ((A>>B)&0x01)
#define CheckSummode   1  //增強(qiáng)型加上ID 一起校驗(yàn)
//#define LinLenMode  0x12//1.2版本ID:D4,D5為數(shù)據(jù)場(chǎng)長(zhǎng)度
#define SLAVE_RX_MODE  0x50//根據(jù)實(shí)際ID來(lái)定義
#define SLAVE_TX_MODE 0x11//隨便寫的ID

#define LIN_HEAD  0x55
#define NODE_MAX  15
#define LEN_MAX8
typedefstruct
{
u8 ID;
u8 len;
u8 ptr[NODE_MAX];
}LIN_Slave;
static LIN_Slave ToSlave_RX[NODE_MAX];
typedefstruct
{
u8 ID;
u8 len;
u8*ptr;
}LIN_Master;
static LIN_Master ToMaster_Tx[NODE_MAX];
static u8 ToSlaveTemp[LEN_MAX];
static u8 ToSlaveWriteOffset,ToSlaveReadOffset;
static u8 ToMasterWriteOffset,ToMasterReadOffset;
static u8 Rx_ReadAddr=1;
u8 const LIN_Len[4]={2,2,4,8};
void Lin_Config(void)
{
   USART_InitTypeDef  USART_InitStructure;/*串口設(shè)置恢復(fù)默認(rèn)參*/
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
   USART_InitStructure.USART_BaudRate = 9600;//LIN高速模式
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   USART_InitStructure.USART_Parity = USART_Parity_No;
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
   USART_Init(UART5, &USART_InitStructure);

   USART_LINBreakDetectLengthConfig(UART5, USART_LINBreakDetectLength_11b);
   USART_LINCmd(UART5, ENABLE);
   USART_Cmd(UART5, ENABLE);
#ifdef USE_LIN_MASTER
   USART_ITConfig(UART5, USART_IT_RXNE,DISABLE);
   USART_ITConfig(UART5, USART_IT_LBD, DISABLE);
#else
   USART_ITConfig(UART5, USART_IT_RXNE,ENABLE);/*先使能接收中斷*/
// USART_ITConfig(UART5,USART_IT_TXE,DISABLE);
   USART_ITConfig(UART5, USART_IT_LBD, ENABLE);/*先使能LIN間隔場(chǎng)檢測(cè)到中斷*/
#endif
}

/*u8 Lin_Response(u8 id,u8 * data, u8 length)
{
u8 i,*ptr;
u16 checksum;
if (length == 0 || length > LEN_MAX)
return 2;

ptr = (u8*)Mem_Malloc(length);

    if (ptr == NULL)
{
return 1;
}
#ifdef CheckSummode
checksum = id;
#else
checksum = 0;
#endif
if (ToMaster_Tx[ToMasterWriteOffset].len== 0)
{
ptr = ToMaster_Tx[ToMasterWriteOffset].ptr ;

for (i=0;i<length;i++)
{
*ptr++ = *data++;
checksum += *(data+i);
if(checksum&0xFF00)
checksum = (checksum&0x00FF)+1;
}
*ptr++ = (u8)((~checksum)&0x00ff);
ToMaster_Tx[ToMasterWriteOffset].len = length+1;
ToMasterWriteOffset = (++ToMasterWriteOffset)%NODE_MAX;
return 0;
}
else
{
Mem_Free(ptr);
}

return 1;
}*/
u8 Lin_Master(u8 id,u8 * data, u8 length)
{
u8 i,*ptr,pid;
u16 checksum;
if (length == 0 || length > LEN_MAX)
return 2;

ptr = (u8*)Mem_Malloc(length+3);

if (ptr == NULL)
{
return 1;
}
pid = (~(BIT(id,1)^BIT(id,3)^BIT(id,4)^BIT(id,5)))<<7;
pid |= (BIT(id,0)^BIT(id,1)^BIT(id,2)^BIT(id,4))<<6;
id = id|pid;
#ifdef CheckSummode
checksum = id;
#else
checksum = 0;
#endif
if (ToMaster_Tx[ToMasterWriteOffset].len== 0)
{
ToMaster_Tx[ToMasterWriteOffset].ptr = ptr;
*ptr++ = LIN_HEAD;
*ptr++ = id;
if(id == SLAVE_RX_MODE)
{
for (i=0;i<length;i++)
{
*ptr++ = *(data+i);
checksum += *(data+i);
if(checksum&0xFF00)
checksum = (checksum&0x00FF)+1;
}
*ptr = (u8)((~checksum)&0x00ff);
ToMaster_Tx[ToMasterWriteOffset].len = length+3;
}
else if(id ==SLAVE_TX_MODE)
{
ToMaster_Tx[ToMasterWriteOffset].len = 2;
}
ToMaster_Tx[ToMasterWriteOffset].ID =id;
ToMasterWriteOffset = (++ToMasterWriteOffset)%NODE_MAX;
return 0;
}
else
{
Mem_Free(ptr);
}

return 1;

}
static void Lin_Send()
{
if (ToMaster_Tx[ToMasterReadOffset].len > 0&& Uart5_TxComplete == ON)
{
Uart5_TxComplete = OFF;
memcpy(Uart5_TxValue,ToMaster_Tx[ToMasterReadOffset].ptr,
ToMaster_Tx[ToMasterReadOffset].len);
USART_SendBreak(UART5);
Uart5_Send_Start(ToMaster_Tx[ToMasterReadOffset].len);
MemFree_BufWrite(ToMaster_Tx[ToMasterReadOffset].ptr);
ToMaster_Tx[ToMasterReadOffset].ptr = NULL;
ToMaster_Tx[ToMasterReadOffset].len = 0;
ToMaster_Tx[ToMasterReadOffset].ID=0;
ToMasterReadOffset = (++ToMasterReadOffset)%NODE_MAX;
}
}
static void Lin_Receive()
{
static u16 cndtr = 0,overtime = 0;
u16 lenght,CheckSum,end,start,addr;
u8 pid,id,i;
if(LinBreak ==ON)
{
end = Uart5_RxCount;
if(cndtr!=end)
{
cndtr = end;
addr =Rx_ReadAddr;
overtime =1;

if (addr > end)
{
end += U5_RXBUF_SIZE;
}
while (addr < end)
{
if(Uart5_RxValue[addr%U5_RXBUF_SIZE]==LIN_HEAD)
{
start= addr;
id = Uart5_RxValue[(addr+1)%U5_RXBUF_SIZE];
pid = (~(BIT(id,1)^BIT(id,3)^BIT(id,4)^BIT(id,5)))<<7;
pid |= (BIT(id,0)^BIT(id,1)^BIT(id,2)^BIT(id,4))<<6;
if(pid == (id&0xC0))
{
#ifdef LinLenMode
lenght= LIN_Len[((id>>4)&0x03)];
#else
lenght= (id == SLAVE_RX_MODE ? 8:4);
#endif
if(lenght > 0 && lenght <= NODE_MAX && addr + lenght + 2 < end)
{
LinBreak =OFF;
addr = addr+2;
if(id == SLAVE_RX_MODE)
{
#ifdef CheckSummode
CheckSum = id;
#else  
CheckSum =0;
#endif
for (i=0; i<lenght; i++)
{
ToSlaveTemp[i] = Uart5_RxValue[(addr++)%U5_RXBUF_SIZE];
CheckSum += ToSlaveTemp[i];
if(CheckSum&0xFF00)
CheckSum = (CheckSum&0x00FF)+1;
}
CheckSum = (u8)((~CheckSum)&0x00ff);

if ((u8)CheckSum == Uart5_RxValue[addr%U5_RXBUF_SIZE])
{
Rx_ReadAddr = (addr+2)%U5_RXBUF_SIZE;
if (ToSlave_RX[ToSlaveWriteOffset].len== 0)
{
memcpy(ToSlave_RX[ToSlaveWriteOffset].ptr,ToSlaveTemp,lenght);
ToSlave_RX[ToSlaveWriteOffset].len = lenght;
ToSlave_RX[ToSlaveWriteOffset].ID =id;
ToSlaveWriteOffset = (++ToSlaveWriteOffset)%NODE_MAX;
}
}
else
{
addr = start;
}
}
else if(id == SLAVE_TX_MODE)
{
//Lin_Response(id,"\x05\x06\x07\x08",4);
}
}
else break;
}
else break;
}
else break;

addr++;
}
}
else if (overtime > 0)
{
overtime = 0;
Rx_ReadAddr = cndtr;
}
}
}
void Lin_IT()
{
#ifdef USE_LIN_MASTER
Lin_Send();
#else
Lin_Receive();
#endif
}
void Lin_Init()
{
u8 i;
Uart5_TxComplete =ON;
LinBreak =OFF;
ToMasterWriteOffset = 0;
ToMasterReadOffset = 0;
for (i=0; i<NODE_MAX; i++)
ToMaster_Tx[i].len= 0;

ToSlaveWriteOffset = 0;
ToSlaveReadOffset = 0;
for (i=0; i<NODE_MAX; i++)
ToSlave_RX[i].len= 0;
Lin_Config();

}
static void Lin_Analyse()
{
//u8*ptr,i,id,lenght,count;
u8 count=0;
while (ToSlave_RX[ToSlaveReadOffset].len != 0&& count++ <NODE_MAX)
{
/*id  = ToSlave_RX[ToSlaveReadOffset].ID;
lenght=ToSlave_RX[ToSlaveReadOffset].len;
ptr =ToSlave_RX[ToSlaveReadOffset].ptr;
if(ptr[0]==0x00)//休眠
{

}*/
ToSlave_RX[ToSlaveReadOffset].len = 0;
ToSlave_RX[ToSlaveReadOffset].ID= 0;
MemFree_BufWrite(ToSlave_RX[ToSlaveReadOffset].ptr);
ToSlaveReadOffset = (++ToSlaveReadOffset)%NODE_MAX;
}

}
void Lin_Main()
{
/*if(Uart5_TxComplete == ON)
{
Uart5_TxComplete = OFF;
Lin_Master(0x10,"\x00\x01\x02\x03\x04\x05\x06\x07",8);
Lin_IT();

}*/
Lin_IT();
Lin_Analyse();
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:37260 發(fā)表于 2014-9-11 09:32 | 只看該作者
樓主,你好,你有沒(méi)有工程文件發(fā)給我一份呢?最近在寫LIN協(xié)議,寫不出來(lái),網(wǎng)上沒(méi)有例程,搞得晚上覺(jué)都睡不好,希望得到樓主的幫助。我的郵箱:wenho@changan.com.cn。   謝謝
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表