steering-wheel/lib/due_can/howtouse.txt

196 lines
8.9 KiB
Plaintext
Raw Normal View History

The library has a ton of functions. A lot of them are complicated
and really aren't necessary for normal use. This document
explains how to use the library simply and will suffice for most
applications.
To start with, you'll need to initialize the canbus hardware. There are two
Canbus ports on the Due. There are objects already created
for each port: Can0 and Can1. All functions below are called on one
of those two objects. Note: The library used to use CAN and CAN2 in place
of Can0 and Can1. You can still use those other names as they've been maintained
as aliases. Where functions have been added the old functions have been left behind
so backward compatibility is maintained. Use whichever functions work best for you.
init(baudrate) - Initializes the given canbus port with the given baud
rate. Sets up for interrupt driven canbus with 7 receive mailboxes
and 1 transmit mailbox. You don't need to worry about mailboxes though
if you don't want to. Also sets the default enable pin (62 for Can0, 65 for Can1)
Example: Can0.init(250000);
begin(baudrate) - Exactly like init above.
begin(baudrate, enablepin) - Like above two but with addition of an enable pin. The enable pin
will be raised high when the relevant canbus port is enabled and sunk low when the relevant port
is disabled. If you do not need an enable pin then pass 255.
Example: Can0.begin(250000, 62);
begin() - Initializes with default settings for both baud and enable (250k baud, enable as above)
set_baudrate(baudrate) - Set the baud rate of the canbus. This
can be set to anything you'd like (within reason) but the common
baud rates are 33333, 125000, 250000, 500000, 1000000. Do not
use this unless you are changing the baud rate of an already
initialized canbus port.
Example: Can0.set_baudrate(500000);
enable() - Enable the canbus port. You don't need to call this unless
you've disabled the port at some time in the past.
Example: Can0.enable();
disable() - Disable the canbus port. You will no longer be able to
properly use it.
Example: Can0.disable();
Then, it is on to using the newly set-up canbus port:
This is the structure you will use for both sending and receiving.
typedef struct
{
uint32_t id; // Can0 be either 11 or 29 bit ID
uint32_t fid; // Family ID is a somewhat advanced thing. You Can0 ignore it.
uint8_t rtr; // Remote Transmission Request - Don't use this.
uint8_t priority; // Priority for TX frames. Probably not that useful normally
uint8_t extended;//Set to true for extended frames, false for standard
uint8_t length; // Number of data bytes
BytesUnion data; // Data bytes
} CAN_FRAME;
In turn, BytesUnion is a way to access the 8 data bytes in a variety of ways with a variety of names:
typedef union {
uint64_t value;
struct {
uint32_t low;
uint32_t high;
};
struct {
uint16_t s0;
uint16_t s1;
uint16_t s2;
uint16_t s3;
};
uint8_t bytes[8];
uint8_t byte[8]; //alternate name so you can omit the s if you feel it makes more sense
} BytesUnion;
int setRXFilter(id, mask, extended) - Set up a filter for incoming frames.
This version of the function allows one to forget about mailboxes and just
set a filter. It will handle the details for you and return which mailbox it used
in case you need to change it later. It returns -1 if there was a problem.
Example: Can0.setRXFilter(0x7E0, 0x7E0, false);
int setRXFilter(mailbox,id,mask,extended) - The other version of setting a filter.
It takes the mailbox to change. So long as you pass a valid mailbox number (0-7)
you will get that number back as the return value. It returns -1 on error.
Example: Can0.setRXFilter(0, 0x10000, 0x10000, true);
int watchFor() - An easy way to allow all traffic through. Will automatically add 1 mailbox
for standard frames and 1 for extended frames.
Example: Can0.watchFor();
int watchFor(uint32_t id) - Watch for a specific and single ID. Will automatically determine whether to accept
extended or standard frames.
Example: Can0.watchFor(0x740);
int watchFor(uint32_t id, uint32_t mask) - Watch for a group of IDs based on ID and a mask. Also uses
automatic determination of extended/standard.
Example: Can0.watchFor(0x620, 0x7F0); //Watch for a range of ids from 0x620 to 0x62F
int watchForRange(uint32_t id1, uint32_t id2) - A potentially much easier routine. Pass the lowest and highest
IDs you want to accept and it will automatically determine a suitable ID and mask to use. It might accept
more IDs than what you passed if necessary.
Example: Can0.watchForRange(0x620, 0x64F); //Accept frames with IDs from 0x620 to 0x64F
int findFreeRXMailbox() - Allows your program to get a free mailbox if you're
going to use the above function directly. You shouldn't need to use this very often.
Example: mailbox = Can0.findFreeRXMailbox();
setNumTXBoxes(txboxes) - Above it was mentioned that the default setup is to
have 7 RX mailboxes and 1 TX mailbox. This should work for 95% of programs
because the underlying library code uses interrupts with large buffers. But, if you
will only be sending or only receiving or if you otherwise really need to tweak the
arrangement you Can0 with this function. This function totally reinitializes all
mailboxes so be sure to call this function before you start setting up your filters.
Example: Can0.setNumTXBoxes(2);
There are two ways to receive canbus frames with this library. You Can0 choose from
callback driven reception or buffered frames. Either one is interrupt driven. The
choice really comes down to whether you'd like to process frames at a given point
in your code or whether you'd like to immediately get a call when a frame comes in.
Buffered / Polling version:
bool rx_avail() - The actual frame reception code is interrupt driven so you do not
need to rapidly poll for incoming frames at risk of losing some. However, it is still
handy to know if one or more frames came in. This function returns true if there
are received frames waiting to be processed by your program.
Example: if (Can0.rx_avail()) //do something here.
int available() - Returns the number of waiting frames in the receive buffer. Can be used in place
of rx_avail()
Example: if (Can0.available() > 0) //do something
get_rx_buff(CAN_FRAME &) - Read a waiting frame into the variable passed to the function.
Example:
CAN_FRAME myFrame;
if (Can0.rx_avail()) get_rx_buff(myFrame);
read(CAN_FRAME &) - Exactly like get_rx_buff but with an easier to remember name.
Example: Can0.read(myFrame);
Callback version:
setCallback(mailbox, cb) - Set a callback function for a mailbox (0-7)
Example:
void someFunction(Can0_FRAME *frame)
{
//do something with frame in here
}
setCallback(3, someFunction); //sets callback for third mailbox
setGeneralCallback(cb) - Set a callback that will be used for any mailbox that doesn't have a registered callback
Example: Can0.setGeneralCallback(someFunction);
void attachCANInterrupt(void (*cb)(CAN_FRAME *)) - Merely an alternative name for setGeneralCallback
void attachCANInterrupt(uint8_t mailBox, void (*cb)(CAN_FRAME *)) - An alternative name for setCallback
void detachCANInterrupt(uint8_t mailBox) - Removes the handler from the given mailbox.
Example: Can0.detachCANInterrupt(0);
These calls will not require any polling at all. You will immediately be given any frames that come into the system.
However, care must be taken as your callback function will be in interrupt context. Do not do very much work
in the callback function. Any frame that was returned via callback will not be buffered and thus will not be available
to the buffered system described previously.
Frame sending:
bool sendFrame(Can0_FRAME&) - Send a frame over canbus. It will try to send immediately
but will automatically fall back to buffering the frame and sending via interrupt
when the bus frees up. Returns whether it could send a frame (true/false). Only false if the TX buffer
fills up for some reason. In that cases you'll have to send frames at a slower rate or check to be sure
that the CAN bus is actually operational.
Example:
CAN_FRAME myFrame;
myFrame.id = 45;
myFrame.length = 1
myFrame.data[0] = 128;
Can0.sendFrame(myFrame);
There is an alternative output method now. You can set the ID and then use write to write out frames. This will
send one frame per call but can be used to output the value of variables up to 8 bytes in size:
void setWriteID(uint32_t id) - Set the ID to use for the write function.
Example: Can0.setWriteID(0x620);
void setBigEndian(bool) - Set how to output the bytes sent by the write function. The Due is little endian so
setting True to this function will cause bytes to be output in reverse order (big endian)
Example: Can0.setBigEndian(true);
template <typename t> void write(t inputValue) - Write the given input bytewise into a frame and send it. Uses
the ID from the setWriteID function. Immediately tries to send the frame. This function is probably most useful
for simple tests as it does not support sending multiple values in the same frame.
Example:
int SomeValue = 23423;
Can0.write(SomeValue);