-
Notifications
You must be signed in to change notification settings - Fork 18
/
howtouse.txt
196 lines (157 loc) · 9.08 KB
/
howtouse.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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.
init(baudrate) - Initializes the canbus port with the given baud
rate. Sets up for interrupt driven canbus with 1 transmit mailbox
and the rest receiving. You don't need to worry about mailboxes though
if you don't want to.
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, 8);
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; // EID if ide set, SID otherwise
uint8_t rtr; // Remote Transmission Request
uint8_t priority; // Priority but only important for TX frames and then only for special uses.
uint8_t extended; // Extended ID flag
uint16_t time; // CAN timer value when mailbox message was received.
uint8_t length; // Number of data bytes
BytesUnion data; // 64 bits - lots of ways to access it.
} CAN_FRAME;
Note that the .time entity is an addition over the current Due library (change request has been submitted). It
is useful to know WHEN a message arrives to do aging, esp in a busy system when the receive queue is active.
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
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();
int setNumTXBoxes(txboxes) - Above it was mentioned that the default setup is to
have 1 TX mailbox and the remaining as RX mailboxes. 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 can 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); setNumTXBoxes() returns the actual number of mailboxes configured
for transmitting, up to and including the entire number of maibboxes on the hardware. As
different hardware can have different number of physical mailboxes, one way to determine this is
to call setNumTXBoxes() with a large number and the actual physical count will be returned.
Example: int numMBx = setNumTXBoxes(99); // How many are there?
setNumTXBoxes(numMBx/2); // Set half of them for TX.
You can then recall setNumTXBoxes with the actual number of boxes you wish to use for Tx.
There are two ways to receive canbus frames with this library. You can 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
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/queue 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 AVR/GCC compiler operates in
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);