I'm developing a project which will require the modest microcontroller specs of:

  • 8 12-bit, 10kHz ADCs
  • 1kB of RAM
  • 48-QFN or smaller footprint
  • 20kbps daisy-chainable noise-resistant and error-correcting communication protocol

Signal processing requirements are fairly low, and most can be exported to the master processor in the system. The first three specs are easy to meet, and can be done for less than $2 in quantity. However, communication will be happening in a very electrically noisy environment, so noise-vulnerable networks like LIN and I2C are out. An additional argument against LIN is that I'd like to run the whole thing at 5V or 3.3V, and LIN transceivers require 12V, and so would require an extra regulator or wire per sensor board. I initially chose CAN for this task. However, CAN controllers add considerable cost, and I'm curious if this can be done in software.

CAN Physical Layer

The CAN specification defines the Data Link and Physical layers of the OSI network reference model. Many inexpensive 8-pin ICs, such as the NXP TJA1040/50, Maxim MAX3058/59, Microchip MCP2551, and TI SN65HVD1050 exist to implement the physical layer. Implementing the physical layer with D/A converters or op-amps would be difficult, if not impossible, so these ICs are well worth the $1 or so that they cost.

CAN Data Link/Protocol Layer

For the Data Link layer, some microcontrollers add CAN protocol modules onto the basic UART, I2C, and SPI communications layers. However, these are significantly more expensive than the basic chips.

Investigation of cost of CAN protocol modules

To substantiate this claim, here are a few popular micros in CAN and non-CAN versions, from the :

  • ATmega16 - ATMEGA16M1 (with CAN): $3.87, ATMEGA168A (no CAN): $3.23
  • dsPIC - DSPIC33FJ64MC802 (with CAN): $6.14, DSPIC33FJ64GP202 (no CAN): $5.48
  • PIC18 - PIC18F2480 (with CAN): $6.80, PIC18F24J10 (no CAN): $2.10
  • Cortex-M3 - STM32F103C4T6A (with CAN): $6.50, STM32F100C4T6B (no CAN): $2.73

To be fair, I only compared microcontrollers with equivalent memory sizes, however, many of the non-CAN versions are available with smaller memory sizes for less. External CAN controllers, like the Microchip MCP2515, are almost $2, so it's obviously more cost-effective to have the CAN integrated into the microcontroller if you have the option.

Interestingly, the ATmega part is by far the cheapest CAN-equipped part in Digikey's inventory.

Function of CAN protocol layer

The CAN module found in the dsPIC microcontrollers does the following:

The CAN bus module consists of a protocol engine and message buffering/control. The CAN protocol engine handles all functions for receiving and transmitting messages on the CAN bus. Messages are transmitted by first loading the appropriate data registers. Status and errors can be checked by reading the appropriate registers. Any message detected on the CAN bus is checked for errors and then matched against filters to see if it should be received and stored in one of the receive registers.

This seems fairly doable in software.

The Question

Can a software protocol layer be used implement the CAN specification with only an inexpensive UART-equipped microcontroller and a CAN transceiver? If so, do any open-source implementations exist?

Alternatively, can CAN transceivers be used with UARTs to implement a custom protocol? I'm OK with a single-master topology; I understand that arbitration can be hard to get right in a custom protocol.

  • \$\begingroup\$ CAN is 12v too, since it was developed for automotive use. \$\endgroup\$
    – kenny
    Aug 12, 2011 at 17:40
  • \$\begingroup\$ @Kenny - The voltage levels used on the above transceivers is 5V. \$\endgroup\$ Aug 12, 2011 at 17:57
  • \$\begingroup\$ If you're going to consider the STM32F series, may I suggest this NXP part as well? It is a Cortex-M0 core. search.digikey.com/scripts/DkSearch/… \$\endgroup\$
    – Jon L
    Aug 12, 2011 at 18:22
  • \$\begingroup\$ @Jon - Those weren't necessarily under consideration, and an M0 would be ideal for this use case - However, consider parts the Nuvoton M052LAN are also Cortex-M0, and roughly half the price in quantity ($1.21 vs. $2.35), but doesn't have the CAN module. That kind of price difference is my motivation. \$\endgroup\$ Aug 12, 2011 at 18:58
  • \$\begingroup\$ you may want to consider operational rating as well. Most parts with CAN support will be industrial or automotive vs commercial for non CAN variants. \$\endgroup\$
    – Mark
    Aug 13, 2011 at 4:38

4 Answers 4


I think implementing the CAN protocol in firmware only will be difficult and will take a while to get right. It is not a good idea.

However, your prices are high. I just checked, and a dsPIC 33FJ64GP802 in QFN package sells for 3.68 USD on microchipdirect for 1000 pieces. The price will be lower for real production volumes.

The hardware CAN peripheral does some real things for you, and the price increment for it is nowhere near what you are claiming.


Since you seem to be determined to try the firmware route, here are some of the obvious problems that pop to mind. There will most likely be other problems that haven't occured to me yet.

You want to do CAN at 20 kbit/s. That's a very slow rate for CAN, which go up to 1Mbit/s for at least 10s of meters. To give you one datapoint, the NMEA 2000 shipboard signalling standard is layerd on CAN at 200 kbits/s, and that's meant to go from one end of a large ship to the other.

You may think that all you need is one interrupt per bit and you can do everything you need in that interrupt. That won't work because there are several things going on in each CAN bit time. Two things in particular need to be done at the sub-bit level. The first is detecting a collision, and the second is adjusting the bit rate on the fly.

There are two signalling states on a CAN bus, recessive and dominant. Recessive is what happens when nothing is driving the bus. Both lines are pulled together by a total of 60 Ω. A normal CAN bus as implemented by common chips like the MCP2551, should have 120 Ω terminators at both ends, hence a total of 60 Ω pulling the two differential lines together passively. The dominant state is when both lines are actively pulled apart, somewhere around 900mV from the recessive state if I remember right. Basically, this is like a open collector bus, except that it's implemented with a differential pair. The bus is in recessive state if CANH-CANL < 900mV and dominant when CANH-CANL > 900mV. The dominant state signals 0, and the recessive 1.

Whenever a node "writes" a 1 to the bus (lets it go), it checks to see if some other node is writing a 0. When you find the bus in dominant state (0) when you think you're sending and the current bit you're sending is a 1, then that means someone else is sending too. Collisions only matter when the two senders disagree, and the rule is that the one sending the recessive state backs off and aborts its message. The node sending the dominant state doesn't even know this happened. This is how arbitration works on a CAN bus.

The CAN bus arbitration rules mean you have to be watching the bus partway thru every bit you are sending as a 1 to make sure someone else isn't sending a 0. This check is usually done about 2/3 of the way into the bit, and is the fundamental limitation on CAN bus length. The slower the bits rate, the more time there is for the worst case propagation from one end of the bus to the other, and therefore the longer the bus can be. This check must be done every bit where you think you own the bus and are sending a 1 bit.

Another problem is bit rate adjustment. All nodes on a bus must agree on the bit rate, more closely than with RS-232. To prevent small clock differences from accumulating into significant errors, each node must be able to do a bit that is a little longer or shorter than its nominal. In hardware, this is implemented by running a clock somewhere around 9x to 20x faster than the bit rate. The cycles of this fast clock are called time quanta. There are ways to detect that the start of new bits is wandering with respect to where you think they should be. Hardware implementations then add or skip one time quanta in a bit to re-sync. There are other ways you could implement this as long as you can adjust to small diferences in phase between your expected bit times and actual measured bit times.

Either way, these mechanisms require various things be done at various times within a bit. This sort of timing will get very tricky in firmware, or will require the bus to be run very slowly. Let's say you implement a time quanta system in firmware at 20 kbits/s. At the minimum of 9 time quanta per bit, that would require 180 kHz interrupt. That's certainly possible with something like a dsPIC 33F, but will eat up a significant fraction of the processor. At the max instruction rate of 40 MHz, you get 222 instruction cycles per interrupt. It shouldn't take that long to do all the checking, but probably 50-100 cycles, meaning 25-50% of the processor will be used for CAN and that it will need to preempt everything else that is running. That prevents many applications these processors often run, like pulse by pulse control of a switching power supply or motor driver. The 50-100 cycle latency on every other interrupt would be a complete show stopper for many of the things I've done with chips like this.

So you're going to spend the money to do CAN somehow. If not in the dedicated hardware peripheral intended for that purpose, then in getting a larger processor to handle the significant firmware overhead and then deal with the unpredictable and possible large interrupt latency for everything else.

Then there is the up front engineering. The CAN peripheral just works. From your comment, it seems like the incremental cost of this peripheral is $.56. That seems like a bargain to me. Unless you've got a very high volume product, there is no way you're going to get back the considerable time and expense it will take to implement CAN in firmware only. If your volumes are that high, the prices we've been mentioning aren't realistic anyway, and the differential to add the CAN hardware will be lower.

I really don't see this making sense.

  • \$\begingroup\$ I value your opinion, but I'm curious as to why no one has tried to work around the difficulties - Every project will have those problems! I'll let you know how it turns out if I end up attempting it. \$\endgroup\$ Aug 12, 2011 at 18:46
  • \$\begingroup\$ At quantities of 1000, I find a price of $3.12 for the dsPIC33FJ64GP202 from microchipdirect - A total value difference of $560! It's at least worth attempting. I was quoting prices per each simply because it was easier to get numbers for individual pieces without having to worry about reeling, standard package quantity etc. \$\endgroup\$ Aug 12, 2011 at 18:49
  • 2
    \$\begingroup\$ @Kevin, low quantity prices are not always proportional to high quantity prices. I don't know how many of these things you plan to make, but $560 won't begin to pay for the engineering to do CAN in firmware. I will add to may answer explainig some of the difficulties you will encounter. \$\endgroup\$ Aug 12, 2011 at 19:29
  • \$\begingroup\$ I played around with this a bit and found that one dollar sign early in the message messed up the formatting for everything past it. Apparently there is a nasty bug somewhere in the formatting sofware. I replaced the dollar sign with "USD" and now the formatting is as intended. \$\endgroup\$ Aug 12, 2011 at 23:36
  • 1
    \$\begingroup\$ The answer is yes you can but I totally agree with Olin here. I actually work full time in this field. I use the dsPIC33FJ256 chip. The time spent getting things write going the bit-bang approach just out strips the cost advantage of having hardware doing it for you and you reinventing the wheel. Not to mention that whatever else you are doing in hardware would need to be carefully planned out on top of things. Also, I wonder if you are looking at other higher level protocols such as ISO14229 or OSEK/Autosar NetworkManagement needs? \$\endgroup\$
    – Eric M
    Feb 6, 2012 at 4:10

If I'm reading this right, it sounds like you want to bit-bash CAN functionality using only a UART and some clever firmware. Trust me, this will never work - I suggest reading a good text on the intricacies of CAN or CANopen. You will have eradicated any cost savings you are looking for by going down this route.

I would either use a microcontroller with a CAN module and pass the extra $2 on, or have you thought about a different protocol that is compatible with a UART, such as Modbus over RS-485?

  • \$\begingroup\$ You're reading it right. I have thoroughly read the Vector training booklet on CAN. It looks like every message will need some preprocessing for CRC, but the rest of the packet should be the same and I'll just need to keep checking the receive line for a conflict. It really doesn't seem as hard as people make it out to be, but I'll definitely take your advice under consideration. \$\endgroup\$ Aug 13, 2011 at 17:05
  • \$\begingroup\$ I do like the Modbus over RS485 idea, though. It appears that most of those transceivers are also 5V supply; I was under the impression that it required a +/- input voltage like RS232. Will have to look into that. \$\endgroup\$ Aug 13, 2011 at 17:06
  • \$\begingroup\$ bit banging will most certainly work! It's not trivial as Olin, above, mentions but can be done. I've personally pulled it off on both a PIC18F series and a dsPIC33 series micro. I can upload the PIC18F source if you really want to see it. I can't, however, give out the dsPIC source as it's part of a commercial project I work on. In both cases we use MCP2551 and I also have LIN code too. LIN is a bit simpler at the protocol layer but implementing LIN schedules is a bit harder... \$\endgroup\$
    – Eric M
    Feb 6, 2012 at 23:32
  • 1
    \$\begingroup\$ @EricM - What was the bit rate, and were you able to implement the full CAN spec in software? I would love to see the PIC18F code for this. \$\endgroup\$ Apr 24, 2012 at 12:56
  • \$\begingroup\$ Yes, implemented the full CAN spec in so far as to not duplicate the ECAN module on the dsPIC which takes care of many aspects. On the PIC18 implementation I bit-banged the bus to the full spec and later and this code will work on a dsPIC making use of GPIO lines. I'll update in a few days with link to code. \$\endgroup\$
    – Eric M
    Apr 27, 2012 at 0:20

We use the PIC18F25K80. While it doesn't have a DSP, it is ~$2 in quantity. It's almost a direct substitute for the PIC18F2480 you mention. We use the CCS compiler and their software stack for CAN which is probably ported from Microchip. It works well for everything I've needed and tried.

  • \$\begingroup\$ Didn't search for ECAN. Silly Microchip name, but I will have to read more closely next time! Like I said, my signal processing needs are low, so I don't think I need an actual DSP. \$\endgroup\$ Aug 12, 2011 at 17:58

I am also thinking about bit-banging CAN-Protocol on a PIC µC, so please EricM, if you really did that, please reply and tell at least, what bitrate at what core-frequency of PIC18F or DSPic you got. Thx!

In general: RS 485 would be the solution for the primary asked problem, but it also would be possible to use CAN-(or even FlexRay)-Transceivers with non-full-duplex UART communications (point 2 point) as all of that protocols use NRZ-coding.

But in UART/V24/RS232 full duplex is mostly used without thinking about in detail, so maybe you will need to put some brain on the superloop or statemachine of your application...

But back to the CAN-bitbanging: I am workin with CAN for many years and never saw a bitbanging implementation, but as far as i can think, that should work for bit-timings up tp 100kBit with modern µC like DSPic or ARM etc. (having Cores at 80MHz or above...)

At least if only read-back is regarded... Sending would mean some overhead in preparing the bit-structures so that not 100% busload would be reachable, but in CAN more than 65% is rare at all...

  • 2
    \$\begingroup\$ Welcome to the Electrical Engineering StackExchange. The first part of your answer isn't really an answer at all, so you ask a new question if that's what you want. The OP asked specifically about software implementation of the CAN protocol and your answer seems to wander around without addressing that question; please try to stay on the question's topic. \$\endgroup\$
    – Joe Hass
    Nov 30, 2013 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.