Forum: Compiler & IDEs Probleme mit dem EEPROM vom ATtiny26


von Gilles R. (roodemol)


Lesenswert?

Hallo, ich habe folgenden Code:

/* EEPROM */
#ifndef EEMEM
#define EEMEM _attribute_ ((section (".eeprom")))
#endif

#define Tabellen_Groesse 8
uint8_t ee_Generator_Tabelle[] EEMEM =  { 56, 48, 40, 32, 24, 16, 8, 0
};
volatile uint16_t Tabellen_Index;


Die Ein-/Ausgänge und Timer sind so festgelegt:
DDRA &= ~( (1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 <<
PA4) | (1 << PA5) | (1 << PA6) );
DDRA |= (1 << PA7); /* Eingang */

TCCR0 = (1 << CS01); /* CPU-Takt/8 */
TCNT0 = 44;
TIMSK |= (1 << TOIE0); /* Timer Interrupt Mask setzen. */


Jetzt habe ich eine Interrupt-Routine die Regelmässig Daten aus der
Tabelle ausgibt:
SIGNAL(SIG_OVERFLOW0)
{
  /* Timer neu laden. */
  TCNT0 = 44;

  /* Nächsten Zustande aus dem EEPROM laden und ausgeben. */
  PORTA = eeprom_read_byte(&ee_Generator_Tabelle[Tabellen_Index]);
  Tabellen_Index++;
  if(Tabellen_Index == Tabellen_Groesse)
    Tabellen_Index = 0;
}


Damit müsste ich an den Pins PA5, PA4 und PA3 ja drei verschiedene
Frequenzen messen können (PA5 = 2*PA4 = 4*PA3). Allerdings habe ich an
allen Pins von Port die Gleiche Frequenz, sogar an PA7, welcher ja ein
Ausgang ist. An PA6 kann man ein sauberes Signal erkennen, mit steilen
Flanken, welches an eine PWM erinnert. An PA0 - PA5 hat das Signal eine
steil steigende Flanke und die fallende Flanke hat die Form einer
e-Funktion.
Anfangs habe ich geglaubt der Mikrocontroller sei kaputt und habe ihn
ausgetauscht, was aber keine Besserung gebracht hat und der gleiche IC
hat auch mit einem anderen Programm ohne Tadel funktioniert.

Habe ich irgendwo vergessen ein Flag zu setzen oder zu löschen?

Gilles

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bitte poste mal einen compilierbaren Code (am besten als Datei
hochladen, zumindest aber in [C]-Tags), dann stecke ich das mal
auf'm STK500 zusammen.

von Gilles R. (roodemol)


Angehängte Dateien:

Lesenswert?

Also hier mal mein Code. An PA3 müsste ich doch jetzt eine Frequenz von
7,353 kHz messen können wenn mein Mikrocontroller mit 8MHz läuft. Oder
ist zwischen zwei Timer-Interrupts nicht genug Zeit um die Werte aus
dem Speicher zu holen?

von mthomas (Gast)


Lesenswert?

Sicher, dass die eeprom-Funktionen der genutze Version der avr-libc auch
mit den ATtiny26 funktionieren? Bei aelteren Versionen der avr-libc gab
es Inkompatibilitaeten mit einigen "neueren" AVR-Modellen, mglw. auch
mit dem tiny26.

von Gilles R. (roodemol)


Angehängte Dateien:

Lesenswert?

Also ich habe jetzt mal den erzeugten Maschinencode mittels:
avr-objdump -h -S Generator.elf > CodeAuswertung.lst
angeschaut. Das EEPROM vom ATtiny26 wird korrekt angesprochen,
allerdings ist mir aufgefallen, dass ich für Tabellen_Index ein
uint16_t benutze und ein uint8_t ja schon gross genug ist. Dabei wird
die Adresse $1F beschrieben, diese Adresse trägt im Datenblatt den
Namen "Reserved". Kann das das Problem sein?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Nun bin ich endlich mal dazu gekommen, wie versprochen das auf einem
STK500 nachzustöpseln.  Damit ich was sehen kann, habe ich mir den
Timer 0 so langsam wie möglich gestellt und die STK500-LEDs an Port A
drangeklemmt.

Ich denke, dein Hauptproblem ist einfach nur, dass du die Logik von
DDRA exakt verdreht hast.  Deinen Eingang (PA7) hast du als Ausgang
beschaltet, die anderen 7 Pins sind Eingänge.

Ansonsten funktioniert das bei mir erst einmal.

Kommentare:

> #include <avr/delay.h>

Das benutzt du gar nicht.  Wenn du es nehmen willst, solltest du F_CPU
zuvor definieren.

> #define Tabellen_Groesse 8

Kann man eigentlich dynamisch ermitteln.

>   PORTA = eeprom_read_byte(&ee_Generator_Tabelle[Tabellen_Index]);
>   Tabellen_Index++;
>   if(Tabellen_Index == Tabellen_Groesse)
>     Tabellen_Index = 0;

Sehr ungünstig mit einer volatile-Variable.  Besser in einer lokalen
Variable zwischenspeichern.

>   /* W?hrend der Initialisierung werden keine Interrupts zugelassem.
*/
>   cli();

Die sind hier sowieso (noch) nicht zugelassen.

>   /* Die Ein-/Ausg?nge und Timer sind so festgelegt: */
>   DDRA &= ~( (1 << PA0) | (1 << PA1) | ...

Wie gesagt, das scheint mir das Grundübel bei dir zu sein.

>     if(PINA & (1 << PA7))
>     {
>       PORTA = 128; /* Generator zeitweise stoppen */
>     }

Hmm, wirklich anhalten tut das den Generator nicht...  Es schreibt
immer wieder Nullen drüber, aber wenn ein Interrupt reinhaut, bekommst
du einen Spike.

Davon abgesehen, das Zurückschreiben von Bit 7 auf einem Eingang in
das Ausgaberegister aktiviert dessen Pullup (was du sicher nicht
wolltest).

Anbei meine Version. ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

p.s.: Aus wahrscheinlich nicht völlig unverständlichen Gründen ;-)
läuft bei mir natürlich eine aktuelle avr-libc-Version.  Falls es also
wirklich Probleme mit der Bibliothek und dem ATtiny26 gegeben haben
sollte, sind diese zumindest repariert.  Allerdings sieht es mir so
aus, als hätte der ATtiny26 ,,Standardlage'' für den EEPROM.  Das
Beschreiben des fehlenden EEARH-Registers sollte kein Problem geben,
das macht avr-libc schon immer so.

von Gilles R. (roodemol)


Lesenswert?

Vielen Dank, ich habe es jetzt entsprechend abgeändert und es läuft im
Simulator. Den Zähler stoppe ich jetzt mit:
TCCR0 = ~(1 << CS01);
und mit
TCCR0 = (1 << CS01);
schalte ich ihn wieder ein. Dann ist das setzen der Interrupt-Maske ja
überfällig, mache es trotzdem.

Schöne Weinachten und einen guten Rutsch.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.