Nov 12

As previously already mentioned, I like to go into details to fully understand how things work. Also for working with the CAN protocol, I want to understand how this works and how the AT90CAN CAN controller supports the interface.

On the CD-ROM that comes with the ATDVK90CAN1 there is sample code including a simple CAN driver that allows you to send and receive a frame. Next to the fact the code is very cryptic and it is not interrupt driven I want to write my own low level code so I truly understand the CAN modules and can solve problems later on that are related to the CAN interface.

The first version of my code can be downloaded here, the most important part is the CAN.c unit. This version is purely to provide the basic level of sending and receiving frames and respond to the various interrupt sources of the CAN controller. If you want nothing more than the basics, this is a good start for generating your own code, I think I will add an extra layers so applications can simply read and write “data” to a specific device similar to the CANOpen protocol. I will not use the CANOpen protocol since it only accepts one master on the bus, I want every device to be a master.

The AT90CAN controller handles almost every task needed for sending and receiving frames. It can handle 14 frames in parallel, for this it uses 14 so called Message OBjects. Each object can be setup to receive or transmit a frame. If something goes wrong during transmission an error interrupt is triggered but all error handling is done by the MOB itself. It continues to retry until it is successful or it fails to many times as defined by the CAN protocol. At that moment the bus is automatically disabled for sending and/or receiving depending the error.

So all that is needed for sending a frame is to find the first available MOB that is not busy, fill in the message priority, the maximum of 8 data bytes and set the mode to sending. After this the CAN controller will do the rest as soon as the CAN interface is not used. When finished, it triggers an interrupt and automatically disables the MOB keeping it locked until the application manually frees it.

For reading a frame this works similar with the exception that now the base priority needs to be set in combination with a filter that sets a range around the base priority. When a frame is received, the filter is used to check if it should be passed to the application or not. If a specific bit in the filter is set to 1 that same bit in the received priority has to match the bit of the base priority. In case of a 0 in the filter the matching bit in the received priority is ignored. As examples:

To accept only message priority 0x317:

  • Base priority  = 011 0001 0111 b
  • Filter              = 111 1111 1111 b

To accept priority from 0x310 up to 0x317:

  • Base priority  = 011 0001 0xxx b
  • Filter              = 111 1111 1000 b

To accept all priority from 0x000 up to 0x7FF:

  • Base priority  = xxx  xxxx  xxxx b
  • Filter              = 000 0000 0000 b

Also here, when it receives a frame matching the base priority and filter it triggers an interrupt and automatically disables the MOB and waits for the application to read the message priority and received data. After this, the MOB can be freed or enabled again for reading using the same filter.

In total, very simple. The only complex part is initializing the CAN controller or actually setting up the required baud rate. The whole timing of receiving a single bit of a frame can be defined using three registers. Luck ally the most common settings for these registers in combination with the crystal frequency and the required baud rate are listed in chapter 19.12 of the specification.

The logic of my code is that each MOB can be used for any action (send or receive). When an action is required the first free MOB is found and assigned to this task, any action later on (like reading the data when it finished receiving) uses the assigned MOB. When it is no longer needed, it must be released so it can be used by a new action.

In order to test it, connect the CANUSB to the PC, use the cable to connect the CANUSB device to the ATDVK90CAN1 evaluation board. Start CAN Monitor Lite, click the Open CANUSB device button followed by the monitor button. Execute the code in AVR Studio 4 in combination with an AVR JTAGICE mkII JTAG interface. The LED’s on the evaluation board should all be off.

Fill in the value 0 in the CAN ID field of the message tab in CAN Monitor Lite. Press the send button, a green flash should be visible on the CANUSB device. If a red flash is shown as well (or continuous red) there is a CAN bus error, check the cable and make sure the application in the AT90CAN is running.

The LED’s on the evaluation board should not change to indicate a frame has been received. Reason for this is that both MOB’s (MonitorMOBOne and MonitorMOBTwo) that are reading will see the frame passing by but it does not pass the filter in both MOB’s. When you enter 310 in the CAN ID field and press the send button again a small green flash will be visible on the CANUSB and the LED’s on the evaluation board will display the value 1. In this case MonitorMOBTwo has received the frame and is enabled again after reading the data. A (modified) frame will be send by the AT90CAN as a response and CAN Monitor Lite will show the incomming frame. Sending priority 311 will also result in the same effect since it can pass through the filter of MonitorMOBTwo.

Sending priority 317 will also result in the same effect but now using MonitorMOBOne. After reading the data it is not renewed, so sending again priority 317 will not show an incomming frame.

The filter mechanism is very powerfull in combination with the 14 MOB’s. You can also setup two MOB’s using the same base priority and filter. This reduces the risk of missing the second frame if the first frame is not read yet. This is important to understand since there is no active acknowledgement of data, even the opposite, messages are just being dumped on the bus without caring if somebody does anything with it. This is something that the next layer on top of these basic commands must take care of.

Een reactie

  1. James Says:

    “If a red flash is shown as well (or continuous red) there is a CAN bus error, check the cable and make sure the application in the AT90CAN is running.”
    What are the main causes about this error?

    I try the code in AT90CAN64


Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.