⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lin.c

📁 mc9s08dz60的LIN部件例子程序,很不容易找到的.
💻 C
字号:
/////////////////////////////////////////////////////////////////////////////////////////
//
// LIN Sample for Freescale EVB9S08DZ60
// LIN communication data from master to slave
//
// --------------------------------------------------------------------------------------
//
// Copyright (c) 2006 SofTec Microsystems
// http://www.softecmicro.com/
//
/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////
//
// NOTES:
//
// - LIN bus communication is set to work about at 20Kb/s.
// - Only standard checksum is used.
//
/////////////////////////////////////////////////////////////////////////////////////////

#include "derivative.h"
#include "lin.h"

/////////////////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////////////////

struct frame rx;

/////////////////////////////////////////////////////////////////////////////////////////
// LINInit
// --------------------------------------------------------------------------------------
// SCI Peripheral Initialization
/////////////////////////////////////////////////////////////////////////////////////////
void LINInit(void)
{

  int sbr,i;
  
  // Calculates SCI baud rate value
  sbr=(SCI_CLOCK/SCI_BAUDRATE/16);
  SCI1BDH =(unsigned char)(sbr>>8);
  SCI1BDL =(unsigned char)sbr;
  //Enable SCI0 and receiver interrupt  
  SCI1C2 =0x2C;
  // Break character is 13 or 14 bit long
  SCI1S2=0x04;  
  // Initializes LIN receive frames
  rx.protected_id=0;
  rx.state=IDLE;
  rx.error=0;
  rx.check=0;
  for (i=0;i<MAX_DATA;i++)
    rx.data[i]=0;
    
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINCalcParity
// --------------------------------------------------------------------------------------
// LIN Parity Calculation Routine
/////////////////////////////////////////////////////////////////////////////////////////
unsigned char LINCalcParity(unsigned char id)
{
  
  unsigned char 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;

}

/////////////////////////////////////////////////////////////////////////////////////////
// LINCalcChecksum
// --------------------------------------------------------------------------------------
// LIN Checksum Calculation Routine
/////////////////////////////////////////////////////////////////////////////////////////
unsigned char LINCalcChecksum(unsigned char *data)
{

  unsigned int sum = 0;
  unsigned char i;

  for(i = 0; i < MAX_DATA; i++)
  {
    sum += data[i];
    if(sum&0xFF00)
      // Adds carry
      sum = (sum&0x00FF) + 1;
  }
  sum ^= 0x00FF;
  return (unsigned char)sum;
  
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINGetChar
// --------------------------------------------------------------------------------------
// SCI data receive routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINGetChar(void)
{

  unsigned volatile char ch;
  
  // State of the LIN receive channel
  switch(rx.state++)
  {
    case IDLE:
      if(!(SCI1S1&0x22))
        return(FALSE);  
      if(SCI1D)
        return(FALSE);
      break;
    case _BREAK:
      if(!(SCI1S1&0x20))
        return(FALSE);
      if(SCI1D != 0x55)
        return(FALSE);   
      break;  
    case SYNCH:
      if(!(SCI1S1&0x20))
        return(FALSE); 
      ch = SCI1D;
      rx.protected_id = ch;
      break;   
    case PROTECTED_IDENTIFIER:
    case DATA_0:
    case DATA_1:
    case DATA_2:
    case DATA_3:
    case DATA_4:
    case DATA_5:
    case DATA_6:
      if(!(SCI1S1&0x20))
        return(FALSE); 
      ch = SCI1D;
      rx.data[rx.state-DATA_0] = ch;
      if((rx.state-DATA_0+1) == MAX_DATA)
        rx.state = DATA_7;
      break;
    case DATA_7:
      if(!(SCI1S1&0x20))
        return(FALSE); 
      ch = SCI1D;
      rx.check = ch;
      break;
    case CHECKSUM:
      return(FALSE);  
  }
  return(TRUE);
  
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINGetMsg
// --------------------------------------------------------------------------------------
// LIN Message Receive Routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINGetMsg(Bool get_data, struct  message *msg)
{
  
  unsigned char i;
    
  if(rx.state < PROTECTED_IDENTIFIER)
    return FALSE;
  msg->identifier = (rx.protected_id&0x3F);
  if (get_data)
  {
    if(rx.state == CHECKSUM) 
    {
      for(i = 0; i < MAX_DATA; i++)
        msg->data_field[i] = rx.data[i];
      rx.state = IDLE;
    }
    else
      for(i = 0; i < MAX_DATA; i++)
        msg->data_field[i] = 0;
  }      
  return(TRUE);
     
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINCheckSend
// --------------------------------------------------------------------------------------
// Sent byte field check routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINCheckSend(enum lin_state status, unsigned char val)
{

  // While until sci data has been received 
  while(rx.state < status)
    if(rx.error)
      return(FALSE);
    
  switch(status) 
  {
    case _BREAK:
    case SYNCH:
      break;
      
    case PROTECTED_IDENTIFIER:
      if(rx.protected_id != val)
        return(FALSE);
      break;
        
    case DATA_0:
    case DATA_1:
    case DATA_2:
    case DATA_3:
    case DATA_4:
    case DATA_5:
    case DATA_6:
    case DATA_7:
      if(rx.data[status-DATA_0] != val)
        return(FALSE);
      break;
        
    case CHECKSUM:
      if(rx.check != val)
        return(FALSE);
      break;
        
  }
  return(TRUE);
  
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINSendChar
// --------------------------------------------------------------------------------------
// SCI byte fields sending routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINSendChar(Bool brk, unsigned char ch)
{

  // Waits until transmit data registry is empty (TDRE=1)
  while(!(SCI1S1&0x80))
    ;
  // If break field, transmits one break character (13-14 bits of dominant value) 
  if(brk) 
  {
    SCI1C2 |= 0x01;
    SCI1C2 &= ~0x01;
  }
  else
    SCI1D = ch;
  return(TRUE);
  
}

/////////////////////////////////////////////////////////////////////////////////////////
// LINSendMsg
// --------------------------------------------------------------------------------------
// LIN Message Sending Routine
/////////////////////////////////////////////////////////////////////////////////////////
Bool LINSendMsg(Bool master, Bool send_data, struct message msg)
{

  unsigned char check_sum, parity_id, i;
  
  rx.error = 0;
  
  if(master) 
  {
    // Sends break feald
    if(!LINSendChar(TRUE, 0x00))
      return(FALSE);
    // Check break sending
    if(!LINCheckSend(_BREAK, 0x00))
      return(FALSE);       
    // Sends synch feald
    if(!LINSendChar(FALSE, 0x55))
      return(FALSE);
    // Checks synch sending
    if(!LINCheckSend(SYNCH, 0x55))
      return(FALSE);    
    parity_id=LINCalcParity(msg.identifier);
    // Sends protected identifier feald
    if(!LINSendChar(FALSE, parity_id))
      return(FALSE);
    // Checks protected identifier sending
    if(!LINCheckSend(PROTECTED_IDENTIFIER, parity_id))
      return(FALSE);  
  }  
  if(send_data)
  {
    for(i=0; i < MAX_DATA; i++) 
    {
      // Sends data field 
      if(!LINSendChar(FALSE, msg.data_field[i]))
        return(FALSE);
      // Checks data sending
      if(!LINCheckSend(DATA_0+i, msg.data_field[i]))
        return(FALSE); 
    }
    check_sum = LINCalcChecksum(msg.data_field);
    // Sends checksum field
    if(!LINSendChar(FALSE, check_sum))
      return(FALSE);
    // Checks checksum sending
    if(!LINCheckSend(CHECKSUM, check_sum))
      return(FALSE);
    rx.state = IDLE;
  }

  return(TRUE);

}

/////////////////////////////////////////////////////////////////////////////////////////
// LINCheckMsg
// --------------------------------------------------------------------------------------
// LIN State Check Routine
/////////////////////////////////////////////////////////////////////////////////////////
enum lin_state LINCheckState(void)
{

  return rx.state;  
  
}

/////////////////////////////////////////////////////////////////////////////////////////
// SCI1_RX
// --------------------------------------------------------------------------------------
// SCI1 receive interrupt service routine
/////////////////////////////////////////////////////////////////////////////////////////
interrupt void SCI1_RX(void)
{ 
 
  if(!LINGetChar()) 
  {
    rx.error = 1;
    rx.state = IDLE;
  }
  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -