1 | // coding: utf-8
|
2 | // ----------------------------------------------------------------------------
|
3 | /*
|
4 | * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V.
|
5 | * All rights reserved.
|
6 | *
|
7 | * Redistribution and use in source and binary forms, with or without
|
8 | * modification, are permitted provided that the following conditions
|
9 | * are met:
|
10 | * 1. Redistributions of source code must retain the above copyright
|
11 | * notice, this list of conditions and the following disclaimer.
|
12 | * 2. Redistributions in binary form must reproduce the above copyright
|
13 | * notice, this list of conditions and the following disclaimer in the
|
14 | * documentation and/or other materials provided with the distribution.
|
15 | *
|
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
26 | * SUCH DAMAGE.
|
27 | */
|
28 | // ----------------------------------------------------------------------------
|
29 | /**
|
30 | * \file can.h
|
31 | * \brief Header-Datei für das allgemeine CAN Interface
|
32 | */
|
33 | // ----------------------------------------------------------------------------
|
34 |
|
35 | #ifndef CAN_H
|
36 | #define CAN_H
|
37 |
|
38 | #if defined (__cplusplus)
|
39 | extern "C" {
|
40 | #endif
|
41 |
|
42 | // ----------------------------------------------------------------------------
|
43 | /**
|
44 | * \ingroup communication
|
45 | * \defgroup can_interface Universelles CAN Interface
|
46 | * \brief allgemeines CAN Interface für AT90CAN32/64/128, MCP2515 und SJA1000
|
47 | *
|
48 | * \author Fabian Greif <fabian.greif@rwth-aachen.de>
|
49 | * \author Roboterclub Aachen e.V. (http://www.roboterclub.rwth-aachen.de)
|
50 | *
|
51 | * \version $Id: can.h 6927 2008-12-03 22:42:59Z fabian $
|
52 | */
|
53 | // ----------------------------------------------------------------------------
|
54 |
|
55 | #include <avr/pgmspace.h>
|
56 | #include <stdint.h>
|
57 | #include <stdbool.h>
|
58 |
|
59 | #include "config.h"
|
60 |
|
61 | // ----------------------------------------------------------------------------
|
62 | /** \ingroup can_interface
|
63 | * \name Bitdefinitionen
|
64 | */
|
65 | //@{
|
66 | #define ONLY_NON_RTR 2
|
67 | #define ONLY_RTR 3
|
68 | //@}
|
69 |
|
70 | /** \ingroup can_interface
|
71 | * \brief Bitraten fuer den CAN-Bus
|
72 | */
|
73 | typedef enum {
|
74 | BITRATE_10_KBPS = 0, // ungetestet
|
75 | BITRATE_20_KBPS = 1, // ungetestet
|
76 | BITRATE_50_KBPS = 2, // ungetestet
|
77 | BITRATE_100_KBPS = 3, // ungetestet
|
78 | BITRATE_125_KBPS = 4,
|
79 | BITRATE_250_KBPS = 5, // ungetestet
|
80 | BITRATE_500_KBPS = 6, // ungetestet
|
81 | BITRATE_1_MBPS = 7, // ungetestet
|
82 | } can_bitrate_t;
|
83 |
|
84 | /**
|
85 | * \ingroup can_interface
|
86 | * \brief Symbol um auf alle Filter zuzugreifen
|
87 | */
|
88 | #define CAN_ALL_FILTER 0xff
|
89 |
|
90 | /**
|
91 | * \ingroup can_interface
|
92 | * \brief Unterstuetzung fuer Extended-IDs aktivieren
|
93 | */
|
94 | #ifndef SUPPORT_EXTENDED_CANID
|
95 | #define SUPPORT_EXTENDED_CANID 1
|
96 | #endif
|
97 |
|
98 | /**
|
99 | * \ingroup can_interface
|
100 | * \brief Unterstützung für Zeitstempel aktivieren
|
101 | * \warning Wird nur vom AT90CANxxx unterstützt
|
102 | */
|
103 | #ifndef SUPPORT_TIMESTAMPS
|
104 | #define SUPPORT_TIMESTAMPS 0
|
105 | #endif
|
106 |
|
107 | /**
|
108 | * \ingroup can_interface
|
109 | * \name Bits des Filters fuer den MCP2515 umformatieren
|
110 | *
|
111 | * \code
|
112 | * prog_uint8_t can_filter[] =
|
113 | * {
|
114 | * MCP2515_FILTER_EXTENDED(0), // Filter 0
|
115 | * MCP2515_FILTER_EXTENDED(0), // Filter 1
|
116 | *
|
117 | * MCP2515_FILTER_EXTENDED(0), // Filter 2
|
118 | * MCP2515_FILTER_EXTENDED(0), // Filter 3
|
119 | * MCP2515_FILTER_EXTENDED(0), // Filter 4
|
120 | * MCP2515_FILTER_EXTENDED(0), // Filter 5
|
121 | *
|
122 | * MCP2515_FILTER_EXTENDED(0), // Maske 0
|
123 | * MCP2515_FILTER_EXTENDED(0), // Maske 1
|
124 | * };
|
125 | * \endcode
|
126 | *
|
127 | * \see can_static_filter()
|
128 | *
|
129 | * \~german
|
130 | * \warning Dieses Makro sollte nur Werte verwendet die schon zur
|
131 | * Compile-Zeit bekannt sind. Der Code sollte ansonsten zwar trotzdem
|
132 | * funktionieren, wird danner aber sehr groß.
|
133 | *
|
134 | * \~english
|
135 | * \warning Do not use this Makro for Variables, only for static values
|
136 | * known at compile-time.
|
137 | */
|
138 | //@{
|
139 | #if defined(__DOXYGEN__)
|
140 |
|
141 | #define MCP2515_FILTER_EXTENDED(id)
|
142 | #define MCP2515_FILTER(id)
|
143 |
|
144 | #else
|
145 |
|
146 | #if SUPPORT_EXTENDED_CANID
|
147 | #define MCP2515_FILTER_EXTENDED(id) \
|
148 | (uint8_t) ((uint32_t) (id) >> 21), \
|
149 | (uint8_t)((((uint32_t) (id) >> 13) & 0xe0) | (1<<3) | \
|
150 | (((uint32_t) (id) >> 16) & 0x3)), \
|
151 | (uint8_t) ((uint32_t) (id) >> 8), \
|
152 | (uint8_t) ((uint32_t) (id))
|
153 | #endif
|
154 |
|
155 | #define MCP2515_FILTER(id) \
|
156 | (uint8_t)((uint32_t) id >> 3), \
|
157 | (uint8_t)((uint32_t) id << 5), \
|
158 | 0, \
|
159 | 0
|
160 | #endif
|
161 | //@}
|
162 | // ----------------------------------------------------------------------------
|
163 | /**
|
164 | * \ingroup can_interface
|
165 | * \brief Datenstruktur zum Aufnehmen von CAN Nachrichten
|
166 | */
|
167 | typedef struct
|
168 | {
|
169 | #if SUPPORT_EXTENDED_CANID
|
170 | uint32_t id; //!< ID der Nachricht (11 oder 29 Bit)
|
171 | struct {
|
172 | int rtr : 1; //!< Remote-Transmit-Request-Frame?
|
173 | int extended : 1; //!< extended ID?
|
174 | } flags;
|
175 | #else
|
176 | uint16_t id; //!< ID der Nachricht (11 Bit)
|
177 | struct {
|
178 | int rtr : 1; //!< Remote-Transmit-Request-Frame?
|
179 | } flags;
|
180 | #endif
|
181 |
|
182 | uint8_t length; //!< Anzahl der Datenbytes
|
183 | uint8_t data[8]; //!< Die Daten der CAN Nachricht
|
184 |
|
185 | #if SUPPORT_TIMESTAMPS
|
186 | uint16_t timestamp;
|
187 | #endif
|
188 | } can_t;
|
189 |
|
190 |
|
191 |
|
192 | // ----------------------------------------------------------------------------
|
193 | /**
|
194 | * \ingroup can_interface
|
195 | * \brief Datenstruktur zur Aufnahme von CAN-Filtern
|
196 | *
|
197 | * \code
|
198 | * rtr | Funtion
|
199 | * -----|------
|
200 | * 00 | alle Nachrichten unabhaengig vom RTR-Bit
|
201 | * 01 | ungültig
|
202 | * 10 | empfange nur nicht RTR-Nachrichten
|
203 | * 11 | empfange nur Nachrichten mit gesetzem RTR-Bit
|
204 | * \endcode
|
205 | *
|
206 | * \b ACHTUNG:
|
207 | * Funktioniert nur mit dem AT90CAN, beim MCP2515 wird der Parameter ignoriert.
|
208 | *
|
209 | * \code
|
210 | * ext | Funtion
|
211 | * -----|------
|
212 | * 00 | alle Nachrichten
|
213 | * 01 | ungueltig
|
214 | * 10 | empfange nur Standard-Nachrichten
|
215 | * 11 | empfange nur Extended-Nachrichten
|
216 | * \endcode
|
217 | *
|
218 | * \warning Filter sind beim SJA1000 nur begrenzt nutzbar, man sollte ihn nur
|
219 | * in Systemen mit entweder Standard- oder Extended-Frames einsetzten,
|
220 | * aber nicht beidem zusammen.
|
221 | */
|
222 |
|
223 | typedef struct
|
224 | {
|
225 | #if SUPPORT_EXTENDED_CANID
|
226 | uint32_t id; //!< ID der Nachricht (11 oder 29 Bit)
|
227 | uint32_t mask; //!< Maske
|
228 | struct {
|
229 | uint8_t rtr : 2; //!< Remote Request Frame
|
230 | uint8_t extended : 2; //!< extended ID
|
231 | } flags;
|
232 | #else
|
233 | uint16_t id; //!< ID der Nachricht 11 Bits
|
234 | uint16_t mask; //!< Maske
|
235 | struct {
|
236 | uint8_t rtr : 2; //!< Remote Request Frame
|
237 | } flags;
|
238 | #endif
|
239 | } can_filter_t;
|
240 |
|
241 |
|
242 | // ----------------------------------------------------------------------------
|
243 | /**
|
244 | * \ingroup can_interface
|
245 | * \brief Inhalt der Fehler-Register
|
246 | */
|
247 | typedef struct {
|
248 | uint8_t rx; //!< Empfangs-Register
|
249 | uint8_t tx; //!< Sende-Register
|
250 | } can_error_register_t;
|
251 |
|
252 | // ----------------------------------------------------------------------------
|
253 | /**
|
254 | * \ingroup can_interface
|
255 | * \brief Modus des CAN Interfaces
|
256 | */
|
257 | typedef enum {
|
258 | LISTEN_ONLY_MODE, //!< der CAN Contoller empfängt nur und verhält sich völlig passiv
|
259 | LOOPBACK_MODE, //!< alle Nachrichten direkt auf die Empfangsregister umleiten ohne sie zu senden
|
260 | NORMAL_MODE //!< normaler Modus, CAN Controller ist aktiv
|
261 | } can_mode_t;
|
262 |
|
263 | // ----------------------------------------------------------------------------
|
264 | /**
|
265 | * \ingroup can_interface
|
266 | * \brief Initialisierung des CAN Interfaces
|
267 | *
|
268 | * \param bitrate Gewuenschte Geschwindigkeit des CAN Interfaces
|
269 | *
|
270 | * \return false falls das CAN Interface nicht initialisiert werden konnte,
|
271 | * true ansonsten.
|
272 | */
|
273 | extern bool can_init(can_bitrate_t bitrate);
|
274 |
|
275 | // ----------------------------------------------------------------------------
|
276 | /**
|
277 | * \ingroup can_interface
|
278 | * \brief Setzen eines Filters
|
279 | *
|
280 | * Für einen MCP2515 sollte die Funktion can_static_filter() bevorzugt werden.
|
281 | *
|
282 | * \param number Position des Filters
|
283 | * \param filter zu setzender Filter
|
284 | *
|
285 | * \return false falls ein Fehler auftrat, true ansonsten
|
286 | */
|
287 | extern bool can_set_filter(uint8_t number, const can_filter_t *filter);
|
288 |
|
289 | // ----------------------------------------------------------------------------
|
290 | /**
|
291 | * \ingroup can_interface
|
292 | * \brief Filter deaktivieren
|
293 | *
|
294 | * \param number Nummer des Filters der deaktiviert werden soll,
|
295 | * 0xff deaktiviert alle Filter.
|
296 | * \return false falls ein Fehler auftrat, true ansonsten
|
297 | *
|
298 | * \warning Wird nur vom AT90CAN32/64/128 unterstuetzt.
|
299 | */
|
300 | extern bool can_disable_filter(uint8_t number);
|
301 |
|
302 | // ----------------------------------------------------------------------------
|
303 | /**
|
304 | * \ingroup can_interface
|
305 | * \brief Setzt die Werte für alle Filter
|
306 | *
|
307 | * \code
|
308 | * // Filter und Masken-Tabelle anlegen
|
309 | * prog_char can_filter[] = {
|
310 | * MCP2515_FILTER_EXTENDED(0), // Filter 0
|
311 | * MCP2515_FILTER_EXTENDED(0), // Filter 1
|
312 | *
|
313 | * MCP2515_FILTER_EXTENDED(0), // Filter 2
|
314 | * MCP2515_FILTER_EXTENDED(0), // Filter 3
|
315 | * MCP2515_FILTER_EXTENDED(0), // Filter 4
|
316 | * MCP2515_FILTER_EXTENDED(0), // Filter 5
|
317 | *
|
318 | * MCP2515_FILTER_EXTENDED(0), // Maske 0
|
319 | * MCP2515_FILTER_EXTENDED(0), // Maske 1
|
320 | * };
|
321 | *
|
322 | * ...
|
323 | *
|
324 | * // Filter und Masken-Tabelle laden
|
325 | * can_static_filter(can_filter);
|
326 | * \endcode
|
327 | *
|
328 | * \param *filter_array Array im Flash des AVRs mit den Initialisierungs-
|
329 | * werten für die Filter des MCP2515
|
330 | *
|
331 | * \see MCP2515_FILTER_EXTENDED()
|
332 | * \see MCP2515_FILTER()
|
333 | * \warning Wird nur vom MCP2515 unterstuetzt.
|
334 | */
|
335 | extern void can_static_filter(const prog_uint8_t *filter_array);
|
336 |
|
337 | // ----------------------------------------------------------------------------
|
338 | /**
|
339 | * \ingroup can_interface
|
340 | *
|
341 | * \~german
|
342 | * \brief Filterdaten auslesen
|
343 | *
|
344 | * \param number Nummer des Filters dessen Daten man haben moechte
|
345 | * \param *filter Pointer in den die Filterstruktur geschrieben wird
|
346 | *
|
347 | * \return \b 0 falls ein Fehler auftrat, \
|
348 | * \b 1 falls der Filter korrekt gelesen werden konnte, \
|
349 | * \b 2 falls der Filter im Moment nicht verwendet wird (nur AT90CAN), \
|
350 | * \b 0xff falls gerade keine Aussage moeglich ist (nur AT90CAN).
|
351 | *
|
352 | * \warning Da der SJA1000 nicht feststellen kann ob der ausgelesene Filter
|
353 | * nun zwei 11-Bit Filter oder ein 29-Bit Filter ist werden nicht
|
354 | * die Filter sondern die Registerinhalte direkt zurück gegeben.
|
355 | * Der Programmierer muss dann selbst entscheiden was er mit den
|
356 | * Werten macht.
|
357 | *
|
358 | * \~english
|
359 | * \warning SJA1000 doesn't return the filter and id directly but the content
|
360 | * of the corresponding registers because it is not possible to
|
361 | * check the type of the filter.
|
362 | */
|
363 | extern uint8_t can_get_filter(uint8_t number, can_filter_t *filter);
|
364 |
|
365 | // ----------------------------------------------------------------------------
|
366 | /**
|
367 | * \ingroup can_interface
|
368 | * \brief Ueberpruefen ob neue CAN Nachrichten vorhanden sind
|
369 | *
|
370 | * \return true falls neue Nachrichten verfuegbar sind, false ansonsten.
|
371 | */
|
372 | extern bool can_check_message(void);
|
373 |
|
374 | // ----------------------------------------------------------------------------
|
375 | /**
|
376 | * \ingroup can_interface
|
377 | * \brief Ueberprueft ob ein Puffer zum Versenden einer Nachricht frei ist.
|
378 | *
|
379 | * \return true falls ein Sende-Puffer frei ist, false ansonsten.
|
380 | */
|
381 | extern bool can_check_free_buffer(void);
|
382 |
|
383 | // ----------------------------------------------------------------------------
|
384 | /**
|
385 | * \ingroup can_interface
|
386 | * \brief Verschickt eine Nachricht über den CAN Bus
|
387 | *
|
388 | * \param msg Nachricht die verschickt werden soll
|
389 | * \return FALSE falls die Nachricht nicht verschickt werden konnte, \n
|
390 | * ansonsten der Code des Puffes in den die Nachricht gespeichert wurde
|
391 | */
|
392 | extern uint8_t can_send_message(const can_t *msg);
|
393 |
|
394 | // ----------------------------------------------------------------------------
|
395 | /**
|
396 | * \ingroup can_interface
|
397 | * \brief Liest eine Nachricht aus den Empfangspuffern des CAN Controllers
|
398 | *
|
399 | * \param msg Pointer auf die Nachricht die gelesen werden soll.
|
400 | * \return FALSE falls die Nachricht nicht ausgelesen konnte,
|
401 | * ansonsten Filtercode welcher die Nachricht akzeptiert hat.
|
402 | */
|
403 | extern uint8_t can_get_message(can_t *msg);
|
404 |
|
405 | // ----------------------------------------------------------------------------
|
406 | /**
|
407 | * \ingroup can_interface
|
408 | *
|
409 | * \~german
|
410 | * \brief Liest den Inhalt der Fehler-Register
|
411 | *
|
412 | * \~english
|
413 | * \brief Reads the Contents of the CAN Error Counter
|
414 | */
|
415 | extern can_error_register_t can_read_error_register(void);
|
416 |
|
417 | // ----------------------------------------------------------------------------
|
418 | /**
|
419 | * \ingroup can_interface
|
420 | *
|
421 | * \~german
|
422 | * \brief Überprüft ob der CAN Controller im Bus-Off-Status
|
423 | *
|
424 | * \return true wenn der Bus-Off-Status aktiv ist, false ansonsten
|
425 | *
|
426 | * \warning aktuell nur auf dem SJA1000
|
427 | */
|
428 | extern bool can_check_bus_off(void);
|
429 |
|
430 | // ----------------------------------------------------------------------------
|
431 | /**
|
432 | * \ingroup can_interface
|
433 | *
|
434 | * \~german
|
435 | * \brief Setzt einen Bus-Off Status zurück und schaltet den CAN Controller
|
436 | * wieder aktiv
|
437 | *
|
438 | * \warning aktuell nur auf dem SJA1000
|
439 | */
|
440 | extern void can_reset_bus_off(void);
|
441 |
|
442 | // ----------------------------------------------------------------------------
|
443 | /**
|
444 | * \ingroup can_interface
|
445 | * \brief Setzt den Operations-Modus
|
446 | *
|
447 | * \param mode Gewünschter Modus des CAN Controllers
|
448 | */
|
449 | extern void can_set_mode(can_mode_t mode);
|
450 |
|
451 | #if defined (__cplusplus)
|
452 | }
|
453 | #endif
|
454 |
|
455 | #endif // CAN_H
|