The msg_len array slot holds the number of data
bytes in the response area of the frame and is not a part
of the LIN frame. The raw identifier — which is supplied
by the application — resides in the id_loc array slot.
After the frame checksum is calculated, it is stuffed into
the array slot immediately following the last data byte in
the response. Look closely and you will find eight
additional load_x functions in the LIN driver source
code which is part of your LIN driver download package
at
www.servo magazine.com. The load_x functions
fill the lin_buf array in preparation for the invocation of
the send_lin_frame function. Once the send_lin_frame
function is called, it immediately creates the PID:
//***********************************************
//* SEND A LIN FRAME
//***********************************************
void send_lin_frame(void)
{
char i;
//save original identifier byte
id_loc_org = lin_buf[id_loc];
//CALCULATE PROTECTED ID CHECKSUM
id_bits.id0 = lin_buf[id_loc] & 0b00000001;
id_bits.id1 = (lin_buf[id_loc] & 0b00000010)
>> 1;
id_bits.id2 = (lin_buf[id_loc] & 0b00000100)
>> 2;
id_bits.id3 = (lin_buf[id_loc] & 0b00001000)
>> 3;
id_bits.id4 = (lin_buf[id_loc] & 0b00010000)
>> 4;
id_bits.id5 = (lin_buf[id_loc] & 0b00100000)
>> 5;
id_bits.p0 = id_bits.id0 id_bits.id1
id_bits.id2 id_bits.id4;
id_bits.p1 = ~(id_bits.id1 id_bits.id3
id_bits.id4 id_bits.id5);
if(id_bits.p1)
{
lin_buf[id_loc] = lin_buf[id_loc]
+ 0b10000000;
}
if(id_bits.p0)
{
lin_buf[id_loc] = lin_buf[id_loc]
+ 0b01000000;
}
The variables id_bits.p0 and id_bits.p1 are added
to the original frame identifier to form the PID. The
next checksum that must be calculated is generated
from the response bytes. If the enhanced checksum is
selected, the checksum calculation will include the PID
byte, as well:
//CALCULATE FRAME CHECKSUM
if(id_loc_org >= 0x3C && id_loc_org <= 0x3F)
{
//for classic checksum calculation
checksum = 0;
}
else if(flags.enhanced)
{
//for enhanced checksum calculation
checksum = lin_buf[id_loc];
}
for(i=0;i<lin_buf[msg_len];++i)
{
checksum = checksum + lin_buf[msg_loc+i];
}
lin_buf[chksum_loc] = ~(checksum & 0x00FF);
I’ve followed the LIN Specification by forcing all frames
with identifiers between 0x3C and 0x3F to use the classic
checksum calculation. With the PID in place and the frame
checksum calculated and placed, the next logical step is to
send the frame on its way:
//add id and checksum to length
lin_buf[msg_len] = lin_buf[msg_len] + 2;
LIN_TX; //place MCP2201 in transmit mode
SENDB = 1; //set SEND BREAK bit
sendchar(0x55); //send dummy character
sendchar(0x55); //send Auto-Baud chirp
//SEND FRAME
for(i=0;i<lin_buf[msg_len];++i)
{
sendchar(lin_buf[id_loc+i]);
}
mdelay1(17);
We must add 2 to the frame length to include the PID
and frame checksum in the outgoing LIN frame. Following
the transmission of the last byte of the frame, we allow
a frame slot time of 17 mS which we calculated earlier.
I issued an endless loop of calls to all nine of the
load_x functions and transmitted a frame for every load_x
function call. I used the LIN Serial Analyzer to capture the
results shown in Screenshot 1.
From the transmission of a Break-Sync pattern, we
can ascertain that the entire preceding LIN frame was
generated by a master node. In reality, the response may
be generated from a subscribing slave node. In that case,
the subscribing slave will calculate the frame checksum
according to the rules that have been set forth by the
master node. For instance, let’s say every PID with a value
of 0x01 (0xC1 with parity bits) will respond with three bytes
to the master using the classic checksum. The subscribing
slave node can process and then ignore the incoming PID,
send the three requested bytes, and append a classic
checksum to the frame. Thus, the master node only sends a
SERVO 07.2009
45