mikrocontroller.net

Forum: Compiler & IDEs AT90CAN128


Autor: Thomas27 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute!

Seit Wochen programmiere ich an der CAN-Schnittstelle des AT90CAN128
rum, jedoch lässt sich keine Nachricht empfangen. Nachrichten möchte
ich keine senden. Meine Vermutung ist, dass etwas mit der
Interupt-Vektortabelle nicht in Ordnung ist. Kann mir vielleicht jemand
weiterhelfen?

Im Anhang findet ihr meine main.c-Datei mit allen Initialisierungen...

Gruß

Thomas

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast Du es schon ohne interrupt versucht?

Autor: Alex (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dann schalte ich mich mal auch noch mit ein:

Das Senden mit dem AT90CAN128 klappt bei mir ohne Probleme. Empfangen
lässt sich bis jetzt nichts (jeweils Polling).

Der einzige Interrupt, den ich zum Auslösen bekomme ist der des
CAN-Timers, dieser jedoch zuverlässig. Sowohl Sende- als auch
Empfangsinterrupt arbeiten nicht.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK,

CANIDM4 = 0;//|= (1<<IDEMSK);

und

CANGIE = 0xA0;

und in der ISR

CANCDMOB = (1<<CONMOB1);

Dann empfängt er schonmal Nachrichten via Interrupt :)

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Thomas27 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe es ausprobiert, jedoch funktioniert jetzt der Controller überhaupt
nicht mehr (SRAM-Error, auch mit meiner ursprünglichen main.c Datei)

@flyingwolf: Wie soll es ohne Interrupts funktionieren? Ich habe doch
nur 2 Möglichkeiten: entweder SIGNAL(...) oder INTERRUPT(...)
-> mit beiden habe ich keine nennenswerten Erfolge erzielt.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Fehler kann ich logischerweise nicht nachvollziehen.

Ohne Interrupts heißt das Ganze Polling.

Du kontrollierst einfach TXOK bzw. RXOK manuell und leitest bei
gesetzten Flags die entsprechenden Aktionen ein. Meine Senderoutine
demonstriert das ganze eigentlich.

Von INTERRUPT würde ich dir generell abraten.

Autor: Alexander Mamajew (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Alex

Dies

CANTIML = 0;
CANTIMH = 0;
CANTTCL = 0;
CANTTCH = 0;

bringt nichts, da CANTIM, CANTTC und ander CAN-Timer nur Lesezugriff
zulassen

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Alexander

Das weiß ich, es ist auch in der Endversion (vgl. Codesammlung) nicht
mehr drinnen. Stammt noch aus dem Testbetrieb.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Thomas27
Ganz einfach. Du fragst die Box sporadisch ab. Du musst die Mailbox
nach jedem empfang explizit freigeben. Wenn Du Angst hast, dass Du
dadurch eine Nachricht verpassen könntest, kannst Du 2 Boxen mit den
gleichen Parametern freigeben. Dann kommt die erste Nachricht in der
ersten Box an und wenn die zeite Nachricht kommt, bevor die erste Box
wieder freigegeben ist, kommt die Nachricht in der zweiten box an. ...
Keine Verluste und keine Interrupts.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
versuchs mal hiermit, nicht schön, aber selten ...
#include <avr/io.h>

#include <avr/pgmspace.h>

#include <stdlib.h>


#include <inttypes.h>
#include <stdio.h>

#include "can.h"



#define setbit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clearbit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define checkbit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define lichtan() setbit(PORTG,PG1)


#define init_mob_rx_0 init_mob_rx(0,8192,536862720);    // einkürzen des
Befehls, damit Tag und Mask nicht immer mit eingegeben werden müssen. 
#define init_mob_rx_1 init_mob_rx(1,16384,536862720);
#define init_mob_rx_2 init_mob_rx(2,24576,536862720);
#define init_mob_rx_3 init_mob_rx(3,32768,536862720);







void Can_bit_timing (void)
{

CANBT1= 0x06;
CANBT2= 0x0C;
CANBT3= 0x5A;

}

void can_init (void)
{
  Can_bit_timing();
  Can_clear_all_MOB();
  setbit(CANGCON,1);                   //Can_enable  
  //test für sleep_Mode
  //CANTCON=0xFF;

}

void Can_clear_all_MOB (void)
{
  int num_mob, num_data;

  for (num_mob = 0; num_mob < 15; num_mob++)
  {
    CANPAGE  = (num_mob << 4);
    CANSTMOB = 0;
    CANCDMOB = 0;
    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;
    }
  }
}

void init_mob_rx (char nummob, long idtag, long idmask)
{
CANPAGE = (nummob << 4);                 // MOB anwählen
CANIDT4 = (uint8_t)((idtag<<3) & 0xFF);          // Tag setzen
CANIDT3 = (uint8_t)((idtag>>5) & 0xFF);
CANIDT2 = (uint8_t)((idtag>>13) & 0xFF);
CANIDT1 = (uint8_t)((idtag>>21) & 0xFF);
CANIDM4 = (uint8_t)((idmask<<3) & 0xFF);          // Maske setzen
CANIDM3 = (uint8_t)((idmask>>5) & 0xFF);
CANIDM2 = (uint8_t)((idmask>>13) & 0xFF);
CANIDM1 = (uint8_t)((idmask>>21) & 0xFF);
CANSTMOB = 0x00;
CANCDMOB = 0x98; // MOB in empfangsmodus
}

void init_mob_rply(char *sendstring,char nummob, long idtag, long
idmask)
{
CANPAGE = (nummob << 4);                 // MOB anwählen
CANIDT4 = (uint8_t)(((idtag<<3)+4) & 0xFF);          // Tag setzen
CANIDT3 = (uint8_t)((idtag>>5) & 0xFF);
CANIDT2 = (uint8_t)((idtag>>13) & 0xFF);
CANIDT1 = (uint8_t)((idtag>>21) & 0xFF);
CANIDM4 = (uint8_t)(((idmask<<3)+4) & 0xFF);          // Maske setzen
CANIDM3 = (uint8_t)((idmask>>5) & 0xFF);
CANIDM2 = (uint8_t)((idmask>>13) & 0xFF);
CANIDM1 = (uint8_t)((idmask>>21) & 0xFF);
CANSTMOB = 0x00;
CANCDMOB = 0xb8; // MOB in reply-mode
for (int counter = 0; counter < strlen(sendstring); counter++)
    {
    CANMSG = sendstring[counter];             //bitweise das MOB einlesen
    }
}


void can_send_mg (char *sendstring, long msid, int m_box,int remote)
{
CANPAGE = (m_box << 4);                 // die ersten 4 Bit initialisieren die
Message Box
//CANPAGE = 0xd0;                         // nur noch zur Sicherheit drin,
quasi als Erinnerung
if(remote == 1) CANIDT4 = (uint8_t)(((msid<<3)+4) & 0xFF);
  else
  CANIDT4 = (uint8_t)((msid<<3) & 0xFF);         //Die ersten 3 Bit müssen
überschieben werden!! RTR-TAG muss eins sein
CANIDT3 = (uint8_t)((msid>>5) & 0xFF);         // &0FF kürzt aud ein Byte
ein
CANIDT2 = (uint8_t)((msid>>13) & 0xFF);
CANIDT1 = (uint8_t)((msid>>21) & 0xFF);
CANSTMOB = 0x00;
CANCDMOB = 80 + strlen(sendstring); //0x58;   // 80 +                 
          

for (int counter = 0; counter < strlen(sendstring); counter++)
    {
    CANMSG = sendstring[counter];             //bitweise das MOB einlesen
    }
  
  
}

mailbox 0 abfragen und wieder initialisieren
CANPAGE = 0x00;
if(checkbit(CANSTMOB,RXOK))
  {
    for(int counter=0;counter < (CANCDMOB & 0x0F); counter++) 
    {displaystring[counter] = CANMSG;}
    init_mob_rx_0;

mail senden
can_send_mg ("TexSolar", 8192 + Controller_ID,14,0);

Autor: Thomas27 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke @flyingwolf!

Das mit dem Polling klappt eigentlich ganz gut, jedoch scheint mit dem
CAN-Takt etwas noch nocht zu stimmen. Meine Einstellungen habe ich aus
der Tabelle der AT90CAN128-Anleitung (ca. Seite 261, Oszillatorfrequenz
4MHz).
Meine Wunschfrequenz ist 500 kbps -> CANBT1 = 0x00
                                     CANBT2 = 0x04
                                     CANBT3 = 0x13

Mit hilfe eines CANalyzer wollte ich dann eine Nachricht senden, die
mein Atmel empfangen und auswerten sollte (Übertragungsgeschw.
ebenfalls 500 kbps, sonst gehts ja nicht).
Nachdem ich mir jedoch die Nachricht mit dem Oszi angesehen habe,
musste ich (mit erschrecken :-) ) feststellen, dass Nachrichten, die
ich vom Atmel sende viel länger sind (3ms) als Nachrichten die ich vom
CANalyzer sende (ca. 120 us).
Gibt es da noch eine Möglichkeit der Konfiguration, um die Länge der
Nachricht zu kürzen?

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich takte mit 8MHz
Bei den CANBT hatte ich mich an die Vorlagen gehalten, weil ich noch
nicht rausbekommen habe wie das mit den Takteinstellungen
funktioniert.
Die Routine sendet  CAN2B Du kannst es ändern indem Du auf 2A
umschaltest, dann ist der Identifierer nur 11 Bit lang statt 29

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was kann man eigentlich bei der USART Initialisierung bei diesem Ding
falsch machen?

void usart0_init (void)
{
  UBRR0H = 0;
  UBRR0L = 0;
  UCSR0A = 0;
  UCSR0C = (3<<1);    //8N1
  UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);
  sei ();
}

SIGNAL (SIG_UART0_RECV)
{
  //do something
}

Irgendwie wird der Interrupt nie ausgelöst (baudratenunabhängig).

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast Du die Interrupttabelle vom 90CAN128 genommen, oder die vom
MEGA128?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende den Header der beim WinAVR dabei ist (at90can128.h). Der
scheint auch mit dem Datenblatt übereinzustimmen. Bin trotzdem ratlos.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, aus irgend einem Grund geht das jetzt auf dem USART0, identischer
Code auf dem USART1 arbeitet nicht. Irgendwie habe ich manchmal das
Gefühl, der Controller will mich veralbern :)

Beim ATMega8 bzw. 128 hatte ich sowas nie festgestellt, aber dieser
verhält sich irgendwie z.T. unberechenbar. Vielleicht werde ich auch
einfach nur senil ...

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe einen haufen ungereimtheiten festgestellt, in der Doku und den
Libs, die es dazu gab. Ich will nicht soweit gehen zu sagen dass es
Fehler sind, weil es ggf auch an mir liegt, aber es empfihlt sich immer
2 mal hinzuschauen und sich zu fragen ob das logisch ist, was in der
Doku steht. Ich habe monate damit zugebracht mich über den 90CAN128 zu
wundern. Bei den Ints war auch mal was krumm...

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht wem ich die Schuld zuschieben soll:

- mir
- dem Controller
- dem gcc

Finde es halt nur irgendwie kurios, dass bestimmte Codefragmente einmal
funktionieren und ein anderes mal wieder nicht.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig doch mal das Beispiel mit den USARTs.
Möglicherweise sind das auch nur Flüchtigkeitsfehler...

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
könnte es an irgend welchen fuses liegen?

Autor: Alex (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
- LED mit blinkt mir 0,5Hz (Timerinterrupt)
- USART schickt jede Sekunde ein 'x'
- Main-Loop pollt auf Empfangsflag, gleichzeitig ist auch
Empfangsinterrupt aktiviert
- wird Flag erkannt bzw. Interrupt ausgelöst, werden Interrupts
deaktiviert
- die LED sollte also aufhören mit blinken

Bei der Hardware bin ich mir eigentlich sicher, dass sie passt
(MAX232), habe das identische schon mit einem ATMega128 aufgebaut. Wenn
ich längere Strings via Terminal sende erkenne ich am Multimeter einen
Spannungsabfall von 4,95V auf 4,6V (RXD1), ich gehe also mal davon aus,
dass Zeichen den MAX232 auch wieder verlassen.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hängst Du vieleicht mit dem ISP-programmer noch an der Schnittstelle
dran?
Keine Ahnung ob das was ausmacht, ich benutze den max232 nicht.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ISP ist an USART0, dort hängt ein FTDI, mit dem es komischerweise
keine Probleme gibt.

Autor: flyingwolf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ja, dann hängt bei mir an USART1 die serielle Schnittstelle. OK ich
habe keine Interrupts darauf aber die Schnittstelle arbeitet klaglos.

Allerdings habe ich keinen max232 dran.
Geht es denn ohne interrupt?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Offensichtlich nicht, da das Flag nicht gesetzt wird. Einzig der
Sendebetrieb scheint klaglos zu arbeiten. Werde morgen mal ein Oszi
dranhalten, im Zweifel liegt der Fehler immer beim Anwender.

Autor: Thomas27 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Nur zur Info: Habe ein paar Fehler beseitigt...
Ein Fehler war, dass ein Fuse-Bit gesetzt wer, nämlich ein Vorteiler,
der die Grundfrequenz von 4Mhz geteilt runtergeteilt hat. Dieses hat
sich dann auch auf die Sendefrequenz des CANS's ausgewirkt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.