View previous topic :: View next topic |
Author |
Message |
mickey231bhq
Joined: 06 Apr 2005 Posts: 19 Location: Formosa
|
|
Posted: Fri Oct 14, 2005 8:04 am |
|
|
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.
|
|
|
Alex N
Joined: 10 Feb 2006 Posts: 16
|
|
Posted: Fri Feb 10, 2006 1:45 pm |
|
|
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!
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
|
|
Posted: Sat Feb 11, 2006 1:33 am |
|
|
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
|
|
Posted: Sat Feb 11, 2006 5:16 am |
|
|
Hi Fabri,
Yes, it's OK. Do you have any tool to monitor LIN bus activity? |
|
|
Fabri
Joined: 22 Aug 2005 Posts: 275
|
|
Posted: Mon Feb 13, 2006 1:22 am |
|
|
Hi Alex,
Yes I have an SEDES rs232-lin bus converter. |
|
|
Alex N
Joined: 10 Feb 2006 Posts: 16
|
|
Posted: Mon Feb 13, 2006 2:17 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:19 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:28 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:40 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:41 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:43 pm |
|
|
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
|
|
Posted: Mon Feb 13, 2006 2:44 pm |
|
|
Good luck! |
|
|
Fabri
Joined: 22 Aug 2005 Posts: 275
|
|
Posted: Tue Feb 14, 2006 1:47 am |
|
|
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
|
|
Posted: Thu Feb 22, 2007 1:42 am |
|
|
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 |
|
|
|