Shown here is the schematic for a simple, inexpensive controller area network (CAN) node (Fig. 1). The PIC12C672 was chosen because of its low pin count (8 pins) and powerful feature set. This set includes an internal oscillator, on-board multichannel 8-bit analog-to-digital converter (ADC), multiple interrupt sources, and a low-power sleep mode.
A full CAN 2.0 implementation with message filtering is supplied by the MCP2510 14-pin standalone CAN controller. Therefore, the host microcontroller is relieved from performing any CAN-bus-related overhead. This is a key feature given the limited available code space of the PIC12C672. The PCA-82C251 transceiver was selected arbitrarily because this article focuses on implementing the CAN protocol, and the physical layer is undefined by CAN.
The PIC12C672 uses all six available I/O pins. It also takes advantage of the internal RC oscillator, which provides a 4-MHz system clock that translates into a 1-µs instruction cycle. Two I/O ports are used for analog input, while four I/Os are used to interface to the MCP2510 (three SPI and one interrupt).
An 8-MHz crystal is used to operate the MCP2510. While the three TXnRTS pins are configured as general-purpose inputs, the RXnBF pins are configured as general-purpose outputs. As a result, all of the pins the MCU lost for the SPI interface are regained. The TXnRTS inputs are connected to switches. These pins have internal pull-up resistors that cause the input to read as a logic "1" when the switch is open. The RXnBF outputs are connected to LEDs.
(To view the firmware, written in assembly, click Download the Code at the top of the page).
Figure 2 shows the top-level flowchart for the overall system operation. After going through self-initialization and initializing the MCP2510, the microcontroller simply goes to sleep and waits for an interrupt to take place (timer 0 or —INT pin).
Communication between the PIC-12C672 and the MCP2510 is accomplished via the MCP2510's built-in SPI interface. Since the PIC12C672 doesn't have a hardware SPI interface, the necessary functions are implemented in firmware. The system achieves a total SPI bus rate of slightly more than 80 kbits/s. Its raw SPI clock rate averages 95 kbits/s. The clock's low time is a fixed 5 µs, while its high time is either 5 µs or 6 µs depending upon whether a "0" or a "1" is being sent/received. These timing values yield a worst case raw clock rate (i.e., sending the value 0xff) of 90.9-kbit/s . The overall effective speed realized includes the additional software overhead of "bit-banging" the SPI protocol.
Note that the SPI rate is slow enough that, in some scenarios, message overruns may result. These are caused by multiple back-to-back messages arriving at the MCP2510 before previous messages can be serviced. As a safeguard to ensure message delivery, each received message is acknowledged with a return message (either with the requested data or with a command-acknowledge-type message). If a predetermined timeout expires without a response from the node, the node requesting the information or change in outputs can assume the message wasn't received.
In this example, the MCP2510 is configured to operate on the CAN bus at 125 kbits/s. This is done by setting the bit time at 8TQ and the baud-rate prescaler equivalent to divide by four.
There are two interrupt sources in the system. One is the PIC12C672's timer0 interrupt. Occurring every 10.16 ms, this interrupt is used as a trigger to transmit the results from analog channel 0. The other interrupt source is the —INT pin of the PIC-12C672, which is connected to the —INT output of the MCP2510. This interrupt happens any time a valid message is received, or if the MCP2510 detects a CAN-bus-related error.
To respond to the four defined re-ceive identifiers, the node uses the MCP2510's multiple filters (see the table). The masks and filters are set to accept messages into receive buffer 1 (RX1) only. Each received message matches only one filter. This simplifies the interrogation required by the MCU as the FILHIT bits in RXB0CTRL are used to determine the message type instead of reading the 11-bit identifier.
Since only receive buffer 1 is used, the masks and filters for receive buffer 0 are set to reject all messages. This is achieved by setting the mask and filters associated with buffer 0 to all ones.
In addition to the four receive messages, there are six transmit message IDs. Four of the transmit messages are in response to the four received messages. The other two transmit messages are for sending the timed AN0 results and for system errors.
All transmitted messages use data byte 1 of the CAN message to hold the data to be sent. Messages intended for the node require a standard identifier that has a value of 0x3f0 to 0x3f3, with each of the four filters configured to accept one of these messages. For the messages transmitted back, the node uses the same identifier as the received message, except the ID3 bit is set to "1." So for instance, when the "read analog channel 1" message is received (ID = 0x3f0), the node transmits the data back using a message ID of 0x3f8 (ID bit three = 1).
As the proliferation of CAN continues, the need for simple, low-cost CAN nodes will increase. The PIC12C672 combined with the MCP2510 CAN controller demonstrates an inexpensive yet versatile CAN node.
To download the listings, click Download the Code.