/******************** (C) COPYRIGHT 2010 YongChen Co., Ltd *************
* File Name : ycc_lin.c
* Author : tangeping
* Version : V1.0.0
* Date : 07/09/2014
* Description : LIN協議驅動程序
************************************************************************/
#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 //增強型加上ID 一起校驗
//#define LinLenMode 0x12//1.2版本ID:D4,D5為數據場長度
#define SLAVE_RX_MODE 0x50//根據實際ID來定義
#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;/*串口設置恢復默認參*/
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間隔場檢測到中斷*/
#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();
}
|