G120 CAN BusOff Error

I’m working with a custom board designed to use the G120 module. This board provides access to the CAN1 port on the module (circuit attached). I have two of these boards, running identical code, connected together through CAN. I’m using the baud calculation from the Wiki. So both nodes on the bus have termination resistors in place and are using the same baud calculated value. My initialization code is shown below.

        public void InitializeCAN()
        {
            Debug.Print("->Initializing CAN Bus...");

            //initialize the can port.
            can = new CAN(CAN.Channel.Channel_1, GetBitRateConfig_60MHZ(Bitrate.BITRATE_125k));

            // create a message list of 10 incoming messages
            rxMsgList = new CAN.Message[10];
            for (int i = 0; i < rxMsgList.Length; i++)
                rxMsgList[i] = new CAN.Message();

            // create a message list of 5 outgoing messages
            txMsgList = new CAN.Message[5];
            for (int i = 0; i < txMsgList.Length; i++)
                txMsgList[i] = new CAN.Message();

            canErrors = 0;
            canGoodPackets = 0;

            // subscribe to events
            can.DataReceivedEvent += new CANDataReceivedEventHandler(can_DataReceivedEvent);
            can.ErrorReceivedEvent += new CANErrorReceivedEventHandler(can_ErrorReceivedEvent);

            // Set the system time. CAN messages will have a time stamp
            Utility.SetLocalTime(new DateTime(2011, 2, 14, 0, 0, 0));

            //*********************************************************************
        }

public uint GetBitRateConfig_60MHZ(Bitrate bitrate)
        {
            int t1 = 0;
            int t2 = 0;
            int brp = 0;

            switch (bitrate)
            {
                case Bitrate.BITRATE_125k:
                    brp = 20;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_250k:
                    brp = 10;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_500k:
                    brp = 5;
                    t1 = 16 - 1;
                    t2 = 8;
                    break;

                case Bitrate.BITRATE_1000k:
                    brp = 5;
                    t1 = 8 - 1;
                    t2 = 4;
                    break;
            }

            uint returnValue = (uint)(((t2 - 1) << 20) | ((t1 - 1) << 16) | ((brp - 1) << 0));
            return returnValue;
        }

/// <summary>
        /// CAN error receive event handler.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void can_ErrorReceivedEvent(CAN sender, CANErrorReceivedEventArgs args)
        {
            canErrors++;

            //ledState = true;  //force the led on 

            //Debug.Print(">>> can_ErrorReceivedEvent <<<");

            switch (args.Error)
            {
                case CAN.Error.Overrun:
                    Debug.Print("Overrun error. Message lost");
                    break;

                case CAN.Error.RXOver:
                    Debug.Print("RXOver error. Internal buffer is full. Message lost");
                    break;

                case CAN.Error.BusOff:
                    Debug.Print("BusOff error. Reset CAN controller.");
                    sender.Reset();
                    break;
            }
        }

I have a loop sending out a CAN packet 20 times per sec.

        public void SendCANMessageIO()
        {
            byte inputs_0to7 = 0;
            byte inputs_8to15 = 0;

            txMsgList[0].ArbID = OUTGOINGCANID_CONTROLLER;  //set the packet ID

            //build the IO 0-7 byte
            if (!Input00.Read()) inputs_0to7 |= 0x01;
            if (!Input01.Read()) inputs_0to7 |= 0x02;
            if (!Input02.Read()) inputs_0to7 |= 0x04;
            if (!Input03.Read()) inputs_0to7 |= 0x08;
            if (!Input04.Read()) inputs_0to7 |= 0x010;
            if (!Input05.Read()) inputs_0to7 |= 0x020;
            if (!Input06.Read()) inputs_0to7 |= 0x040;
            if (!Input07.Read()) inputs_0to7 |= 0x080;

            txMsgList[0].Data[0] = inputs_0to7;

            //build the IO 8-15 byte
            if (!Input08.Read()) inputs_8to15 |= 0x01;
            if (!Input09.Read()) inputs_8to15 |= 0x02;
            if (!Input10.Read()) inputs_8to15 |= 0x04;
            if (!Input11.Read()) inputs_8to15 |= 0x08;
            if (!Input12.Read()) inputs_8to15 |= 0x010;
            if (!Input13.Read()) inputs_8to15 |= 0x020;
            if (!Input14.Read()) inputs_8to15 |= 0x040;
            if (!Input15.Read()) inputs_8to15 |= 0x080;

            txMsgList[0].Data[1] = inputs_8to15;

            txMsgList[0].Data[2] = 3;
            txMsgList[0].Data[3] = 4;
            txMsgList[0].Data[4] = 5;
            txMsgList[0].Data[5] = 6;
            txMsgList[0].Data[6] = 7;
            txMsgList[0].Data[7] = 8;

            txMsgList[0].DLC = 8;
            txMsgList[0].IsEID = false;
            txMsgList[0].IsRTR = false;

            int numberOfMessagesPosted = can.PostMessages(txMsgList, 0, 1); //send the message out
        }

My problem is that I’m constantly getting “BusOff” errors. I know my cable is good, as I took it from a working system. Any suggestions on where I could be going wrong? I have validated proper voltage on the MCP2551 chip and all the board traces are going to their intended locations.

The only issue I can see is that you don’t have RS (pin 8 ) connected at all. I can’t find any reference to this being a valid state as all uses of the MCP2551 I have seen (and use myself) have this connected direct to GND or via a resistor to ground to control the slope.

This pin is also used to put the device into sleep mode is this pin is high. Is it possible the pin is floating to the high state and this would explain the bus-off issue?

1 Like

I passed this on to the board designer and he agrees this is the most likely cause. Our original design used a surface mount component that included a pull down for that pin, but the through-hole version apparently does not. We will rework the board and add a jumper for that pin and see if starts working. Thanks for the help!

Looks like that fixed the issue! Thanks again for your help.

1 Like