You are on page 1of 116

Chapter 13

Controller Area Network


History of CAN (Controller Area Network)

• It was created in mid-1980s for automotive


applications by Robert Bosch.
• Design goal was to make automobiles more
reliable, safer, and more fuel efficient.
• The latest CAN specification is the version 2.0
made in 1991.
Layered Approach in CAN (1 of 3)

• Only the logical link and physical layers are described.


• Data link layer is divided into two sublayers: logical link control
(LLC) and medium access control (MAC).

– LLC sublayer deals with message acceptance filtering, overload


notification, and error recovery management.
– MAC sublayer presents incoming messages to the LLC sublayer and
accepts messages to be transmitted forward by the LLC sublayer.
– MAC sublayer is responsible for message framing, arbitration,
acknowledgement, error detection, and signaling.
– MAC sublayer is supervised by the fault confinement mechanism.
Layered Approach in CAN (2 of 3)

• The physical layer defines how signals are actually


transmitted, dealing with the description of bit timing, bit
encoding, and synchronization.
• CAN bus driver/receiver characteristics and the wiring
and connectors are not specified in the CAN protocol.
• System designer can choose from several different
media to transmit the CAN signals.
Layered Approach in CAN (3 of 3)

Application Layer

Supervisor
CAN LAYERS

Data Link Acceptance filtering


LLC sublayer Overload notification
Recovery management
Data encapsulation/decapsulation
Frame coding (stuffing/destuffing)
Medium access management
MAC sublayer Error detection Fault
Error signaling Confinement
Acknowledgement
Serialization/Deserialization

Physical Bit encoding/decoding


Bit timing Bus Failure
Synchronization Management
Driver/Receiver characteristics

Figure 13.1 CAN layers


General Characteristics of CAN (1 of 3)
• Carrier Sense Multiple Access with Collision
Detection (CSMA/CD)
– Every node on the network must monitor the bus
(carrier sense) for a period of no activity before trying
to send a message on the bus.
– Once the bus is idle, every node has equal
opportunity to transmit a message.
– If two nodes happen to transmit simultaneously, a
nondestructive arbitration method is used to decide
which node wins.
General Characteristics of CAN (2 of 3)
• Message-Based Communication
– Each message contains an identifier.
• Identifiers allow messages to arbitrate and also allow each node to
decide whether to work on the incoming message.
• The lower the value of the identifier, the higher the priority of the
identifier.
– Each node uses one or more filters to compare the incoming
messages to decide whether to take actions on the message.
– CAN protocol allows a node to request data transmission from
other nodes.
– There is no need to reconfigure the system when a new node
joins the system.
General Characteristics of CAN (3 of 3)
• Error Detection and Fault Confinement
– The CAN protocol requires each node to monitor the
CAN bus to find out if the bus value and the
transmitted bit value are identical.
– The CRC checksum is used to perform error checking
for each message.
– The CAN protocol requires the physical layer to use
bit stuffing to avoid long sequence of identical bit
value.
– Defective nodes are switched off from the CAN bus.
Types of CAN Messages (1 of 2)
• Data frame
• Remote frame
• Error frame
• Overload frame
Types of CAN Messages (2 of 2)
• Two states of CAN bus
– Recessive: high or logic 1
– Dominant: low or logic 0
Data Frame
• A data frame consists of seven fields: start-of-
frame, arbitration, control, data, CRC, ACK, and
end-of-frame.
Interframe
space or
Interframe overload
space Data Frame frame

Start of Arbitration Control Data CRC ACK End of


frame field field field field field frame

Figure 13.2 CAN Data frame


Start of Frame
• A single dominant bit to mark the beginning of a
data frame.
• All nodes have to synchronize to the leading
edge caused by this field.
Arbitration Field
• There are two formats for this field: standard format and extended format.
Interframe
space Arbitration field Control field

Start of frame 11 bit Identifier RTR IDE r0 DLC

(a) standard format

Arbitration field Control field


Start of
frame 11-bit identifier SRR IDE 18-bit identifier RTR r0 r1 DLC

(b) extended format


Figure 13.3 Arbitration field

• The identifier of the standard format corresponds to the base ID in the


extended format.
• The RTR bit is the remote transmission request and must be 0 in a data frame.
• The SRR bit is the substitute remote request and is recessive.
• The IDE field indicates whether the identifier is extended and should be
recessive in the extended format.
• The extended format also contains the 18-bit extended identifier.
Control Field
• Contents are shown in figure 13.4.
• The first bit is IDE bit for the standard format but
is used as reserved bit r1 in extended format.
• r0 is reserved bit.
• DLC3…DLC0 stands for data length and can be
from 0000 (0) to 1000 (8).
Arbitration Control Field Data field
field or CRC field

IDE/r1 r0 DLC3 DLC2 DLC1 DLC0

reserved bits Data length code

Figure 13.4 Control field


Data Field
• May contain 0 to 8 bytes of data
CRC Field
• It contains the 16-bit CRC sequence and a CRC
delimiter.
• The CRC delimiter is a single recessive bit.

Data or
Control field CRC field ACK

CRC sequence CRC delimiter

Figure 13.5 CRC field


ACK Field
• Consists of two bits
• The first bit is the acknowledgement bit.
– This bit is set to recessive by the transmitter, but will
be reset to dominant if a receiver acknowledges the
data frame.
• The second bit is the ACK delimiter and is
recessive.
Remote Frame
• Used by a node to request other nodes to send
certain type of messages
• Has six fields as shown in Figure 13.7
– These fields are identical to those of a data frame with
the exception that the RTR bit in the arbitration field is
recessive in the remote frame.
Interframe
space or
Interframe overload
Remote frame
space frame

Start of arbitration Control CRC ACK End of


frame field field field field frame

Figure 13.7 Remote frame


Error Frame
• This frame consists of two fields.
– The first field is given by the superposition of error flags contributed
from different nodes.
– The second field is the error delimiter.
• Error flag can be either active-error flag or passive-error flag.
– Active error flag consists of six consecutive dominant bits.
– Passive error flag consists of six consecutive recessive bits.
• The error delimiter consists of eight recessive bits.
Interframe space
Data or
frame Error frame Overload frame

error flag error delimiter

Superposition of
error flags

Figure 13.8 Error frame


Overload Frame
• Consists of two bit fields: overload flag and overload delimiter
• Three different overload conditions lead to the transmission of the
overload frame:
– Internal conditions of a receiver require a delay of the next data frame or
remote frame.
– At least one node detects a dominant bit during intermission.
– A CAN node samples a dominant bit at the eighth bit (i.e., the last bit) of
an error delimiter or overload delimiter.
• Format of the overload frame is shown in Figure 13.9.
• The overload flag consists of six dominant bits.
• The overload delimiter consists of eight recessive bits.
End of frame or Interframe space
Error demiliter or or
Overload Overload frame Overload frame
delimiter
Overload flag Overload delimiter

Superposition of
overload flags
Figure 13.9 Overload frame
Interframe Space (1 of 2)
• Data frames and remote frames are separated from preceding
frames by the interframe space.
• Overload frames and error frames are not preceded by an
interframe space.
• The formats for interframe space is shown in Figure 13.10 and
13.11.

Frame Interframe space Frame

Intermission bus idle

Figure 13.10 Interframe space for non error-passive nodes or receiver of


previous message

Frame Interframe space Frame

Suspend
Intermission Bus Idle
Transmission

Figure 13.11 Interframe space for error-passive nodes


Interframe Space (2 of 2)
• The intermission subfield consists of three
recessive bits.
• During intermission no node is allowed to start
transmission of the data frame or remote frame.
• The period of bus idle may be of arbitrary length.
• After an error-passive node has transmitted a
frame, it sends eight recessive bits following
intermission, before starting to transmit a new
message or recognizing the bus as idle.
Message Filtering
• A node uses filter (s) to decide whether to work
on a specific message.
• Message filtering is applied to the whole
identifier.
• A node can optionally implement mask registers
that specify which bits in the identifier are
examined with the filter.
• If mask registers are implemented, every bit of
the mask registers must be programmable.
Bit Stream Encoding
• The frame segments including start-of-frame, arbitration field, control
field, data field, and CRC sequence are encoded by bit stuffing.
• Whenever a transmitter detects five consecutive bits of identical
value in the bit stream to be transmitted, it inserts a complementary
bit in the actual transmitted bit stream.
• The remaining bit fields of the data frame or remote frame (CRC
delimiter, ACK field and end of frame) are of fixed form and not
stuffed.
• The error frame and overload frame are also of fixed form and are
not encoded by the method of bit stuffing.
• The bit stream in a message is encoded using the non-return-to-zero
(NRZ) method.
• In the non-return-to-zero encoding method, a bit is either recessive
or dominant.
Errors (1 of 3)
• Error handling
– CAN recognizes five types of errors.
• Bit error
– A node that is sending a bit on the bus also monitors the bus.
– When the bit value monitored is different from the bit value being
sent, the node interprets the situation as an error.
– There are two exceptions to this rule:
• A node that sends a recessive bit during the stuffed bit-stream of the
arbitration field or during the ACK slot detects a dominant bit.
• A transmitter that sends a passive-error flag detects a dominant bit.
Errors (2 of 3)
• Stuff error
– Six consecutive dominant or six consecutive
recessive levels occurs in a message field.
• CRC error
– CRC sequence in the transmitted message consists
of the result of the CRC calculation by the transmitter.
– The receiver recalculates the CRC sequence using
the same method but resulted in a different
value. This is detected as a CRC error.
Errors (3 of 3)
• Form error
– Detected when a fixed-form bit field contains one or more illegal
bits
• Acknowledgement error
– Detected whenever the transmitter does not monitor a dominant
bit in the ACK slot
• Error Signaling
– A node that detects an error condition and signals the error by
transmitting an error flag
• An error-active node will transmit an active-error flag.
• An error-passive node will transmit a passive-error flag.
Fault Confinement
• A node may be in one of the three states: error-active, error-passive, and
bus-off.
• A CAN node uses an error counter to control the transition among these
three states.
• CAN protocol uses 12 rules to control the increment and decrement of the
error counter.
• When the error count is less than 128, a node is in error-active state.
• When the error count equals or exceeds 128 but not higher 255, the node is
in error-passive state.
• When the error count equals or exceeds 256, the node is in bus off state.
• An error-active node will transmit an active-error frame when detecting an
error.
• An error-passive node will transmit a passive-error frame when detecting an
error.
• A bus-off node is not allowed to take part in bus communication.
CAN Message Bit Timing
• The setting of a bit time in a CAN system must
allow a bit sent out by the transmitter to reach
the far end of the CAN bus and allow the
receiver to send back acknowledgement and
reach the transmitter.
• The number of bits transmitted per second is
defined as the nominal bit rate.
Nominal Bit Time
• The inverse of the nominal bit rate is the nominal
bit time.
• A nominal bit time is divided into four segments
as shown in Figure 13.12.
Nominal bit time

sync_seg prop_seg phase_seg1 phase_seg2

Sample point
Figure 13.12 Nominal bit time
Sync seg Segment
• It is used to synchronize the various nodes on
the bus.
• An edge is expected to lie in this segment.
Prop-seg Segment
• Used to compensate for the physical delay times
within the network
• Equals twice the sum of the signal’s propagation
time on the CAN bus line, the comparator delay,
and the output driver delay
Phase_seg1 and phase_seg2
• Used to compensate for edge phase errors
• Both can be lengthened or shortened by
synchronization
Sample Point
• At the end of phase_seg1 segment.
• Users can choose to take three samples instead of one.
• A majority function determines the bit value when three
samples are taken.
• Each sample is separated by half time quantum from the
next sample.
• The time spent on determining the bit value is the
information processing time.
Time Quantum
• A fixed unit of time derived by dividing the oscillator
period by a prescaler
• Length of time segments
– sync_seg is 1 time quantum long
– prop_seg is programmable to be 1,2,…,8 time quanta long
– phase_seg1 is programmable to be 1,2,…,8 time quanta long
– phase_seg2 is programmable to be 2,3,…,8 time quanta long
• Information processing time is fixed at 2 time quanta for
the HCS12.
• The total number of time quanta in a bit time must be
programmable between 8 and 25.
Synchronization Issue
• All CAN nodes must be synchronized while receiving a
transmission.
• The beginning of each received bit must occur during each node’s
sync_seg segment.
• Synchronization is needed to compensate for the difference in
oscillator frequencies of each node, the change in propagation delay
and other factors.
• Two types of synchronizations are defined: hard synchronization
and resynchronization.
– Hard synchronization is performed at the beginning of a message frame,
when each CAN node aligns the sync_seg of its current bit time to the
recessive-to-dominant transition.
– Resynchronization is performed during the remainder of the message
frame whenever a change of bit value from recessive to dominant
occurs outside the expected sync_seg segment.
Overview of the HCS12 CAN Module (1 of 2)
• An HCS12 device may have from one to five on-chip CAN modules.
• Each CAN module has five receive buffers with FIFO storage
scheme and three transmit buffers.
• Each of the three transmit buffers may be assigned with a local
priority.
• Maskable identifier filter supports two full size extended identifier
filters (32-bit), four 16-bit filters, or eight 8-bit filters.
• The CAN module has a programmable loopback mode that supports
self-test operation.
• The CAN module has a listen-only mode for monitoring of the CAN
bus.
Overview of the HCS12 CAN Module (2 of 2)
• The CAN module has separate signaling and interrupts for all CAN
receiver and transmitter error states (warning, error passive, and
bus off).
• Clock signal for CAN bus can come from either the bus clock or
oscillator clock.
• The CAN module supports time-stamping for received and
transmitted messages
• The block diagram of a CAN module is shown in Figure 13.13.
• The CAN module requires a transceiver (e.g., MCP2551,
PCA82C250) to interface with the CAN bus.
• A typical CAN bus system is shown in Figure 13.14.
• The CAN module has a 16-bit free-running timer.
Oscillator clock CANCLK Tq clk
MUX Prescaler RxCAN
Bus clock Receive/
Transmit
Engine TxCAN
Control
and
Status
Message
Tx int. req. filtering
Configuration and
Rx int. req. registers buffering
Err. int. req.
Wake-up int. req.
wake- Low pass
up filter

Figure 13.13 MSCAN12 block diagram


CAN node 1 CAN node 2 CAN node n

HCS12

CAN controller .......


(MSCAN12)

TxCAN RxCAN

Transceiver

CAN_H CAN_L CAN Bus

Figure 13.14 A typical CAN system


MSCAN Module Memory Map
• Each CAN module occupies 64 bytes of memory space.
• The MSCAN register organization is shown in Figure
13.15.
• Each receive buffer and each transmit buffer occupies
16 bytes of space.
• Only one of the three transmit buffers is accessible to the
user at a time.
• Only one of the five receive buffers is accessible to the
user at a time.
address register name access
$_00 MSCAN control register 0 (CANCTL0) R/W
$_01 MSCAN control register 1 (CANCTL1) R/W
$_02 MSCAN bus timing register 0 (CANBTR0) R/W
$_03 MSCAN bus timing register 1 (CANBTR1) R/W
$_04 MSCAN receiver flag register (CANRFLG) R/W
$_05 MSCAN receiver interrupt enable register (CANRIER) R/W
$_06 MSCAN transmitter flag register (CANTFLG) R/W
$_07 MSCAN transmitter interrupt enable register (CANTIER) R/W
$_08 MSCAN transmitter message abort request(CANTARQ) R/W
$_09 MSCAN transmitter message abort acknowledge (CANTAAK) R
$_0A MSCAN transmit buffer selection (CANTBSEL) R/W
$_0B MSCAN identifier acceptance control register (CANIDAC) R/W
$_0C reserved
$_0D reserved
$_0E MSCAN receive error counter register (CANRXERR) R
$_0F MSCAN transmit error counter register (CANTXERR) R
$_10 MSCAN identifier acceptance register 0 (CANIDAR0) R/W
$_11 MSCAN identifier acceptance register 1 (CANIDAR1) R/W
$_12 MSCAN identifier acceptance register 2 (CANIDAR2) R/W
$_13 MSCAN identifier acceptance register 3 (CANIDAR3) R/W
$_14 MSCAN identifier mask register 0 (CANIDMR0) R/W
$_15 MSCAN identifier mask register 1 (CANIDMR1) R/W
$_16 MSCAN identifier mask register 2 (CANIDMR2) R/W
$_17 MSCAN identifier mask register 3 (CANIDMR3) R/W
$_18 MSCAN identifier acceptance register 4 (CANIDAR4) R/W
$_19 MSCAN identifier acceptance register 5 (CANIDAR5) R/W
$_1A MSCAN identifier acceptance register 6 (CANIDAR6) R/W
$_1B MSCAN identifier acceptance register 7 (CANIDAR7) R/W
$_1C MSCAN identifier mask register 4 (CANIDMR4) R/W
$_1D MSCAN identifier mask register 5 (CANIDMR5) R/W
$_1E MSCAN identifier mask register 6 (CANIDMR6) R/W
$_1F MSCAN identifier mask register 7 (CANIDMR7) R/W
$_20
Foreground receive buffer (CANRXFG) R
$_2F
$_30
$_3F Foreground transmit buffer (CANTXFG) R/W

Figure 13.16 CAN module memory map


MSCAN Control Registers
• Motorola names each CAN register as CANxYYYY, where x
indicates the CAN module and YYYY specifies the register.
• MSCAN Control Register 0 (CANxCTL0)
– Bits 7, 6, and 4 are status flags. Other bits are control bits. Status bits
are read-only.
– When the TIME bit is set to 1, the timer value will be assigned to each
transmitted and received message within the transmit and receive
buffers.
– In order to configure the CANxCTL1, CANxBTR0, CANxBTR1,
CANxIDAC, CANxIDAR0-7, and CANxIDMR0-7, the user must set the
INITRQ bit to 1 and wait until the INITAK bit of the CANxCTL1 register
is set to 1.
– The contents of this register are shown in Figure 13.17.
7 6 5 4 3 2 1 0
RXFRM RXACT CSWAI SYNCH TIME WUPE SLPRQ INITRQ
reset: 0 0 0 0 0 0 0 1
RXFRM: Received frame flag
0 = no valid message was received
1 = a valid message was received since last clearing of this flag
RXACT: Receiver active status
0 = MSCAN is transmitting or idle
1 = MSCAN is receiving a message (including when arbitration is lost)
CSWAI: CAN stops in wait mode
0 = the module is not affected during wait mode
1 = the module ceases to be clocked during wait mode
SYNCH: synchronization status
0 = MSCAN is not synchronized to the CAN bus
1 = MSCAN is synchronized to the CAN bus
TIME: Timer enable
0 = disable internal MSCAN timer
1 = enable internal MSCAN timer and hence enable time stamp
WUPE: Wake-up enable
0 = wake-up disabled (MSCAN ignores traffic on CAN bus)
1 = wake-up enabled (MSCAN is able to restart)
SLPRQ: Sleep mode request
0 = running--The MSCAN functions normally
1 = sleep mode request--The MSCAN enters sleep mode when CAN is idle
INITRQ: Initialization mode request
0 = normal operation
1 = MSCAN in initialization mode
Figure 13.17 MSCAN control register 0 (CANxCTL0, x = 0, 1, 2, 3, or 4)
MSCAN Control Register 1 (CANxCTL1)
7 6 5 4 3 2 1 0
CANE CLKSRC LOOPB LISTEN 0 WUPM SLPAK INITAK
reset: 0 0 0 1 0 0 0 1
CANE: MSCAN enable
0 = The MSCAN module is disabled.
1 = The MSCAN module is enabled.
CLKSRC: MSCAN clock source
0 = The MSCAN clock source is the oscillator clock.
1 = The MSCAN clock source is the bus clock.
LOOPB: Loop back self test mode
0 = Loop back self test disabled
1 = Loop back self test enabled
LISTEN: Listen only mode
0 = Normal operation
1 = Listen only mode activated.
WUPM: Wake-up mode
0 = MSCAN wakes up the CPU after any recessive to dominant edge on the
CAN bus and WUPE bit of the CANCTL0 register is set to 1.
1 = MSCAN wakes up the CPU only in case of a dominant pulse on the CAN
bus that has a length of T WUP and the WUPE bit is set to 1.
SLPAK: Sleep mode acknowledge
0 = running--The MSCAN functions normally
1 = sleep mode active--The MSCAN has entered sleep mode.
INITAK: Initialization mode acknowledge
0 = normal operation--The MSCAN operates normally.
1 = Initialization mode active--The MSCAN is in initialization mode.
Figure 13.18 MSCAN control register 1 (CANxCTL1, x = 0, 1, 2, 3, or 4)
MSCAN Bus Timing Register 0 (CANxBTR0)

• This register selects the synchronization jump width and the baud
rate prescale factor.
7 6 5 4 3 2 1 0
SJW1 SJW0 BRP5 BRP4 BRP3 BRP2 BRP1 BRP0
reset: 0 0 0 0 0 0 0 0
SJW1, SJW0: Synchronization jump width
00 = 1 Tq clock cycle
01 = 2 Tq clock cycle
10 = 3 Tq clock cycle
11 = 4 Tq clock cycle
BRP5~BRP0: Baud rate prescaler
000000 = 1
000001 = 2
000010 = 3
....
111110 = 63
111111 = 64
Figure 13.19 MSCAN bus timeing register 0 (CANxBTR0, x = 0, 1, 2, 3, or 4)
MSCAN Bus Timing Register 1 (CANxBTR1)
• This register provides control on phase_seg1 and phase_seg2.
• Time Segment1 consists of prop_seg and phase_seg1.

prescaler value
Bit time = ---------------------  (1 + TimeSegment1 + TimeSegment2)
fCANCLK
7 6 5 4 3 2 1 0
SAMP TSEG22 TSEG21 TSEG20 TSEG13 TSEG12 TSEG11 TSEG10
reset: 0 0 0 0 0 0 0 0
SAMP: Sampling
0 = One sample per bit
1 = Three samples per bit
TSEG22~TSEG20: Time segment 2
000 = 1 Tq clock cycle
001 = 2 Tq clock cycles
....
110 = 7 Tq clock cycles
111 = 8 Tq clock cycles
TSEG13~TSEG10: Time segment 1
0000 = 1 Tq clock cycle
0001 = 2 Tq clock cycles
....
1110 = 15 Tq clock cycles
1111 = 16 Tq clock cycles

Figure 13.20 MSCAN bus timeing register 1 (CANxBTR1, x = 0, 1, 2, 3, or 4)


MSCAN Receiver Flag Register (CANxRFLG)
• The flag bits WUPIF, CSCIF, OVRIF, and RXF are cleared by writing a “1”
to them. 7 6 5 4 3 2 1 0
WUPIF CSCIF RSTAT1 RSTAT0 TSTAT1 TSTAT0 OVRIF RXF
reset: 0 0 0 0 0 0 0 0
WUPIF: Wake-up interrupt flag
0 = No wake-up activity observed while in sleep mode
1 = MSCAN detected activity on the bus and requested wake-up
CSCIF: CAN status change interrupt flag
0 = No change in bus status occurred since last interrupt
1 = MSCAN changed current bus status
RSTAT1~RSTAT0: Receiver status bits
00 = RxOK: 0  Receive error counter 96
01 = RxWRN: 96 < Receive error counter 127
10 = RxERR: 127 < Receive error counter
11 = Bus-off1: Transmit error counter > 255
TSTAT1~TSTAT0: Transmitter status bits
00 = TxOK: 0  Transmit error counter  96
01 = TxWRN: 96 < Transmit error counter  127
10 = TxERR: 127 < Transmit error counter
11 = Bus-off: Transmit error counter > 255
OVRIF: Overrun interrupt flag
0 = No data overrun occurred
1 = A data overrun detected
RXF: Receive buffer full flag
0 = No new message availale within the RxFG
1 = The receive FIFO is not empty. A new message is available in the RxFG.
Note 1. This information is redundant. As soon as the transmitter leaves its bus
off state, the receiver state skips to RxOK too.
Figure 13.21 MSCAN receiver flag register (CANxRFLG, x = 0, 1, 2, 3, or 4)
MSCAN Receiver Interrupt Enable Register (CANxRIER)
7 6 5 4 3 2 1 0
WUPIE CSCIE RSTATE1 RSTATE0 TSTATE1 TSTATE0 OVRIE RXFIE
reset: 0 0 0 0 0 0 0 0
WUPIE: Wake-up interrupt enable
0 = No interrupt request is generated from this event
1 = A wake-up event causes a wake-up interrupt request
CSCIE: CAN status change interrupt enable
0 = No interrupt request is generated from this event
1 = A CAN status change event causes an error interrupt request
RSTATE1~RSTATE0: Receiver status change interrupt enable
00 = do not generate any CSCIF interrupt caused by receiver state changes
01 = generate CSCIF interrupt only if the receiver enters or leaves "bus-off"
state.
10 = generate CSCIF interrupt only if the receiver enters or leaves "RxErr" or
"Bus-Off" state
11 = generate CSCIF interrupt on all state changes
TSTATE1~TSTATE0: Transmitter status change interrupt enable
00 = do not generate any CSCIF interrupt caused by transmitter state changes
01 = generate CSCIF interrupt only if the transmitter enters or leaves "bus-
off" state.
10 = generate CSCIF interrupt only if the transmitter enters or leaves "bus-
off" or "TxErr" state
11 = generate CSCIF interrupt on all state changes
OVRIE: Overrun interrupt enable
0 = No interrupt request is generated from this event
1 = An overrun event causes an error interrupt request
RXFIE: Receive buffer interrupt enable
0 = No interrupt request is generated from this event
1 = A receive buffer full event causes a receiver interrupt request.
Figure 13.22 MSCAN receiver flag register (CANxRIER, x = 0, 1, 2, 3, or 4)
MSCAN Transmitter Flag Register
(CANxTFLG)

7 6 5 4 3 2 1 0
0 0 0 0 0 TXE2 TXE1 TXE0
reset: 0 0 0 0 0 1 1 1
TXE2~TXE0: Transmitter buffer empty
0 = The associated message buffer is full (loaded with a message due for
transmission).
1 = The associated message buffer is empty.

Figure 13.23 MSCAN transmitter flag register (CANxTFLG, x = 0, 1, 2, 3, or 4)


MSCAN Transmit Interrupt Enable Register
(CANxTIER)

7 6 5 4 3 2 1 0
0 0 0 0 0 TXEIE2 TXEIE1 TXEIE0
reset: 0 0 0 0 0 0 0 0
TXEIE2~TXEIE0: Transmitter empty interrupt enable
0 = Disable interrupt from this buffer.
1 = A transmitter empty event causes a transmitter empty interrupt request.

Figure 13.24 MSCAN transmitter interrupt enable register (CANxTIER, x = 0, 1, 2, 3, or 4)


MSCAN Transmitter Message Abort
Request Register (CANxARQ)

• When the application has high-priority message but cannot find any
empty transmit buffer to use, it can request to abort the previous
messages that have been scheduled for transmission.

7 6 5 4 3 2 1 0
0 0 0 0 0 ABTRQ2 ABTRQ1 ABTRQ0
reset: 0 0 0 0 0 0 0 0
ABTRQ2~ABTRQ0: Abort request
0 = No abort request
1 = Abort request pending

Figure 13.25 MSCAN transmitter message abort request register


(CANxTARQ, x = 0, 1, 2, 3, or 4)
MSCAN Transmit Message Abort Acknowledge
Register (CANxTAAK)
• A message that is being transmitted cannot be aborted.
• Only those messages that have not been transmitted
can be aborted.
• MSCAN answers the abort request by setting or clearing
the associated bits in this register.

7 6 5 4 3 2 1 0
0 0 0 0 0 ABTAK2 ABTAK1 ABTAK0
reset: 0 0 0 0 0 0 0 0
ABTAK2~ABTAK0: Abort acknowledge
0 = The message was not aborted.
1 = The message was aborted.

Figure 13.26 MSCAN transmitter message abort acknowledge register


(CANxTAAK, x = 0, 1, 2, 3, or 4)
MSCAN Transmit Buffer Selection
(CANxTBSEL)
• This register selects the actual message buffer
that will be accessible in the CANTxFG register
space.
• The lowest numbered bit which is set makes the
respective transmit buffer accessible to the user.
7 6 5 4 3 2 1 0
0 0 0 0 0 TX2 TX1 TX0
reset: 0 0 0 0 0 0 0 0
TX2~TX0: Transmit buffer select bits
0 = The associated message buffer is deselected.
1 = The associated message buffer is selected, if it is the lowest numbered bit.

Figure 13.27 MSCAN transmitter buffer select register


(CANxTBSEL, x = 0, 1, 2, 3, or 4)
Method to Identify an Empty
Transmit Buffer for Data Transmission

• Reads the CANxTFLG register and then writes it into the


CANxTBSEL register.
• If there are multiple bits set to 1, then only the lowest numbered bit
in the CANxTBSEL register will be left to be 1.

ldaa CANxTFLG ; assume value read is %00000111


staa CANxTBSEL ; value written is %00000111
ldaa CANxTBSEL ; value read is %00000001
MSCAN Identifier Acceptance
Register (CANxIDAC)
• This register provides for identifier acceptance control.
• The IDHITs indicators are always related to the message in the foreground
receive buffer (RxFG).
7 6 5 4 3 2 1 0
0 0 IDAM1 IDAM0 0 IDHIT2 IDHIT1 IDHIT0
reset: 0 0 0 0 0 0 0 0
IDAM1~IDAM0: Identifier acceptance mode
00 = Two 32-bit acceptance filters
01 = Four 16-bit acceptance filters
10 = Eight 8-bit acceptance filters
11 = Filter closed
IDHIT2~IDHIT0: Identifier acceptance hit indicator (read only)
000 = Filter 0 hit
001 = Filter 1 hit
010 = Filter 2 hit
011 = Filter 3 hit
100 = Filter 4 hit
101 = Filter 5 hit
110 = Filter 6 hit
111 = Filter 7 hit

Figure 13.28 MSCAN Identifier acceptance control register


(CANxIDAC, x = 0, 1, 2, 3, or 4)
MSCAN Identifier Acceptance
Registers (CANxIDAR0~7)
• On reception, each message is written into the background receive buffer.
• The CPU is only signaled to read the message if it passes the criteria in the identifier
acceptance and identifier mask registers.
• These registers are applied on the IDAR0 to IDAR3 registers of the incoming
messages in a bit by bit manner.
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR0
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR1
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR2
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR3
reset: 0 0 0 0 0 0 0 0

Figure 13.29 MSCAN Identifier acceptance registers (first bank)


(x = 0, 1, 2, 3, or 4)
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR4
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR5
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR6
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AC7 AC6 AC5 AC4 AC3 AC2 AC1 AC0 CANxIDAR7
reset: 0 0 0 0 0 0 0 0

Figure 13.30 MSCAN Identifier acceptance registers (second bank)


(x = 0, 1, 2, 3, or 4)
MSCAN Identifier
Mask Registers (CANxIDMR0~7)
• The identifier mask registers specify which of the corresponding bits in the
identifier acceptance registers are relevant for acceptance filtering.
• If a mask bit is 1, its corresponding acceptance bit will be ignored.
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR0
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR1
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR2
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR3
reset: 0 0 0 0 0 0 0 0

Figure 13.31 MSCAN Identifier mask registers (first bank)


(x = 0, 1, 2, 3, or 4)
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR4
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR5
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR6
reset: 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
AM7 AM6 AM5 AM4 AM3 AM2 AM1 AM0 CANxIDMR7
reset: 0 0 0 0 0 0 0 0
Figure 13.32 MSCAN Identifier mask registers (second bank)
(x = 0, 1, 2, 3, or 4)
MSCAN Message Buffers
• The receive message and transmit message buffers have the same
outline.
• The message buffer organization is illustrated in Figure 13.33.

address register name


$_x0 Identifier register 0
$_x1 Identifier register 1
$_x2 Identifier register 2
$_x3 Identifier register 3
$_x4 Data segment register 0
$_x5 Data segment register 1
$_x6 Data segment register 2
$_x7 Data segment register 3
$_x8 Data segment register 4
$_x9 Data segment register 5
$_xA Data segment register 6
$_xB Data segment register 7
$_xC Data length register
$_xD Transmit buffer priority register 1
$_xE Time stamp register high byte2
$_xF Time stamp register low byte2
Note 1. Not applicable for receive buffer.
2. Read only for CPU
Figure 13.33 MSCAN message buffer organization
Identifier Registers (IDR0~IDR3)
• All four identifier registers are compared when a message with
extended identifier is received.
• Only the first two identifier registers are compared when a message
with standard identifier is received.
7 6 5 4 3 2 1 0
IDR0 ID28 ID27 ID26 ID25 ID24 ID23 ID22 ID21
IDR1 ID20 ID19 ID18 SRR(=1)IDE(=1) ID17 ID16 ID15
IDR2 ID14 ID13 ID12 ID11 ID10 ID9 ID8 ID7
IDR3 ID6 ID5 ID4 ID3 ID2 ID1 ID0 RTR

Figure 13.34 Receive/transmit message buffer extended identifier


7 6 5 4 3 2 1 0
IDR0 ID10 ID9 ID8 ID7 ID6 ID5 ID4 ID3
IDR1 ID2 ID1 ID0 RTR IDE(=0)
IDR2
IDR3

Figure 13.35 Receive/transmit message buffer standard identifier


• Data Segment Registers (DSR0~DSR7)
– These registers contain the data to be transmitted or received.
– The number of bytes to be transmitted or received is determined by the
data length code.
• Data Length Register (DLR)
– The lowest four bits of this register indicate the number of bytes
contained in the message.
• Transmit Buffer Priority Register (TBPR)
– This register defines the local priority of the associated message buffer.
– All transmit buffer with a cleared TXEx flag participate in the
prioritization.
– The transmit buffer with the lowest local priority field wins the
prioritization.
– In case of more than one buffer having the same lowest priority, the
message buffer with the lowest index number wins
Time Stamp Register (TSRH, TSRL)
• If the TIME bit of CANxCTL0 is set to 1, the MSCAN will write a special
time stamp to the respective registers in the active transmit or receive
buffer as soon as a message has been acknowledged.
• The time value used for stamping is taken from a free running internal
CAN bit clock.

7 6 5 4 3 2 1 0
TSR15 TSR14 TSR13 TSR12 TSR11 TSR10 TSR9 TSR8 TSRH
reset: x x x x x x x x
7 6 5 4 3 2 1 0
TSR7 TSR6 TSR5 TSR4 TSR3 TSR2 TSR1 TSR0 TSRL
reset: x x x x x x x x
Figure 13.36 MSCAN Time stamp registers
Can Foreground Receive
Buffer Register Names
Table 13.2a CAN foreground receive buffer x variable names
Name Address Description
CANxRIDR0 $_0 CAN foreground receive buffer x identifier register 0
CANxRIDR1 $_1 CAN foreground receive buffer x identifier register 1
CANxRIDR2 $_2 CAN foreground receive buffer x identifier register 2
CANxRIDR3 $_3 CAN foreground receive buffer x identifier register 3
CANxRDSR0 $_4 CAN foreground receive buffer x data segment register 0
CANxRDSR1 $_5 CAN foreground receive buffer x data segment register 1
CANxRDSR2 $_6 CAN foreground receive buffer x data segment register 2
CANxRDSR3 $_7 CAN foreground receive buffer x data segment register 3
CANxRDSR4 $_8 CAN foreground receive buffer x data segment register 4
CANxRDSR5 $_9 CAN foreground receive buffer x data segment register 5
CANxRDSR6 $_A CAN foreground receive buffer x data segment register 6
CANxRDSR7 $_B CAN foreground receive buffer x data segment register 7
CANxRDLR $_C CAN foreground receive buffer x data length register
Note 1. x can be 0, 1, 2, or 3
2. The absolute address of each register is equal to the sum of the base address
of the CAN foreground receive buffer base x address and the address
field of the corresponding register.
CAN Foreground Transmit
Buffer Register Names
Table 13.2b CAN foreground transmit buffer x variable names
Name Address Description
CANxTIDR0 $_0 CAN foreground transmit buffer x identifier register 0
CANxTIDR1 $_1 CAN foreground transmit buffer x identifier register 1
CANxTIDR2 $_2 CAN foreground transmit buffer x identifier register 2
CANxTIDR3 $_3 CAN foreground transmit buffer x identifier register 3
CANxTDSR0 $_4 CAN foreground transmit buffer x data segment register 0
CANxTDSR1 $_5 CAN foreground transmit buffer x data segment register 1
CANxTDSR2 $_6 CAN foreground transmit buffer x data segment register 2
CANxTDSR3 $_7 CAN foreground transmit buffer x data segment register 3
CANxTDSR4 $_8 CAN foreground transmit buffer x data segment register 4
CANxTDSR5 $_9 CAN foreground transmit buffer x data segment register 5
CANxTDSR6 $_A CAN foreground transmit buffer x data segment register 6
CANxTDSR7 $_B CAN foreground transmit buffer x data segment register 7
CANxTDLR $_C CAN foreground transmit buffer x data length register
CANxTBPR $_D CAN foreground transmit buffer x priority register
CANxTSRH $_E CAN foreground transmit buffer x time stamp register high
CANxTSRL $_F CAN foreground transmit buffer x time stamp register low
Note 1. x can be 0, 1, 2, or 3
2. The absolute address of each register is equal to the sum of the base
address of the CAN foreground transmit buffer x and the address field of the
corresponding register.
Transmit Storage Structure

Tx0
• Multiple messages TXE0

can be set up in

TxBG
advance and achieve PRIO
real-time
performance.
• A transmit buffer is Tx1
TXE1
made accessible to MSCAN
CPU bus

TxFG
the user by writing
appropriate value into PRIO

the CANxTBSEL
register. Tx2
TXE2
• The transmit buffer
organization is shown
in Figure 13.37. TxBG PRIO

Figure 13.37 User model for transmit buffer organization


Procedure for Message Transmission
• Step 1
– Identifying an available transmit buffer by checking the TXEx flag
associated with the transmit buffer.
• Step 2
– Setting a pointer to the empty transmit buffer by writing the
CANxTFLG register to the CANxTBSEL register. This makes the
transmit buffer accessible to the user.
• Step 3
– Storing the identifier, the control bits, and the data contents into
one of the transmit buffers.
• Step 4
– Flagging the buffer as ready by clearing the associated TXE flag.
Receive Storage Structure (1 of 2)
• Received messages
are stored in a five-
stage FIFO data RX0

structure. RX1

RxBG
MSCAN RX2
• The message buffers RX3
are alternately mapped RX4
RXF
into a single memory
area referred to as the CPU bus

RxFG
foreground receive
buffer.
• The application reads Figure 13.38 User model for receive buffer organization

the foreground receive


buffer to access the
received message.
Receive Storage Structure (2 of 2)
• When a valid message is received at the background
receive buffer, it will be transferred to the foreground
receive buffer and the RXF flag will be set to 1.
• The user’s program has to read the received message
from the RxFG and then clear the RXF flag to
acknowledge the interrupt and to release the foreground
receive buffer.
• When all receive buffers in the FIFO are filled with
received messages, an overrun condition may occur.
Identifier Acceptance Filter
• Identifier acceptance registers define the acceptance patterns of the
standard or extended identifier.
• Any of the bits in the acceptance identifier can be marked “don’t care” in the
MSCAN identifier mask registers.
• A message is accepted only if its associated identifier matches one of the
identifier filters.
• A filter hit is indicated by setting a RXF flag to 1 and the three hit bits in the
CANIDAC register.
• The identifier acceptance filter can be programmed to operate in one of the
four modes:
– Two 32-bit identifier acceptance filters. This mode may cause up to 2 hits.
– Four 16-bit identifier acceptance filters. This mode may cause up to 4 hits.
– Eight 8-bit identifier acceptance filters. This mode may cause up to 8 hits.
– Closed filter. No CAN message is copied into the foreground buffer RxFG.
Bus clock MSCAN

CANCLK Prescaler Time quanta clock (Tq)


(1...64)
CLKSRC

CLKSRC
Oscillator clock

Figure 13.39 MSCAN clocking scheme

MSCAN Clock System


• Either the bus clock or the crystal oscillator output can be used as the
CANCLK.
• The clock source has to be chosen so that it meets the 0.4% tolerance
requirement of the CAN protocol.
• If the bus clock is generated from a PLL, it is recommended to select the
oscillator clock rather than the bus clock due to the jitter considerations,
especially at the higher baud rate.
• A programmable prescaler generates the time quanta (Tq) clock from the
CANCLK.
fTq = fCANCLK  prescaler
MSCAN Bit Time
• MSCAN divides a bit time into three segments:
– Sync_seg: fixed at one time quantum
– Time segment 1: This segment includes the prop_seg
and phase_seg1 of the CAN standard.
– Time segment 2: This segment represents the
phase_seg2 of the CAN standard.
NRZ signal

Time segment 1 Time segment 2


SYNC_SEG
(prop_seg + phase_seg1) (phase_seg2)
1 4 ... 16 2 ... 8

8 ... 25 time quanta


= 1 bit time
Transmit point Sample point
(single or tripple sampling)
Figure 13.40 Segments within the bit time
MSCAN Interrupt Operation
• Transmit interrupt
– At least one of the three transmit buffers is empty, its TXEx flag is set.
• Receive interrupt
– When a message is successfully received and shifted to the foreground
buffer of the receive FIFO. The associated RXF flag is set.
• Wakeup interrupt
– Activity on the CAN bus occurred during the MSCAN internal sleep
mode generates this type of interrupts.
• Error interrupt
– An overrun of the receiver FIFO, error, warning, or bus-off condition
may generate an error interrupt.
MSCAN Initialization
• Procedure of MSCAN Initialization Out of Reset
– Assert the CANE bit
– Enter the initialization mode (make sure both the INITRQ and INITAK
bits are set)
– Write to the configuration registers including CANxCTL1, CANxBTR0,
CANxBTR1, CANxIDAC, CANxIDAR0-7, CANxIDMR0-7.
– Clear the INITRQ bit to leave the initialization mode and enter normal
mode.
• Procedure of MSCAN Initialization in Normal Mode
– Make sure that the MSCAN transmission queue gets empty and bring
the module into sleep mode by asserting the SLPRQ bit and waiting for
the SLPAK bit to be set.
– Enter the initialization mode
– Write to the configuration registers in initialization mode.
– Clear the INITRQ bit to leave initialization mode to enter normal mode.
Physical CAN Bus Connection
• CAN is designed for data communication over a short
distance.
• CAN protocol does not specify what medium to use for
data communication.
• Using a shielded or unshielded cable is recommended
for a short distance communication.
• A typical CAN bus setup using a cable is shown.

node node node node

1 2 3 n

CAN_H

RT
RT = 120 
(120 
CAN_L

Figure 13.41 A typical CAN bus setup using cable


CAN Bus Signal Levels

voltage

5V

CAN_H
3.5V

2.5V
CAN_L
1.5V

0V
Recessive Dominant Recessive

Figure 13.42 Nominal CAN bus levels


Microchip MCP2551 CAN Bus Transceiver (1 of 3) VDD

TXD
VDD Thermal
Dominant
Detect shutdown

TxD 1
Driver
control
Slope power- 7 CANH
Rs control on reset VDD
8

RxD Receiver
4
GND
6
CANL
Reference
VREF
5 Voltage

Figure 13.43 The block diagram of Microchip MCP2551


Microchip MCP2551 CAN Bus Transceiver (2 of 3)
• MCP2551 provides a differential transmit and receive capability.
• Operates up to 1 Mbps data rate
• Allows a maximum of 112 nodes to be connected to the same CAN
bus.
• The RxD pin reflects the differential voltage between CAN_H and
CAN_L.
• The Rs input allows the user to select one of the three operation
modes:
– High speed – ground the Rs pin
– Slope control – can reduce the EMI by limiting the rise and fall times of
the CAN_H and CAN_L signals. This is achieved by connecting Rs pin
to a resistor. The slew rate vs. slope control resistance is shown in
Figure 13.44.
– Standby – pull the Rs pin to high
Microchip MCP2551 CAN Bus Transceiver (3 of 3)
25

20
Slew rate V/uS

15

10

0
10 20 30 40 49 60 70 80 90 100 110
Resistance (K)

Figure 13.44 Slew rate vs. slope control resistance value


Interfacing the MCP2551 to the HCS12
HCS12
TXCAN RXCAN

TxD RxD VREF RS REXT


5V VCC
100nF MCP2551
GND
CANH CANL REXT set to 0 in high-
speed mode

CAN_H

120 CAN Bus Line 120


CAN_L

Figure 13.45 Interfacing the MCP2551 with the HCS12


Setting the CAN Timing Parameters (1 of 2)
Table 13.3 CAN bus bit rate /bus length relation
Bit rate (kbit/s) Bus length
1000 40
500 100
250 250
125 500
62.5 1000

• Let tBUS, tTX, and tRX represent the data traveling


time on the bus, transmitter propagation delay,
and receiver propagation delay, respectively.
– The worst-case value for tPROP_SEG is
tPROP_SEG = 2  (tBUS + tTX + tRX) (13.4)
– In units of time quantum,
prop_seg = round_up (tPROP_SEG  tQ) (13.5)
Setting the CAN Timing Parameters (2 of 2)
• In the absence of bus errors, bit stuffing guarantees a maximum 10-
bit period between resynchronization edges.
• The accumulated phase errors are due to the tolerance in the CAN
system clock. This requirement can be expressed as
(2  f)  10  tNBT < tRJW (13.6)
where,  f is the largest crystal oscillator frequency variation.
• When bus error exists, an error flag from an error active node
consists of six dominant bits, and there could be up to six dominant
bits before the error flag, if, for example, the error was a stuff error.
• A node must correctly sample the 13th bit after the last
resynchronization. This can be expressed as
(2   f)  (13  tNBT – tPHASE_SEG2) < min (tPHASE_SEG1, tPHASE_SEG2) (13.7)
Procedure for Determining
the Optimum Bit Timing Parameters (1 of 2)
• Step 1
– Determine the minimum permissible tprop_seg using equation 13.4.
• Step 2
– Choose the CAN system clock frequency. The CAN system
clock frequency will be either the CPU oscillator output or the
bus clock divided by a prescale factor. The chosen clock
frequency must make the tNBT an integral multiple of tQ from 8
to 25.
• Step 3
– Calculate the prop_seg duration using equation 13.5. If the
resultant value is greater than 8, go back to Step 2 and choose a
lower CAN system clock frequency.
Procedure for Determining
the Optimum Bit Timing Parameters (2 of 2)
• Step 4
– Determine phase1_seg and phase_seg2. Subtract the prop_seg value
and 1 from the time quanta contained in a bit time. If the difference is
less than 3 than go back to Step 2 and select a higher CAN system
clock frequency. If the difference is 3, then phase_seg1 = 1 and
phase_seg2 = 2 and only one sample per bit may be chosen. If the
difference is an odd number greater than 3, then add 1 to the prop_seg
value and recalculate. Otherwise divide the remaining number by two
and assign the result to phase_seg1 and phase_seg2.
• Step 5
– Determine the resynchronization jump width (RJW). RJW is the
smaller one of 4 and phase_seg1.
• Step 6
– Calculate the required oscillator tolerance from equation 13.6 and
13.7. If phase_seg1 > 4, it is recommended that you repeat Steps 2 to 6
with a larger value for the prescaler.
• Example 13.1 Calculate the CAN bit segments for the following constraints:
– Bit rate = 1 Mbps
– Bus length = 25 m
– Bus propagation delay = 5  10-9 sec/m
– CAN transceiver plus receiver propagation delay = 150 ns at 85 oC
– CPU oscillator frequency = 24 MHz
• Solution:
– Step 1
Physical delay of the CAN bus = 25  5 = 125 ns
tPROP_SEG = 2  (125 + 150) = 550 ns
– Step 2
A prescaler of 1 for 24 MHz gives a time quantum of 41.67 ns.
One bit time is 1/1 Mbps = 1 s.
One bit time (NBT) corresponds to 24 (= 1000 ns  41.67) time quanta.
– Step 3
Prop_seg = round_up (550 ns  41.67) = 14 > 8. Set prescaler to 2. Then one time
quantum is 83.33 ns and one bit time is 12 time quanta. The new prop_seg = 7.
– Step 4
NBT – prop_seg1 – sync_seg = 12 – 7 – 1 = 4.
phase_seg1 = 4/2 = 2,
phase_seg2 = 4 – phase_seg1 = 2
– Step 5
RJW = min (4, phase_seg1) = 2
– Step 6
From equation 13.7,
f < RJW  (20  NBT) = 2  (20  12) = 0.83%

From equation 13.8,


f < min(phase_seg1, phase_seg2)  [2  (13  NBT – phase_seg2)]
= 2  308 = 0.65%

The desired oscillator tolerance is 0.65%.


• Most crystal oscillators have tolerance smaller than 0.65%.
•In summary,
Prescaler =2
Nominal bit time = 12
prop_seg =7
sync_seg =1
phase_seg1 =2
phase_seg2 =2
RJW =2
oscillator tolerance = 0.65%
• Example 13.2 Calculate the CAN bit segments for the following constraints:
– Bit rate = 500 Kbps
– Bus length = 50 m
– Bus propagation delay = 5  10-9 sec/m
– CAN transceiver plus receiver propagation delay = 150 ns at 85 oC
– CPU oscillator frequency = 16 MHz
• Solution:
– Step 1
Physical delay of the bus = 50  5  10-9 sec/m = 250 ns
tPROP_SEG = 2  (250 + 150) = 800 ns
– Step 2
Use 2 as the prescaler.
The resultant TQ is 125 ns. A normal bit time is 2 s.
Quanta per bit = 2,000 /125 = 16
– Step 3
Prop_seg = round_up (800  125) = 7.
– Step 4
Subtract 7 and 1 from 16 time quanta per bit gives 8. Since this number is
even and greater than 4, divide it by 2 and assign it to phase_seg1 and
phase_seg2.
– Step 5
RJW = min (4, phase_seg1) = 4
– Step 6
From equation 13.6,
f < RJW  (20  NBT) = 4  (20  16) = 1.25%
From equation 13.7,
f < min(phase_seg1, phase_seg2)  [2  (13  NBT – phase_seg2)]
= 4  408= 0.98%

• In summary,
Prescaler =2
Nominal bit time = 16
Prop_seg =7
Sync_seg =1
Phase_seg1 =4
Phase_seg2 =4
RJW =4
Oscillator tolerance = 0.98%
MSCAN Configuration
• Timing parameters for the CAN module need only be set once after reset.
• Other parameters such as acceptance filters may be changed after reset
configuration.
• Example 13.3 Write a program to configure the MSCAN module 1 after
reset with the timing parameters in Example 13.1 and the following setting:
– Enable wakeup
– Disable time stamp
– Select oscillator as the clock source to the MSCAN
– Disable loopback mode, disable listen only mode
– Take one sample per bit
– Acceptance messages with extended identifiers that start with T1 and P1 (use
two 32-bit filters)
• Solution:
openCan1 bset CAN1CTL1,CANE ; required after reset
bset CAN1CTL0,INITRQ ; request to enter initialization mode
w1 brclr CAN1CTL1,INITAK,w1 ; make sure initialization mode is entered
movb #$84,CAN1CTL1 ; enable CAN1,select oscillator as clock
; source, enable wake up filter
movb #$41,CAN1BTR0 ; set jump width to 2 Tq, prescaler set to 2
movb #$18,CAN1BTR1 ; set phase_seg2 to 2 Tq, phase_seg1 to 2 Tq,
; set prop_seg to 7 Tq
movb #$54,CAN1IDAR0 ; acceptance identifier 'T'
movb #$3C,CAN1IDAR1 ; acceptance identifier '1‘ (IDE bit = 1)
movb #$40,CAN1IDAR2 ; "
movb #$00,CAN1IDAR3 ; "
movb #$00,CAN1IDMR0 ; acceptance mask for extended identifier "T1"
movb #$00,CAN1IDMR1 ; "
movb #$3F,CAN1IDMR2 ; "
movb #$FF,CAN1IDMR3 ; "
movb #$50,CAN1IDAR4 ; acceptance identifier 'P'
movb #$3C,CAN1IDAR5 ; acceptance identifier '1‘ (IDE bit = 1)
movb #$40,CAN1IDAR6 ; "
movb #$00,CAN1IDAR7 ; "
movb #$00,CAN1IDMR4 ; acceptance mask for extended identifier "P1"
movb #$00,CAN1IDMR5 ; "
movb #$3F,CAN1IDMR6 ; "
movb #$FF,CAN1IDMR7 ; "
clr CAN1IDAC ; set two 32-bit filter mode
bclr CAN1CTL0,INITRQ ; leave initialization mode
movb #$24,CAN1CTL0 ; stop clock on wait mode, enable wakeup
rts
C Function to Initialize the CAN1 Module
void openCan1(void)
{
CAN1CTL1 |= CANE; /* enable CAN, required after reset */
CAN1CTL0 |= INITRQ; /* request to enter initialization mode */
while(!(CAN1CTL1&INITAK)); /* wait until initialization mode is entered */
CAN1CTL1 = 0x84; /* enable CAN1, select oscillator as MSCAN clock
source, enable wakeup filter */
CAN1BTR0 = 0x41; /* set SJW to 2, set prescaler to 2 */
CAN1BTR1 = 0x18; /* set phase_seg2 to 2Tq, phase_seg1 to 2Tq,
prop_seg to 7 Tq */
CAN1IDAR0 = 0x54; /* set acceptance identifier "T1" */
CAN1IDAR1 = 0x3C; /* " */
CAN1IDAR2 = 0x40; /* " */
CAN1IDAR3 = 0x00; /* " */
CAN1IDMR0 = 0x00; /* acceptance mask for "T1" */
CAN1IDMR1 = 0x00; /* " */
CAN1IDMR2 = 0x3F; /* " */
CAN1IDMR3 = 0xFF; /* " */
CAN1IDAR4 = 0x50; /* set acceptance identifier "P1" */
CAN1IDAR5 = 0x3C; /* " */
CAN1IDAR6 = 0x40; /* " */
CAN1IDAR7 = 0x00; /* " */
CAN1IDMR4 = 0x00; /* acceptance mask for "P1" */
CAN1IDMR5 = 0x00; /* " */
CAN1IDMR6 = 0x3F; /* " */
CAN1IDMR7 = 0xFF; /* " */
CAN1IDAC = 0x00; /* select two 32-bit filter mode */
CAN1CTL0 &= ~INITRQ; /* exit initialization mode *
CAN1CTL0 = 0x24; /* stop clock on wait mode, enable wake up */
}
• Example 13.4 Write an instruction sequence to change the configuration of the CAN1
module so that it would accept messages with standard identifier starting with letter ‘T’
or ‘P’.
• Solution:
- This reconfiguration is done in normal mode.
- Need to wait until the transmit buffer is empty
- Need to place CAN1 in sleep mode
Instruction Sequence to change the CAN1
Configuration
ct1 brset CAN1TFLG,$07,tb_empty ; wait until all transmit buffers are empty
bra ct1
tb_empty bset CAN1CTL0,SLPRQ ; request to enter sleep mode
ct2 brclr CAN1CTL1,SLPAK,ct2 ; wait until sleep more is entered
bset CAN1CTL0,INITRQ ; request to enter initialization mode
ct3 brclr CAN1CTL1,INITAK,ct3 ; wait until initialization mode is entered
movb #$10,CAN1IDAC ; select 4 16-bit acceptance mode
movb #$54,CAN1IDAR0 ; set up filter for letter 'T' for standard
movb #0,CAN1IDAR1 ; identifier (IDE bit = 0)
movb #$50,CAN1IDAR2 ; set up filter for letter 'P' for standard
clr CAN1IDAR3 ; identifier (IDE bit = 0)
clr CAN1IDMR0 ; acceptance mask for 'T'
movb #$F7,CAN1IDMR1 ; check IDE bit only (must be 0)
clr CAN1IDMR2 ; acceptance mask for 'P'
movb #$F7,CAN1IDMR3 ; check IDE bit only (must be 0)
movb #$54,CAN1IDAR4 ; set up filter for letter 'T' for standard
movb #0,CAN1IDAR5 ; identifier
movb #$50,CAN1IDAR6 ; set up filter for letter 'P' for standard
clr CAN1IDAR7 ; identifier
clr CAN1IDMR4 ; acceptance mask for 'T'
movb #$F7,CAN1IDMR5 ; check IDE bit only (must be 0)
clr CAN1IDMR6 ; acceptance mask for 'P'
movb #$F7,CAN1IDMR7 ; check IDE bit only (must be 0)
bclr CAN1CTL0,INITRQ ; exit initialization mode
bclr CAN1CTL0,SLPRQ ; exit sleep mode
Data Transmission and Reception in MSCAN
• Data transmission in CAN bus can be driven by polling method or interrupts.
• When data to be transmitted is small and infrequent, polling method is quite
good.
• Data arrival is usually less predictable. It is more convenient to use
interrupt-driven method for data reception.
– Example 13.5 Write a function to send out the message stored at a buffer pointed
to by index register X from the CAN1 module. The function should find an
available buffer to hold the message to be sent out.
– Solution:
tbuf equ 0 ; tbuf offset from top of stack
snd2can1 pshy
pshb
leas -1,sp ; allocate one byte for local variable
sloop1 brset CAN1TFLG,$01,tb0 ; is transmit buffer 0 empty?
brset CAN1TFLG,$02,tb1 ; is transmit buffer 1 empty?
brset CAN1TFLG,$04,tb2 ; is transmit buffer 2 empty?
bra sloop1 ; if necessary wait until one buffer is empty
tb0 movb #0,tbuf,sp ; mark transmit buffer 0 empty
bra tcopy
tb1 movb #1,tbuf,sp ; mark transmit buffer 1 empty
bra tcopy
tb2 movb #2,tbuf,sp ; mark transmit buffer 2 empty
tcopy movb CAN1TFLG,CAN1TBSEL ; make the empty transmit buffer accessible
ldy #CAN1TIDR0 ; set y to point to the start of the transmit buffer
ldab #7 ; always copy 7 words (place word count in B)
cploop movw 2,x+,2,y+
dbne b,cploop
ldab tbuf,sp
cmpb #0
beq istb0
cmpb #1
beq istb1
movb #$04,CAN1TFLG ; mark buffer 2 ready for transmission
bra dcopy
istb0 movb #$01,CAN1TFLG ; mark buffer 0 ready for transmission
bra dcopy
istb1 movb #$02,CAN1TFLG ; mark buffer 1 ready for transmission
dcopy leas 1,sp ; deallocate local variables
pulb
puly
rts
C Function for CAN1 Data Transmission
void snd2can1(char *ptr)
{
int tb,i,*pt1,*pt2;
pt1 = (int *)ptr; /* convert to integer pointer */
while(1) { /* find an empty transmit buffer */
if(CAN1TFLG & 0x01){
tb = 0;
break;
}
if(CAN1TFLG & 0x02){
tb = 1;
break;
}
if(CAN1TFLG & 0x04){
tb = 2;
break;
}
}
CAN1TBSEL = CAN1TFLG; /* make empty transmit buffer accessible */
pt2 = (int *)&CAN1TIDR0; /* pt2 points to the IDR0 of TXFG */
for (i = 0; i < 7; i++) /* copy the whole transmit buffer */
*pt2++ = *pt1++;
if (tb == 0)
CAN1TFLG = 0x01; /* mark buffer 0 ready for transmission */
else if (tb == 1)
CAN1TFLG = 0x02; /* mark buffer 1 ready for transmission */
else
CAN1TFLG = 0x04; /* mark buffer 2 ready for transmission */
}
• Example 13.6 Write a program to send out the string “3.5 V” from CAN1
and use “V1” as its identifier. Set transmit buffer priority to the highest.
• Solution:
org $1000
tbuf0 ds 16
org $1500
movb #$56,tbuf0 ; identifier V1
movb #$3C,tbuf0+1 ; "
movb #$40,tbuf0+2 ; "
movb #0,tbuf0+3 ; “
movb #$34,tbuf0+4 ; data "3"
movb #$2E,tbuf0+5 ; data "."
movb #$35,tbuf0+6 ; data "5"
movb #$20,tbuf0+7 ; data " "
movb #$56,tbuf0+8 ; data "V"
movb #5,tbuf0+12 ; data length (=5)
movb #0,tbuf0+13 ; set transmit buffer priority to highest
ldx #tbuf0
jsr snd2can1 ; call subroutine to perform the actual transmission
rts
swi
end
C Program that Sends Out “3.5 V” from CAN1
#include “c:\egnu091\include\hcs12.h”
void snd2can1(char *ptr);
int main(void)
{
char tbuf0[16];
tbuf0[0] = 'V'; /* identifier V1 */
tbuf0[1] = 0x3C; /* " */
tbuf0[2] = 0x40; /* " */
tbuf0[3] = 0; /* " */
tbuf0[4] = '3'; /* letter 3 */
tbuf0[5] = '.'; /* character . */
tbuf0[6] = '5'; /* letter 5 */
tbuf0[7] = 0x20; /* space */
tbuf0[8] = 'V'; /* letter V */
tbuf0[12] = 5; /* data length */
tbuf0[13] = 0; /* tbuf0 priority */
snd2can1(tbuf0);
return 0;
}
• Example 13.7 Assuming that the CAN1 receiver has been set up to
accept messages with extended identifiers “T1” and “V1”. The filter 0 is set
up to accept the identifier started with “T1,” whereas the filter 1 is set up to
accept the identifier started with “V1”. Write the interrupt handling routine for
the RXF interrupt. If the acceptance is caused by filter 0, the RXF service
routine would display the following message on a 20  2 LCD:
Temperature is
xxx.yoF
If the acceptance of the message is caused by filter 1, the RXF interrupt service
routine would display the following message:
Voltage is
x.y V
• Solution:
- The interrupt service routine checks the RXF flag of the CAN1RFLG register to
make sure that the interrupt is caused by the RXF flag.
- CAN data reception is performed by the interrupt service routine.
can1Rx_ISR brset CAN1RFLG,RXF,RxfSet ; is the RXF flag set to 1?
rti ; if not, do nothing
RxfSet ldab CAN1IDAC ; check into IDHIT bits
andb #$07 ; mask out higher 5 bits
beq hit0 ; filter 0 hit?
cmpb #1 ; filter 1 hit?
beq hit1
rti ; not hit 0 nor hit 1, do thing
hit0 ldab CAN1RDLR ; get the byte count of incoming data
beq rxfDone ; byte count 0, return
ldx #t1_line1 ; output "Temperature is"
jsr puts2lcd ; "
ldx #CAN1RDSR0
outLoop1 ldaa 1,x+ ; output one byte at a time
jsr putc2lcd ; "
dbne b,outLoop1 ; "
rti
hit1 ldab CAN1RDLR ; get the byte count of incoming data
beq rxfDone ; byte count 0, return
ldx #v1_line1 ; output "Voltage is"
jsr puts2lcd ; "
ldx #CAN1RDSR0 ; x points to data segment register 0
outLoop2 ldaa 1,x+
jsr putc2lcd
dbne b,outLoop2
rxfDone rti
t1_line1 fcc "Temperature is"
dc.b 0
v1_line1 fcc "Voltage is"
dc.b 0
C Program for the Interrupt-driven Data Reception in
CAN Bus
#include “c:\egnu091\include\hcs12.h”
#include “c:\egnu091\include\vectors12.h”
#include “c:\egnu091\include\delay.c”
#include “c:\egnu091\include\lcd_util_SSE256.c”
#define INTERRUPT __attribute__((interrupt))
void INTERRUPT RxISR(void);
void openCan1(void);
char *t1Msg = "Temperature is";
char *v1Msg = "Voltage is";
int main (void)
{
UserMSCAN1Rx = (unsigned short) &RxISR;
openCan1();
openlcd();
CAN1RIER = 0x01; /* enable CAN1 RXF interrupt only */
asm("cli");
while(1); /* wait for RXF interrupt */
return 0;
}
void INTERRUPT RxISR (void)
{
char tmp,i,*ptr;
if (!(CAN1RFLG & RXF)) /* interrupt not caused by RXF, return */
return;
tmp = CAN1IDAC & 0x07; /* extract filter hit info */
if (tmp == 0) { /* filter 0 hit */
if (CAN1RDLR==0) /* data length 0, do nothing */
return;
cmd2lcd(0x80); /* set LCD cursor to first row */
puts2lcd(t1Msg); /* output "Temperature is" on LCD */
cmd2lcd(0xC0); /* set LCD cursor to second row */
ptr = (char *)&CAN1RDSR0; /* ptr points to the first data byte */
for (i = 0; i < CAN1RDLR; i++)
putc2lcd(*ptr++); /* output temperature value on the LCD 2nd row */
}
else if (tmp == 1) { /* filter 1 hit */
if(CAN1RDLR == 0) /* data length 0, do nothing */
return;
cmd2lcd(0x80); /* set LCD cursor to first row */
puts2lcd(v1Msg); /* output "Voltage is" on the 1st row of LCD */
cmd2lcd(0xC0); /* set LCD cursor to second row */
ptr = (char *)&CAN1RDSR0; /* PTR points to the first data byte */
for(i = 0; i < CAN1RDLR; i++)
putc2lcd(*ptr++); /* output voltage value on the 2nd row of LCD */
}
else asm(“nop”); /* other hit, do nothing */
}
• Example 13.8 Write a C program to be run in a CAN environment using
the same timing parameters as computed in Example 13.1. Each CAN
node measures the voltage (in the range from 0 to 5 V) and sends it out
from the CAN bus and also receives the voltage message sent over the
CAN bus by other nodes. Configure the CAN1 module to receive messages
having an extended identifier started with “V1”. The transmission and
reception are to be proceeded as follows:
- The program measures the voltage of the AN7 pin every 200 milliseconds and
sends out the value with identifier “V1”. The voltage is represented in the format of
“x.y V”. After sending out a message, the program outputs the following message on
the first row of the LCD:
Sent: x.y V
- Message reception is interrupt driven. Whenever a new message is accepted, the
program outputs the following message on the second row of the LCD:
Received x.y V
• Solution:
#include “c:\egnu091\include\hcs12.h”
#include “c:\egnu091\include\delay.c”
#include “c:\egnu091\include\vectors12.h”
#include “c:\egnu091\include\lcd_util_SSE256.c”
#define INTERRUPT __attribute__((interrupt))
char *msg1 = "Sent: ";
char *msg2 = "Received: ";
void INTERRUPT RxISR(void);
void openAD0(void);
void wait20us (void);
void OpenCan1(void);
void MakeBuf(char *pt1, char *pt2);
void snd2can1(char *ptr);
int main(void)
{
char buffer[6]; /* to hold measured voltage */
char buf[16]; /* transmit data buffer */
int temp;
UserMSCAN1Rx = (unsigned short)&RxISR; /* set up interrupt vector */
openlcd(); /* configure LCD kit */
OpenCan1(); /* configure CAN1 module */
buffer[1] = '.'; /* decimal point */
buffer[3] = 0x20; /* space character */
buffer[4] = 'V'; /* volt character */
buffer[5] = 0; /* null character */
openAD0(); /* configure AD0 module */
CAN1RIER = 0x01; /* enable RXF interrupt only */
asm("cli"); /* enable interrupt globally */
while(1) {
ATD0CTL5 = 0x87; /* convert AN7, result right justified */
while(!(ATD0STAT0 & SCF)); /* wait for conversion to complete */
buffer[0] = 0x30 + (ATD0DR0*10)/2046; /* integral digit of voltage */
temp = (ATD0DR0 * 10)%2046; /* find the remainder */
buffer[2] = 0x30 + (temp * 10)/2046; /* compute the fractional digit */
MakeBuf(&buf[0],&buffer[0]); /* format data for transmission */
snd2can1(&buf[0]); /* send out voltage on CAN bus */
cmd2lcd(0x80); /* set LCD cursor to first row */
puts2lcd(msg1); /* output the message "sent: x.y V" */
puts2lcd(&buffer[0]); /* " */
delayby100ms(2); /* wait for messages to arrive for .2 seconds */
}
return 0;
}
/*******************************************************************************************/
/* The following function formats a buffer into the structure of a CAN transmit */
/* buffer so that it can be copied into any empty transmit buffer for transmission. */
/*******************************************************************************************/
void MakeBuf(char *pt1, char *pt2)
{
char i;
*pt1 = 'V'; /* set "V1" as the transmit identifier */
*(pt1+1) = 0x3C; /* " */
*(pt1+2) = 0x40; /* " */
*(pt1+3) = 0; /* " */
for(i = 4; i < 9; i++) /* copy voltage data */
*(pt1 + i) = *(pt2 + i - 4);
*(pt1+12) = 5; /* set data length to 5 */
}
/************************************************************************************/
/* The following function handles the RXF interrupt. It checks if the RXF */
/* is set. If not, return. It also ignores the RTR request. */
/************************************************************************************/
void INTERRUPT RxISR (void)
{
char tmp,i,*ptr;
if (!(CAN1RFLG & RXF)) /* interrupt not caused by RXF, return */
return;
tmp = CAN1IDAC & 0x07; /* extract filter hit info */
if (tmp == 0){ /* filter 0 hit */
if (CAN1RDLR==0) /* if data length is 0, do nothing */
return;
cmd2lcd(0xC0); /* set LCD cursor to second row */
puts2lcd(msg2); /* output "received: " */
ptr = (char *)&CAN1RDSR0; /* ptr points to the first data byte */
for (i = 0; i < CAN1RDLR; i++)
putc2lcd(*ptr++); /* output "x.y V" */
return;
}
else return; /* other hit, do nothing */
}
void openAD0 (void)
{
int i;
ATD0CTL2 = 0xE0;
delayby10us(2);
ATD0CTL3 = 0x0A; /* perform one conversion */
ATD0CTL4 = 0x25; /* 4 cycles sample time, prescaler set to 12 */
}
void OpenCan1(void)
{
CAN1CTL1 |= CANE; /* enable CAN, required after reset */
CAN1CTL0 |= INITRQ; /* request to enter initialization mode */
while(!(CAN1CTL1&INITAK)); /* wait until initialization mode is entered */
CAN1CTL1 = 0x84; /* enable CAN1, select oscillator as MSCAN clock
source, enable wakeup filter */
CAN1BTR0 = 0x41; /* set SJW to 2, set prescaler to 2 */
CAN1BTR1 = 0x18; /* set phase_seg2 to 2Tq, phase_seg1 to 2Tq,
prop_seg to 7 Tq */
CAN1IDAR0 = 0x56; /* set acceptance identifier "V1" */
CAN1IDAR1 = 0x3C; /* " */
CAN1IDAR2 = 0x40; /* " */
CAN1IDAR3 = 0x00; /* " */
CAN1IDMR0 = 0x00; /* acceptance mask for "V1" */
CAN1IDMR1 = 0x00; /* " */
CAN1IDMR2 = 0x3F; /* " */
CAN1IDMR3 = 0xFF; /* " */
CAN1IDAR4 = 0x00; /* set acceptance identifier NULL */
CAN1IDAR5 = 0x00; /* " */
CAN1IDAR6 = 0x00; /* " */
CAN1IDAR7 = 0x00; /* " */
CAN1IDMR4 = 0x00; /* acceptance mask for NULL */
CAN1IDMR5 = 0x00; /* " */
CAN1IDMR6 = 0x00; /* " */
CAN1IDMR7 = 0x00; /* " */
CAN1IDAC = 0x00; /* select two 32-bit filter mode */
CAN1CTL0 &= ~INITRQ; /* exit initialization mode */
CAN1CTL0 = 0x24; /* stop clock on wait mode, enable wake up */
}
void snd2can1(char *ptr)
{
int tb,i,*pt1,*pt2;
pt1 = (int *)ptr; /* convert to integer pointer */
while(1) {
if(CAN1TFLG & 0x01){
tb = 0;
break;
}
if(CAN1TFLG & 0x02){
tb = 1;
break;
}
if(CAN1TFLG & 0x04){
tb = 2;
break;
}
}
CAN1TBSEL = CAN1TFLG; /* make empty transmit buffer accessible */
pt2 = (int *)&CAN1TIDR0; /* pt2 points to the IDR0 of TXFG */
for (i = 0; i < 7; i++) /* copy the whole transmit buffer */
*pt2++ = *pt1++;
if (tb == 0)
CAN1TFLG = 0x01; /* mark buffer 0 ready for transmission */
else if (tb == 1)
CAN1TFLG = 0x02; /* mark buffer 1 ready for transmission */
else
CAN1TFLG = 0x04; /* mark buffer 2 ready for transmission */
}

You might also like