Themen:

AVR, avr-gcc, CAN, CPLD, Elektronik, Mikrocontroller, MSP430, PIC, Roboter, Schaltungen, Sensoren, Software, Testboards

Universelle CAN Bibliothek

Tags: AVR, Software, CAN, avr-gcc
Stand: 16. Juni 2008, 15:57
231 Kommentar(e)

Motivation

Die Bibliothek ist für den Roboterclub Aachen e.V. entstanden. Vor zwei Jahren stand ein Wechsel des internen Bussystems an, die Wahl fiel dabei auf den CAN-Bus, da er eigentlich ideal für diese Anwendung ist.
Es gab nur leider keine Open-Source Bibliotheken für die Ansteuerung der gebräuchlichsten CAN-Controller, so dass selbst schreiben angesagt war.

Die Bibliothek ist jetzt seit einiger Zeit in Gebrauch und wurde dabei vom MCP2515 auf die anderen CAN-Controller erweitert.

Features

Die Bibliothek braucht ca. 1500 Byte Flash mit allen Funktionen. Verwendet man keine dynamischen Filter sind es 370 Byte weniger.

Filter

Für den MCP2515 gibt es zwei Arten die Masken und Filter anzusprechen, zum einen “statisch” mit einer Liste die zur Compile-Zeit angelegt wird oder “dynamisch” während der Laufzeit, dann aber mit größerem Flash Verbrauch.

Die AT90CANxxx kennen nur die dynamischen Filter.

Gleiches gilt für den SJA1000. Dieser bietet zwar theoretisch zwei Filter für Standard-Nachrichten bzw. einen für Extended-Nachrichten, in der Praxis sind diese aber mehr oder weniger unbrauchbar.

Einbinden ins eigene Programm

Zuerst einmal muss die Bibliothek erstellt werden: Dazu ändert man im src/-Ordner die Datei ‘config.h’ für seine Konfiguration ab und stellt im Makefile den verwenden AVR-Typ ein.

Dann kann die Bibliothek gebaut werden:

$ make lib

Wer WinAVR verwendet kann auch einfach im Programmers Notepad eine der Dateien aus dem src/-Ordner öffnen und dann “Tools > [WinAVR] Make All” auswählen.

Jetzt sollte eine Datei ‘libcan.a’ entstanden sein. Zusammen mit ‘can.h’ und ‘config.h’ können diese Dateien jetzt in das eigene Projektverzeichnis kopiert werden.

Um die Funktionen wirklich nutzten zu können muss nur noch den Linker mitgeteilt werden, dass er die Bibliothek einbinden soll. Bei dem Standard-WinAVR-Makefile muss dazu die folgende Zeile hinzugefügt werden (um Zeile 266ff):

...
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)

LDFLAGS += -L. -lcan        # hinzufügen

Der Linker sucht dann automatisch im aktuellen Verzeichnis nach der Datei libcan.a und fügt die benötigten Funktionen (und nur die) in den Quellcode ein.

Testprogram

Ein Programm was einfach eine Nachricht per CAN verschickt könnte folgendermaßen aussehen:

C:
int main(void)
{
    // initialisieren des MCP2515
    can_init(BITRATE_125_KBPS);
   
    // erzeuge eine Testnachricht
    can_t msg;
   
    msg.id = 0x123456;
    msg.flags.rtr = 0;
    msg.flags.extended = 1;
   
    msg.length = 4;
    msg.data[0] = 0xde;
    msg.data[1] = 0xad;
    msg.data[2] = 0xbe;
    msg.data[3] = 0xef;
   
    // Nachricht verschicken
    can_send_message(&msg);
   
    while (1) {
       
    }
}

In der Datei can.zip gibt es außerdem im demo-Ordner ein fertiges Programm für das CAN-Testboard, welches am Anfang eine Nachricht verschickt und danach alle Nachrichten die es empfängt mit einem um Eins vergrößertem Identifier zurückschickt.

Lizenz

Die Bibliothek steht unter der 2-Klausel-BSD-Lizenz und darf damit frei verwendet werden.

Wenn jemand Änderungen vornimmt würde ich bitten mir oder jemand anderem aus dem Roboterclub diese zukommen zu lassen, damit wir sie gegebenenfalls in die Software einbauen können, so dass dann alle etwas davon haben.

Update

2.1.08:

16.6.08:

19.8.08:

23.8.08

2.9.08

6.1.09

19.8.10

17.9.10

Downloads:

can-lib.zip [194.75 kB]

Zum Anfang

Kommentare

# Wolfram meinte am 21. März 2008, 18:26 dazu:

Hallo Fabian, sehr schöne CAN Lib. Funktioniert auf Anhieb mit ATMEGA 644
Grosses LOB !!! !!! !!! BEAR WARE License ist Dir sicher ;-)

# Christoph meinte am 21. März 2008, 20:03 dazu:

Ich bin begeistert!

Da ich in naher Zukunft Prozessstraßen für die Industrie entwickeln (und verkaufen) werde, die als Baukastensysteme über CAN vernetzt sind, wird mir diese Bibliothek viel Arbeit abnehmen. Wenn ich Verbesserungen habe, werde ich mich auf jeden Fall melden.

Und selbstverständlich gibt es bei den ersten verkauften Geräten eine entsprechende Spende an den Roboterclub der RWTH. Wenn ich nicht schon mehr als genug Arbeit hätte - autonome Roboter wären ein tolles Betätigungsfeld.

Nochmal ein herzliches Dankeschön für die Bibliothek und vielen Grüße aus der Eifel,
Christoph

# tuxlein meinte am 7. Juli 2008, 09:22 dazu:

Supper sache, muss man nicht alles ihmmer neu schreiben sondern nur anpassen!

Kleine anmerkung, was ich machen würde: ist die SPI Funcs auslagern.

Nice To have:

  • Unter anderm Tab durch 4 Spaces ersetzen.
  • keine Windows \r

ansonsten alles bestens nur weiter so!

# Simon meinte am 18. August 2008, 21:31 dazu:

Hi Fabian,

ich habe im Grunde den gleichen Aufbau wie beim CAN-Testboard, nur hängt noch ein Display am Controller mit dem ich die Debug-Ausgaben mache.

Sobald ich aber can_init() aufrufe (im Beispielprogramm oben) stürzt der controller ab. Alles was nach can_init() kommt wird nicht ausgeführt.

Fällt dir da auf die schnelle ein möglicher Grund ein der die can_init() evtl. in eine endlosschleife o.ä. laufen lassen könnte??

dank!

# Fabian Greif meinte am 19. August 2008, 08:51 dazu:

Das konnte passieren wenn der MCP2515 nicht ansprechbar ist. Ich habe gerade eine korrigierte Version hochgeladen in der can_init() in so einem Fall false zurückliefern sollte.

# Simon meinte am 19. August 2008, 12:33 dazu:

Danke für die schnelle Antwort! Ich habe gerade die can-lib.zip von oben runtergeladen und neu kompiliert. Am Verhalten hat sich aber nichts geändert: Er bleibt immer noch in der can_init() hängen.

Oder gibts vll. ein svn-rep von dem ich nix weiß?

# Fabian Greif meinte am 19. August 2008, 14:45 dazu:

Oder gibts vll. ein svn-rep von dem ich nix weiß?

Das gibt es zwar, ist allerdings nicht öffentlich. Die can_lib.zip von oben ist schon richtig.

Kannst du mir vielleicht mal per E-Mail deinen Code der das Problem erzeugt schicken, dann würde ich das mal bei mir ausprobieren.

Grüße Fabian

# Otmar Schmid meinte am 23. August 2008, 09:14 dazu:

Hallo Fabian
Zuerst einmal ein grosses Lob und vielen Dank für diese can-lib. Ich will den CAN-Bus als Hausbus einsetzen. Zwei kleine Punkte:
- Der Filenamen at90can_disable_dynamic_filter.c ist zu lang (> 32 Zeichen) und erzeugt bei meinem Makefile einen Fehler.
- Das Label SUPPORT_FOR_MC2515__ in mcp2515_error_register.c in Zeile 33 ist falsch geschrieben.
Nun zu meinem eigentlichen Problem:
Ich habe zwei identische Testboards mit ATmega168 und MCP2515 nachgebaut. Auf beiden läuft bis auf die Identifier das gleiche Programm. Wenn ich die Programme nacheinander starte, funktioniert alles einwandfrei. Nur wenn ich beide geichzeitig starte (simultanes Power on bei beiden), dann zeigt sich der Fehler. Der eine MCP2515 sendet fälschlicherweise Daten die er vorher empfangen hat, oder die zufällig in den Registern stehen. Natürlich wird es auf dem CAN-Bus zu kollisionen kommen. Doch damit sollte der MCP2515 umgehen können. Gibt es eine Erklärung dazu? Das ganze Projekt ist unter (...) zu finden. Ich verwende Debian testing.
Vielen Dank für die Hilfe und schöne Grüsse Otmar

# Fabian Greif meinte am 23. August 2008, 10:22 dazu:

Die Fehler hab sind korrigiert, für den Rest hab ich dir eine E-Mail geschrieben.

# Marcus meinte am 20. Oktober 2008, 18:00 dazu:

Hallo,

mir ist aufgefallen, dass wenn ich den mcp2515 mit BITRATE_250_KBPS initialisiere, dann kann ich Daten mit meinem USB PEAK Adapter nur mit einer Baudrate von 125kBit/s empfangen oder senden. Stelle ich BITRATE_500_KBPS ein, dann kann ich mit dem PEAK Adapter die Daten mit 250kBit/s empfangen oder senden. usw?
Ich habe mir natürlich die can.h entsprechend angepasst.

Aber mich würde generell interessieren warum das so ist. Der Peak Adapter ist in Ordnung und funktioniert in anderen Anwendungen ohne Probleme?

# Frank meinte am 18. November 2008, 18:59 dazu:

Hallo!
Habe kürzlich gute Erfahrungen gemacht. Kompiliert und lief. Sehr schönes Stück Software. :-) Unter Welcher BSD-Lizenz steht sie eigentlich genau. Das ist ein wenig schwammig formuliert?

# Fabian Greif meinte am 20. November 2008, 11:17 dazu:

Ganz genau steht sie unter der “2-Klausel-BSD” oder auch FreeBSD-Lizenz.

Der genaue Text steht aber auch in Quelltext.

# Adrian meinte am 15. Dezember 2008, 10:53 dazu:

Hallo Fabian,

ich habe gelesen, dass Simon am 18.und 19. August den selben Fehler mit der Libary hatte, wie ich ihn jetzt habe. Auch bei mir bleibt das Programm bei can_init in einer Endlosschleife hängen. Wäre super, wenn Du mir da auch ggf helfen könntest.

Gruß Adrian

# Alex meinte am 16. Dezember 2008, 09:59 dazu:

Hallo,

ich hab eine kleine Frage zu deiner Lib. Ich bin dabei mit 2 AT90CAN128 CAN Nachrichten zu versenden. Der eine sendet, wie im Beispiel beschrieben. Allerdings nur 15 mal. Ich nehme an dass dann der Buffer voll ist. Der zweite CAN Knoten sollte eigentlich empfangen tut er aber nicht. Ich hab hier mal mein Codeausschnitt:

if (can_check_message())
{		
can_t msg;
// Try to read the message

  if (can_get_message(&msg))
  {
				   
    uart_putc(msg.data[0]);
  }
}

Vielleicht hast du ja ein Beispiel dass Senden und Empfangen zeit.

Gruß Alex

# Fabian Greif meinte am 16. Dezember 2008, 11:39 dazu:

@Adrian
In der aktuellen Version des Code sollte das eigentlich nicht mehr vorkommen. Kannst du mir mal deinen Code zur Initialisierung des MCP2515 per E-Mail schicken? Dann würde ich mir das mal anschauen.

@Alex
Dein Code zum Empfangen ist schon vollkommen richtig. Hast du denn beim Initialisieren einen Filter gesetzt?

Zum Beispiel folgendermaßen um alle Nachrichten zu empfangen:

// Initialize AT90CAN
can_init(BITRATE_125_KBPS);

// create a new filter for receiving all messages
can_filter_t filter = {
    .id = 0,
    .mask = 0,
    .flags = {
        .rtr = 0,
        .extended = 0
    }
};

can_set_filter(0, &filter);

// enable interrupts
sei();

Ansonsten könnte das voll-laufen des Sendepuffers des AT90CAN eigentlich nur an einer fehlenden Verbindung zwischen den beiden liegen.

Grüße
Fabian

# Alex meinte am 16. Dezember 2008, 20:58 dazu:

Nein hab leider kein Filter gesetzt gehabt. Werds aber mal austesten.

# Kristof Koch meinte am 10. Februar 2009, 11:58 dazu:

Ich habe ein ähnliches Problem wie Alex. Ich kann mit meinem AT90CAN128 nur 15 Nachrichten verschicken. Diese kommen auch an. Getestet mit USB-CAN-Adapter von Peak. Er ist in Ordnung. Eine andere Platine mit ATmega8 und MCP2515 läuft fehlerfrei.

Wenn ich den AT90CAN128 ab und zu mit can_init(BITRATE_125_KBPS); neu initialisiere ? schickt der Controller auch mehr Nachrichten ? Also Hardware sollte in Ordnung sein. Habt ihr eine Idee?

grüße Kristof

# Fabian Greif meinte am 11. Februar 2009, 00:28 dazu:

Es hört sich an als würde der AT90CAN128 nicht das Acknowledge vom Bus empfangen. Überprüfe doch mal mal die RX-Leitung vom CAN Transceiver zum AT90CAN.

Grüße
Fabian

# Kristof Koch meinte am 11. Februar 2009, 10:27 dazu:

Vom RXD des Transceivers zum RXCAN pin des AT90CAN 0 Ohm

Ich könnte aber mal ausprobieren. Ob der Controller Nachrichten empfangen kann …

# Frédéric meinte am 11. Februar 2009, 19:53 dazu:

Thanks you Fabien for your library, it’s the best thing since sliced bread :)

With the library (and an ATMEGA168 and a small LCD) I made an onboard gauge for CAN enabled cars that display fuel consumption, trip data, engine info, etc.

# Bernhard Ibertsberger meinte am 24. Februar 2009, 18:07 dazu:

Hallo,

erstmal gratuliere zu deiner offenbar tollen Arbeit! Ich habe eine Frage zum AT90128:

—-snip—-

$ make lib

[..]

-DF_CPU=1500000UL

[..]

at90can_private.h:54:3: error: #error only 16MHz supported!

—-snap—-

Mein Quarz hat 12Mhz. Habe ich jetzt ein Problem, oder kann ich im File at90can.c auf Zeile 171 einfach den Teiler (jetzt 199) ändern?

Grüße

Bernhard

# Fabian Greif meinte am 24. Februar 2009, 18:51 dazu:

Mein Quarz hat 12Mhz. Habe ich jetzt ein Problem,

Problem hast du keines, außer das du die Werte selbst anpassen musst.

oder kann ich im File at90can.c auf Zeile 171 einfach den Teiler (jetzt 199) ändern?

Das wäre das Eine. Viel wichtiger sind aber die Werte ab Zeile 39 in der ‘at90can.c’. Die Werte werden in die Register CNF1..3 geschrieben und bestimmten die Bitrate für den CAN Bus.

Grüße Fabian

# Bernhard Ibertsberger meinte am 25. Februar 2009, 15:58 dazu:

Das wäre das Eine. Viel wichtiger sind aber die Werte ab Zeile 39 in der ?at90can.c?.
Die Werte werden in die Register CNF1..3 geschrieben und bestimmten die Bitrate für den CAN Bus.

Aha, ich sehe?

Was mir dabei auffällt:

  • Register CNF finde ich in der Spec nicht. Wahrscheinlich verwechselt mit CANBTx.
  • Bei dem Timing für 1Mbps sind die Werte im Code {0x00, 0x0C, 0x37}. Laut meiner Spec sollte (bei 16MHz) sein: {0x00, 0x0c, 0x36}.

Im Datenblatt steht dazu:

'SMP=1' is not compatible with BRP=0...

Das heißt wenn der erste der drei Werte (CANBT1 = SMP) gleich Null, dann darf Bit 0 von CANBT3 ( = Sample Points) nicht gesetzt sein.

Übersehe ich das was, oder sollte man das in der Library reparieren?

Grüße

Bernhard

# Bernhard Ibertsberger meinte am 26. März 2009, 17:42 dazu:

Hallo Fabian,
die CANlib verrichtet ganz wunderbar ihren Dienst. Jetzt habe ich aber das Problem eine CAN verbindung mit einem Programm in der bootloader section aufzubauen. µC ist at90can128

Ein kleines Demo (verschickt jede Sekunde ein CAN message und toggled eine LED) funktioniert in der application section.
Wenn ich aber das Programm in die bootloader section verschiebe blinkt nur mehr die LED, es kommen aber keine CAN Telegramme an.
can_send_message liefert keinen Error.

Hast du eine Idee woran das liegen könnte? Ich bin schon ein wenig Ratlos.

lg Bernhard

# Manfred meinte am 10. Mai 2009, 00:28 dazu:

Hallo
Ich habe ein seltsames Problem. Solange der Programmer (von MyAVR) am Mega angeschlossen ist funktionirt deine CAN.lib wunderbar. wenn ich den Programmer abschliese geht nichts mer.
Kannst Du mir sagen woran das liegen kann ??
Prozessor AtMega16 mit interner Frequent 8Mhz

Danke Manfred

# Uwe Dierolf meinte am 22. Mai 2009, 12:36 dazu:

Hallo Florian, ich versuche gerade dein Testpogramm, das beim “CAN-Lib” download dabei war zu compailieren. Die “libcan.a” hab ich mit WIN-AVR erstellt und wie im Tutorium beschrieben in den Projektordner eingefügt. Jetzt versuch ich, da ich eigentlich nicht mit WIN-AVR Arbeite, mit AVR-Studio das Testprogramm zu compeilieren.

Er erkennt die Lib, da er wenn ich sie rausnehme meldet dass er die Funktionen nicht finden. aber wenn ich sie drin hab bekomme ich folgene Fehlermeldung. ” avr-gcc -mmcu=atmega32 -Wl,-Map=CAN_DEMO2.map CAN_DEMO2.o -lcan -o CAN_DEMO2.elf c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: cannot find -lcan make: *** [CAN_DEMO2.elf] Error 1 Build failed with 1 errors and 0 warnings… ” Leider weiss ich nicht was er mit “cannot find -lcan”
meint, da ich mit, aus mehreren Files zusammengestellten libs keine Erfahrungen hab.

Vielen Dank schon mal im Voraus MFG Uwe

# Fabian Greif meinte am 27. Mai 2009, 18:54 dazu:

cannot find -lcan

das bedeutet das der Linker die Datei libcan.a nicht finden kann. Liegt sie den in dem Verzeichnis des Makefiles?

# Uwe meinte am 28. Mai 2009, 21:51 dazu:

Hallo,
ja sie ist im selben wie im Makefile. Ich hab jetzt meine "main" in main umbenannt, was in AVR-Studio ja nicht von Haus aus so ist. Er bringt aber immer noch einen Fehler beim erstellen der Debugg-Datei was glaube ich mit "CAN_DEBUG_LEVEL" in can_private.h zusammenhängt. Code läuft jetzt, SPI und LCD, nur CAN, kann noch nicht so ;-)
Ich hab jetzt mal Alles gedruckt und kau es übers Wochenende durch, dann sehe ich villeicht klarer.

MFG
Uwe

# Fabian Greif meinte am 29. Mai 2009, 01:16 dazu:

Er bringt aber immer noch einen Fehler beim erstellen der Debugg-Datei

Was gibt es den genau für eine Fehlermeldung?

# Uwe meinte am 30. Mai 2009, 16:09 dazu:

Jetzt hab ich meine Startprobleme überwunden, und wie immer ist es nichts Weltbewegendes,sonder was das man mit etwas ruhigem Nachdenken lösen kann. Wenn ich nur immer ruhig bleiben könnte :-(

  1. Er hat die Lib. nicht gefunden, da ich im "library Search Path" nichts eingegeben hab, es muss aber immer was drin stehen, wenn auch nur ein "./"

  2. Das mit der Debugg Datei war ein Namensfehler, da ich Deine Datei in Meinem anders benannten Projekt hatte.

Ich hätte AVR-Sudio villeicht erst updaten sollen, wenn die Lib. gelaufen wär. Zuviel Neues auf einmal geht meistens einfach schief.

Besten Dank noch mal für Alles.

jetzt mach ich mich an die Lösung des Eigentlichen Problems. MFG Uwe

# Simon meinte am 21. Juni 2009, 12:21 dazu:

Hi Fabian,

im Beispiel oben ist ein Fehler drin.

Wahrscheinlich hast du irgendwann tCAN in can_t umbenannt und oben nicht nachgezogen.

Da heißt es noch "tCAN msg;" müsste aber wohl "can_t msg;" sein.

Grüße Simon

# Fabian Greif meinte am 21. Juni 2009, 12:57 dazu:

Stimmt, das hatte ich mal geändert. Vielen Dank für den Hinweis, ist korrigiert.

Grüße Fabian

# Simon meinte am 21. Juni 2009, 21:58 dazu:

Sooo. Ich habe (mal wieder) das Problem dass er bei can_init() hängen bleibt^^

Habe mich jetzt mal dran gemacht die genaue Stelle herauszufinden (per LED mangels ICD für Atmels). Hier das Ergebnis: Er schmiert in der Funktion uint8_t spi_putc(uint8_t data) in spi.c ab bzw. bleibt in der folgenden schleife hängen:

while( !( SPSR & (1rrSPIF) ) )
         ;

(bei rr links shift denken - sonst beendet er der die ganze nachricht)

Allerdings nicht beim ersten aufruf von putc sondern wenn es in bool mcp2515_init(uint8_t bitrate) bei

RESET(MCP2515_CS);
spi_putc(SPI_WRITE);

aufgerufen wird. Also nach dem reset des MCP2515.

Irgendeine Idee warum das genau in der Schleife passiert? Die Beschaltung habe ich schon hundertmal überprüft.

Achja controller ist ein Atmega88 mit 8Mhz (interner Quarz).

# Fabian Greif meinte am 22. Juni 2009, 18:18 dazu:

Irgendeine Idee warum das genau in der Schleife passiert? Die Beschaltung habe ich schon hundertmal überprüft.

Nein, so spontan nicht. Es scheint so als würde die SPI Übertragung nicht richtig gestartet.

Kannst du mal versuchen ohne die canlib Daten per SPI zu übertragen und schauen ob er da auch beim zweiten Aufruf hängen bleibt?

Grüße Fabian

# Thomas R. meinte am 23. Juni 2009, 08:21 dazu:

Hallo,

die Jungs in diesem Thread haben schwierigkeiten mit der lib: http://www.mikrocontroller.net/topic/141667#1308894

Vielleicht könntest Du ihen weiterhelfen.

Grüße Thomas

# Fabian Greif meinte am 28. Juni 2009, 09:47 dazu:

Sooo. Ich habe (mal wieder) das Problem dass er bei can_init() hängen bleibt^^

Ich habe mir das nochmal genauer angeschaut, das Problem tritt eigentlich nur auf wenn man die Bibliothek für einen AVR kompiliert und dann einen anderen verwendet. Zwischen den verschieden AVRs verschieben sich nämlich auch die Registeradressen, dann wird dann darauf gewartet das sich ein Bit in einem vollkommen falschen Register setzt.

Schau mal nach nach ob die Einstellungen für dein Projekt und die für das Erzeugen der Bibliothek übereinstimmen.

Grüße Fabian

# Simon meinte am 30. Juni 2009, 13:59 dazu:

damisch natürlich - genau das Problem das ich damals auch hatte (wie mir natürlich erst jetzt wieder einfällt). Vielen dank Fabian dass du dich da nochmal drum gekümmert hast - ich bin jetzt seit Tagen dabei SPI Kommunikation zu sniffen und mit timings rumzuspielen.

Natürlich isses immer die einfachste Lösung, ich habe im makefile der library einfach den controllertyp nicht eingstellt.

Dass das anderen nicht auch passiert wäre es evtl. nicht schlecht das in der nächsten Version ins Readme aufzunehmen.

# CTruller meinte am 11. Juli 2009, 14:16 dazu:

Hallo Fabian,

ich möchte mich Deinen ersten Schreiber anschliessen und ein großes Lob aussprechen, einfach tolles Lib. Ich setze sie schon mehrfach mit großen Erfolg auf dem AT90CAN128 ein. Meine selbst kreierte Routine zum CAN-Bus hatte Macken, desshalb bin ich froh ein so gut funktionierende Lib gefunden zu haben.

Leider kommt jetzt doch ein ABER, ich wollte die Libcan.a auch im Bootloader einsetzen, weil meine Routine eben Macken hat, das ging solange gut wie mein Bootloader nicht im Flashspeicher ab 0x1E000 (bzw. im AVR-Studio 0xF000) laufen sollte, der Fehler ist reproduzierbar. Es kommen nur Fehlerdatentelegramme raus, beim Flashspeicher ab 0x0000 läuft das Programm wunderbar, richtige Datentelegramme. Ich habe schon gedebuggt, aber nichts aufälliges gefunden die Register vom CAN-Kontroller sind (so weit der Debugger (mit Eclipse) nicht lügt und ich das Richtige sehe) mit gleichen Daten gefüllt und ich habe alle Register mir direkt anzeigen lassen. Ich mach jetzt schon 3 Tage damit rum.

Es währe wirklich Super wenn Du einen Tip geben könntest.

Gruß CTruller

# CTruller meinte am 13. Juli 2009, 14:56 dazu:

Hallo Fabian,

nun ich hab, da die Zeit drängt, ein bisschen weiter gesucht und konnte feststellen das dieser Fehler (oben beschrieben am 11.Juli 2009) aus der Ecke der CAN-Baudrate kam, spricht die CANBT1-3 Register wurden mit 0xFF beschrieben obwohl das Array at90can_cnf eigendlich richtig vorhanden war und wie schon erwähnt das ganze wunderbar im Flash-bereich ab 0x0000 funktionierte. Nun nach einigen Googeln kam ich drauf. In Deiner Datei at90can.c holst Du mit dem Befehl pgm_read_byte() die Daten aus dem Flashspeicher, dieser Befehl arbeitet aber nur mit einem 16Bit Zeiger, sprich nur bis 0xFFFF. Wird aber Deine Libcan.a für einen Bootloader und das gilt nur für den at90can128 nicht für die at90can32 + can64, verwendet landet Dein Array at90can_cnf auf einer Adresse von ca. 0x1E094. Diese kann aber die Routine ?pgm_read_byte()? nicht erreichen da sie nur im 64K-Bereich arbeitet. Lösung für den at90can128: -> verwenden statt der Routine pgm_read_byte() die Routine pgm_read_byte_far() die auch 32Bit Adressen verarbeitet. Aber das ist noch nicht alles.

Erst mal eine 32Bit Adresse habe, denn der Aufruf ?&(var)? liefert maximal eine Adresse bis 0xFFFF (64K) zurück, da der AVR nur ein 16Bit Register für den Adresspointer hat, sprich im oben genannten Fall kommt bestenfalls 0xE094 zurück. Momentan habe ich mich mit einen define NO_BOOTBEREICH beholfen und für den Aufruf der pgm_read_byte_far(Adr) Funktion im Bereich ab 0x1E000 zum zurückgegebenen Wert die 0x10000UL dazu addiert und sonst eben nicht. Das funktioniert, ist nicht schön aber vielleicht hast Du noch einen besseren Vorschlag.

Gruß CTruller

# Fabian Greif meinte am 20. Juli 2009, 18:46 dazu:

Das funktioniert, ist nicht schön aber vielleicht hast Du noch einen besseren Vorschlag.

Nicht so wirklich. Die einzige andere Möglichkeit die mir noch einfällt wäre die Tabelle zu deaktivieren und die Registerwerte direkt zu setzen. Wenn ich wieder Zeit habe werde ich das mal einbauen.

Grüße Fabian

# Artur meinte am 23. Juli 2009, 15:50 dazu:

Hallo Fabian, ich mache zur Zeit eine projektarbeit und wollte dort Deine Lib einsetzen. Ich habe mein Programm so weit geschrieben doch leider bekomme ich keine Nachrichten auf den Bus… Ich verwende eine AT90can128 Controller.

can_t geschwindigkeit, licht;

can_init(BITRATE_500_KBPS);

geschwindigkeit.id = 0xcfe6cee;
geschwindigkeit.flags.rtr = 0;
geschwindigkeit.flags.extended = 1;
geschwindigkeit.length = 8;
geschwindigkeit.data[0] = 0;
geschwindigkeit.data[1] = 0;
geschwindigkeit.data[2] = 0;
geschwindigkeit.data[3] = 0xC0;
geschwindigkeit.data[4] = 0;
geschwindigkeit.data[5] = 0;
geschwindigkeit.data[6] = 0;
geschwindigkeit.data[7] = 60;

licht.id = 0x14b;
licht.flags.rtr = 0;
licht.flags.extended = 0;
licht.length = 1;
licht.data[0] = 2;


blinkLED();
_delay_ms(5000);

while(1)
{
    can_send_message(&licht);

    can_send_message(&geschwindigkeit);

    blinkLED();
    _delay_ms(zeitverzoegerung);
}

Hab ich da etwas übersehen in meinem Programm???

Vielen Dank für die Hilfe im Vorraus

Gruß

Artur

# Fabian Greif meinte am 27. Juli 2009, 16:44 dazu:

Hast du die Interrupts aktiviert?

Setzt mal ein sei() nach die Initialisierung des CAN Controllers.

Grüße Fabian

# Jens meinte am 2. August 2009, 17:38 dazu:

Hallo!
Schon mal vielen Dank für die hilfreichen Ausführungen. Wie sollte es aber auch anders sein: auch ich habe ein kleines Problem.
Ich arbeite mit avr-gcc (GCC) 3.4.6
Zum einen Versuche ich das ganze auf einem ATmega644 laufen zu lassen. Nachdem ich alle SPI-Register um eine ?0? ergänzt habe, klappt schon mal das compilieren, auch wenn ich alle Naselang ein warning ausgespuckt bekomme:
spi.h:74: warning: 'gnu_inline' attribute directive ignored
usw.

Im eigenen Code klappt wohl auch das Senden, aber nicht das empfangen. Ich bekomme auch dieses warning:
can.h:229: warning: type of bit-fieldrtr? is a GCC extension
can.h:230: warning: type of bit-field extended' is a GCC extension

Die dortige Syntax ist mir leider auch völlig unbekannt. Was bedeutet
uint8_t rtr : 2;

Kann es sein, daß ich deswegen nichts empfange? Danke!

# Fabian Greif meinte am 4. August 2009, 10:17 dazu:

spi.h:74: warning: ‘gnu_inline’ attribute directive ignored

Scheinbar kennt diese Version des GCCs __attribute__((gnu_inline)) noch nicht. Du solltest es durch static inline ersetzen können.

Die dortige Syntax ist mir leider auch völlig unbekannt. Was bedeutet uint8_t rtr : 2;

Das legt ein Bitfeld an, wobei rtr zwei Bit groß ist. Versuch mal das uint8_t durch int zu ersetzen.

Sag Bescheid ob es damit klappt.

Grüße Fabian

# Alex meinte am 4. August 2009, 10:20 dazu:

Hallo,

ich möchte gern ein Filter zum empfangen von nur einer bestimmten Botschaft definieren. Bin aber aus der Doku micht schlau geworden. Ich benutze den AT90CAN.

// create a new filter for receiving all messages

can_filter_t filter = {
    .id = 0x100,
    .mask = 0,
    .flags = {
        .rtr = 0,
        .extended = 0
    }
};

can_set_filter(0, &filter);

Was bedeutet hier mask?

Viele Grüße

# Fabian Greif meinte am 4. August 2009, 10:35 dazu:

Was bedeutet hier mask?

mask gibt an welche Bits von id zur Filterung der Nachricht herangezogen werden.

Mit mask = 0 werden alle Nachrichten empfangen, unabhängig von id. Mit mask = 1 werden alle Nachrichten empfangen bei denen das niederwertigste Bit mit dem Bit aus id übereinstimmt. Mit mask = 0x7ff werden bei Standard-Frames alle Bits von id überprüft usw.

Siehe auch Filter bei MCP2515.

# Jens meinte am 4. August 2009, 14:13 dazu:

Danke, das half alles schon mal, um fehlerfrei zu compilieren. Es ist zwar noch
static inline void spi_start(uint8_t data)
static inline uint8_t spi_wait(void)

doppelt drin gewesen, aber das habe ich einfach einmal auskommentiert. Senden klappt weiterhin, nur empfange ich immer noch nichts. Muss also irgendwo an mir liegen. Werde weiter suchen. Ich tippe ja irgendwie auf die Masken…

# maxf meinte am 17. August 2009, 17:44 dazu:

Hallo Fabian,

ich habe ein kleines Problem mit der Library. Ich benutze den MCP2515 an einem ATMega8. Aus irgendeinem Grund kann ich im normalen Modus (mit oder ohne Busteilnehmer) nur genau 3 Nachrichten verschicken. Im Loopback-Modus tritt dieses Problem nicht auf. Hast du eine Idee, wie das kommt? Wenn das Senden fehlschlägt, gibt die Methode can_send_message () 0 zurück, und auch die CAN_INDICATE_TX_TRAFFIC_FUNCTION wird nicht mehr ausgeführt…

# Fabian Greif meinte am 18. August 2009, 15:29 dazu:

Hallo maxf,

dein MCP2515 bekommt von den anderen Busteilnehmern kein ACK zurück, somit kann er die Nachrichten nicht verschicken und die Puffer bleiben belegt. Da er genau drei Puffer hat kannst du auch so viele Nachrichten “verschicken” bis das auffällt. Wenn du dir die Fehlerregister anschaust sollte der TX-Fehlerzähler auf 255 stehen und der MCP2515 im Bus-Off-Modus sein.

Überprüfe mal ob die Anbindung an den Bus korrekt ist und du die richtige Bitrate eingestellt hast.

Grüße Fabian

# Nik meinte am 20. August 2009, 10:40 dazu:

Ich verwende den AT90CAN128, das Demo-Programm sendet, aber scheint nichts zu empfangen, zu mindest anwortet es nicht durch zurücksenden der Message mit anderer ID. WOran kann das liegen ?

# maxf meinte am 20. August 2009, 15:03 dazu:

Stimmt, wenn ich einen zweiten mega8 mit mcp2515 und deinem Bootlader dranhänge, kann ich über meinen einfachen Adapter (der war das Problemkind) von der Linux-Kiste aus via Socketcan senden. Jetzt muss ich nur noch herausfinden, warum der Mega8 schon nach einem Datenblock direkt einen Fehler sendet… ;)

# CTruller meinte am 24. September 2009, 11:47 dazu:

Hallo Fabian,

sorry, das ich die Frage über den RCA direkt an Dich schon mal gemailt habe. Wie schon am 11. und 13. Juli 2009 geschrieben setzen wir Deine Lib erfolgreich ein. Ich vermute mal das die nachfolgende Anfrage kein Fehler der Lib ist aber vielleicht hast Du oder jemand anderes einen Tip wie man ihn beheben kann. Beim verwenden der Funktion can_set_filter und can_disable_filter kommt es zu Errorframes auf dem CAN-Bus (Baudrate 250), wenn der CAN-Kontroller bereits gearbeitet hat, also anders gesagt, es kommt nicht dazu wenn can_set_filter gleich nach can_init aufgerufen wird. Auslöse Zeile ist in der Datei at90can_private.h in der Funktion _enter_standby_mode die Zeile 113 ?CANGCON=(1 kleinerals kleinerals ABRQ)?. Ab dieser Zeile kommtes bis zur Zeile in gleicher Datei bei der Funktion _leave_standby_mode Zeile 147 ?CANGCON=(1 kleinerals kleinerals ENASTB);? entsprechend der Durchlaufzeit von einem bis im Debughalt zu was weiß ich wie viele. Ich tippe mal auf ein Hardwareproblem, den wieso sendet der CAN-Kontroller weiter im Debughalt (ermittelt mit dem Canalyzer von Vector). Ich währe für jeden Tip dankbar, denn momentan kann ich die Funktion can_disable_filter nicht verwenden.

Danke schon mal im Voraus CTruller

# Marcel meinte am 3. Oktober 2009, 13:35 dazu:

Hallo Fabian,

ich benutze AVRStudio und bekomme ständig diesen Fehler:

c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: cannot find -l2srclibcan

Ich habe bei ?Configuration Options? im AVRstudio genau angegebnen, wo die lib ist, trotzdem funktioniert es nicht. Woran kanns liegen?

VG, Marcel

# Fabian Greif meinte am 7. Oktober 2009, 15:35 dazu:

Hallo Marcel,

Es muss -lcan heißen, unabhängig davon wo die Bibliothek liegt. Das gibt man über die Option -Lpfad/zur/bibliothek/ an. Wie man das genau im AVR Studio einstellen muss kann ich dir leider nicht sagen, da ich es selbst nicht verwende.

Grüße Fabian

# gaffa meinte am 26. Oktober 2009, 18:17 dazu:

Im Studio kann man unter Bibliotheken/Libraries in der Project Configuration hinzufügen. Ich habe folgende Probleme: ich habe zwei Boards die über CAN kommunizieren sollen. Das eine soll zwischen Rechner und Bus hängen (CAN2RS232) und das andere hat ein Display. Ich kann mir also alles schön zum debuggen ausgeben lassen. Nun machen beide das gleiche. can_init liefert true zurück. can_send_message liefert drei mal true und danach false (ich schicke einfach im Sekundentakt Nachrichten auf den Bus). Und zwar bei beiden. can_check_message liefert immer false. Verbunden sind beide Boards mit etwa 50cm Kabel. Bei beiden Boards ist ein 120 Ohm Abschlusswiderstand installiert. Ist irgendwo verständlich dokumentiert, wie das mit den Filtern läuft? Kann das der Grund sein, warum die Kommunikation nicht klappt? Bekommt nicht jeder Busteilnehmer seine eigene ID? Wo setzt man die? Ich bin noch etwas verwirrt?

# Fabian Greif meinte am 27. Oktober 2009, 11:49 dazu:

can_send_message liefert drei mal true und danach false

Das bedeutet das die beiden Boards nicht miteinander kommunizieren können. Überprüf noch mal sämtliche Leitungen und die CAN Transceiver.

Wenn du die Fehlerregister ausliest solltest du auch sehen können das keine Kommunikation zustande kommt.

Ist irgendwo verständlich dokumentiert, wie das mit den Filtern läuft?

Im Datenblatt des MCP2515 findet sich einiges.

Kann das der Grund sein, warum die Kommunikation nicht klappt?

Nein. Auch ohne Filter sollten sich Nachrichten verschicken lassen.

Bekommt nicht jeder Busteilnehmer seine eigene ID? Wo setzt man die?

Nein, dafür ist der Programmierer verantwortlich. CAN kennt nur Nachrichten mit Identifiern, wie diese belegt werden ist nicht festgelegt. Das spezifizieren dann weitere Protokoll die auf CAN aufsetzen. Da kannst du dir ein schönes aussuchen oder dir selbst was ausdenken.

Grüße Fabian

# Jens meinte am 9. November 2009, 10:09 dazu:

Hallo

Was mache ich falsch, wenn ich nur 8 Bytes als Antwort geliefert bekomme, die Antwort CAN Message aber mehr enthält? Ich sende eine 8 Byte Nachricht, habe aber in der can.h uint8_t data[25]; eingestellt.

Danke für die Hilfe.

# Fabian Greif meinte am 9. November 2009, 12:10 dazu:

Hallo Jens,

Was mache ich falsch, wenn ich nur 8 Bytes als Antwort geliefert bekomme, die Antwort CAN Message aber mehr enthält?

Du hast eine wichtige Einschränkung des CAN Protokolls nicht beachtet, nämlich das eine Nachricht maximal 8 Bytes an Nutzdaten enthalten kann.

Daher ist es vollkommen egal was du in der Software einstellst, der CAN Controller wird dir nicht erlauben mehr als 8 Bytes in einer Nachricht zu übertragen.

Grüße Fabian

# Lukas meinte am 12. November 2009, 15:09 dazu:

Hallo Fabian,
erst einmal herzlichen Dank für dies tolle Bibliothek! Ich habe nur leider folgendes Problem mit meinem AT90CAN: Er sendet schön brav bei 125kbps periodisch eine Nachricht nur ist DLC immer Null und die Nachricht enthält keine Daten. Die Daten sollten die gleichen sein, wie in deinem Testprogramm, das du zur Lib beigefügt hast.

Hast du vielleicht eine Idee woran das liegen könnte?
Danke für jede Hilfe.

# Georg meinte am 16. November 2009, 13:58 dazu:

Hallo Fabian, ich habe ein Problem und zwar habe ich ein CAN-Netzwerk mit insgesamt 8 Teilnehmern, davon 7 mit den mcp2515 und 1 atcan128. Jetzt habe ich aber das Problem, dass mir der MCP die Daten, die vom atcan128 gesendet werden, zwar empfängt, jedoch nicht löscht. Da muss ich danach die Daten wieder senden, damit ich überhaupt neue Daten empfangen kann. Meine Routine zum Empfangen: can_get_message;

v= (msg.data[0]-34)/3;

vor= msg.data[1];

zur= msg.data[2];

can_send_message(&msg);

Ich habe die ID in einem Empfangspuffer genau so konfiguriert, dass nur dieser 1 die Daten empfängt. Dieser Puffer soll aber jede neue Datei die mit dieser IP gesendet wird empfangen und die alte löschen. Gibt es eine bessere Möglichkeit um die Daten aus dem Empfangspuffer zu löschen als die Datei einfach wieder zu senden?

Schon mal vielen Dank!

# Fabian Greif meinte am 16. November 2009, 17:58 dazu:

Hallo Georg,

Jetzt habe ich aber das Problem, dass mir der MCP die Daten, die vom atcan128 gesendet werden, zwar empfängt, jedoch nicht löscht. Da muss ich danach die Daten wieder senden, damit ich überhaupt neue Daten empfangen kann

Das habe ich nicht verstanden. Welche Daten willst du löschen?

Wenn du per can_get_message() eine Nachricht ließt wird sie aus dem internen Empfangspuffer des MCP2515 gelöscht und ins RAM kopiert. Oder was meintest du? Das senden von Nachrichten ist davon vollkommen unabhängig.

Grüße Fabian

# Jens meinte am 18. November 2009, 08:43 dazu:

Leider hatte ich bei http://www.mikrocontroller.net/topic/157019#1484234 keine Antwort bekommen, also doch noch mal hier.

Ich nutze die CAN Bibliothek

Alle Nachrichten empfangen klappt auch.

Was ich irgendwie gar nicht kapiere ist, wie ich nur Nachrichten mit bestimmten IDs empfangen kann. Kann mir jemand ein Beispiel für zwei zugelassene IDs erstellen? Ggf. einmal für 11 und einmal für 29 Bit?

Danke.

# Fabian Greif meinte am 18. November 2009, 10:51 dazu:

Die Idee bei den Filtern und Masken ist folgende: Es wird überprüft ob alle Bits die in der Maske gesetzt sind bei der ankommenden Nachricht und dem Filter übereinstimmen. Ist das der Fall wird die Nachricht akzeptiert, wenn nicht wird sie verworfen.

Willst du also nur zwei unterschiedliche IDs empfangen solltest du alle Bits der Maske auf 1 setzten und im Filter die Gewünschte ID eintragen. Dann werden nur Nachrichten mit genau dieser ID durchgelassen.

Mit welchen CAN Controller arbeitest du denn?

Grüße Fabian

# Jens meinte am 19. November 2009, 09:14 dazu:

Ich arbeite mir dem MCP2515

# Jens meinte am 20. November 2009, 11:29 dazu:

Tja, ich stelle mich irgendwie zu dämlich an. Egal, was ich mache, es werden immer alle Botschaften empfangen. Kannst Du mir einen Codeausschnitt geben? Oder muß ich beim compilieren der library was einstellen?
Danke

# Fabian Greif meinte am 20. November 2009, 13:10 dazu:

Hallo Jens,

Oder muß ich beim compilieren der library was einstellen?

Nein, nichts was mit den Filtern zu tun.

Angenommen du willst nur Standard-Nachrichten mit den Identifiern 0x123 und 0x456 empfangen. Dann kann man die Filter zum Beispiel folgendermaßen einstellen:

prog_uint8_t can_filter[] = 
{
    // Group 0
    MCP2515_FILTER(0x123),  // Filter 0
    MCP2515_FILTER(0x123),  // Filter 1

    // Group 1
    MCP2515_FILTER(0x456),  // Filter 2
    MCP2515_FILTER(0x456),  // Filter 3
    MCP2515_FILTER(0x456),  // Filter 4
    MCP2515_FILTER(0x456),  // Filter 5

    MCP2515_FILTER(0x7FF),  // Mask 0 (for group 0)
    MCP2515_FILTER(0x7FF),  // Mask 1 (for group 1)
};
...
can_static_filter(can_filter);

Jetzt empfängt das erste Register nur die Identifier 0x123 und das zweite nur 0x456. Will man mit beiden Registern beide Identifier empfangen muss es folgendermaßen aussehen:

prog_uint8_t can_filter[] = 
{
    // Group 0
    MCP2515_FILTER(0x123),  // Filter 0
    MCP2515_FILTER(0x456),  // Filter 1

    // Group 1
    MCP2515_FILTER(0x123),  // Filter 2
    MCP2515_FILTER(0x123),  // Filter 3
    MCP2515_FILTER(0x456),  // Filter 4
    MCP2515_FILTER(0x456),  // Filter 5

    MCP2515_FILTER(0x7FF),  // Mask 0 (for group 0)
    MCP2515_FILTER(0x7FF),  // Mask 1 (for group 1)
};
...
can_static_filter(can_filter);

Beide Varianten sollten aber wirklich nur die beiden Identifier durchlassen und keine anderen.

Für Extended-Nachrichten musst du einfach MCP2515_FILTER durch MCP2515_FILTER_EXTENDED ersetzten und die Werte entsprechend anpassen.

Grüße Fabian

# Georg meinte am 27. November 2009, 10:31 dazu:

Hallo, ich weis auch nicht was da genau falsch ist, ich habe nur das Problem, dass ich nur mit dem befehl can_get_message; oft die Daten nicht empfange, obwohl ich die Filter richtig eingestellt habe. Erst wenn ich nach den can_get_message; wieder ein can_send_message; schreibe, empfängt der Controller wieder neue Nachrichten. Somit habe ich mir gedacht, dass der MCP-Controller die alten Daten aus den Puffern nicht löscht. Zur Sicherheit nochmal meine Filter:

prog_char can_filter[] = 
{
	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 0
	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 1

	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 2
	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 3
	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 4
	MCP2515_FILTER_EXTENDED(0x12345678),	// Filter 5
	
	MCP2515_FILTER_EXTENDED(0x1fffffff),	// Maske 0
	MCP2515_FILTER_EXTENDED(0x1fffffff),	// Maske 1
};

Ich möchte nur 1 Datei empfangen. Ich habe dann auch noch das Problem, dass ich 7 Can Controller habe, und alle unterschiedliche Nachrichten empfangen sollen. Das funktioniert aber nicht bei allen, wobei aber alle denselben Controller haben und den selben Programmcode mit unterschiedlichen ID?s.

Hat es vielleicht damit zu tun, dass ich die Interrupts des MCP?s ausgeschaltet habe und immer selber nach 10ms den Controller auslese (muss ich machen, da ich schon sonst zu viele Interrupts habe)?

Vielen Dank schon mal für die Hilfe !

# Frank meinte am 15. Januar 2010, 23:13 dazu:

Hallo, ich versuche gerade die Lib auf einen ATmega644 20PU zum laufen zu bringen. Nur leider bekomme ich folgende Fehlermeldung: spi.h: In function ‘spi_start’: spi.h:75: error: ‘SPDR’ undeclared (first use in this function) spi.h:75: error: (Each undeclared identifier is reported only once spi.h:75: error: for each function it appears in.) spi.h: At top level: spi.h:78: warning: ‘gnu_inline’ attribute directive ignored spi.h: In function ‘spi_wait’: spi.h:80: error: ‘SPSR’ undeclared (first use in this function) spi.h:80: error: ‘SPIF’ undeclared (first use in this function) spi.h:83: error: ‘SPDR’ undeclared (first use in this function) In file included from mcp2515.c:50: mcp2515_private.h: At top level: mcp2515_private.h:144: warning: ‘gnu_inline’ attribute directive ignored make.exe: *** [build/mcp2515.o] Error 1

Woran kann das liegen? Gruss Frank

# Fabian Greif meinte am 16. Januar 2010, 22:49 dazu:

Kann es sein das du eine ältere WinAVR Version verwendest? Generell läuft die Bibliothek ohne Probleme auf einem ATMega644, selbst schon häufiger getestet.

Grüße Fabian

# Frank meinte am 17. Januar 2010, 17:35 dazu:

Hallo Fabian,

danke!!! Daran hat es gelegen! Gruss Frank

# Helmut Mahr meinte am 30. Januar 2010, 11:02 dazu:

MCP2515/SAJ1000/AT90CAN Wenn man ganz am Anfang vor der Frage steht: “Was soll ich davon nehmen?”, gibts da eine Info, die Vor- und Nachteile der einzelnen Lösungen auflistet? Oder kann man das in ein paar Sätzen sagen? Nicht immer wird man einen AT90CAN einsetzen. Dann kommen noch die beiden anderen Lösungen in Frage. Was sind die Stärken und Nachteile jeweils?

# Carsten Komnik meinte am 10. Februar 2010, 14:59 dazu:

Hallo Fabian.
Nachdem ich es schon fast aufgegeben hatte, klappt der Empfang von CAN-Nachrichten mit deiner lib nun auch auf meinem AT90CAN128.
Problem war die fehlende Initialisierung des Filters wie unter deiner Antwort vom 16.12.2008 beschrieben.
Vielen Dank!
Nun muss ich nur noch den Hänger nach 15x Nachrichten senden lösen :-)

# Carsten Komnik meinte am 11. Februar 2010, 13:51 dazu:

Hi, der Hänger nach 15x gesendeten Botschaften ist nun ebenfalls weg.
Auch hier: nachdem ich im “sendenden” AT90CAN ebenfalls Interrupts aktiviert und den Filter initialisiert habe, läuft alles perfekt.

# Martin meinte am 8. März 2010, 16:27 dazu:

Hallo Fabian, Vielen dank für diese tolle Lib. Alles funktioniert einwandfrei, ob AT90CAN oder mit der spi Variante. SUPER!!! Nur schade, dass du das es keinen CAN-Bootloader für den AT90CAN gibt.

# Wolfram meinte am 16. Mai 2010, 12:18 dazu:

Hallo Fabian, ich verwende Deine Lib jetzt schon recht lange und sie funktioniert auch sehr gut. Jetzt habe ich eine Anwendung wo ich 2 CAN Busse parallel betreiben möchte. Ich denke mal dazu brauch ich erstmal zwei CAN Controller 8 aber wie kann ich die denn dann ansprechen. Du verwendest ja einen int Eingang am ATMEGA. Muss ich das quasi “zu Fuss” programmieren per separatem Port-Bit ? Gruß wolfram

# Fabian Greif meinte am 16. Mai 2010, 15:43 dazu:

Hallo Wolfram.

Zwei CAN Controller parallel ist mit der Bibliothek in der jetzigen Form noch nicht vorgesehen. Du müssest also wirklich die MCP-Funktionen kopieren, neu benennen und dann für den zweiten CAN Controller verwenden. Anders geht es im Moment leider nicht.

Erst mit der nächsten Version der Bibliothek (die dann in C++ geschrieben sein wird) wird das funktionieren. Allerdings ist diese noch nicht wirklich fertig und daher noch nicht öffentlich verfügbar.

Grüße Fabian

# Andi meinte am 26. Mai 2010, 14:36 dazu:

Hallo Fabian, ich benutze das AVR-Studio. Könntest du vielleicht nocheinmal genauer beschreiben wie man die Bibliothek erstellt und dann auch nutzen kann. Ich bekomme vom Compiler immer die Fehlermeldung “c:/winavr-20080610/bin/../lib/gcc/avr/4.3.0/../../../../avr/bin/ld.exe: cannot find -lcan”

Vielen Dank im Vorraus das wär echt dufte :) !!

Andi

PS: Echt tolle Arbeit! ^^

# Thorsten Krell meinte am 7. Juni 2010, 15:18 dazu:

Was muss ich eigentlich für eine Frequenz im Makefile einstellen, wenn ich den MCP2515 mit 8MHz betreibe und meinen ATMega128 mit 16MHz?

# Fabian Greif meinte am 8. Juni 2010, 15:21 dazu:

@Thorsten
Die Bibliothek funktioniert in ihrer jetzigen Form nicht mit einem 8 MHz Quarz für den MCP2515. Damit es klappt müsstest du die Tabelle mit den Werten für die Konfigurationsregister CNF1-3 anpassen.

Alternativ könnte man als schnellen Hack immer die doppelte Geschwindigkeit anstelle der eigentlich gewünschten auswählen. Wenn ich das richtig in Erinnerung habe, dann sollte das auch funktionieren.

Grüße Fabian

# Smon meinte am 20. Juni 2010, 17:59 dazu:

Grüße Fabian. Ich nutze derzeit deine Biliothek für ein kleines Hausbussystem an unserer Uni und ich bin auch schon recht weit gekommen. Bislang habe ich den Atmega8 verwendet aber nun stoße ich speichertechnisch an seine Grenzen und will deswegen auf den Atmege644 umsteigen und genau da liegt das Problem.

Die Initialisierung des CAN-Busses funktioniert nicht. Er liefert nicht nur ein “False” zurück, der Controller hängt sich komplett auf. Ich habe im Makefile für die MCU den Atemag644 angegeben. Das Aufspielen der Software ist kein Problem und auch andere Programme gehen tadellos. Ich habe auch das SPI-Interface selbst initialisiert (war beim Atmega8 nicht nötig), ohne Erfolg. Gibt es noch irgendwelche Einstellungen die ich vergessen/übersehen habe? Grüße, Simon

PS: Meine Schaltung ist richtig aufgebaut, habs auf dem Steckboard nun bestimmt schon 20 mal überprüft ;)

# Stefan meinte am 10. August 2010, 12:08 dazu:

Hallo Fabian,

habe dein Projekt schon erfolgreich mit einem MCP2515 und einem ATMega8 genutzt. Jetzt habe ich auf einen ATMega328PA umgesattelt und konnte soweit alles zum Laufen bringen. Allerdings musste ich dazu die MCP2515_private.h ändern und den IC zur Liste hinzufügen. (Hinweis für Beginner)

#if (BUILD_FOR_MCP2515 == 1)
#if defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega644__)
    #define P_MOSI  B,5
    #define P_MISO  B,6
    #define P_SCK   B,7
    #define SUPPORT_FOR_MCP2515__
#elif defined(__AVR_ATmega8__)  || defined(__AVR_ATmega48__) || \
      defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)

    #define P_MOSI  B,3
    #define P_MISO  B,4
    #define P_SCK   B,5
    #define SUPPORT_FOR_MCP2515__
#elif defined(__AVR_ATmega128__)
    #define P_MOSI  B,2
    #define P_MISO  B,3
    #define P_SCK   B,1
    #define SUPPORT_FOR_MCP2515__
#elif defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    #define P_MOSI  B,0
    #define P_MISO  B,1
    #define P_SCK   B,2

    #define USE_SOFTWARE_SPI        1
    #define SUPPORT_FOR_MCP2515__
#else
    #error  choosen AVR-type is not supported yet!
#endif
#endif

Jetzt befindet sich mein Mega allerdings nach Aufruf der can_init allerdings in einer Endlosschleife, in der er ständig über SPI mit dem MCP2515 kommunizieren will (MOSI periodisch ausgelastet), über MISO allerdings nur ein paar Bits zurückkommen, und zwar immer die selben. Ich kann den Fehler nicht entdecken. Habe mir die letzte Version der Blbliothek runtergeladen.

Hoffe, du kannst mir eine Tipp geben.

Danke dir. Viele Grüße

# Benjamin meinte am 12. August 2010, 09:08 dazu:

Hallo,

ich habe Deine Lib bei meiner Diplomarbeit in Verbindung mit einem SJA1000-Soft-IP-Core auf einem FPGA verwenden können und sage dafür einfach mal Danke :) Einen Fehler habe ich allerdings gefunden, in der sja1000_get_message.c liest Du die Register 17 und 18 in der falschen Reihenfolge aus (Zeile 81+82). Also einfach die 17 und 18 vertauschen, und dann kann man auch die ID der empfangenen Nachricht korrekt weiterverarbeiten ;)

Gruß Benjamin

# Stefan meinte am 16. August 2010, 15:01 dazu:

So, ich habe jetzt herausgefunden, woran es bei mir lag. Die UART Bibliothek war nicht an den ATMega328PA angepasst. ich hatte zwar die neuste Version von Peter Fleurys Webseite runtergeldane, in der sich auch der ATMega328P findet, allerdings scheinen die Interrupt Vektoren nicht zu stimmen und so hing der Controller immer im der Routine fest. Habe die upgedatete Bibliothek von hier benutzt, die einwandfrei funktioniert. Sie basiert auf der von Peter Fleury.

Viele Grüße und herzlichen Dank für diese Bibliothek!

# Fabian Greif meinte am 19. August 2010, 22:06 dazu:

@Stefan
Freut mich das es jetzt funktioniert. So was ist natürlich ein hinterhältiger Fehler.

@Benjamin
Da merkt man das ich den SJA1000 noch nicht wirklich viel eingesetzt habe ;-) Über einen Test auf meinem Testboard ist er nicht hinausgekommen.

Der Fehler ist jetzt korrigiert und ein aktualisiertes Archiv online. Danke für den Fehlerbericht ;-)

Grüße Fabian

# Sascha meinte am 2. September 2010, 11:07 dazu:

Hallo,
danke für die Erstellung der Lib. Sie spart mir sehr viel Arbeit.
Leider tue ich mich sehr schwer die SPI Funktionen auszulagern. Ich möchte am SPI Bus noch zwei weitere Gerätschaften betreiben.
Gibt es eine einfache möglichkeit eine externe spi.c Datei zu verwenden.
Ich hoffe ich habe mich verständlich ausgedrückt.

Gruß Sascha

# Fabian Greif meinte am 2. September 2010, 15:07 dazu:

Hallo Sascha,

du kannst einfach die SPI-Funktionen der canlib verwenden. Das ist nur eine Funktion nämlich spi_putc(). Leg einfach eine entsprechende Deklaration oberhalb der Stelle an der du die Funktion verwenden willst an:

uint8_t spi_putc(uint8_t data);

Grüße Fabian

# JJ meinte am 14. September 2010, 09:11 dazu:

Hallo Fabian, hallo Benjamin,

ich benutze die can-lib seit einiger Zeit zusammen mit dem SJA1000. Alles läuft super. Deshalb hat es mich gewundert, als Benjamin plötzlich so einen grundlegenden “Fehler” entdeckt hat. Gestern habe ich mir die Sache sowohl theoretisch als auch praktisch am Board angeguckt und bisschen rumgetestet.
Ich befürchte, dass das Problem bei Benjamin woanders liegt. Die Implementierung in der can-lib war richtig! Deshalb würde ich empfehlen wieder auf die vorletzte Release-Version umzusteigen.

# Fabian Greif meinte am 17. September 2010, 16:05 dazu:

Hallo JJ,

Die Implementierung in der can-lib war richtig! Deshalb würde ich empfehlen wieder auf die vorletzte Release-Version umzusteigen.

danke für den Hinweis. Ich habe mir gerade nochmal genau das Datenblatt des SJA1000 genauer zu Gemüte geführt. Du hast vollkommen recht, die bisherige Implementierung war korrekt und entspricht dem Datenblatt. Ich habe das Archiv mal wieder auf die vorherige Version “aktualisiert”.

Grüße Fabian

# Klaus meinte am 24. September 2010, 14:44 dazu:

Moin,

tolle Bibliothek, bin begeistert, dass Ihr sie zur Verfügung stellt! Ich benutzte die Testplatine, so modifiziert, dass RX1BF an RS des 2551 ist. Normale Kommunikation hat problemlos geklappt, nachdem ich in der config.h MCP2515_TRANSCEIVER_SLEEP definiert habe. Nun möchte ich den MCP2515 in den Schlafmodus versetzen und gehe dazu so vor wie in can.h beschrieben. Leider hängt sich das Programm beim Aufwachen auf, und zwar in mcp2515_set_mode(NORMAL_MODE), das von mcp2515_wakeup() aufgerufen wird — weil mcp2515_read_register(CANSTAT) & 0xe0 immer 0x20 anstatt 0x00 ergibt. Selbst bei mehrfachem Schreiben von CANCTRL ändert sich nichts in CANSTAT. Woran könnte das nur liegen?

Vielen Dank und Gruß, Klaus

# Benjamin meinte am 27. September 2010, 15:56 dazu:

Hallo zusammen, es tut mir leid um die Verwirrung, die ich hier verursacht habe :). Dann muss bei mir was Anderes falsch gewesen sein (z.B. die Verilog-Beschreibung des SJA1000).

Gruß Benjamin

# Oliver meinte am 1. Oktober 2010, 23:26 dazu:

Hallo, erstmal vielen Dank für die tolle Libary. Die Kommunikation funktionierte auf anhieb mit einem Mega8 und dem MCP2515. Ich hatte sonst aber auch keine Filter setzen wollen. Nun wollt ich mein Projekt erweitern und die Filter nutzen. Ich habe es nun etwas umständlich gelöst, funktioniert aber erstmal.

can_filter_t filter0 = {
    .id = 0x100,
    .mask = 0x700,
    .flags = {
        .rtr = 0,
    }
};
can_filter_t filter1 = {
    .id = 0x2,
    .mask = 0x7ff,
    .flags = {
        .rtr = 0,
    }
};
can_filter_t filter2 = {
    .id = 0x2,
    .mask = 0x7ff,
    .flags = {
        .rtr = 0,
    }
};
can_filter_t filter3 = {
    .id = 0x2,
    .mask = 0x7ff,
    .flags = {
        .rtr = 0,
    }
};
can_filter_t filter4 = {
    .id = 0x2,
    .mask = 0x7ff,
    .flags = {
        .rtr = 0,
    }
};
can_filter_t filter5 = {
    .id = 0x2,
    .mask = 0x7ff,
    .flags = {
        .rtr = 0,
    }
};

//Filter aktivieren
can_set_filter(0, &filter0);
can_set_filter(1, &filter1);
can_set_filter(2, &filter2);
can_set_filter(3, &filter3);
can_set_filter(4, &filter4);
can_set_filter(5, &filter5);

Nun wollte ich es aber eigentlich eher so haben wie Sie es hier schon einmal beschrieben haben

prog_uint8_t can_filter[] = { // Group 0 MCP2515_FILTER, // Filter 0 MCP2515_FILTER, // Filter 1

// Group 1
MCP2515_FILTER(0x123),  // Filter 2
MCP2515_FILTER(0x123),  // Filter 3
MCP2515_FILTER(0x456),  // Filter 4
MCP2515_FILTER(0x456),  // Filter 5

MCP2515_FILTER(0x7FF),  // Mask 0 (for group 0)
MCP2515_FILTER(0x7FF),  // Mask 1 (for group 1)

}; …

can_static_filter(can_filter);

Nur wenn ich es so mache und danach die Filter auslese bekomme ich für ID und Mask immer nur 0 zurück und es werden aber keine Nachrichten mehr empfangen.

Woran kann das liegen? Vielen Dank schonmal!

MFG Olli

# Andrey meinte am 7. November 2010, 16:05 dazu:

Hi Fabian,

Sorry I don’t know German. I’ll try to include a Google Translate translation of this. Thanks for the library, I would like to use it with ATmega324p and mcp2515. mcp2515_private.h says 324p is not supported but ATmega32 and ATmega644 are supported. Can I use the library with ATmega324p and modify mcp2515_private.h or do I need to use ATmega644 in my design to make it work?

Thank you again. Andrey

Hallo Fabian,

Leider weiß ich nicht Deutsch. Ich werde versuchen, eine Google Translate Übersetzung dieses aufzunehmen. Vielen Dank für die Bibliothek, würde Ich mag es mit ATmega324p und MCP2515 verwenden. mcp2515_private.h sagt 324p wird nicht unterstützt, sondern ATmega32 und ATmega644 unterstützt. Kann ich die Bibliothek mit ATmega324p und ändern mcp2515_private.h oder muss ich in meinem ATmega644 Design zu verwenden, damit es funktioniert?

Nochmals vielen Dank. Andrey

# Fabian Greif meinte am 7. November 2010, 23:55 dazu:

Hi Andrey,

Sorry I don’t know German

No problem, English is fine ;-)

… or do I need to use ATmega644 in my design to make it work?

No. Just add the definitions for the ATmega324p and it should work. There are no special features of a particular AVR used in the library. Only the location of the pins for the hardware SPI needs to be known.

Best regards, Fabian

# Andrey meinte am 10. November 2010, 00:53 dazu:

Thanks a lot Fabian for your help and such a quick response. :)

Andrey

# SP meinte am 10. November 2010, 10:17 dazu:

Hallo,

vielen Dank für die schöne Library.

Sie funktioniert auch tadellos mit einem ATTiny44A.

Die MCP2515_private.h könnte um die folgenden Einträge erweitert werden:

#elif defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    #define P_MOSI  A,6
    #define P_MISO  A,5
    #define P_SCK   A,4

    #define USE_SOFTWARE_SPI        1

VG SP

# Klaus meinte am 17. November 2010, 17:59 dazu:

Moin,

ich bin gerade dabei, die canlib für den ATtiny44 unter Benutzung der Hardware-USI zu portieren (wenn ich fertig bin, werde ich den Patch hier reinstellen). Da ich Euren Code sinnvoll erweitern will, ohne Eure Struktur durcheinanderzubringen, eine Frage dazu: Gibt es einen besonderen Grund, weshalb spi_start() und spi_wait() zweimal definiert sind, einmal als Inline-Funktion in spi.h und einmal als statische Funktion in mcp2515_write_id.c? Weshalb wird in spi_putc() nicht auf spi_start() und spi_wait() zurückgegriffen?

Herzlichen Gruß, Klaus

# Fabian Greif meinte am 21. November 2010, 14:32 dazu:

Gibt es einen besonderen Grund, weshalb spi_start und spi_wait zweimal definiert sind

Nein. Ich vermute das ist historisch so gewachsen. Kann also gerne geändert werden.

Grüße Fabian

# Andi meinte am 14. Dezember 2010, 21:49 dazu:

Die Funktion mcp2515_get_message enthält einen Fehler beim Ermitteln ob es sich um einen Standard Remote Frame handelt und zwar beim Auswerten über SPI_RX_STATUS. Sollte man gerade dabei sein den RXB1 Buffer auszulesen, so darf nicht SPI_RX_STATUS für die RTR Auswertung verwendet werden, da im Status Byte die Bits 0:4 nur für RXB0 gelten … zumindest laut Datenblatt ;-)

# Jens H. meinte am 15. Dezember 2010, 18:46 dazu:

Hi, ich habe mich nun ein Weilchen mit der CAN Lib beschäftigt und muss sagen es ist echt ein cooles Stück Code ;) Die meisten Funktionen laufen Problemlos oder ließen sich nach ein paar Stunden basteln nutzen. Ein wenig mehr Doku währe wünschenswert…

So nun zu meinem eigentlichen Problem: Ich möchte mir die gesetzten filter anzeigen lassen und habe mir dazu folgende Funktion geschrieben:

void print_filter(uint8_t i) { can_filter_t filter; uint8_t res = can_get_filter(i, &filter); uart_put_string("FILTER ("); uart_put_uint16(i); uart_put_string(" / "); uart_put_uint16(res); uart_put_string("):\n\rID: "); uart_put_uint16(filter.id); uart_put_string("\n\rMASK: "); uart_put_uint16(filter.mask); uart_put_string("\n\r\n\r"); }

Wenn ich die Funktion aufrufe gibt der Controller seine aufgaben auf (irgend so eine Art “freze”). Mit dem gleichen Programmcode ohne den Aufruf dieser Funktion funktioniert alles einwandfrei.

Viele Gruesse Jens H.

# Jo meinte am 20. Januar 2011, 16:25 dazu:

Hi, ist es eigentlich möglich, mit der Lib zwei MCP2515 an einem µC zu betreiben? Für ein Gateway …

Gruß Jo

# Fabian Greif meinte am 21. Januar 2011, 14:32 dazu:

Hi, ist es eigentlich möglich, mit der Lib zwei MCP2515 an einem µC zu betreiben? Für ein Gateway …

Nein, in der jetztigen Form ist das nicht möglich. Es gibt allerdings eine Template-basierte C++ Variante davon, die kann das. Schreib mir am besten mal eine E-Mail.

Grüße Fabian

# André meinte am 6. Februar 2011, 23:15 dazu:

Where´s the MCP2515 can_check_message function gone? Checked all *.h and *.cpp files … cant find a reference to this function? Where is it gone?

thx André

# Fabian Greif meinte am 7. Februar 2011, 00:00 dazu:

Hi André,

Where is it gone?

It is and always had been in mcp2515_buffer.c. It is named mcp2515_check_message there and will be renamed in can_private.h when compiling for the MCP2515.

Best regards,
Fabian

# André meinte am 7. Februar 2011, 17:16 dazu:

Ah, really great! :o) One more question, how do i compile it? I´ve never done this before. I want to use it with arduino (have an older compiled version from skpang.co.uk).

thx! André :o)

# Fabian Greif meinte am 8. Februar 2011, 18:06 dazu:

how do i compile it?

You need an installed Version of WinAVR.

Then you go the src/ folder and adapt the config.h file and the Makefile (MCU and F_CPU) to your needs. Then open a command line and type make lib. This should build the library.

See also “Einbinden ins eigene Programm” in the article above.

Best regards,
Fabian

# Rainer meinte am 9. Februar 2011, 23:18 dazu:

Hallo Fabian,

mühsam nährt sich das Eichhörnchen, doch ich komme voran. Habe deine CAN-Demo erweitert, damit ich an einem Display ein bisschen debuggen kann. Aber soweit ich das feststellen kann hängt sich das Programm schon beim can_init auf. Ich bekomme nicht mal eine Ausgabe. Hast du eine Ahnung woran das liegen könnte?

Grüße

Rainer

# Fabian Greif meinte am 10. Februar 2011, 14:12 dazu:

Hallo Rainer,

Hast du eine Ahnung woran das liegen könnte?

Hast du die CAN lib für den richtigen AVR Typ compiliert? Das Hängenbleiben ist bisher nur vorgekommen wenn die CAN Bibliothek für einen anderen AVR Typ als den letztenends verwendeten compiliert wurde.

Grüße Fabian

# Rainer meinte am 10. Februar 2011, 18:56 dazu:

Hallo Fabian,

habs gestern hingekriegt. Das Ding schickt und empfängt. Deine Vermutung war zudem richtig. Sollte nächstes Mal einfach später schreiben, dann nerv ich dich nicht.

Du hast in deiner Demo für den ATMEGA32 kompiliert. Ich hab die Lib für den ATMEGA644 nochmal erstellt und jetzt gehts. Wieder was gelernt. Tja und wer lesen kann ist natürlich klar im Vorteil…

Vielen Dank für die Unterstützung. War ne lange Nacht gestern. ;-)

Rainer

# Tom meinte am 28. April 2011, 19:25 dazu:

Hallo Fabian,

ich habe gerade mal mit deiner Library experimentiert und auf einem ATMega32 ein äußerst seltsames Problem:

  • Die CAN Lib selber geht problemlos, senden & empfangen
  • Wenn ich nun eine UART Interrupt Routine verwende (die alleine für sich auch problemlos geht), dann resettet sich der ATMega sporadisch beim Empfang von Zeichen via seriell

Hat vielleicht jemand schon mal sowas gehabt?

Gruß, Tom

# Niko meinte am 2. Mai 2011, 19:00 dazu:

Hallo,

ich bin gerade dabei die Can-Lib auf einem AT90CAN128 (auf dem Olimex AVR-CAN-Board) zu testen.

Mein Problem ist folgendes: Obwohl ich den Controller (meiner Meinung nach) richtig initialisiere kann ich im nicht mal im Loopback-Modus Nachrichten empfangen…

Im großen und ganzen schaut mein Programm so aus:

uart_init(UART_BAUD_SELECT(9600, F_CPU));
can_init(BITRATE_125_KBPS);

can_filter_t filter = {
    .id = 0,
    .mask = 0,
    .flags = {
        .rtr = 0,
        .extended = 0
    }
};

can_set_filter(0, &filter);
can_set_mode(LOOPBACK_MODE);
can_t message;

message.id = 0x123;
message.length = 2;
message.data[0] = 0xab;
message.data[1] = 0xcd;

print_can_message(&message);

while(1) {
    can_send_message(&message)) {

        delay(300);

        if (can_check_message()) {
            if (can_get_message(&message)) {
                print_can_message(&message);
            } else {
                PRINT("Fehler\n\r");
            }
        } else {
            PRINT("Fehler\n\r");
        }
        delay(1000);
    }

return 0;

Der AT90CAN sendet 15x, dann kommen Errors und empfangen wird gar nichts :-(

Vor längerer Zeit hab ich die Library auch schon mit einem MCP2515 verwendet (da hat alles einwandfrei funktioniert).

Ist meine Software falsch, oder liegts eher am Olimex-Board?

Liebe Grüße und Vielen Dank für die Mühe und die tolle Library :-)

Niko

# Niko meinte am 2. Mai 2011, 19:11 dazu:

Sorry, ich habe im geposteten Code das sei (); vergessen (daran liegts aber leider nicht :D).

Danke und Liebe Grüße

Niko

# Niko meinte am 3. Mai 2011, 09:13 dazu:

Oh Mann, jetzt seh ich erst was für einen Blödsinn ich da gepostet habe (das kommt davon, wenn man den Code im Comment-Fenster editiert…).

Ich hab jetzt ein Testprogramm geschrieben und auf pastebin gepostet: PasteBin - Main.c

In der config.h ist nur der AT90CAN aktiviert und timestamps sowie extended-can-ids sind deaktiviert.

Im Library-Makefile habe ich auch den at90can128 eingestellt.

Das Makefile ist sicher richtig, da es das gleiche ist wie bei meinem letzten (erfolgreichen) Versuch mit dem MCP2515.

In dem Testprogramm mache ich folgendes:

  • CAN & UART-Init

  • Interrupts aktivieren

  • Filter setzen (Alles auf 0)

  • Loopback-Mode setzen

Und dann endlos:

  • Message senden

  • Message empfangen (Naja, eigentlich nur checken ob eine da ist)

Init etc. klappt, senden klappt 15x (bis die buffer voll sind), empfangen wird nichts…

Ich bitte um Entschuldigung für die vielen Comments (und vor allem für den uncompilierbaren Code).

# Niko meinte am 3. Mai 2011, 23:40 dazu:

Ich hab jetzt ein nochmal vereinfachtes Programm (1x Senden, 1x empfangen im Loopback-Mode) im AVR-Studio Simulator mit CAN-Plugin getestet und es verhält sich genauso wie auf meinem Board:

  1. Ein MOb ist auf Empfang geschaltet
  2. Ein zweites MOb sendet ein Package (Interrupt wird korrekt aufgerufen)
  3. Das wars… Empfangen wird nichts (Tx Done, Rx Pending, Interrupt wird nicht mehr aufgerufen)

Ich muss allerdings sagen, dass ich den Simulator (besonders das CAN-Plugin) zum ersten mal (ernsthaft) verwende, eventuell ist es also auch ein Bedienungsfehler.

Ich glaube ich übersehe da irgendwas grundlegendes…

Bitte um Ratschläge :-)

# Niko meinte am 4. Mai 2011, 19:15 dazu:

So, kurz vorm aufgeben hab ich den AVR jetzt mal an die OBD Schnittstelle von meinem Auto gehängt und siehe da -> Er empfängt :-)

Ich vermute also, dass der Loopback-Modus nicht geht, oder ich falsch sende.

So, jetzt muss ich nur noch sinnvolle Daten vom Auto bekommen, dann bin ich glücklich :-)

Liebe Grüße

# Michael meinte am 14. Mai 2011, 10:47 dazu:

Hi Leute bin grad dabei diese Lib in mein Projekt einzubinden. In mcp2515_get_message ist meiner Meinung nach aber noch eine kleine “Unlogik” ich will nicht Fehler sagen. Wenn SUPPORT_EXTENDED_CANID nicht gesetzt ist dann werden die Interrupt Flags der beiden Empfangspuffer zwei mal gelöscht. Könnte man sich also ein wenig Zeit sparen wenn nur einmal gelöscht wird.

Gruß Michael

# Alex meinte am 28. Mai 2011, 23:03 dazu:

Hallo Fabian,

Danke für die tolle lib!! Ich habe sie testweise hier auf 5 CAN Boards laufen. Soweit geht alles, senden, empfangen, filtern. Nun habe ich aber ein Problem: Wenn mehrere Units gleichzeitig senden (natürlich mit anderer CAN ID), dann gehen mir Nachrichten verloren. Es sind immer andere die da fehlen, scheint zufällig zu sein. Einen ERROR Zustand auf dem Bus bekomme ich aber nicht. Was übersehen ich da?

Wenn der Empfänger immer wieder can_check & can_get_message aufrift, kann es sein daß er da einige “übersieht” wenn er zwischen den Checks beschäftigt ist mit Nachrichten verarbeiten?

Gruß, Alexandra

# Alex meinte am 29. Mai 2011, 13:41 dazu:

Nachtrag:

Ich habe mal die gesamte Verarbeitung rausgenommen damits schneller geht und erhöhe nur noch einen Counter der die eingehenden CAN Nachrichten zählt, trotzdem kommen nicht alle Nachrichten an wie es scheint. Weiss evtl. jemand Hilfe?

# Eugen meinte am 11. Juli 2011, 10:49 dazu:

Hallo Alex! Falls es sich noch nicht erledigt hat, hier ein Paar Überlegungen zum Thema: Kann es sein, dass die Empfangspuffer des MCP2515 volllaufen (er hat ja nur 2), also, dass praktisch die Nachrichten nicht schnell genug abgeholt werden? Auf dem Bus würde man in dem Fall keine Error-Frames sehen, denn die ACK-Flags werden weiterhin gesendet. Ich habe dieses Problem noch nie gehabt (weil ich gerade nur zwei Busteilnehmer habe), habe aber dafür gesorgt dass so was nicht passiert: die Nachrichten werden in der ISR erstmal aus dem MCP2515 ausgelesen (somit sind die interne Puffer des MCP2515 sofort wieder frei), in einen Zwischenpuffer geschrieben und anschließend vom Hauptprogramm aus dem Puffer geholt und verarbeitet. Gruß Eugen

# Jakob meinte am 15. Juli 2011, 21:03 dazu:

Hallo,
danke für Lib!
Ich habe aber das gleich Problem mit dem AT90CAN wie einige meiner Vorrednder: Er empfängt keinen Nachrichten und senden nur 15 mal.
Ich habe mir die Signal am RXCAN-Pin angeschaut und es ist ein ACK zu sehen.
Ich verwende einen 3,3V-Bustreiber, aber da das Senden ja geht, sollte dies ja nicht das Problem sein.

Hat vielleicht jemand eine Idee woran dies liegen könnte?

Gruß Jakob

# Jakob meinte am 20. Juli 2011, 21:09 dazu:

Hallo, inzwischen läuft die Lib. Es lag wie schon weiter oben an den Filtern und an sei.

Nun ist es so, das ich alle 100 ms 3 CAN-Botschaften an den AT90CAN schicken, er aber immer nur eine empfängt und verarbeitet (meinstens die erste der versendeten). Kann es sein, das in der Lib nicht alle Empfangspuffer verwendet oder abfragt?

Gruß Jakob

# Fabian Greif meinte am 20. Juli 2011, 21:53 dazu:

inzwischen läuft die Lib.

Super.

Kann es sein, das in der Lib nicht alle Empfangspuffer verwendet oder abfragt?

Es werden nur die verwendet die du vorher darauf konfiguriert hast. Wenn jetzt eine Nachricht empfangen wird, dann ist der Puffer so lange gesperrt bis die Nachricht ausgelesen wurde (per can_get_message). Kommt in der Zwischenzeit eine weitere Nachricht an, so wird diese verworfen (falls nicht ein zweiter Puffer entsprechend konfiguriert ist und sie aufnehmen kann). Wenn die Nachrichten direkt hintereinander kommen, dann sollte man mindestens zwei Puffer zum Empfangen vorsehen.

Eine andere Möglichkeit wäre CAN_RX_BUFFER_SIZE zu verwenden (das Gegenstück ist CAN_TX_BUFFER_SIZE). Wenn du die in der config.h auf einen Wert größer 0 setzt, dann wird ein zusätzlicher Software-Puffer für die empfangenen bzw. zu sendende Nachrichten angelegt und die Empfangspuffer werden schneller wieder freigegeben.

Grüße Fabian

# Christian meinte am 24. Juli 2011, 13:37 dazu:

Hallo, ich bin Neuling in dieser Materie und möchte eigentlich nur das test program erstmal zu laufen bekommen. Dieses Habe ich in MYAVR ein gefügt die dateien can.h , config.h und libcan.a in den Programm ordner geladen. Desweiteren habe ich #include “can.h” und #include “config.h” gemacht. doch leider kennt MyAVR can_init() und can_send_message() immer noch nicht. kann mir jemadn einen Tip geben was ich falsch mache. Ich verwende Atmega32, MCP2515, MCP2551, CANUSB Adapter (Lawicel)

Gruß Christian

# Fabian Greif meinte am 24. Juli 2011, 13:50 dazu:

doch leider kennt MyAVR can_init() und can_send_message() immer noch nicht.

Was heißt das genau? Hast du eine Fehlermeldung dazu? Das du daran gedacht die libcan.a beim Linken mit anzugeben?

Eine andere Sachen: hast du die libcan.a für deine Einstellungen neu compiliert? Das verursacht auch immer gerne Probleme wenn man es nicht tut, hat aber mit dem was du geschildert hast erstmal nichts zu tun.

Grüße Fabian

# Jakob meinte am 27. Juli 2011, 21:33 dazu:

Es werden nur die verwendet die du vorher darauf konfiguriert hast. Wenn jetzt eine Nachricht empfangen wird, dann ist der Puffer so lange gesperrt bis die Nachricht ausgelesen wurde (per can_get_message). Kommt in der Zwischenzeit eine weitere Nachricht an, so wird diese verworfen (falls nicht ein zweiter Puffer entsprechend konfiguriert ist und sie aufnehmen kann). Wenn die Nachrichten direkt hintereinander kommen, dann sollte man mindestens zwei Puffer zum Empfangen vorsehen.

Hallo Fabian,

danke für die Antwort.

Wie folgt habe ich die MOBs als Empfänger initalisiert:

# Jakob meinte am 27. Juli 2011, 21:35 dazu:

for (num_mob = 0; num_mob < 15; num_mob++)
  {
    CANPAGE  = (num_mob < 4);
    CANSTMOB = 0;
    CANCDMOB = 0x88;
    CANIDT4  = 0;
    CANIDT3  = 0;
    CANIDT2  = 0;
    CANIDT1  = 0;
    CANIDM4  = 0; 
    CANIDM3  = 0;
    CANIDM2  = 0;
    CANIDM1  = 0;
    for (num_data = 0; num_data < 8; num_data++)
    {
      CANMSG = 0;
    }
  }

Ist das so I.O.?

# Fabian Greif meinte am 28. Juli 2011, 10:58 dazu:

Ist dass so I.O.?

Nein.

Wenn du die Bibliothek verwenden willst musst du sie auch verwenden:

can_filter_t filter = {
    .id = 0,
    .mask = 0,
    .flags = {
        .rtr = 0,
        .extended = 0
    }
};

for (uint8_t i = 0; i < 15; i++) {
    can_set_filter(i, &filter);
}

Damit kannst du allerdings nichts mehr senden weil alle MObs mit empfangen beschäftigt sind. Mindestens ein MOb sollte also frei gelassen werden.

Grüße Fabian

# Jakob meinte am 29. Juli 2011, 11:10 dazu:

Hallo Fabian, danke für die Antwort.

Wie konfiguriere ich eigentlich ein MOB als Sender mit deiner LIB?

Gruß Jakob

# Fabian Greif meinte am 29. Juli 2011, 11:42 dazu:

Wie konfiguriere ich eigentlich ein MOB als Sender mit deiner LIB?

Gar nicht. Du lässt es einfach “frei” bzw. konfigurierst es nicht als Empfänger, dann wird es zum Senden verwendet.

Grüße Fabian

# Jakob meinte am 29. Juli 2011, 13:05 dazu:

Wenn ich mehr als einen Filter konfiguriere, bleibt der µC irgendwie hängen?!

Also z.B.:

can_set_filter(0, &filter);

funktioniert.

can_set_filter(0, &filter);
can_set_filter(1, &filter);

funktioniert nicht!?

# Jakob meinte am 29. Juli 2011, 20:07 dazu:

Hallo Fabian,

ist die Funktion can_set_filter() aus der Datei at90can_set_dyn_filter.c ?

Gruß

# Fabian Greif meinte am 30. Juli 2011, 20:51 dazu:

ist die Funktion can_set_filter aus der Datei at90can_set_dyn_filter.c ?

Ja, genau. Sie wird nur beim compilieren über den Preprozessor umbenannt.

# Stefan meinte am 1. August 2011, 13:52 dazu:

Hallo Fabian, Hallo Gemeinde,

Ich möchte mich hiermit zunächst in die Reihe der Danksagungen einreihen! Ohne die Bibliothek wäre mein Projekt wohl zum Scheitern verurteilt. Trotzdem habe ich als MCU-Anfänger einige Probleme.

Frage: Ich möchte meinen AT90CAN auf einen Remote-Request-Frame antworten lassen. Dabei soll, nach Theorie, der Empfänger der empfangenen CAN-Botschaft mit gesetzten RTR-Bit, nur die Daten anhängen. Mir ist erstmal generell noch etwas unklar, wie ich auf empfange Botschaften reagiere bzw. diese verarbeiten kann. Aber ich habe mir gedacht, dass ich das rtr-bit von msg auswerten müsste und damit an das rtr-Bit der can_t-Stuktur gelangen müsste.

 int main(void) {
   can_init(BITRATE_125_KBPS);
   can_filter_t filter = {
         .id = 0x555,   //erwatet Frame mit ID:0x555?!
         .mask = 0,     //Maskierung "egal" 
         .flags = {     
         .rtr = 1,              
         .extended = 0  }       
        };
   can_set_filter(0, &filter);

   while (1) {
       if (can_check_message()) {
          can_t msg2;
          can_get_message(&msg2);   
          if (msg2.flags.rtr == 1){
            msg2.data[0] = 0xde;
            msg2.data[1] = 0xad;
            can_send_message(&msg2);
   }
  } 
 }
}

Ist natürlich aber irgendwie falsch. Ich versende über einen PCAN-Tester die Remote-Frames, aber die MCU antwortet nicht. Die Abfrage nach dem Eingangspuffer muss doch in die while-Schleife, damit die MCU ständig nach neuen Daten prüft!? Oder es ist mal wieder irgendwo ein typischer Anfängerfehler vorhanden?

Danke und VG

# Fabian Greif meinte am 2. August 2011, 11:02 dazu:

Hallo Stefan,

du musst dir die Beschreibung zu can_filter_t anschauen. Der Wert filter.rtr = 1 ist ungültig. Wenn du nur RTR-Frames empfangen willst dann muss dort eine 3 stehen.

Wenn du dann später Daten an die Nachricht anhängen willst musst du aber auch das RTR-Bit zurücksetzen, ansonsten werden die Daten nicht mitgeschickt!

Die Abfrage nach dem Eingangspuffer muss doch in die while-Schleife, damit die MCU ständig nach neuen Daten prüft!?

Ja, genau.

Ansonsten versuch doch erstmal Nachrichten ohne RTR-Flag zu verschicken und zu empfangen.

Grüße Fabian

PS: Wenn du mask auf Null setzt dann ist es egal was du in id hineinschreibst.

# Klaus meinte am 6. August 2011, 21:19 dazu:

Habe die Bibliothek nun mit Hardware-SPI auf dem ATtiny44 laufen. Das Posting von SP zu diesem Baustein ist irreführend, da er MOSI und MISO vertauscht hat. Dies kommt durch eine Besonderheit des ATtiny44-Bausteins: Data out ist immer Data out, egal ob man ihn als Master oder als Slave konfiguriert, weshalb das MISO-Pin nur für Slave-Betrieb MISO ist, im Master-Betrieb jedoch Data Out. Man muss das Datenblatt aber schon etwas genauer anschauen, um das zu finden. Den Patch habe ich Dir bereits per Email geschickt.

# Johannes meinte am 21. August 2011, 17:59 dazu:

Hallo, habe da ein Problem. Ich habe die Lib erstellt und in AVR Studio eingefügt. Das Problem ist aber sobald ich die Funktion can_get_message; im Code einfüge bekomme ich einen Fehler beim builden.

…\can-lib\src/mcp2515_read_id.c:70: undefined reference to `spi_start’

…\can-lib\src/mcp2515_read_id.c:74: undefined reference to `spi_wait’

Habe mal gelesen, dass man die neueste WIN AVR Version verwenden soll aber das hat auch nicht geholfen.

Problem scheint irgendwie zu sein, dass der spi.h nicht zur Bibliothek hinzugefügt hat.

Kann mir jemand helfen?

Ps: Ich verwende zwei identische Boards mit einem ATMega32 und einem MCP2515 Controller aber der Fehler tritt ja schon beim Übersetzen auf.

Gruss

# Fabian Greif meinte am 25. August 2011, 14:23 dazu:

Hallo Johannes,

versuch mal in der Datei spi.h die Zeile

extern __attribute__ ((gnu_inline)) inline void spi_start(uint8_t data)

durch

static inline void spi_start(uint8_t data)

zu ersetzen. Gleiches bei spi_wait().

Wenn das noch nichts hilft, dann schreib mir am besten nochmal eine E-Mail.

Grüße Fabian

# Flins meinte am 22. September 2011, 19:24 dazu:

Hallo Fabian! Vielen Dank schonmal für deine Bibliothek, auch wenn ich sie noch nicht zum laufen gebracht habe. Bei meinen Platinen (Mega16, MCP2515) hänge ich beim initialisieren. Init etc. läuft, aber bei mcp2515_static_filter bleibt er hängen. Er wartet in der Funktion auf das Bit OPMOD2, welches aber nie gesetzt wird. Dazu sagen müsste ich wohl, dass ich deine Bibliothek erst zusamen mit meinem Code kompiliere. Sind dir irgendwelche Stolpersteine bekannt? Ich sitze seit Tagen über diesem Fehler. Ein Auslesen der Register liefert plausible Ergebnisse zurück, SPI scheint also zu funktionieren. Wäre Nett wenn du mir helfen könntest.

MfG, Flins

# Dennis meinte am 25. September 2011, 17:41 dazu:

Vielen Dank für die Lib. Leider bekomme ich sie nicht zum laufen. Ich habe deine Demo um ein par UART Debug prints erweitert, und festgestellt das er gar nichts Empfängt. Das ganze läuft aus deinen Testboards mit ATMEGA644.

Gibt es fertigen Code mit UART Kommandos der Garantiert funktioniert, damit ich Hardwarefehler ausschließen kann? Oder kann ich irgendwie per Uart die Kommunikation zwischen AVR und MCP debuggen? ich habe kein gescheites Oszi, somit kann ich die Signale nicht beobachten.

Danke

# Fabian Greif meinte am 5. Oktober 2011, 23:17 dazu:

Gibt es fertigen Code mit UART Kommandos der Garantiert funktioniert, damit ich Hardwarefehler ausschließen kann?

Ich habe gerade nichts fertiges da was nur das enthält. Der Demo-Code funktioniert aber so wie er ist. Eine Kommunikation per UART sollte ihn nicht “kaputt” machen können.

Oder kann ich irgendwie per Uart die Kommunikation zwischen AVR und MCP debuggen?

Du kannst entsprechende Ausgaben einbauen. Schau dir vor allem mal die Fehlerregister an (siehe can_read_error_register). Eventuell stimmt was mit der Bus-Anbindung nicht.

Grüße Fabian

# Sebastian meinte am 29. November 2011, 12:09 dazu:

Hallo Fabian,

wir würden deine Bibliothek gerne für einen ATxmega128A1 nutzen, da dies Teil unseres Projektseminars ist. Kannst du uns sagen welche Anpassungen wir vornehmen müssen um deinen Code übernehmen zu können? Eine Library konnten wir mit WINAVR leider nicht erstellen da wir immer die Fehlermeldung erhalten, dass die MCU nicht nicht untertützt wird.

Wir nutzen die aktuellste Version von WINAVR (2010). Den passenden MCU identifier haben wir auch schon eingetragen (MCU = atxmega128a1).

Hast du eine Idee was wir vergessen haben?

Viele Grüße, Thorsten und Sebastian

# Fabian Greif meinte am 29. November 2011, 12:41 dazu:

Hi,

Eine Library konnten wir mit WINAVR leider nicht erstellen da wir immer die Fehlermeldung erhalten, dass die MCU nicht nicht untertützt wird.

Ihr müsstest die passenden Definitionen in mcp2515_private.h eintragen (siehe Zeile 58-85). Wenn ich das richtig in Erinnerung habe müssen auch die IO Pins bei den xmegas anders angesprochen werden, dafür müsstest ihr die Makros in utils.h (Zeile 222-253) ändern.

Bleibt noch die SPI Schnittstelle, die muss noch in spi.c angepasst werden. Der Rest müsste dann soweit ohne Änderungen passen.

Ansonsten, wenn ihr vor C++ keine Angst habt: http://xpcc.sourceforge.net/api/classxpcc_1_1_mcp2515.html

Das ist quasi der Nachfolger dieser Bibliothek und lässt sich für die xmegas compilieren und wurde auch schon damit getestet. Allerdings würde es vermutlich eine größere Umstellung bei euch bedeuten.

Grüße Fabian

# Chris meinte am 6. Dezember 2011, 12:02 dazu:

Hi, hatte auch Probleme die Library bei mir zum laufen zu bekommen (can_init blockiert). Bei mir lag es daran, dass ich nicht den SS-Pin für slave select benutzt habe. Dann kann es passieren, dass sich der Atmel in den slave-mode verabschiedet. Lösung ist entweder den SS-Pin als Output zu konfigurieren oder die Pull-ups zu aktivieren. (Siehe Datasheet SPI -> SS Pin Functionality)

# Rick meinte am 22. Dezember 2011, 14:39 dazu:

Sorry for posting in english… Can this library be used on the atmega32C1 processor? It’s a smaller and more simple MCU with CANBus from Atmel instead of the AT90CAN series

# Fabian Greif meinte am 22. Dezember 2011, 16:42 dazu:

Can this library be used on the atmega32C1 processor?

Basically yes, but not without changes. At a first glance the registers for the AT90CAN and the ATmega32C1 look very similar. So it should be easy the perform the necessary changes (e.g. only 6 MObs instead of 15, a few defines etc.).

Best regards,
Fabian

# Sebastian meinte am 28. Dezember 2011, 13:46 dazu:

Hallo, ich benutze das AVRStudio da ich den ATMega8515 einsetze. Können sie mir einen Tip geben, wie ich die Library dort kompiliere und einbinde? Danke!

# Fabian Greif meinte am 28. Dezember 2011, 15:41 dazu:

Hallo, ich benutze das AVRStudio da ich den ATMega8515 einsetze. Können sie mir einen Tip geben, wie ich die Library dort kompiliere und einbinde?

Nein, vom AVR Studio habe ich leider gar keine Ahnung. Ich entwickle sämtliche Software mit Hilfe von Eclipse und Make/SCons.

Das compilieren der Bibliothek kann ja auch außerhalb von AVR Studio passieren da es ja pro Projekt nur einmal erfolgen muss. Zum Einbinden der Bibliothek sollte dann bei “Linkereinstellungen” oder so ähnlich im AVR Studio möglich sein.

Grüße Fabian

# Sebastian meinte am 29. Dezember 2011, 11:15 dazu:

Hallo Fabian, habe jetzt die Lib erfolgreich kompiliert und eingebunden. Ich kann auch 3 Nachrichten senden (Normal oder Loopback-Mode) aber dann bleibt das Programm hängen. Es scheint beim lesen/schreiben der Registern nicht weiter zu kommen. Werde morgen das ganze mal mit einem Mega8 aufbauen, da kann ich debuggen. Hast du eine Idee, woran das liegen könnte? Muss ich für SPI noch irgendetwas zusätzlich definieren?

Danke schon mal!

# Fabian Greif meinte am 29. Dezember 2011, 14:20 dazu:

Ich kann auch 3 Nachrichten senden (Normal oder Loopback-Mode) aber dann bleibt das Programm hängen.

Dann sind vermutlich danach die drei Sendepuffer voll. Was hängt denn außer dem MCP2515 noch an deinem CAN Bus? Du brauchst immer einen zweiten Teilnehmer, ansonsten bekommt der MCP2515 kein Acknowledge vom Bus und schaltet sich in den Bus-Off-Modus.
Wenn du die Fehlerzähler ausließt solltest du das dort direkt erkennen können.

Grüße Fabian

# Sebastian meinte am 29. Dezember 2011, 19:29 dazu:

Hallo Fabian,

ich habe noch einen zweiten Teilnehmer am Bus hängen, der das Acknowledge sendet. Außerdem müsste es im Loopback-mode doch sowieso zweiten Teilnehmer funktionieren.

Mein Code sieht folgendermaßen aus:

 int main(void)
 {
    uart_init();
    uart_puts("-------------------------------------------\n\r");

    // initialisieren des MCP2515
    can_init(BITRATE_125_KBPS);
    can_set_mode(LOOPBACK_MODE);

    // erzeuge eine Testnachricht
    can_t msg_out;
    can_t msg_in;

    msg_out.id = 0x532;
    msg_out.flags.rtr = 0;

    msg_out.length = 4;
    msg_out.data[0] = 0xde;
    msg_out.data[1] = 0xad;
    msg_out.data[2] = 0xbe;
    msg_out.data[3] = 0xef;

    can_error_register_t error_reg;

    uint8_t i;

    char bla[40];

    while (1)
    {
        uart_puts("register ... ");
        error_reg = can_read_error_register();
        uart_puts("done!");

        sprintf(bla, "TX: %X ", error_reg.tx);
        uart_puts(bla);
        sprintf(bla, "RX: %X ", error_reg.rx);
        uart_puts(bla);


        // Nachricht verschicken
        uart_puts("send ... ");
        can_send_message(&msg_out);
        uart_puts("done!\n\r");

        //Nachricht ausgeben
        if (can_check_message())
        {
            uart_puts("Message recieved!\n\r");
            can_get_message(&msg_in);

            sprintf(bla, "ID:  %X - ", msg_in.id);
            uart_puts(bla);
            sprintf(bla, "Len: %X \n\r", msg_in.length);
            uart_puts(bla);

            for (i=0; i < msg_in.length; i++)
            {
                sprintf(bla, "Data[%i]: 0x%x \n\r", i, msg_in.data[i]);
                uart_puts(bla);
            }

        }
        else uart_puts("No Message recieved\n\r");

        _delay_ms(200);
    }
  }

Folgende Ausgabe bekomme ich:

-------------------------------------------
register ... done!TX: 0 RX: 0 send ... done!
Message recieved!
ID:  532 - Len: 4
Data[0]: 0xde
Data[1]: 0xad
Data[2]: 0xbe
Data[3]: 0xef
register ... done!TX: 0 RX: 0 send ... done!
Message recieved!
ID:  532 - Len: 4
Data[0]: 0xde
Data[1]: 0xad
Data[2]: 0xbe
Data[3]: 0xef
register ... done!TX: 0 RX: 0 send ... done!
Message recieved!
ID:  532 - Len: 4
Data[0]: 0xde
Data[1]: 0xad
Data[2]: 0xbe
Data[3]: 0xef
register ...

Mir kommt das alles gerade etwas spanisch vor. Hast du vielleicht noch einen Tip für mich?

# Sebastian meinte am 30. Dezember 2011, 16:46 dazu:

Hallo Fabian,

ich habe gefunden, woran es lag. Ich muss nur den PIN SS als Output definieren, bevor das SPI initialisiert wird. Sonst läuft dies nämlich im Slave-Modus und bleibt dann hängen. Warum ich trotzdem mehr als drei Nachrichten senden konnte bleibt mir aber ein Rätsel! Trotzdem danke für deine Mühe!

# Schorsch meinte am 5. Januar 2012, 17:19 dazu:

Hallo Fabian, mit Hilfe der Erklärungen aus der Doku zum MCP2515 habe ich eine Schaltung mit 2 Stk MCP2515 an einem ATMega32 aufgebaut und auch realisiert. Um die Leistungsfähigkeit beim Datendurchsatz etwas zusteigern würde ich gerne an einem AT90CAN den MCP2515 betreiben und natürlich auch beide am CAN. Kann ich daür die Lip nutzen oder geht das zusammen nicht. Da ich das AVR Studio nutze komme ich mit der Einbindung der Lip nicht weiter. Kann man die Funktionen auch ohne Lip direkt einbinden sofern man genug Flaskspeicher hat !!!! Danke.

# Fabian Greif meinte am 5. Januar 2012, 17:55 dazu:

Hallo Schorsch,

Grundsätzlich geht das, aber im Moment besteht das Problem das #defines für den MCP2515 und den AT90CAN gleich benannt sind. Die entsprechenden Defines müsstest du umbenennen, dann sollte das klappen.

Kann man die Funktionen auch ohne Lip direkt einbinden sofern man genug Flaskspeicher hat

Natürlich kann man das auch. Es sind aber vermutlich einige kleinere Anpassungen nötig.

Grüße Fabian

# Marcel meinte am 18. Januar 2012, 23:21 dazu:

Hallo Fabian,

ich habe gerade meine erste µC-Schaltung(ATMega88) mit einem MCP2515 gebastelt und würde sehr gerne deinen CAN-Treiber ausprobieren wollen. Ich benutze aber, wie Schorsch, auch AVRStudio und würde die benötigten Files dann auch direkt einbinden.

Ist das sehr viel, was man da abändern müßte? Und WAS genau müsste man denn ändern? Spricht eigentlich etwas dagegen, dass ich die einzelnen Files dazu gleich ‘zusammenfasse’?

Liebe Grüße

# Fabian Greif meinte am 19. Januar 2012, 13:01 dazu:

Ist das sehr viel, was man da abändern müßte? Und WAS genau müsste man denn ändern?

Das müsste man ausprobieren. Wenn du alles in den gleichen Ordner wie deine Anwendung schmeißt (was ich nicht empfehlen würde) dann könnte es so direkt funktionieren. Ansonsten musst du vermutlich Pfade anpassen.

Spricht eigentlich etwas dagegen, dass ich die einzelnen Files dazu gleich ‘zusammenfasse’?

Nein. Wenn du das gerne tun möchtest kannst du das gerne tun.

Grüße Fabian

# Portisch meinte am 9. Februar 2012, 12:39 dazu:

Hallo,

ich bin auch noch recht am Anfang mit eurer Super can-lib! Und als Anfänger habe ich natürlich einige Verständnisprobleme wegen den Filtern. Ich möchte z.B. nur IDs mit 0xX00 und 0xX11 empfangen.

Ich hätte das dann so umgesetzt:

  // Group 0
  MCP2515_FILTER(0x000),  // Filter 0
  MCP2515_FILTER(0x011),  // Filter 1

  // Group 1
  MCP2515_FILTER(0x000),  // Filter 2
  MCP2515_FILTER(0x000),  // Filter 3
  MCP2515_FILTER(0x011),  // Filter 4
  MCP2515_FILTER(0x011),  // Filter 5

  MCP2515_FILTER(0x0FF),  // Mask 0 (for group 0)
  MCP2515_FILTER(0x0FF),  // Mask 1 (for group 1)

Was ich nicht verstehe ist Group 0/1!? Was bedeuten sie? Wenn ich jetzt z.B. 4 IDs filtern will geht das dann so?

  // Group 0
  MCP2515_FILTER(0),  // Filter 0
  MCP2515_FILTER(0),  // Filter 1

  // Group 1
  MCP2515_FILTER(0x000),  // Filter 2
  MCP2515_FILTER(0x011),  // Filter 3
  MCP2515_FILTER(0x022),  // Filter 4
  MCP2515_FILTER(0x033),  // Filter 5

  MCP2515_FILTER(0),  // Mask 0 (for group 0)
  MCP2515_FILTER(0x0FF),  // Mask 1 (for group 1)

Oder gilt Group 0 für den Receive Buffer 0 und Group 1 für Receive Buffer 1? Und warum hat Group 1 vier Filter und Gourp 0 nur zwei?

Danke!

# Fabian Greif meinte am 9. Februar 2012, 16:17 dazu:

Hallo Hugo,

Ich möchte z.B. nur IDs mit 0xX00 und 0xX11 empfangen. Ich hätte das dann so umgesetzt: (…)

das ist genau richtig so.

Was ich nicht verstehe ist Group 0/1!? Was bedeuten sie?

Es gibt mehrere Filter die die gleiche Maske benutzen. Ich habe einfach mal alle Filter mit gleicher Maske zu Gruppen zusammengefasst, nämlich Group 0 und Group 1. Diese Gruppen entsprechenden dann auch in beiden Empfangspuffern. Das steckt dahinter.

(…) Wenn ich jetzt z.B. 4 IDs filtern will geht das dann so?

Jein. Der zweite Empfangspuffern (Group 1) macht genau das was du willst, allerdings empfängt du mit dem ersten Puffer alle Nachrichten (da Mask = 0).

Und warum hat Group 1 vier Filter und Gourp 0 nur zwei?

Das musst du Microchip fragen. Keine Ahnung warum sie es so gelegt haben.

Grüße Fabian

# Marcel meinte am 15. Februar 2012, 12:18 dazu:

Hallo Fabian,

ich arbeite mit AVR_Studio und habe es endlich geschafft, die Lib in mein Projekt einzubinden (zumindest scheinbar, da alle Fehlermeldungen verschwunden sind?^^). Ich habe aber große Probleme, eine einfache Kommunikation zwischen zwei Teilnehmern aufzubauen.

Meine Konfiguration:

  • zwei CAN-Nodes, basierend auf MCP2515 und ATMega88p (ein Node mit einem Taster als Signalquelle; der andere Node mit PWM-gesteuerter HighPowerLED als Aktor)
  • Quarz der µC hat 20MHz
  • Takt für den MCP2515 wird jeweils über den CLKOUT-Pin PB0 (mit 1:1 Verhältnis) am µC hergestellt (FUSE CKOUT am µC wurde aktiviert)
  • CAN_BUS-Testlänge ist 15cm
  • INT-Ausgang der µC wurde in der config.h von INT1 auf INT0 abgeändert(da die HardwarePWM von INT1/PD3 benötigt wird)

Programm:

prog_uint8_t can_filter[] = 
{
// Group 0
MCP2515_FILTER(0),          // Filter 0
MCP2515_FILTER(0),          // Filter 1

// Group 1
MCP2515_FILTER_EXTENDED(0),     // Filter 2
MCP2515_FILTER_EXTENDED(0),     // Filter 3
MCP2515_FILTER_EXTENDED(0),     // Filter 4
MCP2515_FILTER_EXTENDED(0),     // Filter 5

MCP2515_FILTER(0),          // Mask 0 (for group 0)
MCP2515_FILTER_EXTENDED(0),     // Mask 1 (for group 1)
};

...

int main (void)
{
// initialisieren des MCP2515
can_init(BITRATE_125_KBPS);
sei();

// Load filters and masks
can_static_filter(can_filter);

// Create a test messsage
can_t msg;

msg.id = 0x123456;
msg.flags.rtr = 0;
msg.flags.extended = 1;

msg.length = 4;
msg.data[0] = 0xde;
msg.data[1] = 0xad;
msg.data[2] = 0xbe;
msg.data[3] = 0xef;

// Send the message
can_send_message(&msg);
}

# Marcel meinte am 15. Februar 2012, 12:27 dazu:

Der Rest hatte leider nicht mehr reingepasst:

Die While…

while(1)
{
// Check if a new messag was received
if (can_check_message())
{
can_t msg;

// Try to read the message
if (can_get_message(&msg))
{
// If we received a message resend it with a different id
OCR1A = 100;
}
}

"wenn Button gedrückt"(die Formatierung lässt leider keinen
   Shift-Operator zu und schneidet immer den Text ab, 
   desshalb auf diese Weise^^)
{
can_t msg;

msg.id = 0x123456;
msg.flags.rtr = 0;
msg.flags.extended = 1;

msg.length = 4;
msg.data[0] = 0xde;
msg.data[1] = 0xad;
msg.data[2] = 0xbe;
msg.data[3] = 0xef;

// Send the message
can_send_message(&msg);
}
}

WAS mache ich denn nur falsch? Etwas vergessen?

Liebe Grüße

# Frank meinte am 24. Februar 2012, 15:54 dazu:

Hallo Fabian,

die Lib ist Klasse. Senden oder Empfangen geht soweit super. Habe nur ein Problem auf einem AT90Can: Ich möchte 6 Nachrichten senden und 1 Nachricht empfangen. Entweder senden oder empfangen geht super. Nur wenn ich mit

can_set_filter(0, &filter);

Mob0 zum Empfangen konfiguriere wird nichts mehr gesendet. Senden versuche ich so:

msg.id = 0x1A0; msg.flags.rtr = 0; msg.length = 8; can_send_message;

Ich bin echt ratlos !?

Gruss Frank

# Frank meinte am 25. Februar 2012, 16:39 dazu:

Hallo,

habe ein wenig rumprobiert: Es geht alles einwandfrei, wenn ich die RX-Objekte nacht den TX-Objekten palziere. Also in meinem Fall 0..5 TX-Nachrichten und mit:

can_set_filter(6, &filter);

das 6te Objet zum empfangen nehme. Habe ich da was übersehen ? Ich finde irgendwie nicht den Grund dafür …

Gruss Frank

# Marcel meinte am 25. Februar 2012, 21:59 dazu:

Hallo Fabian,

das Problem von letztens hat sich erledigt, war ein Hardware-Fehler. Die Lib funktioniert einwandfrei! DANKE!;-)

Eine Frage hab’ ich aber noch: Kann es sein, dass (ATMega88) TIMSK1 u.2 durch CAN/SPI belegt sind, da nach deren Aktivierung/Initialisierung nichts mehr funktioniert?

Liebe Grüße,

Marcel

# Steffen meinte am 26. Februar 2012, 22:06 dazu:

Hallo,

ich spiele seit kurzem mit einem AT90CAn128 herum, geneuer gesagt mit dem CAN-Controller usw. Ich habe dazu einmal die Lib in Betrieb genommen. Das funktionierte eigentlich auch grundsätzlich auf anhieb.

Senden geht wunderbar, am laufenden Band in einer Schleife ohne Probleme. Das Empfangen funktioniert aber nicht 100%ig. Generell kann der Controller empfangen und sendet eben die empfangene CAN Message auch zur Kontrolle wieder an den PC zurück, aber irgendwo steckt noch der Wurm drin.

Im Codeausschnitt unten sieht man in der while-Schleife ein Delay von xy ms. Wenn dies drin ist, wird jede empfangene Message beantwortet. Aufgrund des Delays können die Nachrichten natürlich nicht unendlich schnell empfangen werden. Wenn zu schnell an den 90Can gesendet wird, fallen einige empfangene Nachrichten unter den Tisch und es wird eben nur auf jede X-te geantwortet. Wenn ich die Schleife ohne Delay laufen lasse, werden gar keine Nachrichten empfangen. Ich kann dann so viele Nachrichten an den Controller senden wie ich will, es kommt keine an.

Ich habe im Moment in der while-Schleife noch Tasterabfragen und ein paar weitere kleine Dinge, aber egal, ob nur die CAN Geschichte in der While-Schleife steht oder auch die anderen Sachen. Ohne das Delay werden keine Nachrichten empfangen. Mit dem Dealy geht es dann, aber eben recht langsam. Die

CAN-Nachrichten, die empfangen werden sollen, brauchen eben einen entsprechenden Abstand, um empfangen zu werden.

Allgemein, wenn dann mal eine Message empfangen wird, wird sie auch ordnungsgemäß zurück an den PC gesendet.

Ich habe schon versucht CAN_RX_BUFFER_SIZE zu nutzen, aber das ändert an der ganzen Sache nix. Scheinbar ist auch die Bitrate egal. Habe es von 125K bis 1M probiert, immer das Gleiche.

Gibt es da irgendwo noch eine Schraube in der Lib, an der man da drehen kann?

Beste Grüße Steffen

` int main { cli; initPorts; initInterupt;

can_init(BITRATE_125_KBPS);         
can_filter_t filter = {
        .id = 0,
        .mask = 0,
        .flags = {
                .rtr = 0
             }
              };

    for (uint8_t i = 0; i < 7; i++) 
{
    can_set_filter(i, &filter);
}

can_set_mode(NORMAL_MODE);
    sei();                              
msg.id= 0x1234567;                  
msg.flags.rtr= 0;
msg.flags.extended= 1;              
msg.length= 4;                      
msg.data[0]= 0x89;                  
msg.data[1]= 0xAB;
msg.data[2]= 0xCD;
msg.data[3]= 0xEF;
can_send_message(&msg);             

while(1)
    {

    _delay_ms(13);
    if(can_check_message())
    {
        can_t msg;

        if(can_get_message(&msg))
        {
        msg.id += 10;  
        can_send_message(&msg);

        }
    }


}

}`

# Sven meinte am 1. März 2012, 13:59 dazu:

Hallo,

ich habe eine Frage zum Auslesen der Fehlerregister. Wenn ich das richtig verstanden habe, werden die Fehlerregister mit der Funktion can_read_error_register; ausgelesen. In diesen Registern werden die Sende und Empfangsfehler gezählt, wenn ich das so richtig aus dem Datenblatt des AT90CAN128 verstanden habe.

Bei CAN ist es ja nun so, dass bei einer bestimmten Fehlerzahl bestimmte Fehlerzustände des Controllers eingenommen werden; Error active (default);Error passive;Bus off; Wenn der Controller in den Bus off Modus geht, kann es einen Interrupt geben, wenn man es entsprechend einschaltet. Weiter kann man ja Interrupts einschalten, die kommen, wenn ein Fehler entdeckt wurde..siehe Datenblatt Seite 248 -> Interrupt on error (bit error, stuff error, CRC error, form error, acknowledge error).

Meine Frage wäre nun, ob Fehler z.B. beim senden direkt erkannt und ausgewertet werden oder ist es mit der Lib einfach nur möglich die Fehlerregisterstände auszulesen? Die Idee wäre eben fehler durch eine LED nach außen zu signalisieren und im weiteren eventuell weitere Maßnahmen nach einem Fehler einzuleiten.

Bei der Fehlerbehandlung blicke ich halt noch nicht so ganz durch. Beste Grüße Sven

# Fabian Greif meinte am 1. März 2012, 14:18 dazu:

Meine Frage wäre nun, ob Fehler z.B. beim senden direkt erkannt und ausgewertet werden

Nein, die Fehler werden nicht automatisch behandelt. Das müsstest du selbst tun.

Grüße Fabian

# yankee meinte am 10. März 2012, 02:21 dazu:

Ich würde die lib gerne auf einem ATtiny2313 zum laufen bringen. Dafür habe ich diese (noch 100% ungetestete) Definition erstellt:

#elif defined(__AVR_ATtiny2313__)
    #define P_MOSI  B,17
    #define P_MISO  B,18
    #define P_SCK   B,19
    #define USE_SOFTWARE_SPI        1
    #define SUPPORT_FOR_MCP2515__

Das USE_SOFTWARE_SPI flag hat so erstmal nicht funktioniert und nach etwas Recherche ist mir dann aufgefallen, dass in der mcp2515_private.h die spi.h included wird BEVOR die oben genannten define’s dran sind, dabei werden die defines in der spi.h bereits benötigt. Das include zu verschieben hat erstmal geholfen.

# yankee meinte am 10. März 2012, 03:03 dazu:

Ist die Information “Die Bibliothek braucht ca. 1500 Byte Flash mit allen Funktionen. Verwendet man keine dynamischen Filter sind es 370 Byte weniger.” noch aktuell? Mein kleines Testprogramm hat ohne dynamische Filter hat ca. 4000 Bytes was bei 2kb Speicher auf dem ATtiny2313 garnicht mal so gut ist…

# yankee meinte am 11. März 2012, 05:41 dazu:

Mittlerweile bin ich mit meinem ATtiny2313 weitergekommen. Hier ist meine getestete, funktionierende Konfiguration:

    #elif defined(__AVR_ATtiny2313__)
            #define P_MOSI  B,5
            #define P_MISO  B,6
            #define P_SCK   B,7
            #define USE_SOFTWARE_SPI                1
            #define SUPPORT_FOR_MCP2515__

Da es Software-SPI ist dürften aber auch weitere Kombinationen möglich sein. Mit diesen PINs müsste es theoretisch auch über den USP-Treiber vom ATtiny laufen. Die Mühe habe ich mir allerdings nicht gemacht…

Außerdem ist mir aufgefallen, dass die mcp2515_regdump.c wegen printf’s verdammt groß ist. Nachdem ich die Datei rausgeworfen habe, war mein Programm plötzlich weniger als halb so groß und passt jetzt auch in den 2kb flash von meinem ATtiny 2313.

# Sven meinte am 17. März 2012, 12:03 dazu:

Hallo,

ich habe ein Problem mit der Einstellung

define SUPPORT_EXTENDED_CANID 1

Steht das eben auf 1 ist alles OK, wenn ich das nicht definiere oder auf Null setze, bekomme ich eine fehlermeldung:

'_messages_waiting' undeclared (first use in this function'

Das ist dann in der Datei:

at90can_get_message.c

Zeile 83.

_messages_waiting--;

Woran könnte das liegen? Beste Grüße

Sven

# Christoph meinte am 17. April 2012, 19:03 dazu:

Ich habe diese Libary gerade probiert, leider habe ich ein Problem. Ich habe ein Knoten der nur sendet und einen der nur empfängt. Das Problem ist das nach dem ersten mal senden, die gleiche Nachricht die ganze Zeit wiederholt wird. Auch wenn der AVR (hier ATmega8), programmiert wird bzw. resetet wird. Erst wenn man den MCP2515 stromlos macht und wieder bestromt wird nichts mehr gesendet. Aber nach dem ersten anstoßen vom Senden seitens des AVR’s fängt es wieder an. Kann es eventuell an den 3 RTS pins am MCP2515 liegen, die habe ich in der schaltung offen gelassen?

# Fabian Greif meinte am 17. April 2012, 23:10 dazu:

Hallo Christoph, ich vermute das dein zweiter Knoten kein korrektes Acknowledge sendet. Überprüf mal die Leitungen vom und zum CAN Transceiver. Was auch gerne zu seltsamen Fehlern führt, ist wenn man den Reset offen lässt.

Grüße Fabian

# Christoph meinte am 18. April 2012, 00:28 dazu:

Hallo Fabian, danke für die Antwort. Leitungen habe ich mit Durchgangsmesser überprüft, sind ok. Reset vom MCP2515 liegt fix auf +5V. Vref vom MCP2551 ist offen und RS liegt auf GND. Ich habe statt 120 Ohm Abschlusswiderstände 100 Ohm verwendet, das kann es aber wohl auch nicht sein. Sollte der CAN Trasceiver nicht automatisch abschalten wenn er merkt das dauernd Fehler auftreten? Weiters kommt die Nachricht mit dem exakten Inhalt am Empfänger an. Als Workaround versetzte ich derzeit den Sendenode in den LISTEN_ONLY_MODE nachdem ich eine CAN Nachricht sende. Und vorm Nachrichtensenden entsprechend in den NORMAL_MODE. So geht es, ist aber dirty :-( Kann ich auf noch etwas prüfen?

# Fabian Greif meinte am 18. April 2012, 13:11 dazu:

Sollte der CAN Trasceiver nicht automatisch abschalten wenn er merkt das dauernd Fehler auftreten?

Das CAN Transceiver nicht, der ist ja nur ein Pegelwandler. Aber der CAN Controller sollte das nach einer Zeit tun. Du könntest mal die Fehlerregister auslesen und schauen ob dort etwas drinnen steht.

(…) So geht es, ist aber dirty :-(

In der Tat, das ist nicht schön. Mir ist so ein Verhalten bisher noch nicht begegnet, von daher kann ich leider nicht so viel dazu sagen. Kannst du weitere CAN Konten an das Netzwerk hängen von denen du weißt, dass sie sicher funktionieren?

Grüße Fabian

# Christoph meinte am 19. April 2012, 00:10 dazu:

Hi, habe leider keinen anderen funktionierenden CAN Knoten. Sind die ersten zwei pcb’s die ich gefertigt habe :-) Also beim sendenden Knoten habe ich das Fehlerregister ausgelesen, im can_error_register_t.tx ist das MSB gesetzt. Leider weiß ich net wo ich schauen kann was das heißt, im Datenblatt hab ich net genau gefunden welches register das sein kann.

# Fabian Greif meinte am 19. April 2012, 02:36 dazu:

im can_error_register_t.tx ist das MSB gesetzt. Leider weiß ich net wo ich schauen kann was das heißt, im Datenblatt hab ich net genau gefunden welches register das sein kann.

Das ist TEC Register. MSB gesetzt = 128 hieße der Controller ist im Error-passive Mode (siehe Seite 45 im Datenblatt). Das bedeutet irgendwas klappt bei deiner Kommunikation nicht. Das erklärt auch die sich wiederholenden Nachrichten, die werden nämlich so lange versendet bis sie von mindestens einem Empfänger fehlerfrei empfangen wurden.

Grüße Fabian

# Christoph meinte am 19. April 2012, 18:51 dazu:

Vielen Dank! Hab das Problem dank deiner Hilfe finden können, der EmpfangsKnoten war im LISTEN_ONLY_MODE (Sollte ja nur empfangen), daher sendet er wohl kein ACK und es waren ja keine anderen Teilnehmer am Bus :-) Zum Fehlerregister, anscheind ist ja der Fehlercounter nur bis 128 hochgezählt worden, kanns sein das er ab da nur weiter zählt wenn Fehler Frames von anderen Knoten kommen (was in diesem Fall ja nicht möglich war?)

# Stefan meinte am 7. Mai 2012, 21:45 dazu:

Hallo,

ich benutze die CAN Lib mit einen AT90can128. In der heruntergeladenen CAN Lib habe ich folgendes geändert: makefile:

Makefile: MCU = at90can128 config.h:

define SUPPORT_EXTENDED_CANID 0

define SUPPORT_TIMESTAMPS 0

define SUPPORT_AT90CAN 1

define CAN_FORCE_TX_ORDER 0

define CAN_TX_BUFFER_SIZE 20

define CAN_RX_BUFFER_SIZE 20

Fehler bei bauen der Lib: at90can_send_message.c: In function ‘at90can_send_message’: at90can_send_message.c:114: error: ‘_transmission_in_progress’ undeclared (first use in this function) at90can_send_message.c:114: error: (Each undeclared identifier is reported only once at90can_send_message.c:114: error: for each function it appears in.) make: *** [build/at90can_send_message.o] Error 1

Was mache ich falsch? Kann mir jemand helfen?

Gruß Stefan

# Jay meinte am 11. Juni 2012, 15:54 dazu:

hallo zusammen.

ich hoffe ihr könnt mir helfen. Ich habe einen AT90can128 und will ein CAN-Bus Kommunikation aufbauen. das senden klappt ohne Problem mit der Bibliothek, aber bei empfangen habe ich Probleme. Obwohl auf dem Bus viel Nachrichten liegen, gibt die Funktion Can_check_massage mir ein false aus.

Alex hatte weiter oben im Verlauf ein ähnliches Problem. Konnte aber trotz den Beispielen keine Nachricht empfangen. Hat einer vllt eine Idee waren es liegen kann? würde mich sehr über Antworten freuen

danke im Voraus

# Bernhard meinte am 20. Juli 2012, 09:25 dazu:

Hallo Jay,

ich kenn mich mit der Lib nicht so gut aus aber vielleicht hilfts ja….

  1. Ist das GlobalInterruptflag gesetzt (sei();)?
  2. Hast Du einen Filter gesetzt und wenn auch nur einen für alle Nachrichten? (Wenn Du keinen Filter setzt, dann ist kein Mob für den Empfang der Nachrichten eingerichtet)

Nach dem Du schreibst, das das Senden ohne Probleme funktioniert (ich vermute Du erhälst auch ein ACK von den anderne Teilnehmern) wird es wohl nicht an der Hardware liegen aber vielleicht kontrollierts Du die auch noch mal

mfg. Bernhard

# Martin meinte am 27. August 2012, 12:04 dazu:

Hallo!

Zuerst einmal Danke für die Library!

Allerdings werden über kurz oder lang einige das selbe Problem bekommen wie ich jetzt habe: in avr-libc 1.8 und avr-gcc 4.7.0 gibt es das Problem, dass standardmäßig prog_uint8_t nicht mehr definiert ist:

avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=14745600UL -Os -funsigned-char
    -funsigned-bitfields -fpack-struct -fshort-enums
    -Wall -Wstrict-prototypes -Wa,-adhlns=build/mcp2515.lst-I../ -std=gnu99 -Wundef
    -MMD -MP -MF .dep/mcp2515.o.d mcp2515.c -o build/mcp2515.o
In file included from mcp2515_private.h:50:0,
             from mcp2515.c:50:
../can.h:392:1: error: unknown type name 'prog_uint8_t'
mcp2515.c:128:1: error: unknown type name 'prog_uint8_t'

Wenn man es dann mit -D__PROG_TYPES_COMPAT__=1 compiliert (um die alten typedefs zu aktivieren), so kommt folgender Fehler:

avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -D__PROG_TYPES_COMPAT__=1 -DF_CPU=14745600UL -Os 
    -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums 
    -Wall -Wstrict-prototypes -Wa,-adhlns=build/mcp2515.lst -I../ -std=gnu99 -Wundef
    -MMD -MP -MF .dep/mcp2515.o.d mcp2515.c -o build/mcp2515.o
In file included from mcp2515_private.h:50:0,
             from mcp2515.c:50:
../can.h:392:1: warning: 'prog_uint8_t' is deprecated: prog_uint8_t
    type is deprecated. [-Wdeprecated-declarations]
mcp2515.c:128:1: warning: 'prog_uint8_t' is deprecated: prog_uint8_t
    type is deprecated. [-Wdeprecated-declarations]
mcp2515.c:128:14: error: variable '_mcp2515_cnf' must be const in order
    to be put into read-only section by means of '__attribute__((progmem))'

sprich: zuerst eine liste von depreciated warnung und dann noch als nicht const definiert…

Das einzige was zu “fruchten” scheint ist in config.h folgendes einzubauen:

# include < inttypes.h >
typedef const uint8_t   prog_uint8_t __attribute__((__progmem__));

(das include wird benötigt, denn sonst compilliert can_buffer.c nicht…)

Nur dann kompilliert das ganze…

Danke,Martin

P.s: wünschenswerte Erweiterungen wäre auch noch:

  • bei aufrufen RESET ( MCP2515_CS ) zusätzlichen code ausführen (ansprechen eines de-multiplexer)

  • ONE-shot-modus aktivieren

# Hermann meinte am 29. August 2012, 09:51 dazu:

Hallo, gleiches Problem hatte ich auch. Für mich brachte folgenden Änderung Abhilfe (Orginal oben, abgeänderte Zeile unten):

in der can.h

//can_static_filter(const prog_uint8_t *filter_array);

can_static_filter(const uint8_t PROGMEM *filter_array);

in der at90can.h:

//prog_char _at90can_cnf[8][3] = {

const char PROGMEM _at90can_cnf[8][3] = {

viele Grüße, Hermann

# fckw meinte am 13. September 2012, 20:45 dazu:

Ab der Version 4.7.0 des avr-gcc steht der neue Address-Space Qualifier __flash zur Verfügung. gcc.gnu.org/onlinedocs

# Faisal Alam meinte am 5. Oktober 2012, 12:32 dazu:

Hallo Fabian. Super Library erstmal. Ich möchte diese auf meinen AtMega328 anwenden und habe deshalb in der config.h CS auf den Pin 10 gelegt. Welche Daten muss ich noch in der Makefile anpassen?

Vielen Dank im voraus.

# Marc meinte am 9. Oktober 2012, 01:38 dazu:

Hallo, ich arbeite gerade daran, die Bibliothek auf einem Xmega256A3BU zu implementieren. Ist dies vielleicht schon jemandem gelungen? Und muss ich dazu nur mcp2515_private.h abändern, die Defines bei den IO-Pins anpassen und spi.c abändern? Oder fehlen für einen Xmega Support noch andere Anpassungen? Für eine Hilfe wäre ich sehr dankbar! Viele Grüße Marc

# Fabian Greif meinte am 9. Oktober 2012, 08:52 dazu:

Und muss ich dazu nur mcp2515_private.h abändern, die Defines bei den IO-Pins anpassen und spi.c abändern?

Ja, mehr sollte nicht nötig sein. Der Rest ist ja dann prozessorunabhängig.

Grüße Fabian

# JayB meinte am 10. November 2012, 17:39 dazu:

Guten Tag

Ich bin dabei mich mit dem CAN Bus ein wenig zu beschäftigen. Ich verwende dazu den AT90CAN128 und die CANLib dieser seite. Jedoch steh ich schon direkt am Anfang vor einem Problem mit der can_init.

can_init(BITRATE_125_KBPS);

da kommt beim erstellen der Fehler “undefined reference to ´can_init´”

kann mir da jemand helfen vielleicht ?!

# Alexander meinte am 11. November 2012, 17:33 dazu:

Hallo Fabian, versuche gerade Deine Library auf dem Atmel Studio 6 zu übersetzten. Dafür habe ich diesen typedef gesetzt: typedef uint8_t prog_uint8_t; Ausserdem will ich einen ATmega162 an dem mcp2515 ankoppeln. Dazu habe ich folgende Zeile (mcp2515_private.h)

if defined || defined || defined || \

defined(__AVR_ATmega162__) Habe ich noch etwas vergessen? Kompilierung läuft. Test werde ich noch machen. Danke

# stefanct meinte am 14. November 2012, 07:46 dazu:

hello

is there a public repository for this library? i have uploaded the current state to github anyway: https://github.com/stefanct/avr-can-lib

# Fabian Greif meinte am 14. November 2012, 11:10 dazu:

is there a public repository for this library? i have uploaded the current state to github anyway: (…)

As there is obviously a demand I did the same thing and created a “official” github repository:

https://github.com/dergraaf/avr-can-lib

# Bill Lewis meinte am 23. November 2012, 23:22 dazu:

Hallo Fabian,

(Ich hoffe Englisch ist OK)

I believe there is a bug in mcp2515_get_message.

The MCP2515 datasheet says only certain registers can be used with Bit Modify.

As a result, this code clears the entire CANINTF register, vs. the single flag in question:

mcp2515_bit_modify(CANINTF, (1..RX0IF), 0); (.. above is the C shift chars, web post wouldn’t allow those chars)

Reading SPI_RX_STATUS register has side effect of clearing the RXnIF bit automatically. So the above call is not needed.

-Bill

# Jürgen meinte am 25. November 2012, 14:34 dazu:

Hallo, ich habe massiv Probleme beim Übersetzen der lib unter Atmel Studio 6. - Problem prog_uint8_t: den Typ kennt Studio nicht mehr. Der Tipp von fckw (“__flash”) scheitert: kennt er auch nicht. Tipp von Hermann (uint8_t PROGMEM) führt zu:

can.h:393:1: warning: ‘progmem’ attribute ignored [-Wattributes] mcp2515.c:130:17: error: variable ‘_mcp2515_cnf’ must be const in order to be put into read-only section by means of ‘attribute((progmem))’

Testweise mal PROGMEM weggelassen (was zu ner falschen lib führt, ich weiß). Dann käme als nächster Fehler:

mcp2515.c:268:1: fatal error: opening dependency file .dep/mcp2515.o.d: No such file or directory

Das alles in der Kommandozeile, die ich aus Atmel Studio aufrufen kann. Bin mit meinem Latein am Ende. Kannst du bitte weiterhelfen? Oder wenigstens ein paar Tipps? Danke, Jürgen

# Mebus meinte am 3. Dezember 2012, 15:54 dazu:

Hallo Jürgen,

probier das mal das:

https://github.com/Mebus/avr-can-lib/commit/296a48088e1a8f4a943a74ad3ca8e9bbc0df1bdf

Gruß

Mebus

# Jürgen meinte am 16. Dezember 2012, 14:25 dazu:

Hallo Mebus, kann in der github-Version keinen Unterschied zum Original feststellen. Dort wird nach wie vor “const prog_uint8_t *filter_array” definiert, und das Problem bleibt, dass prog_uint8_t in Atmel Studio 6 nicht definiert ist… siehe oben: die Workarounds der beiden anderen Kommentatoren fruchten nicht. Es muss doch möglich sein, hierfür einen Ersatz zu definieren… Ich kann zwar C, aber im Bereich der Atmel-Programmierung bin ich Anfänger. Eine Idee?

# Jürgen meinte am 16. Dezember 2012, 15:36 dazu:

Oh Mann, damit darf man wirklich keinem normal denkendem Menschen kommen:

  • der von mir drei weiter oben angesprochene .dep-Fehler kann behoben werden, wenn im Makefile alle 2>/dev/null ersatzlos rausgelöscht werden. Windows ist eben kein Linux.

  • prog_uint8_t-Fehler: wie von Martin oben beschrieben in config.h durch das typedef substituieren.

  • das von Martin angesprochene #include führt beim ersten make zu einem Fehler. Rauskommentieren, bis zum Fehler übersetzen, reinkommentieren und nochmal machen

-> libcan.a

Ganz ehrlich, man muss erst Freak sein, um sein erstes “Hallo CAN-World” hinzukriegen. Extreme Lernkurve, war recht frustrierend. Aber danke an alle hier auf dieser Seite, es ist geschafft!

# bhaskar meinte am 19. Dezember 2012, 11:42 dazu:

I a new to CAN shield, I use CAN hield from sparkfun and arduino mega 2560 , volks wagen ECU ,PCAN-TJA1054 between can shield and ecu,when I send some mesaage I am unable to get any reply from the ecu, can somebody help me in this regard…..

# JayB meinte am 2. Januar 2013, 22:52 dazu:

Guten Tag Ich hab mal da deine frage zu can_check_message, bleibt das solange True bis alle Puffer ausgelesen worden sind oder wie kann ich wenn ich mehrere eingangspuffer definiere alle Auslesen ?:

can_set_filter(0,&filter); can_set_filter;

while(1) {

_delay_ms(13);
if(can_check_message())
{
    can_t msg;

    if(can_get_message(&msg))
    {

    Test=   msg.data[0];

    }
}

Da hier ja anscheint nur ein Puffer ausgelesen wird,

Ist nur ein darstellungscode

# Toni meinte am 11. Januar 2013, 18:02 dazu:

Hi, ich habe das gleiche Problem wie Jay. Ich nutze einen MCP2515 und einen ATMega88. Nachrichten senden funktioniert, empfangen leider nicht. sei verwende ich und eine Filter setze ich auch. Wie bekommt denn der ATMega mit ob eine Nachricht im MCP2515 liegt? Läuft das über ein Interrupt? Und ja welcher Pin wird dafür genutzt?

# Fabian Greif meinte am 11. Januar 2013, 18:15 dazu:

Wie bekommt denn der ATMega mit ob eine Nachricht im MCP2515 liegt?

Er fragt den INT-Pin ab.

Läuft das über ein Interrupt?

Nein, auch wenn der Pin beim MCP2515 so heißt.

Und ja welcher Pin wird dafür genutzt?

Der der beim compilieren der Library über die Defines eingestellt wurde.

Grüße Fabian

# Fabian Greif meinte am 11. Januar 2013, 18:17 dazu:

@JayB

Ich hab mal da deine frage zu can_check_message, bleibt das solange True bis alle Puffer ausgelesen worden sind oder wie kann ich wenn ich mehrere eingangspuffer definiere alle Auslesen ?

Das bleibt TRUE bis keine Nachricht mehr in den Puffern vorhanden ist.

Da hier ja anscheint nur ein Puffer ausgelesen wird,

Ja, aber der Code steht meist in einer Schleife. Beim nächsten Durchlauf würde dann der zweite Puffer ausgelesen werden.

Grüße Fabian

# Romy meinte am 31. Januar 2013, 22:35 dazu:

Hallo Fabian, könntest du bitte mir zeigen wie ich deine lib.h benuzen könnte,um eine nachricht von arduino1 adk auf das canbus zu versenden und der andre arduino2 adk diese nachrict an andre knote bekommt?es wäre mir lieb,wenn du das programm ein bisschen kommentierst. wie muss mann auch die mask und filter implementieren?

# clemens meinte am 21. Februar 2013, 15:10 dazu:

Ich bin gerade dabei die lib auf die xmegas zu portieren. bis jetzt komme ich gut zurecht, habe aber bei folgendem makro noch keine idee: SET würde ich gerne zu PORTC.Set=MCP2515_CS konvertieren wobei PORTC als “#”define MCP2515_Xmega_CS_Port PORTC in der config.h liegt hat jemand eine idee, wie sowohl für atmega und xmega eine konvertierugn möglich ist? sonst werde ich es über ein #ifdef abfangen, wobei ich das weniger schön fände

# Bernd meinte am 25. Februar 2013, 15:24 dazu:

Hallo Fabian, erstmal danke für die lib, hat mich längere Zeit treu begleitet. Ich hatte unter XP das AVR-Studio installiert, und habe die lib mit den vorhandenen avr-tools übersetzt. Mittlerweile habe ich Windows7 und ATMEL-Studio 6. Ich habe die libs (*.o) weiterverwendet und in die Programme eingebunden, funktionierte alles. Aber nun mußte ich eine lib neu übersetzen, weil der MCP2515 anders am ATMega88 angeschlossen ist. Die Übersetzung funktioniert aber nicht mehr unter W7/AtmelStudio. Gibt es dazu schon Hinweise, woran es liegen könnte? Gruß Bernd

# Fabian Greif meinte am 25. Februar 2013, 17:15 dazu:

Hallo Bernd, ohne eine Fehlermeldung/Beschreibung kann ich dir da leider nicht weiterhelfen.

Versuche es mal mit der Version von GitHub, wenn es das Problem mit den prog_char Typen ist, dann ist das dort behoben: https://github.com/dergraaf/avr-can-lib

Grüße Fabian

# Bernd meinte am 25. Februar 2013, 17:42 dazu:

Hallo Fabian, danke für die schnelle Antwort. Ja, die Fehlermeldungen wechselten sich ab. Ich hatte schon alles mögliche versucht, die Toolchain und auch das Atmel-Studio in verschiedenen Directorys installiert, die sh.exe ins “bin” kopiert usw… Als ich dann ziemlich ratlos war, habe ich die Anfrage geschrieben. Inzwischen war ich auch auf die Sache mit dem prog_char gestoßen und gerade drüber, die Lösung rauszufinden. Deine Lösung von Github war dann schon fertig. Jetzt funktioniert es wieder. Das einzige, was noch nicht klappt, ist das automatische Anlegen von “.dep” und “build”. Wenn man das von Hand macht, funktioniert es. Aber das ist wohl nur noch eine Sache der Berechtigungen in Windows7, das kriege ich noch hin. Also nochmals DANKE für deine Lösung mit den prog_char-Typen! Viele Grüße Bernd

# Sebastian meinte am 26. Februar 2013, 21:29 dazu:

Hallo Fabian,

nochmal danke für deine tolle Library! Sie hat mir echt geholfen und meine Faszination für uCs erneut geweckt! Großes Lob!

Eine kleine Frage hätte ich noch. Ich benutze den dynamischen Filter, da ich die ID aus dem EEPROM lese. Für den Puffer 1 setze ich Mask auf 0xFFFF und ID auf meine ID, für Püffer 2 ebenso. Mein Ziel ist es nur die Nachrichten für meine ID zu bekommen.

 can_set_filter( 0, &mycanfilter)
 can_set_filter( 2, &mycanfilter)

Das klappt soweit auch, wenn ich jedoch im Standby bin wacht der uC jedes mal auf. Dann fragt er mit

 can_get_message(&msg_in)

die Nachricht ab und gibt als Rückgabewert 0x00 zurück - sprich das Lesen der Nachricht ist fehlgeschlagen. Ist ja auch logisch, da gar keine Nachricht da ist. Ist der uC nicht im Standby bekommt er komischerweise keinen Interrupt und er fragt auch nicht nach.

Gibt es eine Möglichkeit wie man verhindert, dass der uC im Standby einen Interrupt vom MCP bekommt? Ich hätte jetzt erwartet, dass der dauerhaft im Standby bleibt da ja keine Nachricht für ihn da ist … . Habe ich noch etwas übersehen?

Danke für deine Rückmeldung!

# Fabian Greif meinte am 27. Februar 2013, 11:16 dazu:

Hallo Sebastian,

nochmal danke für deine tolle Library! Sie hat mir echt geholfen und meine Faszination für uCs erneut geweckt! Großes Lob!

Freut mich :-)

Gibt es eine Möglichkeit wie man verhindert, dass der uC im Standby einen Interrupt vom MCP bekommt?

Grundsätzlich verwendet die Bibliothek für den MCP2515 gar keinen Interrupt, auch wenn der Pin vom MCP2515 so heißt. Im AVR wird dafür ein normaler IO-Pin verwendet und dieser beim Aufruf von can_get_message() gepollt.

Du musst irgendwo selbst Interrupts für den verwendeten Pin aktiviert haben, ansonsten kann ich mir das Verhalten nicht erklären.

Grüße Fabian

# Sebastian meinte am 4. März 2013, 13:54 dazu:

Hallo Fabian,

du hast natürlich recht. Ich habe den INT-Pin des MCP2515 direkt an den INT0 meines ATMega8 gehängt. Dieser ist dann als Interrupt auf LowLevel definiert.

Wenn der MCP2515 eine Nachricht bekommt, die er eigentlich filtern müsste legt er einen Low-Pegel an seinem INT-Pin an und mein ATMega8 wacht daraufhin aus dem Standby auf. Ich hoffe ich habe mein Problem verständlich geschildert.

# Andreas meinte am 8. März 2013, 17:36 dazu:

Hey, ich würde auch gerne die Library ausprobieren. Bin leider noch nicht soooo alt im Thema Mikrocontroller und Librarys.

Kann mir einer kurz und knapp erklären wie ich die Library in AVR Studio einbinde? oder muss ich das gesammte src Verzeichnis ins Projekt einbinden?

Würde mich sehr über eine Starthilfe freuen ;)

# Karsten meinte am 14. März 2013, 11:58 dazu:

Moin Moin Fabian und Wissende,

Vielleicht eine dumme Frage: Die can.id ist mir uint32_t definiert. Bei extended möchte ich nun die 29bit ID übergeben. Dazu schreibe ich die Bits in ein unit32_t. Es bleiben dann ja 3 bit unbenutzt. Sind das die msb (most significant BIT) oder muss ich alles um 3 nach “links” shiften ?? Daaanke für eure hilfe

# Fabian Greif meinte am 14. März 2013, 13:57 dazu:

Es bleiben dann ja 3 bit unbenutzt. Sind das die msb (most significant BIT) oder muss ich alles um 3 nach “links” shiften ??

Es sind natürlich die obersten Bits unbenutzt, so dass man gerade nicht schieben muss :-)

Grüße Fabian

# Sebastian meinte am 18. März 2013, 12:05 dazu:

Hallo Fabian,

ich benutzte die Lib das erste Mal in einem AT90CAN128. Senden, sowie empfangen laufen prima. Ich hab eine Frage zu den Filtern. Wenn ich den folgenden Filter auf eine ID z.B. 0x80 setze, funktioniert das auch.


can_filter_t filter = {
  .id = 0x80,
  .mask = 0x7FF,  // nur die ID wird enpfangen
  .flags = {
      .rtr = 0,
  }
};
can_set_filter(0, &filter);

Kann ich mehrere Filter auf verschiedene ID´s setzen? Ich kann doch eigentlich lt. Datenblatt jedes von den 15 Mob einzeln mit einem Filter versehen. Ich möchte 6 verschieden ID´s beim Empfang filtern. Danke für die Unterstützung!

# Fabian Greif meinte am 18. März 2013, 13:23 dazu:

Kann ich mehrere Filter auf verschiedene ID´s setzen?

Ja.

Ich kann doch eigentlich lt. Datenblatt jedes von den 15 Mob einzeln mit einem Filter versehen.

Ja, das geht, allerdings kannst du dann keine Nachrichten mehr senden. Dafür musst du mindestens ein MOb frei lassen.

Grüße Fabian

# Sebastian meinte am 18. März 2013, 16:13 dazu:

Hallo Fabian,

danke für Deine Antwort. Das Einrichten mehrerer Filter hat tadellos funktioniert. Eine Kleinigkeit hätte ich noch. Ich nutze den Timer1 für eine ISR und bekomme seitdem die Lib eingebunden ist 3 Warnings beim übersetzen. Wird durch die Lib der Timer1 benutzt oder blockiert?

ISR (TIMER1_COMPA_vect) { … }

warning: return type defaults to ‘int’ warning: type of ‘__vector_12’ defaults to ‘int’ warning: control reaches end of non-void function

Nochmals vielen Dank für deine Hilfe!

# Sebastian meinte am 18. März 2013, 16:36 dazu:

Hallo Fabian,

ich kann meine Frage zurück nehmen. Die interrupt.h war nicht eingebunden. Danke dir nochmals!

# Chris meinte am 30. März 2013, 00:14 dazu:

Absolut großartig! Die Library hat auf Anhieb auf meinem AtMega8 funktioniert. Vielen Dank dafür, die Lib bietet einen tollen Einstieg in das Thema CAN.

Das Demoboard habe ich allerdings als SMD-Variante gelayoutet, mit einem FT232RL, also USB Anschluss. Soll ich dir das Layout für deine Seite schicken? Ist aber nicht perfekt…

# Steeve meinte am 29. April 2013, 09:33 dazu:

Hello Fabian, and congratulation for your work that’s very impressive !

I’m trying to use it into my home automation project but I faced some problems using your bootloader. Because I work with atmega32u4, I’ve added the management of my board into default.h but when I run the python script, the board doesn’t seem to ACK the message (and my boot led doesn’t blink at start too…)

I’ve seen that you put hfuse 0xDC and lfuse 0x94 into your board which correspond to an Ext Low freq crystal (instead of a 8Mhz for me) and a clk output on C7 (my boot led port). Does it mean that my board can’t work with your bootloader ?

# Fabian Greif meinte am 29. April 2013, 10:15 dazu:

Hello Steeve,

Hello Fabian, and congratulation for your work that’s very impressive !

Thanks!

I’ve seen that you put hfuse 0xDC and lfuse 0x94 into your board (…). Does it mean that my board can’t work with your bootloader ?

No, it just means that you have to change these values according to your AVR. These values are only valid for an ATMega32 without the u4.

When you use the internal 8 MHz oscillator than lfuse=0xd2, hfuse=0xdc and efuse=0xf3 should work.

Regards, Fabian

# JayB meinte am 13. Mai 2013, 21:14 dazu:

Guten Tag

Ich habe folgendes Problem…. Wenn ich bei meinem AT90CAN128 das fuse bit CKDIV8 deaktiviere um meine 16 MHz zu erhalten, was ich für mein vorhaben auch benötige, funktioniert der CAN Bus net mehr. Woran kann das liegen, bzw wo muss das in der CAN Lib angepasst werden das der Prozessor jetzt statt mit 2 mit 16 MHz läuft ?

# Dennis W: meinte am 25. August 2013, 11:31 dazu:

Hallo Fabian,

erst einmal vielen Dank für diese Bibliothek, sie funktioniet auf meinem AT90CAN128 ohne Probleme. Ich verwende den AVR-CAN von der Firma Olimex.

Aus Kostengründen der “Slave”-Knoten würde ich gerne auf ein Gespann von ATMega 8x, MCP2515 CAN Controller, MCP2551 Treiber aufsatteln. Da bietet sich das CAN Testboard an.

Frage: Um die Last auf den µC zureduzieren, wollte ich fragen, warum die Interruptleitung des MCP2515 nicht auch zu einem Interrupt im AVR führt? Auch im AT90CAN128 muss ich “pollen”, ob Nachrichten vorhanden sind. Was sind die Gründe für diese Handlungsweise? Gibt es Ansätze in der Bibliothekt, Interrupthandling zu verwenden?

Viele Grüße aus Bremen, Dennis

# Michael meinte am 6. September 2013, 13:44 dazu:

Hallo! Danke für die hervorragende Library! Senden und empfangen funktioniert hervorraggend. Mann muss dazu sagen das ich die für den Arduino auf einem AT90CAN128 portierte Library von https://github.com/Railstars/OpenLCB verwenden wo sich bei den Variablen leicht etwas geändert hat. Mein Problem besteht bei den Filtern:

    tCANFilter filter_1;
    tCANFilter filter_2;

    void setup()
    {
    can_init(BITRATE_500_KBPS); 
    filter_1.id = 0x130; 
    filter_1.mask = 0x7FF;     
    filter_1.flags.rtr = 0; 
    filter_1.flags.extended = 0;  

    filter_2.id = 0x132; 
    filter_2.mask = 0x7FF;  
    filter_2.flags.rtr = 0; 
    filter_2.flags.extended = 0;

    for (int i = 0; i < 10; i++) 
      {
      can_set_filter(i, &filter_1);
      } 

    for (int i = 10; i < 15; i++) 
      {
      can_set_filter(i, &filter_2);
      }
      can_set_mode(NORMAL_MODE); // 
    }

So funktionieren die Filter und nur Messages mit ID 130 und 132 kommen durch. Wenn ich allerdings nicht alle MOB mit einem Filter belegen, also zB nur von 0-14 gehe, dann kommen wieder alle Messages durch. Gibt es hier eine Trick zB Filter einem bestimmen MOB zuzuordnen.

Danke für die Library und die Hilfe

# Viktor meinte am 26. September 2013, 11:39 dazu:

Hallo Fabian! Vielen Dank für deine tolle Arbeit. Wie du dir sicherlich denken kannst, könnte auch ich deine Hilfe gebrauchen. Ich habe hier einen ATmega32 @8MHz mit einem MCP2515 @8MHz und versuche Daten mit einem CAN-fähigen Datenlogger zu senden und zu empfangen. Das Senden funktioniert nur bedingt, da der MCP nach ca. 10 bis 25 Nachrichten in den Fehlermodus geht (Sendepuffer wird nicht geleert bzw. überschrieben). Empfangen kann ich auch nur 3 Nachrichten. Was mich allerdings wundert, ist es wenn ich den MCP mit 100kBps initialisiere, funktioniert die Kommunikation mit 500kBps. Ich sitze bereits seit einer Woche daran und finde den Fehler einfach nicht. Hättest du evtl. einen Tipp für mich?

Viele Grüße Viktor

# Fabian Greif meinte am 26. September 2013, 19:01 dazu:

Hallo Viktor,

die Timing-Einstellungen für den MCP2515 sind für 16 MHz ausgelegt. Für den 8 MHz Quarz musst du die Werte für die Register CNF1..3 anpassen.

Grüße Fabian

# Marco meinte am 3. November 2013, 15:58 dazu:

Hallo, ich möchte mich gern meinen Vorgängern anschließen und mich für die tolle Lib bedanken, die Einbindung ging relativ schnell und ohne Probleme.

nun habe ich aber doch ein kleines Problemchen und hoffe das ich hier hilfe finde. Einige haben das Problem schon geschildert, jedoch habe ich keine Lösung finden können, welche das Problem behebt. Ich benutze ein At90Can128 Board. und möchte gern eine Kommunikation mit einem PeakCan zum PC herstellen.

Das senden funktioniert sehr gut, jedoch das empfangen nicht.

ich habe den Code relativ einfach gehalten und möchte nur auf den Status überprüfen und anschließend eine LED blinken lassen. jedoch funktioniert dies schon nicht.


int main{
    // Initialize LED
       LED_INIT;

    // LED Blinken
       LED_Welcome(); 

    // CAN initialisieren 
       can_init(BITRATE_125_KBPS);

    // anfangszustand alle Filter off
   can_disable_filter(0xff);

   // Modus festlegen  
   can_set_mode(NORMAL_MODE);

    // Filter festlegen
       can_filter_t filter = {
      .id = 0x1FFFFFFF,
      .mask = 0x7ff,
      .flags = {
      .rtr = 0,
      .extended = 1
    }
     };

   // Filter setzen 
   can_set_filter(0, &filter);  

   // Int. einschalten
   sei();

   // Nachricht erzeugen    
   can_t msg;
msg.id = 0x12345678;
msg.flags.rtr = 0;
msg.flags.extended = 1;
msg.length = 1;
msg.data[0] = 0xff;

// Nachricht verschicken
can_send_message(&msg);
LED_Off;        _delay_ms(1000);


while (1){

    if (can_check_message())
    {
        LED_Welcome();  // blinken
    }
}

return 0; }


Die Terminierung wurde auf dem Board vorgenommen. Der USB CanAdapter steckt direckt am Board.

vielleicht kann mir jemand von euch weiter helfen

Danke

Danke

# Andy meinte am 8. November 2013, 18:38 dazu:

Hallo miteinander, erstmal danke für die Bibliothek sieht relativ einfach aus anzuwenden. Ich habe allerdings ein grundlegendes Problem damit. Ich benutze das Olimex AVR Can Board und bekomms einfach nicht auf die Reihe die Bibliothek zum laufen zu bekommen. Ich benutze Win-AVR und das AVR-Studio 4.19. Vielleicht hat schonmal jemand das Olimex damit zum laufen bekommen und kann mir einen Tipp geben.

Gern auch per Mail: jey159@web.de Vielen Dank

# Marco meinte am 15. November 2013, 19:54 dazu:

Hallo,

deine Lib funktioniert nun auch bei mir. Nach einigen Anfangsproblemen, welche aber immer durch den Anwender verursacht werden.

Nun möchte ich gern dir Lib mit einem Interrupt benutzen.

Hat jemand ein Beispiel? Ich möchte gern auf eine Empfangen Nachricht ein Interrupt auslösen, welche die Nachricht verarbeitet und wieder eine Nachricht zurücksendet.

in der restlichen Zeit will ich den µC in den Standby setzen um Strom zu sparen. Ich höre auch noch auf andere Interrupts (Taster usw)

In der Doku konnte ich leider kein Beispiel für einen Interrupt finden, Stelle mich bestimmt wieder total blöd an,

aber erst einmal vielen Dank für die Hilfe

Marco

# Abdul meinte am 11. Dezember 2013, 13:20 dazu:

Hallo,

vielen Dank schon mal für die tolle Bibliothek!

Gibt es eine Möglichkeit den SPI_PRESCALER, also die SPI Frequenz, einzustellen ohne dies in der Datei spi.c anzupassen? Dies erfordert auch ein erneutes erstellen der Bibliothek. Je nach Umständen kann dies ja erforderlich sein. Ich habe zur config.h folgende Zeile beigefügt um es zumindest zentral zu steuern:
#define SPI_PRESCALER 8

Aber es ist eben ein erneutes erstellen der Bibliothek erforderlich. Geht das nicht anders oder übersehe ich etwas? Es wäre praktisch. Es ist ja auch ein wichtiger Parameter.

Tausend Dank und Grüße,

Abdul

# jacyju meinte am 1. Januar 2014, 20:48 dazu:

Auch von meiner Seite ein herzliches Dankeschön für die echt nützliche CAN-Bibliothek. Ich habe allerdings lange mit einem Problem kämpfen müssen bei dem ich dachte, es hängt mit meinem Code zusammen: Wenn mehrere Nachrichten schnell hintereinander (ohne delay_ms) gesendet wurden ist es vorgekommen, dass die Nachrichten in der Reihenfolge vertauscht waren. Das mag zwar bei einfachen Steueraufgaben nicht stören, wohl aber z.B. bei einem Bootloader, bei dem die Daten genau in der Reihenfolge ankommen müssen, wie sie gesendet wurden.

Das Problem liegt in der Datei “mcp2515_send_message.c”. Hier werden die Sendepuffer in der falschen Reihenfolge gefüllt. Nach einem Blick ins Datenblatt habe ich hier den Fehler verortet. Mein verbesserter und funktionierender Code sieht so aus:


uint8_t mcp2515_send_message(const can_t *msg)
{
    // Status des MCP2515 auslesen
    uint8_t status = mcp2515_read_status(SPI_READ_STATUS);

/* Statusbyte:
 *
 * Bit  Funktion
 *  2   TXB0CNTRL.TXREQ
 *  4   TXB1CNTRL.TXREQ
 *  6   TXB2CNTRL.TXREQ
 */
uint8_t address;
/*
ORIGINAL GEÄNDERT, SONST WAREN NACHRICHTEN BEI SCHNELLEM SENDEN HINTEREINANDER IN FALSCHER REIHENFOLGE,
DA PUFFER VON HOCH NACH NIEDRIG ABGEARBEITET WERDEN (s. Datenblatt MCP2515 Transmit Priority, S. 15:
"If two buffers have the same priority setting, the buffer with the highest buffer number will be sent first.")

In den ersten der 3 Puffer darf erst geschrieben werden, wenn alle anderen leer sind.
Sonst könnte es sein dass die Nachricht im ersten Puffer gerade weg ist, aber noch 2 ältere
in den anderen Puffern sind. Dann würde die jetzige neue Nachricht vor den älteren weggeschickt werden,
da sie ja dann ganz vorne im Puffer steht.
Man könnte das umgehen, indem man die anderen Nachrichten im Puffer "umschichtet", das heißt
alle anderen Nachrichten um einen Pufferplatz vorrückt. Oder man könnte die Priorität
der Puffer ändern. Beides ist aber kompliziert und braucht im Endeffekt sowieso
die gleiche Zeit, die es auch braucht bis die Nachrichten verschickt sind.
*/
if ((_bit_is_clear(status, 6)) && (_bit_is_clear(status, 4)) && (_bit_is_clear(status, 2))) {
    address = 0x04;
}
else if ((_bit_is_clear(status, 4)) && (_bit_is_clear(status, 2))) {
    address = 0x02;
} 
else if (_bit_is_clear(status, 2)) {
    address = 0x00;
}
else {
    // Alle Puffer sind belegt,
    // Nachricht kann nicht verschickt werden
    return 0;
}

RESET(MCP2515_CS);
spi_putc(SPI_WRITE_TX | address);
#if SUPPORT_EXTENDED_CANID
    mcp2515_write_id(&msg->id, msg->flags.extended);
#else
    mcp2515_write_id(&msg->id);
#endif
uint8_t length = msg->length & 0x0f;

// Ist die Nachricht ein "Remote Transmit Request" ?
if (msg->flags.rtr)
{
[…]

# Andy meinte am 20. Februar 2014, 15:01 dazu:

Hallo mitnander, die Bibliothek ist klasse vielen Dank dafür funktioniert einwandfrei auf nem AT90CAN128.

Meine Frage ist nur: Könnte man die Bibliothek nutzen um einen AT90CAN128 mit einem MCP2515 zu erweitern, so dass man 2 Can Channel hätte und diese separat ansteuern könnte?

mFG

# Key Music meinte am 10. April 2014, 23:41 dazu:

Hallo zusammen, hallo Fabian,

habe gerade mal in die Library geschaut. Sehr gepflegt alles. Zu der Interrupt Service Routine ISR hätte ich mal eine Frage: Was passiert denn, wenn der TransmitOK- und ReceiveOK-Interrupt-Request gleichzeitig auftreten?! Könnte dann nicht der Receive-Part verloren gehen?

Wäre statt

if (CANSTMOB & _BV(TXOK))
{ ... }
else
{ ... }

nicht folgendes besser?

if (CANSTMOB & _BV(TXOK))
{ ... }
if (CANSTMOB & _BV(RXOK))
{ ... }

Gruß Key Music

# Fabian meinte am 11. April 2014, 10:40 dazu:

Hallo,

auch wenn es jetzt schon etwas her ist das ich Datenblatt in der Tiefe gelesen habe: Der RX und TX Interrupt könnten nur zusammen auftreten wenn die Nachricht die gerade gesendet wird auch gleichzeitig wieder empfangen und in die Empfangspuffer abgelegt wird. Das wird vom CAN Controller aber verhindert. Somit kann es hier (im Gegensatz zum Beispiel zum UART) nie dazu kommen das beide Interrupts gleichzeitig auslösen.

Selbst wenn beide gleichzeitig aktiv wären, so würde nur eine Interrupt Bedingung behandelt, damit würde der Interrupt sofort wieder angesprungen werden sobald er das erste mal verlassen wird.

Grüße Fabian

# René meinte am 14. Mai 2014, 10:42 dazu:

Hallo,

deine Biblothek wurde mir empfohlen, bloss ist diese auch möglihch mit dem Xmega von Atmel zu betreiben?

Danke im voraus.

# Sebastian meinte am 18. Juli 2014, 21:33 dazu:

Hi,

Wenn der uC den MCP aufweckt klappt das mit dem aktuellen Stand nicht (siehe Problem von Klaus). Schlafen geht, jedoch bleibt die funktion in can_wakeup hängen. Mit folgender Änderung geht es:

mcp2515_wakeup(void) { // reset int enable and cancel the interrupt flag mcp2515_bit_modify(CANINTE, (1