j1339 PIC Library Microchip
j1339 PIC Library Microchip
• Microchip believes that its family of products is one of the most secure families of its kind on the market today, when used in the
intended manner and under normal conditions.
• There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our
knowledge, require using the Microchip products in a manner outside the operating specifications contained in Microchip's Data
Sheets. Most likely, the person doing so is engaged in theft of intellectual property.
• Microchip is willing to work with the customer who is concerned about the integrity of their code.
• Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as “unbreakable.”
Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of our
products. Attempts to break Microchip’s code protection feature may be a violation of the Digital Millennium Copyright Act. If such acts
allow unauthorized access to your software or other copyrighted work, you may have a right to sue for relief under that Act.
Table of Contents
Preface ........................................................................................................................... 1
Chapter 1. Introduction
1.1 Overview ...................................................................................................... 3
1.2 J1939 Support and Limitations .................................................................... 3
Chapter 2. How To Use The Library
2.1 Introduction .................................................................................................. 5
2.2 Basic Setup ................................................................................................. 6
2.3 Messages .................................................................................................... 8
Chapter 3. Library Configuration
3.1 Introduction ................................................................................................ 11
Chapter 4. Library Functions
4.1 Introduction ................................................................................................ 15
4.2 External Interface Routines ....................................................................... 16
4.3 Internal Routines ....................................................................................... 17
Appendix A. Examples
A.1 Introduction ................................................................................................ 19
Worldwide Sales and Service .................................................................................... 32
NOTES:
Preface
HIGHLIGHTS
This section contains general information that will be useful to know before using the
J1939 C Library for PIC16 Microcontrollers and MCP2515 User’s Guide.
The topics discussed in this section are:
- About This Guide
- Recommended Reading
- The Microchip Internet Web Site
- Customer Support
RECOMMENDED READING
The following is recommended reading.
CUSTOMER SUPPORT
Users of Microchip products can receive assistance through several channels:
• Distributor or Representative
• Local Sales Office
• Field Application Engineer (FAE)
• Corporate Applications Engineer (CAE)
• Hot Line
Customers should call their distributor, representative or field application engineer
(FAE) for support. Local sales offices are also available to help customers. See the
back cover for a listing of sales offices and locations.
Corporate applications engineers (CAEs) may be contacted at (480) 786-7627.
In addition, there is a Systems Information and Upgrade Line. This line provides system
users a listing of the latest versions of all of Microchip’s development systems software
products. Plus, this line provides information on how customers can receive any
currently available upgrade kits.
The Hot Line Numbers are:
• 1-800-755-2345 for U.S. and most of Canada, and
• 1-480-786-7302 for the rest of the world.
Chapter 1. Introduction
1.1 OVERVIEW
The J1939 C Library is targeted for use with PIC16 microcontroller applications written
with HI-TECH’s PICC™ C compiler using the MCP2515 Stand-alone CAN Controller.
It offers J1939 communications protocol support for single address capable Controller
Applications (CA’s) that are either non-configurable, service configurable or command
configurable. The library routines handle initialization and network functions automati-
cally. User messages are placed in a queue for transmission. Messages that are
received for the CA are placed in a separate queue for processing. The queue sizes
are configurable by the user, based on available RAM. Many other aspects of the
library operation are also configurable to allow for various hardware and software
designs.
NOTES:
2.3 MESSAGES
2.3.1 Message Definition and Structure
Create one or more message buffers using the following definition:
J1939_USER_MSG_BANK J1939_MESSAGE MyMessage;
Since each message buffer requires 13 bytes of RAM, try to keep the number of
message buffers to a minimum. In most situations, only one or two CA message buffers
will be needed.
The message structure is defined in j1939_16.h, but here are the main fields that the
CA will use. Refer to the J1939 Specification for details on each portion of the message.
• MyMessage.Msg.DataPage, one bit
• MyMessage.Msg.Priority, three bits
• MyMessage.Msg.PDUFormat, one byte
• MyMessage.Msg.PDUSpecific, one byte. This field can also be referenced as
DestinationAddress or GroupExtension to help clarify the CA code.
• MyMessage.Msg.SourceAddress, one byte (this is automatically filled in by the
library before transmission)
• MyMessage.Msg.DataLength, 4 bits, but must be between 0 and 8
• MyMessage.Msg.Data[8], array of 8 bytes
NOTES:
3.1.1.2 INTERRUPTS
If interrupts are used, connect the MCP2515 INT pin to the PIC device’s INT pin (RB0).
3.1.1.7 CLKOUT/SOF
The library does not use the CLKOUT/SOF pin. To enable the CLKOUT pin, set
J1939_CLKOUT to CLKOUT_ENABLE and set J1939_CLKOUT_PS to CLKOUT_PS1,
CLKOUT_PS2, CLKOUT_PS4 or CLKOUT_PS8 for prescalers of FCLOCKOUT of System
Clock/1, 2, 4 or 8. Otherwise, set J1939_CLKOUT to CLKOUT_DISABLE. If the CA uses
this feature, ensure that other MCP2515 functions are not altered.
Note the following when deciding which bank to place the queues and the size of the
queues:
• Each message in the queue requires 13 bytes of RAM.
• The bank containing the receive queue will have an additional 16 bytes used by
the library (8 bytes if the Commanded Address message is not allowed).
• The bank containing the transmit queue will have an additional 13 bytes used by
the library.
4.1.1.2 CA NAME
The CA NAME can be accessed (and modified if necessary) through the array
CA_Name. This is an array of unsigned chars, stored Least Significant Byte to Most
Significant Byte.
NOTES:
Appendix A. Examples
A.1 INTRODUCTION
The following examples show how the J1939 library routines are used in a CA. Note
that the applications and values are for demonstration only and are not intended to
mimic an actual automotive application. Read these examples in order, as each one
builds on the last. Important items to note from one to the next are bolded.
EXAMPLE A-1:
/*
Example 1
#include <pic.h>
#include ".\j1939\j1939cfg.h"
J1939_Initialization();
while (1)
{
CurrentSwitch = RD0;
if (LastSwitch != CurrentSwitch)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = OTHER_NODE;
Msg.Msg.DataLength = 0;
if (CurrentSwitch == 0)
Msg.Msg.PDUFormat = TURN_ON_LED;
else
Msg.Msg.PDUFormat = TURN_OFF_LED;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
LastSwitch = CurrentSwitch;
}
/*********************************************************************/
/*********************************************************************/
/*
Example 2
This example shows the same concept as Example 1, except that instead
of polling, it uses interrupts to check for a message to light an LED
and to send a message if a button is pressed.
#include <pic.h>
#include ".\j1939\j1939cfg.h"
#pragma interrupt_level 0
void interrupt isr( void )
{
if (INTF)
J1939_ISR();
J1939_Initialization();
GIE = 1;
while (1)
{
CurrentSwitch = RD0;
if (LastSwitch != CurrentSwitch)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = OTHER_NODE;
Msg.Msg.DataLength = 0;
if (CurrentSwitch == 0)
Msg.Msg.PDUFormat = TURN_ON_LED;
else
Msg.Msg.PDUFormat = TURN_OFF_LED;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
LastSwitch = CurrentSwitch;
}
/*********************************************************************/
/*********************************************************************/
/*
Example 3a
#include <pic.h>
#include ".\j1939\j1939cfg.h"
#pragma interrupt_level 0
void interrupt isr( void )
{
if (INTF)
J1939_ISR();
J1939_Initialization();
GIE = 1;
while (1)
{
CurrentSwitch = RD0;
if (LastSwitch != CurrentSwitch)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = SECOND_ADDRESS;
Msg.Msg.DataLength = 0;
if (CurrentSwitch == 0)
Msg.Msg.PDUFormat = TURN_ON_LED;
else
{
Msg.Msg.PDUFormat = TURN_OFF_LED;
if (PushCount < 6)
PushCount ++;
}
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
LastSwitch = CurrentSwitch;
if (PushCount == 5)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = J1939_GLOBAL_ADDRESS;
Msg.Msg.DataLength = 8;
Msg.Msg.PDUFormat = J1939_PF_CM_BAM;
Msg.Msg.Data[0] = 1939_BAM_CONTROL_BYTE;
Msg.Msg.Data[1] = 9; // 9 data bytes
Msg.Msg.Data[2] = 0;
Msg.Msg.Data[3] = 2; // 2 packets
Msg.Msg.Data[4] = 0xFF; // Reserved
Msg.Msg.Data[5] = J1939_PGN0_COMMANDED_ADDRESS;
Msg.Msg.Data[6] = J1939_PGN1_COMMANDED_ADDRESS;
Msg.Msg.Data[7] = J1939_PGN2_COMMANDED_ADDRESS;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = J1939_GLOBAL_ADDRESS;
Msg.Msg.DataLength = 8;
Msg.Msg.PDUFormat = J1939_PF_DT;
Msg.Msg.Data[0] = 1; // First packet
Msg.Msg.Data[1] = NODE_NAME0;
Msg.Msg.Data[2] = NODE_NAME1;
Msg.Msg.Data[3] = NODE_NAME2;
Msg.Msg.Data[4] = NODE_NAME3;
Msg.Msg.Data[5] = NODE_NAME4;
Msg.Msg.Data[6] = NODE_NAME5;
Msg.Msg.Data[7] = NODE_NAME6;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
/*********************************************************************/
/*********************************************************************/
/*
Example 3b
This example shows what the receiving node for Example 3a should look
like, using the same concept as Example 2 of using interrupts to check
for a message to light an LED and to send a message if a button is
pressed. Note that three basic changes are required:
- it must accept the Commanded Address message (j1939cfg.h)
- it must have a CA_AcceptCommandedAddress function
- it must call J1939_Poll during the main loop, even though inter-
rupts are being used.
The rest of the code is identical. The change of address will be
handled in the background.
#include <pic.h>
#include ".\j1939\j1939cfg.h"
#pragma interrupt_level 0
void interrupt isr( void )
{
if (INTF)
J1939_ISR();
J1939_Initialization();
GIE = 1;
while (1)
{
CurrentSwitch = RD0;
if (LastSwitch != CurrentSwitch)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = OTHER_NODE;
Msg.Msg.DataLength = 0;
if (CurrentSwitch == 0)
Msg.Msg.PDUFormat = TURN_ON_LED;
else
Msg.Msg.PDUFormat = TURN_OFF_LED;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
LastSwitch = CurrentSwitch;
}
/*********************************************************************/
/*********************************************************************/
/*
Example 4
This example shows the same concept as Example 2, except that broadcast
messages are used rather than messages sent to a specific address.
#include <pic.h>
#include ".\j1939\j1939cfg.h"
#pragma interrupt_level 0
void interrupt isr( void )
{
if (INTF)
J1939_ISR();
J1939_Initialization();
GIE = 1;
if (LastSwitch != CurrentSwitch)
{
Msg.Msg.DataPage = 0;
Msg.Msg.Priority = 7;
Msg.Msg.DestinationAddress = OTHER_NODE;
Msg.Msg.PDUFormat = 254;
Msg.Msg.DataLength = 0;
if (CurrentSwitch == 0)
Msg.Msg.GroupExtension= TURN_ON_LED;
else
Msg.Msg.GroupExtension= TURN_OFF_LED;
while (J1939_EnqueueMessage( &Msg ) != RC_SUCCESS);
LastSwitch = CurrentSwitch;
}
/*********************************************************************/
/*********************************************************************/
01/26/04