CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

About LIN BUS 2.0
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mickey231bhq



Joined: 06 Apr 2005
Posts: 19
Location: Formosa

View user's profile Send private message

PostPosted: Fri Oct 14, 2005 8:04 am     Reply with quote

No matter UART or EUART can realize LIN BUS, the method to just realize is difficult or easy.
It is relatively easy to use EUART to realize.
Smile
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Fri Feb 10, 2006 1:45 pm     Reply with quote

Hi All!

A year ago I unsuccesfully tried to find any information about LIN bus on the CCS forum. And now LIN bus topics are here! Very Happy

I have successfully transferred LIN bus code from Microchip examples to CCS for both master and slave nodes. It works fine, but it is not made as one completed driver yet. I am using PIC18F4680 for master node and PIC18F1320 for slave node.

As for LIN bus to RS-232 converter, it can easily be made by connection MCP201 and MAX232 chips together with getting +5V from MCP201 built-in voltage regulator. After that LIN bus activity can be viewed via Serial Port Monitor in CCS IDE.
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sat Feb 11, 2006 1:33 am     Reply with quote

Hi Alex,

My work on LIN BUS stopped because I haven't time to going on, but itsn't complete.

Is possible to try your the code ?

otherwyse let us know.

Bye
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Sat Feb 11, 2006 5:16 am     Reply with quote

Hi Fabri,

Yes, it's OK. Do you have any tool to monitor LIN bus activity?
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 1:22 am     Reply with quote

Hi Alex,

Yes I have an SEDES rs232-lin bus converter.
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:17 pm     Reply with quote

Fabri,

A code, which I am giving you now, is for LIN Master node. You can see the LIN Master messages via RS-232 and Serial Port Monitor. It should be repeated sequence

00 55 C4 00 00 FF
00 55 C4 02 00 FD
00 55 C1

The code for LIN Master is a LIN piece of Microchip example code for PICDEM CAN-LIN 3, translated to CCS. The example code can be downloaded from
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010064
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:19 pm     Reply with quote

Main file

Code:

// Main program file (LIN)

// Header files
#include "Board.h"

#include "Timers.h"
#include "HW.h"
#include "USART.h"
#include "LIN.h"

#include "RegBits18F4680.h"
#include "Regs18F4680.h"

// Code files
#include "Board.c"

#include "Timers.c"
#include "HW.c"
#include "USART.c"
#include "LIN.c"

void main()
{
   int8 buf[8];
   int8 myid=4;
   int8 myid1=1;

   B_FlashOnStart();
   delay_ms(500);

   // Preliminary actions
   timerSetup();
   linSetup();

   printf("Start Program\n\r");

   buf[0]=255;
   buf[1]=0;
   buf[2]=0;
   linWriteMessage(myid, buf);

   // Main cycle
   while (TRUE)
   {
      // WDT
      if (TRUE)
      {
         restart_wdt();
      }

      // Off cycle
      output_high(LIN_WAKE_PIN);
      output_high(R_LED);
      delay_ms(100);

      buf[0]=0;
      buf[1]=0;
      buf[2]=255;
      linWriteMessage(myid, buf);
      delay_ms(1000);
      output_low(LIN_WAKE_PIN);
      output_low(R_LED);
      delay_ms(500);

      // On cycle
      output_high(LIN_WAKE_PIN);
      output_high(Y_LED);
      delay_ms(100);

      buf[0]=2;
      buf[1]=0;
      buf[2]=252;
      linWriteMessage(myid, buf);
      delay_ms(1000);
      output_low(LIN_WAKE_PIN);
      output_low(Y_LED);
      delay_ms(500);

      // Read cycle
      output_high(LIN_WAKE_PIN);
      output_high(G_LED);
      delay_ms(100);

      buf[0]=0;
      buf[1]=0;
      buf[2]=0;
      linReadMessage(myid1, buf);
      printf("%u %u %u \n\r", buf[0], buf[1], buf[2]);
      delay_ms(1000);
      output_low(LIN_WAKE_PIN);
      output_low(G_LED);
      delay_ms(500);

   }
}
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:28 pm     Reply with quote

Board.h

Code:

// PIC Board

#include <18F4680.h>
#fuses H4, WDT4096, NOPROTECT
#use delay(clock=40000000)

// Settings for RS-232
#use rs232(baud=9600, xmit=PIN_B0, rcv=PIN_B1, BITS=8, PARITY=N)

// LEDs for output
#define G_LED     PIN_A0
#define Y_LED     PIN_A1
#define R_LED     PIN_A2

#define G2_LED     PIN_D5
#define Y2_LED     PIN_D6
#define R2_LED     PIN_D7

#define LIN_WAKE_PIN     PIN_C5

// Function declarations
void B_FlashOnStart();


Timers.h

Code:

// Timers Functions

#ifndef __TIMERS_H
#define __TIMERS_H

/* used to hold 16-bit timer value */
union Timers
{
  unsigned int16 lt;
  char bt[2];
};

/* Interrupt bit mask to be 'anded' with the other configuration masks and
 * passed as the 'config' parameter to the 'open' routines. */
#define TIMER_INT_OFF  0b01111111  // Interrupts disabled
#define TIMER_INT_ON   0b11111111  // Interrupts enabled

// Replace this line to another cofiguration or header file
#define __TIMER3

#ifdef __TIMER3

/* TIMER3 configuration masks -- to be 'anded' together and passed to the
 * 'open' routine. */
#define T3_8BIT_RW      0b11111110 // 8-bit mode
#define T3_16BIT_RW     0b11111111 // 16-bit mode
#define T3_PS_1_1       0b11001111 // 1:1 prescale value
#define T3_PS_1_2       0b11011111 // 1:2 prescale value
#define T3_PS_1_4       0b11101111 // 1:4 prescale value
#define T3_PS_1_8       0b11111111 // 1:8 prescale value
#define T3_OSC1EN_OFF   0b11111101 // Timer 3 oscillator enable off
#define T3_OSC1EN_ON    0b11111111 // Timer 3 oscillator enable on
#define T3_SYNC_EXT_ON  0b11111011 // Synchronize external clock input
#define T3_SYNC_EXT_OFF 0b11111111 // Do not synchronize external clock input
#define T3_SOURCE_INT   0b11111101 // Internal clock source
#define T3_SOURCE_EXT   0b11111111 // External clock source

// Function declarations
void OpenTimer3 (unsigned char config);
//void CloseTimer3 (void);
unsigned int16 ReadTimer3 (void);
//void WriteTimer3 (PARAM_SCLASS unsigned int16 timer3);

#endif // __TIMER3

// Variables

#endif // __TIMERS_H



HW.h

Code:

// Some hardware Functions

#ifndef __HW_H
#define __HW_H

#define FOSC 40000000L // Oscillator frequency

#define TIMERFREQ 95 // Approx timer frequency in Hz
#define TIMERHFREQ 10000000L // The frequency of the high speed timer

typedef unsigned int16 timerT;

void timerSetup(void);
timerT timerGetValue(void);
#define timerHGetValue() ReadTimer3()

// Variables
int16 timerIntCount;
static timerT tc;


#endif // __HW_H



USART.h

Code:

// Hardware USART Functions

#ifndef __USART_H
#define __USART_H

/* Configuration bit masks to be 'anded' together and passed as the 'config'
 * parameter to the 'open' routine. */
#define USART_TX_INT_ON   0b11111111  // Transmit interrupt on
#define USART_TX_INT_OFF  0b01111111  // Transmit interrupt off
#define USART_RX_INT_ON   0b11111111  // Receive interrupt on
#define USART_RX_INT_OFF  0b10111111  // Receive interrupt off
#define USART_BRGH_HIGH   0b11111111  // High baud rate
#define USART_BRGH_LOW    0b11101111  // Low baud rate
#define USART_CONT_RX     0b11111111  // Continuous reception
#define USART_SINGLE_RX   0b11110111  // Single reception
#define USART_SYNC_MASTER 0b11111111  // Synchrounous master mode
#define USART_SYNC_SLAVE  0b11111011  // Synchrounous slave mode
#define USART_NINE_BIT    0b11111111  // 9-bit data
#define USART_EIGHT_BIT   0b11111101  // 8-bit data
#define USART_SYNCH_MODE  0b11111111  // Synchronous mode
#define USART_ASYNCH_MODE 0b11111110  // Asynchronous mode

/* The baud configuration bit masks to be 'anded' together and passed to
 * the 'baud' routine. */
// For enhanced USART only
#define BAUD_IDLE_CLK_HIGH  0b11111111  // idle state for clock is a high level
#define BAUD_IDLE_CLK_LOW   0b11101111  // idle state for clock is a low level
#define BAUD_16_BIT_RATE    0b11111111  // 16-bit baud generation rate
#define BAUD_8_BIT_RATE     0b11110111  // 8-bit baud generation rate
#define BAUD_WAKEUP_ON      0b11111111  // RX pin monitored
#define BAUD_WAKEUP_OFF     0b11111101  // RX pin not monitored
#define BAUD_AUTO_ON        0b11111111  // auto baud rate measurement enabled
#define BAUD_AUTO_OFF       0b11111110  // auto baud rate measurement disabled

/* ***** USART (TXSTA, RCSTA, etc.) ***** */

/* status bits */
union USART
{
  unsigned char val;
  struct
  {
    unsigned RX_NINE:1;         // Receive Bit 8 if 9-bit mode is enabled
    unsigned TX_NINE:1;         // Transmit Bit 8 if 9-bit mode is enabled
    unsigned FRAME_ERROR:1;     // Framing Error for USART
    unsigned OVERRUN_ERROR:1;   // Overrun Error for USART
    unsigned fill:4;
  }S1;
};

// Function declarations
void OpenUSART (unsigned char config, unsigned spbrg);
#define DataRdyUSART() (PIR1bits.RCIF)
char ReadUSART (void);
void WriteUSART (char data);
#define CloseUSART() RCSTA&=0b01001111,TXSTAbits.TXEN=0,PIE1&=0b11001111
#define BusyUSART() (!TXSTAbits.TRMT)

// Variables
union USART USART_Status;

#endif __USART_H



LIN.h

Code:

// LIN Functions

#ifndef __LIN_H
#define __LIN_H

typedef enum { // LIN bus result codes. We use the same numberical value as for canStatus.
  linOK                  = 0,
  linERR_NOMSG           = 2,     // No messages available
  linERR_CSUM            = 6,     // Checksum error on reception
  linERR_TIMEOUT         = 7,     // Timeout ocurred
  linERR_TXBUFOFL        = 13,    // Transmit buffer overflow
  linERR_HARDWARE        = 15     // Some hardware error has occurred
} linStatus;


// Function declarations
// initialize the LIN hardware
linStatus linSetup(void);

#define linBps 10000
//#define linBps 9600
#define linBpsSynch 6923 // (linBps*0.6923)
#define linBrg ( (FOSC/64+linBps/2)/linBps-1 )
#define linBrgSynch ( (FOSC/64+linBpsSynch/2)/linBpsSynch-1 )

// Variables

#endif // __LIN_H




RegBits18F4680.h

Code:

// Register Bits of 18F4680

#ifndef __REGBITS18F4680_H
#define __REGBITS18F4680_H

#define __18F4680

// Register & bits declarations
struct {
  unsigned TMR1IE:1;
  unsigned TMR2IE:1;
  unsigned CCP1IE:1;
  unsigned SSPIE:1;
  unsigned TXIE:1;
  unsigned RCIE:1;
  unsigned ADIE:1;
  unsigned PSPIE:1;
} PIE1bits;

struct {
  unsigned TMR1IF:1;
  unsigned TMR2IF:1;
  unsigned CCP1IF:1;
  unsigned SSPIF:1;
  unsigned TXIF:1;
  unsigned RCIF:1;
  unsigned ADIF:1;
  unsigned PSPIF:1;
} PIR1bits;

struct {
  unsigned TMR1IP:1;
  unsigned TMR2IP:1;
  unsigned CCP1IP:1;
  unsigned SSPIP:1;
  unsigned TXBIP:1;
  unsigned RCIP:1;
  unsigned ADIP:1;
  unsigned PSPIP:1;
} IPR1bits;

union {
  struct {
    unsigned ECCP1IE:1;
    unsigned TMR3IE:1;
    unsigned LVDIE:1;
    unsigned BCLIE:1;
    unsigned EEIE:1;
    unsigned tmp1:1;
    unsigned CMIE:1;
    unsigned OSCFIE:1;
  }S1;
  struct {
    unsigned tmp2:2;
    unsigned HLVDIE:1;
  }S2;
} PIE2bits;

union {
  struct {
    unsigned ECCP1IF:1;
    unsigned TMR3IF:1;
    unsigned LVDIF:1;
    unsigned BCLIF:1;
    unsigned EEIF:1;
    unsigned tmp1:1;
    unsigned CMIF:1;
    unsigned OSCFIF:1;
  }S1;
  struct {
    unsigned tmp2:2;
    unsigned HLVDIF:1;
  }S2;
} PIR2bits;

union {
  struct {
    unsigned ECCP1IP:1;
    unsigned TMR3IP:1;
    unsigned LVDIP:1;
    unsigned BCLIP:1;
    unsigned EEIP:1;
    unsigned tmp1:1;
    unsigned CMIP:1;
    unsigned OSCFIP:1;
  }S1;
  struct {
    unsigned tmp2:2;
    unsigned HLVDIP:1;
  }S2;
} IPR2bits;

struct {
  unsigned RX9D:1;
  unsigned OERR:1;
  unsigned FERR:1;
  unsigned ADEN:1;
  unsigned CREN:1;
  unsigned SREN:1;
  unsigned RX9:1;
  unsigned SPEN:1;
} RCSTAbits;

struct {
  unsigned TX9D:1;
  unsigned TRMT:1;
  unsigned BRGH:1;
  unsigned SENDB:1;
  unsigned SYNC:1;
  unsigned TXEN:1;
  unsigned TX9:1;
  unsigned CSRC:1;
} TXSTAbits;

union {
  struct {
    unsigned TMR1ON:1;
    unsigned TMR1CS:1;
    unsigned T1SYNC:1;
    unsigned T1OSCEN:1;
    unsigned T1CKPS0:1;
    unsigned T1CKPS1:1;
    unsigned T1RUN:1;
    unsigned RD16:1;
  }S1;
  struct {
    unsigned tmp1:2;
    unsigned T1INSYNC:1;
  }S2;
  struct {
    unsigned tmp2:2;
    unsigned NOT_T1SYNC:1;
  }S3;
} T1CONbits;

union {
  struct {
    unsigned TMR3ON:1;
    unsigned TMR3CS:1;
    unsigned T3SYNC:1;
    unsigned T3CCP1:1;
    unsigned T3CKPS0:1;
    unsigned T3CKPS1:1;
    unsigned T3CCP2:1;
    unsigned RD16:1;
  }S1;
  struct {
    unsigned tmp1:2;
    unsigned T3NSYNC:1;
  }S2;
  struct {
    unsigned tmp2:5;
    unsigned T3ECCP1:1;
  }S3;
  struct {
    unsigned tmp3:2;
    unsigned NOT_T3SYNC:1;
  }S4;
} T3CONbits;

#endif // __REGBITS18F4680_H




Regs18F4680.h

Code:

// Registers of 18F4680

#ifndef __REGS18F4680_H
#define __REGS18F4680_H

// Bytes
#byte PIE1 = 0x0f9d
#byte PIR1 = 0x0f9e
#byte IPR1 = 0x0f9f
#byte PIE2 = 0x0fa0
#byte PIR2 = 0x0fa1
#byte IPR2 = 0x0fa2
#byte RCSTA = 0x0fab
#byte TXSTA = 0x0fac
#byte TXREG = 0x0fad
#byte RCREG = 0x0fae
#byte SPBRG = 0x0faf
#byte SPBRGH = 0x0fb0
#byte T3CON = 0x0fb1
#byte TMR3L = 0x0fb2
#byte TMR3H = 0x0fb3
#byte T1CON = 0x0fcd
#byte RCON = 0x0fd0
#byte INTCON = 0x0ff2

// Bits of the bytes
#byte PIE1bits = PIE1
#byte PIR1bits = PIR1
#byte IPR1bits = IPR1
#byte PIE2bits = PIE2
#byte PIE2bits1 = PIE2
#byte PIR2bits = PIR2
#byte PIR2bits1 = PIR2
#byte IPR2bits = IPR2
#byte IPR2bits1 = IPR2
#byte RCSTAbits = RCSTA
#byte TXSTAbits = TXSTA
#byte T1CONbits = T1CON
#byte T1CONbits1 = T1CON
#byte T1CONbits2 = T1CON
#byte T3CONbits = T3CON
#byte T3CONbits1 = T3CON
#byte T3CONbits2 = T3CON

#endif // __REGS18F4680_H



Last edited by Alex N on Mon Feb 13, 2006 7:12 pm; edited 1 time in total
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:40 pm     Reply with quote

Board.c

Code:

// PIC Board

void B_FlashOnStart()
{
   const int8 FlashTime = 100;
   int i = 0;

   for(i=0; i<=1; i++)
   {
      output_high(G2_LED);
      delay_ms(FlashTime);
      output_low(G2_LED);

      output_high(Y2_LED);
      delay_ms(FlashTime);
      output_low(Y2_LED);

      output_high(R2_LED);
      delay_ms(FlashTime);
      output_low(R2_LED);

      output_high(G_LED);
      delay_ms(FlashTime);
      output_low(G_LED);

      output_high(Y_LED);
      delay_ms(FlashTime);
      output_low(Y_LED);

      output_high(R_LED);
      delay_ms(FlashTime);
      output_low(R_LED);

   }
}



Timers.c

Code:

// Timers Functions

void OpenTimer3(unsigned char config)
{
  T3CON = (0x7e & config);  // Set everything except 8/16 mode, and
                            // don't start timer yet

  TMR3H=0;          //Clear timer3-related registers
  TMR3L=0;
  PIR2bits.S1.TMR3IF = 0;

  if(config & 0x80)   // Interrupt on/off
    PIE2bits.S1.TMR3IE = 1;
  else
    PIE2bits.S1.TMR3IE = 0;

  if(config & 0x02)
    T1CONbits.S1.T1OSCEN = 1;  // Enable Timer 1 Oscillator enable
                            // (200KHz max freq)

  if(config & ~T3_8BIT_RW) // Select between 8-bit and 16-bit modes
  {
    T3CONbits.S1.RD16 = 1;
  }
  else
  {
    T3CONbits.S1.RD16 = 0;
  }

  T3CONbits.S1.TMR3ON = 1;   // Turn on Timer3
}

unsigned int16 ReadTimer3(void)
{
  union Timers timer;

  timer.bt[0] = TMR3L;   // Read low byte of Timer3
  timer.bt[1] = TMR3H;   // Read high byte of Timer3

  return (timer.lt);     // Return 16-bit value
}



HW.c

Code:

// Some hardware Functions

// Timer handling
void timerSetup(void) {
  // Clear IPEN so that only one level is used; all interrupts will branch to vector 0x08.
  // Set PEIE and GIE in INTCON.

  INTCON = 0xc0; // 1100 0000    GIE|PEIE
  RCON = 0x0a; // Disable priority levels on interrupts.
  PIE2bits.S1.TMR3IE = 1;
  IPR2bits.S1.TMR3IP = 1; // High priority (no effect as IPEN is 0)

  timerIntCount = 0;
  OpenTimer3(TIMER_INT_ON & T3_SOURCE_INT & T3_16BIT_RW &
             T3_PS_1_1 & T3_OSC1EN_OFF & T3_SYNC_EXT_OFF);
}

#INT_TIMER3
static void intHandlerHigh(void)
{
  if (PIE2bits.S1.TMR3IE && PIR2bits.S1.TMR3IF)
  {
    timerIntCount++;
    PIR2bits.S1.TMR3IF = 0;
  }
}

timerT timerGetValue(void) {
  // For a 16 bit timer, we just return timerIntCount.
  return timerIntCount;
}

Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:41 pm     Reply with quote

USART.c

Code:

// Hardware USART Functions

/********************************************************************
*    Function Name:  OpenUSART                                      *
*    Return Value:   void                                           *
*    Parameters:     config: bit definitions to configure USART     *
*                    spbrg: baudrate value for register SPBRG1      *
*                    or for SPBRGH:SPBRG for 16-bit baud rate       *
*                    generation for applicable parts                *
*    Description:    This routine first resets the USART regs       *
*                    to the POR state. It then configures the       *
*                    USART for interrupts, synch/async, 8/9-bit,    *
*                    sync slave/master and single/cont. rx.         *
*    Notes:          The bit definitions for config can be found    *
*                    in the usart.h file.                           *
********************************************************************/
void OpenUSART(unsigned char config, unsigned spbrgIn)
{
  TXSTA = 0;           // Reset USART registers to POR state
  RCSTA = 0;

  if(config&0x01)      // Sync or async operation
    TXSTAbits.SYNC = 1;

  if(config&0x02)      // 8- or 9-bit mode
  {
    TXSTAbits.TX9 = 1;
    RCSTAbits.RX9 = 1;
  }

  if(config&0x04)      // Master or Slave (sync only)
    TXSTAbits.CSRC = 1;

  if(config&0x08)      // Continuous or single reception
    RCSTAbits.CREN = 1;
  else
    RCSTAbits.SREN = 1;

  if(config&0x10)      // Baud rate select (asychronous mode only)
    TXSTAbits.BRGH = 1;
  else
    TXSTAbits.BRGH = 0;

  PIR1bits.TXIF = 0;

  if(config&0x40)      // Interrupt on receipt
    PIE1bits.RCIE = 1;
  else
    PIE1bits.RCIE = 0;

  PIR1bits.RCIF = 0;

  if(config&0x80)      // Interrupt on transmission
    PIE1bits.TXIE = 1;
  else
    PIE1bits.TXIE = 0;

  SPBRG = spbrgIn;       // Write baudrate to SPBRG1
#if defined(__18F1220) || defined(__18F1320) || \
    defined(__18F2480) || defined(__18F2580) || \
    defined(__18F4480) || defined(__18F4580) || \
    defined(__18F2585) || defined(__18F2680) || \
    defined(__18F4585) || defined(__18F4680) || \
    defined(__18F2515) || defined(__18F2525) || \
    defined(__18F2610) || defined(__18F2620) || \
    defined(__18F4515) || defined(__18F4525) || \
    defined(__18F4610) || defined(__18F4620)
  SPBRGH = spbrgIn >> 8; // For 16-bit baud rate generation
#endif
  TXSTAbits.TXEN = 1;  // Enable transmitter
  RCSTAbits.SPEN = 1;  // Enable receiver
}

/********************************************************************
*    Function Name:  ReadUSART                                      *
*    Return Value:   char: received data                            *
*    Parameters:     void                                           *
*    Description:    This routine reads the data from the USART     *
*                    and records the status flags for that byte     *
*                    in USART_Status (Framing and Overrun).         *
********************************************************************/
char ReadUSART(void)
{
  char data;   // Holds received data

  USART_Status.val &= 0xf0;          // Clear previous status flags

  if(RCSTAbits.RX9)                  // If 9-bit mode
  {
    USART_Status.S1.RX_NINE = 0;        // Clear the receive bit 9 for USART
    if(RCSTAbits.RX9D)               // according to the RX9D bit
      USART_Status.S1.RX_NINE = 1;
  }

  if(RCSTAbits.FERR)                 // If a framing error occured
    USART_Status.S1.FRAME_ERROR = 1;    // Set the status bit

  if(RCSTAbits.OERR)                 // If an overrun error occured
    USART_Status.S1.OVERRUN_ERROR = 1;  // Set the status bit

  data = RCREG;                      // Read data

  return (data);                     // Return the received data
}

/********************************************************************
*    Function Name:  WriteUSART                                     *
*    Return Value:   none                                           *
*    Parameters:     data: data to transmit                         *
*    Description:    This routine transmits a byte out the USART.   *
********************************************************************/
void WriteUSART(char data)
{
  if(TXSTAbits.TX9)  // 9-bit mode?
  {
    TXSTAbits.TX9D = 0;       // Set the TX9D bit according to the
    if(USART_Status.S1.TX_NINE)  // USART Tx 9th bit in status reg
      TXSTAbits.TX9D = 1;
  }

  TXREG = data;      // Write the data byte to the USART
}



Last edited by Alex N on Mon Feb 13, 2006 7:10 pm; edited 1 time in total
Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:43 pm     Reply with quote

LIN.c

Code:

// LIN Functions

linStatus linSetup(void)
{
  OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE &
            USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW,
            (char)(unsigned char)linBrg);
  // We want to transmit a ninth' bit as an extra stop bit,
  // but do not want to receive nine bits.
  // So we set TXSTA.TX9 manually
  return linOK;
}

void linWait(void)
{
  while(BusyUSART());
}

// Reads any pending bytes from the USART.
static void linPurge(void)
{
  for (;;)
  {
    // Check for errors. If the OERR bit is set, nothing is received.
    if (RCSTAbits.OERR)
    {
      RCSTAbits.CREN = 0;
      RCSTAbits.CREN = 1;
    }
    if (DataRdyUSART())
    {
      (void)ReadUSART();
      //break;
    }
    else
      break;
  }
}

// Call to insert a delay between certain bytes in the message
static void linDelay(unsigned char bits)
{
  timerT t0;
  linWait();
  t0 = timerHGetValue();
  while (timerHGetValue()-t0 < bits*((timerT)(TIMERHFREQ/linBps)));
}

static void linWriteChar(unsigned char c)
{
  while(BusyUSART());
  WriteUSART((char)c);
}

static void linWriteHeader(unsigned char id)
{
  unsigned char ident, p;
  id &= 0x3f;

  // Start by transmitting a synch break.
  linWait(); // Wait if the previous messag isn't finished yet.
  SPBRG = linBrgSynch;
  linWriteChar(0);
  linWait(); // Wait for the synch break to finish before changing the BRG
  // Transmit the synch field
  linDelay(7);
  SPBRG = linBrg;
  linWriteChar(0x55);

  // Calculate the parity bits.
  // P0 is XOR of id bits 0,1,2 and 4
  ident = id;
  p = 0;
  if (id & (1/*<< 0*/))
    p++;
  if (id & (1 << 1))
    p++;
  if (id & (1 << 2))
    p++;
  if (id & (1 << 4))
    p++;
  if (p & 0x01)
    ident |= 0x40;

  // P1 is the inverted XOR of id bits 1,3,4 and 5
  p = 1;
  if (id & (1 << 1))
    p++;
  if (id & (1 << 3))
    p++;
  if (id & (1 << 4))
    p++;
  if (id & (1 << 5))
    p++;
  if (p & 0x01)
    ident |= 0x80;

  // Transmit the ident field
  linDelay(7);
  linWriteChar(ident);
  linPurge();
  //linDelay(7);
}

// Calculates the dlc from a LIN bus id.
unsigned char linDlc(unsigned char id)
{
  unsigned char dlc;
  dlc = 1 << ((id >> 4) & 0x03);
  if (dlc == 1)
    dlc = 2;
  return dlc;
}

// Caclulates the 6-bit LIN bus id from the a four bit id and the dlc.
// The result is in the range 0..63.
unsigned char linId(unsigned char id, unsigned char dlc)
{
  id &= 0x0f;
  switch(dlc) {
    case 2:
    default:
      break;
    case 3:
      id += 0x10;
      break;
    case 4:
      id += 0x20;
      break;
    case 8:
      id += 0x30;
      break;
  }
  return id;
}

// Writes a LIN message to the bus.
// 0 <= id <= 63. The data length is derived from the id.
linStatus linWriteMessage(unsigned char id, unsigned char *msg)
{
  unsigned char dlc, i;
  unsigned int16 csum;
  id &= 0x3f;

  linWriteHeader(id);

  // Transmit the data, calculate the checksum
  dlc = linDlc(id);
  csum = 0;
  for (i = 0; i < dlc; i++) {
    csum += msg[i];
    if (csum >= 256)
      csum = (csum+1)&0xff;
    linDelay(2);
    linWriteChar(msg[i]);
  }
  linDelay(2);
  linWriteChar(~(unsigned char)csum);

  return linOK;
}

// Transmit a message header and waits for a response.
linStatus linReadMessage(unsigned char id, unsigned char *msg)
{
  unsigned char i;
  unsigned char dlc;
  STATIC unsigned char csumR;
  STATIC unsigned int16 csum;
  timerT t0,t1;
  unsigned char b[8];
  unsigned char purgedChar;
  // Write the header

  purgedChar = 0xaa;
  // Empty the serial receive buffer should there be any garbage.
  linPurge();
  linWriteHeader(id);

  // Now, nothing should be placed in the receive buffer --- but there is!
  // So we purge again.
  //linPurge();

  // Wait for and discard echo of id
  while( !DataRdyUSART() );
  purgedChar = ReadUSART();


  // Wait for a response.
  dlc = linDlc(id);
  for (i = 0; i < dlc+1; i++)
  {

      // Inserted: reset timer counter
      timerIntCount = 0;

    t0 = timerGetValue();
    while (!DataRdyUSART())
    {
      // Check for errors. If the OERR bit is set, nothing is received.
      if (RCSTAbits.OERR)
      {
        RCSTAbits.CREN = 0;
        RCSTAbits.CREN = 1;
      }
      // Timeout?
      t1 = timerGetValue();
      if (t1-t0 > TIMERFREQ/10)
      {
        return linERR_TIMEOUT;
      }
    }
    csumR = (unsigned char)ReadUSART();
    if (i < dlc)
    {
      msg[i] = csumR;
      b[i] = csumR;
    }
  }

  csum = 0;
  for (i = 0; i < dlc; i++) {
    csum += msg[i];
    if (csum >= 256)
      csum = (csum+1)&0xff;
  }
  if (csumR != ~(unsigned char)csum)
    return linERR_CSUM;
  return linOK;
}


// Shut down the LIN bus communication
void linShutdown(void)
{
  CloseUSART();
}

Alex N



Joined: 10 Feb 2006
Posts: 16

View user's profile Send private message

PostPosted: Mon Feb 13, 2006 2:44 pm     Reply with quote

Good luck! Very Happy
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Tue Feb 14, 2006 1:47 am     Reply with quote

Hi ALex,

I'll try your code as soon as possible. I'll tell you about.

Thanks & Regards,

Fabri
weisiong



Joined: 22 Feb 2007
Posts: 1

View user's profile Send private message Send e-mail

PostPosted: Thu Feb 22, 2007 1:42 am     Reply with quote

I have tried to compile the code but it has an error as below:

Clean: Deleting intermediary and output files.
Clean: Deleted file "board.ERR".
Clean Warning: File "C:\PIC Project\PIC4860 LIN\board.o" doesn't exist.
Clean: Done.
Executing: "C:\Program files\Picc\CCSC.exe" "board.c" +FH +DF +LN +T -A +M +Z +Y=9 +EA
*** Error 128 "C:\PIC Project\PIC4860 LIN\board.c" Line 6(1,1): A #DEVICE required before this line
1 Errors, 0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Thu Feb 22 15:41:32 2007
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group