DESIGN CYCLE
using the elements of a structure:
canBitConfig.phaseSeg2Tq = CAN_BIT_3TQ;
canBitConfig.phaseSeg1Tq = CAN_BIT_3TQ;
canBitConfig.propagationSegT = CAN_BIT_3TQ;
canBitConfig.phaseSeg2TimeSelect = TRUE;
canBitConfig.sample3Time = TRUE;
canBitConfig.syncJumpWidth = CAN_BIT_2TQ;
CANSetSpeed(CAN2,&canBitConfig,SYSTEM_FREQ,CAN_
BUS_SPEED);
The canBitConfig structure was spawned from the
CAN_BIT_CONFIG parent structure that is found in the
peripheral library’s CAN.h file. Note that all of the
parameters we took into consideration for our calculations
are used by the CANSetSpeed function. You can bet the
results of the CANSetSpeed function match our manual
calculations.
message, which includes a time stamp, the message ID,
and data payload. The Remote Transmit Request (RTR)
feature is disabled. RTR allows a CAN node to request a
transmission from another CAN node.
NO UNFILTERED TAP WATER, PLEASE
Every CAN message is a broadcast message. That
means every CAN node on the wire has the ability to
receive every message that is transmitted. We have the
ability to only accept CAN messages that are of interest to
us. We do this by setting up a message acceptance filter.
Each CAN SID (Standard ID) message has an 11-bit ID
field that we can sift through our filter. So, let’s set up the
first filter (CAN_FILTER0) to accept SID messages with an
ID of 0x222:
CARVING OUT THE MESSAGE BUFFER
MEMORY AREA
As you become more familiar with the CAN module,
you’ll notice that it likes to do things for itself. All you have
to do is decide what you want to happen and turn the
module loose. With that, we can use the peripheral library
functions to easily set up separate transmit and receive
buffer areas in SRAM with a minimum of coding. Let’s
specify enough message buffer area for a transmit channel
and a receive channel with each channel containing eight
message buffers of 16 bytes each:
BYTE CAN2MessageFifoArea[2 8 16];
CANAssignMemoryBuffer(CAN2,CAN2MessageFifoArea,
2 8 16);
The CAN module automatically allocates the specified
memory space for a transmit FIFO and a receive FIFO
according to the arguments of the CANAssign
MemoryBuffer function. You can get an idea of how the
PIC32MX module organizes FIFO buffer area in Figure 2.
Once the message buffer memory is allocated, we
can tell the CAN module to slice and dice it into
addressable transmit and receive buffer areas:
CANConfigureFilter (CAN2, CAN_FILTER0, 0x222,
CAN_SID);
Since we’re only interested in receiving SID messages,
we want to trigger our filter on all 11 bits of the ID and
reject EID (Extended ID) messages:
CANConfigureFilterMask (CAN2, CAN_FILTER_MASK0,
0xFFF, CAN_SID, CAN_FILTER_MASK_IDE_TYPE);
Our first CAN2 filter mask value of 0xFFF covers all
11 bits of the incoming SID message’s ID field while the
other arguments make sure that nothing but SID messages
are allowed to flow to the receive buffer. CAN_FILTER0 is
the first filter we defined and CAN_FILTER_MASK0 is the
first filter mask we defined. We can specify up to 32 filters
(CAN_FILTER0-CAN_FILTER31) and up to four filter masks
(CAN_FILTER_MASK0-CAN_FILTER_MASK3). The zero in
the names of the filter and masks we coded do not
associate them with Channel 0. After all, Channel 0 is our
transmit channel. We need to associate the filter and mask
we just created to the receive channel, which happens to
be Channel 1:
CANLinkFilterToChannel (CAN2, CAN_FILTER0,
CAN_FILTER_MASK0, CAN_CHANNEL1);
CANConfigureChannelForTx(CAN2,CAN_CHANNEL0,8,CAN_
TX_RTR_DISABLED,CAN_LOW_MEDIUM_PRIORITY);
Now that CAN_FILTER0 and CAN_FILTER_MASK0 are
attached to the receive channel, we can activate
CANConfigureChannelForRx(CAN2,CAN_CHANNEL1,8,CAN_
RX_FULL_RECEIVE);
Okay. Now we’ve
established that we will
transmit CAN messages
on Channel 0 and
receive CAN messages
on Channel 1. Each
channel is supported by
eight 16-byte message
buffers with the receive
message buffer able to
capture the entire CAN
■ FIGURE 2. Our code will instruct the PIC32MX CAN module to build two FIFO areas with
eight 16-byte message buffers per FIFO.
November 2011 71