At90S2313 EEPROM auslesen mit Wartezeit

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From German to

Threaded View
Hallo,

bei meinem ersten AVR-Projekt bin ich nun an einer Stelle zum Stehen
gekommen, wo ich nicht mehr weiter weiss und mal um Euren Rat fragen möchte.

Gebaut werden soll eine Motorsteuerung mit einem At90S2313. Zum
Programmieren nutze ich BASCOM AVR, geflasht wird mit WinAVR. Der Motor
ist über einen BUK 100 am PWM Ausgang PB3 angeschlossen. Timer1 ist so
konfiguriert:

Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear
Down , Compare B Pwm = Clear Down

Durch Verändern des Wertes von Compare1a wird die Motordrehzahl
gesteuert. Einfluss auf die Motordrehzahl haben 2 Tasten UP/DOWN,
ankommende Befehle des UART (RS-232) und 4bit Informationen, die auf
Int0 an den Eingängen PB0,PB1,PB2,PB4. Mit den Tasten wird der gesamte
mögliche Wertebereich für Compare1a (byte) durchschritten, bei den
übrigen Ereignissen wird Compare1a auf einen Wert zwischen 0-255 gesetzt
(Tabelle).

Es läuft soweit alles, die Ansteuerung über Tasten, UART und auch von
extern 4bit+strobe an Int0 klappen.

Als nächstes sollen Geschwindigkeits- und Zeitinformationen als Sequenz
im EEPROM abgelegt werden. Das Schreiben (Writeeeprom) und das Auslesen
(Readeeprom) der Daten funktioniert bereits.

Aber nun kommt das Problem:

Das Programm soll bis zum Auslesen des nächsten Befehls eine definiert
lange Pause machen, bis der nächste Wert geholt wird. Dabei darf aber
der sonstige Programmablauf nicht angehalten werden wie das bei einem
WaitMs der Fall ist. Als Geschwindigkeitsinformation dient das obere
nibble, als Zeitinformmation das untere nibble des im EEPROM
hinterlegten bytes.

Ich suche also eine Möglichkeit, im Hintergrund eine Zeit verstreichen
zu lassen (einstellbare Dauer). Ich habe dabei an den noch vorhandenen
timer0 gedacht... der sollte doch in der Lage sein, unabhängig von allen
anderen Ereignissen einen internen Interupt auszulösen wenn die
voreingestellte Zeit verstrichen ist und so das Übernehmen des nächsten
EEPROM Wertes einleiten können (Subroutine). Aber genau hier komme ich
nicht weiter... Wer hat eine Idee, wie ich das Auslesen des EEPROM in
den Hintergrund legen kann, ohne dass mit einem WaitMS das ganze
Programm angehalten wird?

Hier mein bisheriges Quellcodegewurstel zum Angucken:

http://www.kai-ebersbach.de/avr/12-2313.bas

Für Verbesserungsvorschläge am gesamten Code bin ich natürlich auch
jederzeit dankbar... wie gesagt, es ist mein erstes AVR Projekt und ich
stelle mich bestimmt noch ungeschickt dabei an...

Danke

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit
Autsch... ich stelle gerade mit Ercshrecken fest, dass wir ein neues
Quartal haben und die alte Mailadresse schon gelöscht ist...

Benutzbar ist nun usenet042003@kai-ebersbach.de

Ich bitte um Entschuldigung!

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit
On Fri, 03 Oct 2003 12:56:02 +0200, Kai Ebersbach

Quoted text here. Click to load it
[...]
Quoted text here. Click to load it


Allgemeinzu Deinem Programm:
Versuch Dich mal von dieser strukturierten Programmierung, wie man das
früher mal gemacht hat, zu lösen und zu einer eventorientierten
Programmierung zuzuwenden. Solche Sachen wie  das auslesen der
UART-Daten gehören direkt in die IRQ-Routine der UART, sonst kann es
bei Deinen Waits auch sporadisch mal passieren, das Deine Daten in der
UART überschrieben werden. Kann ja auch mal eine Störung in die UART
kommen und dann ist das Byte weg.

Unter eventorientierten Programmierung verstehe ich, dass man wie bei
einem Betriebssystem kleine Treiber schreibt (UART, Taster, Timer),
die die Hardware managen. In der Regel sind das IRQ-Routinen, aber
auch Routinen zur Initialisierung und zum Setzen und Abfragen von
Werten. Dabei sollte man sich auch gleich angewöhnen, jeden Treiber in
eine eigene Datei zu packen. Ideal ist es, wenn man aus dem
Haptprogramm auf die Hardware nur noch mit "SetValue()" und
"GetValue()" zugreift. Ereignisse, die sofort bearbeitet werden
müssen, macht die IRQ-Routine selbst, die welche mehr Zeit
haben/brauchen (z.B. Taste X wurde gedrückt) trägt jeder Treiber in
eine Liste ein (kann man auch noch priorisieren), die dann von
Hauptprogramm abgearbeitet wird.  

Abläufe welche erst mal in jedes Modul schauen, ob irgendwas zu tun
ist, fressen nur sinnlos Zeit. (insbesondere wenn die Programme größer
werden).

-----------------------------------------------------------------

Zu Deinem Timer Problem:
Versuch mal das zu implementieren, dann kannst Du die Funktionen

void setTimer(unsigned int duration, char type);
void killTimers(char type);

verwenden. In diesem Beispiel wird (wenn die Timer-ISR alle 1ms kommt)
wenn setTimer(  100, TIMER_LS_OBEN) aufgerufen wird. die Funktion
processLSoben() nach 100ms gestartet (on_timer wird einfach nur
erweitert). In diesem Beispiel können max. 15 Timer gleichzeitig aktiv
sein (TIMER_BUFFER_SIZE evtl. erweitern).

-----------------------------------------------------------------------------------------------------------

#define    TIMER_EMPTY            0
#define     TIMER_DELAY            1
#define     TIMER_1            2
#define     TIMER_2            3
#define    TIMER_LS_UNTEN        4    
#define    TIMER_LS_OBEN            5
#define    TIMER_TLE6220            6
#define    TIMER_KEY            7
#define    TIMER_DISPLAY            8
#define    TIMER_TAS_LICHT        10
#define    TIMER_LICHT            11
#define    TIMER_RECEIVE            12
#define     TIMER_SEND            13
#define    TIMER_RECEIVE_EXIT        14
#define    TIMER_RECEIVE_DELAY        15

#define     TIMER_BUFFER_SIZE        15
#define    TIMER_IRQ_PRIORITY        1


#pragma INTERRUPT  ta0int       /* Declares interrupt handler ta0  */


void initTimer( void);
void delay_ms( unsigned int delay);
void on_timer(char type);
void setTimer(unsigned int duration, char type);
void process_timers( void);
void killTimer(char type);

struct TIMER
{
    char timer_id;
    unsigned int end_time;
};

static struct TIMER  timer_queue[TIMER_BUFFER_SIZE] = ;
unsigned int global_ms_timer;
unsigned char ucDelayTimerOn;



/****************************
*        Start of code      *
****************************/

void initTimer( void)
{
    ta0ic = 0;                // disable timer irq
    ta0mr = 0x40;            // set Timer Mode
    ta0ud = 0;            // set count down    
    ta0   = 0x800;            // set 1mS
    ta0s  = 1;                //get ready
    ta0ic = TIMER_IRQ_PRIORITY;
}

void delay_ms( unsigned int delay)
{

    ucDelayTimerOn = 1;
    setTimer( delay, TIMER_DELAY);
    while( ucDelayTimerOn);
}



void on_timer(char type)
{
    switch (type)
    {
    case TIMER_DELAY:            ucDelayTimerOn = 0;
                        break;
    case TIMER_LS_UNTEN:            processLSunten();
                        break;
    case TIMER_LS_OBEN:            processLSoben();
                        break;
    case TIMER_TLE6220:            processTLE6220();
                        break;
    case TIMER_KEY:                processKey();
                        break;
    case TIMER_TAS_LICHT:            processTasterLicht();
                        break;
    case TIMER_LICHT:            processLicht();
                        break;
    case TIMER_DISPLAY:            processDisplay();
                        break;
    case TIMER_SEND:            processSend();
                        break;
    case TIMER_RECEIVE_EXIT:        processReceive( type);
                        break;
    case TIMER_RECEIVE_DELAY:        receiveOn();
                        break;

    }
}


void far ta0int(void)
{

    global_ms_timer++;
       process_timers();


}

void setTimer(unsigned int duration, char type)
{
char i;

    ta0ic = 0x00;
// Disable timers

    for (i = 0; i < TIMER_BUFFER_SIZE; i++)        
    {
        if (timer_queue[i].timer_id == TIMER_EMPTY)
// Suche nach freien Timern
        {
            timer_queue[i].timer_id = type;
            timer_queue[i].end_time = duration +
global_ms_timer;
            ta0ic = TIMER_IRQ_PRIORITY;
// Re-enable timers
            return;
        }
    }

    ta0ic = TIMER_IRQ_PRIORITY;
// Re-enable timers

}

void process_timers( void)
{
char i;


     for (i=0;i<TIMER_BUFFER_SIZE;i++)
     {
           if ((timer_queue[i].end_time == global_ms_timer) &&
               (timer_queue[i].timer_id != TIMER_EMPTY))
         {
              on_timer(timer_queue[i].timer_id);
             timer_queue[i].timer_id = TIMER_EMPTY;
             timer_queue[i].end_time = TIMER_EMPTY;
        }
    }
}

void killTimer(char type)
{
char i;

    ta0ic = 0x00;    // Disable timers..

    for (i = 0; i < TIMER_BUFFER_SIZE; i++)
    {// loop through and check for timers of this type, then kill
them...
        if (timer_queue[i].timer_id == type)
        {// kill timers...
            timer_queue[i].timer_id = TIMER_EMPTY;
            timer_queue[i].end_time = TIMER_EMPTY;
            ta0ic = TIMER_IRQ_PRIORITY;    // Re-enable
timers..
            return;
        }
    }


    ta0ic = TIMER_IRQ_PRIORITY;    // Re-enable timers..

}

---------------------------------------------------------------------------------------------------------------------------------


Tschö
   Dirk

Re: At90S2313 EEPROM auslesen mit Wartezeit
Hallo Dirk,

Dirk Ruth schrieb:

Quoted text here. Click to load it

Leichter gesagt, als getan ;-) Ich bin ja schon froh, dass der Atmel
erst mal das tut, was ich möchte... wenn auch noch nicht alle Wünsche
implementiert sind...

Quoted text here. Click to load it

Hmmm... wird denn der Wert nicht bis zur nächsten Abfrage im
entsprechenden Register gehalten? Wie das bei Störungen aussieht kann
ich natürlich nicht beurteilen...

Quoted text here. Click to load it

OK, das sehe ich ein... ich muss es jetzt "nur noch" verstehen und
umsetzen können...

[Quellcode (war es C?) gelöscht]

Uih... schwere Kost ;-) Das muss ich erst noch 20-30 mal lesen und
begreifen, was Du damit gemeint hast...

Vielen Dank für Deine Anregungen und einen schönen Feiertag!

Kai

--
***          homepage: http://www.erosoft.de ***
Die angegebene Mailadresse ist replyfähig, sie verfällt
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit
On Fri, 03 Oct 2003 15:20:59 +0200, Kai Ebersbach

Quoted text here. Click to load it


Wird schon noch.

Quoted text here. Click to load it
Schon richtig. Aber wenn ein neuer Wert kommt (worst case: Störung)
oder Du Dich bei Deinen Wartezeiten vertan hast, dann ist es weg.

Quoted text here. Click to load it

Viele Designs arbeiten auch mit Batterieversorgung, dann frist das
polling auch nur sinnlos Strom.

Quoted text here. Click to load it

Es war C.
Quoted text here. Click to load it


Was ich da gepostet hatte war ein Entwurfsmuster (Pattern) für eine
Timerroutine (hier für einen M16C). Du must lediglich die
Timer-Initialisierung anpassen, dann läuft die auf jedem
Microcontroller. Brauchst also nicht mehr jedesmal von vorn anfangen
und die Fehler da zu suchen.

Kann man natürlich noch erweitern, dass auch Callback-Funktionen
möglich sind, aber das gibt's in Basic ohnehin nicht.

Tschö
  Dirk

Re: At90S2313 EEPROM auslesen mit Wartezeit
Hallo Dirk,

Dirk Ruth schrieb:

Quoted text here. Click to load it

Ja, mühseelig ernährt sich das Eichhörnchen ;-)
Momentan bin ich am 1024 byte Limit der Demo-Version von BASCOM AVR
angekommen...

Quoted text here. Click to load it


Bei einigen kritschen Anwendungen sicherlich ein wichtiger Aspekt...
wenn bei meinem Projekt ein Zeichen verloren geht, muss es eben noch mal
gesendet werden... Ich behalte Deine Anregung aber im Hinterkopf.

Quoted text here. Click to load it

So weit habe ich noch gar nicht gedacht... aber Du hast völlig recht,
für eine Optimierung ein wichtiger Punkt.

Quoted text here. Click to load it

Ich habe es mir in meinen Sammelordner abgelegt, aus dem ich mir immer
mal häppchenweise etwas zum Verarbeiten raushole... Manchmal qualmt mir
allerdings als Hobbyist der Kopf, dann lege ich das alles erst mal zur
Seite ;-).

Viele Grüsse

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit
On Sat, 04 Oct 2003 18:19:14 +0200, Kai Ebersbach

Quoted text here. Click to load it

Vergiss das mit dem Basic. Bei Microcontroller wird es hin und wieder
notwendig sein "Low Level" zu programmieren, also auf Adressen
zuzugreifen, zu verschieben und überhaupt mit Zeigern zu arbeiten. Mit
Basic wirst Du da auf die Dauer nicht glücklich. Und wenn Du die
Grundlagen erstmal kapiert hast, dann willst Du auch schnell mehr
versuchen.

Besorg Dir einen richtigen Compiler zum programmieren. Der GCC ist
dafür nicht schlecht, oder wenn Du Geld ausgeben möchtest, dann kann
ich Dir auch den ICC-AVR empfehlen. Da gibt's dann auch die richtigen
Librarys im Quellcode dazu.

Basic ist, wie der Name schon sagt,  wirlich nur Basic.

Tschö
   Dirk

Re: At90S2313 EEPROM auslesen mit Wartezeit

Quoted text here. Click to load it


Wobei auch für den GCC dank der weiten Verbreitung einiges zu haben ist. Und
die meisten Leute, die Libs dafür machen, geben die auch unter der GPL
weiter. Ich habe immer den Eindruck, daß es nichts gibt, was nicht auch für
den GCC zu haben ist - ist allerdings nur meine Hobby-Erfahrung.
Industriell mag das anders aussehen (v.a. Support etc.).

Quoted text here. Click to load it
Jepp...

Sebastian


Re: At90S2313 EEPROM auslesen mit Wartezeit
Hallo Dirk,

Dirk Ruth schrieb:

Quoted text here. Click to load it

Ich habe mich nun entschlossen, dasselbe Programm noch einmal zu
schreiben und zwar gleich in Assembler. Dazu kann ich auch die
kostenlosen Werkzeuge, die Atmel verfügbar macht, benutzen.

Quoted text here. Click to load it

Bevor ich mich in eine weitere Hochsprache einarbeite, nehm ich gleich
den harten Weg ;-) Da ich ja Zeit habe, kann ich mich da langsam Schritt
für Schritt durchwühlen und lerne dabei sicher gleich mehr über den
inneren Aufbau der Mikrocontroller.

Herzlichen Dank für alle Anregungen und viele Grüsse

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit

Quoted text here. Click to load it

In meinem Projekt habe ich all diese Geschichten mit einem Timer gelöst, der
immer mitläuft und jede ms ausgelöst wird. Wann immer das Hauptprogramm
eine Aktion ausführen will, macht sie das nicht selbst, sondern setzt ein
Flag (z.B. updateLCD). Wenn der Timer überläuft, wird der Flagwert
dekriminiert (falls > 0). Ist er null, wird die entsprechende Routine
aufgerufen und führt die Aktion aus. Wenn man keine Boolean-Variablen
verwendet (gibt's beim AVR sowieso nicht), kann man auch festlegen, daß
eine Aktion z.B. nur alle 10ms ausgeführt wird (Flag auf 10 setzen, 9 Timer
verstreichen ohne Aktion, bei der 10. wird ausgeführt). Außerdem läßt sich
die Aktion damit auch mehrfach ausführen (Aktionsroutine setzt selbst das
Flag wieder auf 10). Zur Initialisierung muß dann nur einmalig das Flag
gesetzt werden. Außerdem kann das Hauptprogramm ein Update "außer der
Reihe" anordnen, indem das Flag auf 1 gesezt wird (Update beim nächsten
Timer, unabhängig vom aktuellen Zählerstand).

Zusätzlich kann man natürlich noch Queues einbauen (jede Aktion führt genau
einen Queue-Befehl aus). Etwas haushalten sollte man nur mit den Zähl- bzw.
Flagvariablen (ich muß CF lesen, brauche also von den 1024 Bytes allein 512
für den Sektorbuffer, variable Strings etc. brauchen auch ganz schön);
schließlich müssen das globale Variablen sein und belegen dauerhaft
Speicher. Also char verwenden (evtl. unsigned, mehr als 256 Timer-Ticks
wird man nicht brauchen - sonst paßt man die Timerfrequenz entsprechend
an).

Wenn Du magst, kann ich Dir auch gerne meinen Quellcode schicken (AVR-GCC,
ist auch nur rudimentär kommentiert, form follows function ;o)) --> PM

Sebastian

Re: At90S2313 EEPROM auslesen mit Wartezeit
Hallo Sebastian,

Sebastian Voitzsch schrieb:

Quoted text here. Click to load it

So in der Form hatte ich es auch mal überlegt... das Ganze wurde dann
allerdings so aufwendig, dass Bascom AVR in der Demo Version streikte,
weil da nur 1024 byte Code zulässig sind...

Ich habe nun erst einmal MaWins Vorschlag verfolgt und es funktioniert
momentan so wie es soll. Da das ganze Projekt allerdings noch nicht
endgültig ausgetüftelt ist, kann und wird sich sicher noch einiges
ändern und ich versuche dabei auch gern andere Ansätze, man wird ja
nicht dümmer dadurch ;-)

Nun muss ich mir erst mal BASCOM AVR in der Vollversion kaufen, damit
ich auch die 2048 byte voll nutzen kann ;-) Kennt da jemand noch eine
Bezugsquelle ausser den auf der MSCELEC-Homepage genannten Distributoren?

Quoted text here. Click to load it

Ich würde mich sehr darüber freuen, die Adresse
usenet042003nospam@kai-ebersbach.de ist gültig. Ich habe allerdings wie
wohl fast jeder Usenetteilnehmer mit einer Masse von Swens zu kämpfen,
die das Mailen nicht gerade schöner macht :-(, daher der Wechsel (hoffe
Swen verschont die Mailadresse weil "spam" drin vorkommt). Die alte
Adresse ist aber auch noch eine Weile gültig.

Viele Grüsse

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.
Re: At90S2313 EEPROM auslesen mit Wartezeit

Quoted text here. Click to load it

Nimm halt AVR-GCC und Du bist die Lizenzquerelen los. Mich würde es auch
nicht wundern, wenn C zu kleinerem Code führt.

Quoted text here. Click to load it

SWEN dürfte eher interessieren, ob er die Adresse in irgendwelchen
Adreßbüchern oder im Web findet, nicht, ob SPAM drin vorkommt. Von mir
jedenfalls gibt's keinen SWEN, IMHO ist KMail dafür nicht anfällig ;o)

Sebastian


Re: At90S2313 EEPROM auslesen mit Wartezeit
Hallo Sebastian,

Sebastian Voitzsch schrieb:

Quoted text here. Click to load it

Wie ich schon zu Dirks Posting schrieb, wähle ich nun den harten Weg und
schreibe das Programm Schritt für Schritt in Assembler neu.

Quoted text here. Click to load it

In d.a.n.a.m  wird z.Zt. diskutiert und ausprobiert, ob Mailadressen die
"spam" enthalten verschont werden... daher der Versuch.

Quoted text here. Click to load it

Von mir gibts auch keinen, selbst Mozilla führt <iframe> Tags nihct
einfach aus ;-). Gemeint war aber, dass Swen neben lokalen Adressbüchern
und HTML-Files auch Newsgroups auf Mailadressen durchforstet und sich
dann innerhalb kürzester Zeit mehrfach an die gefundenen Adressen
verschickt. Es hat gerade mal eine Stunde gedauert nachdem ich mit der
frischen Adresse usenet042003@kai-ebersbach.de gepostet hatte und die
ersten Swens kamen herein :-(. Egal... das ist hier eh OT.

Vielen Dank für Deine Anregungen und viele Grüsse

Kai

--
Die angegebene Mailadresse ist replyfähig, sie verfällt
jedoch zum Ende eines jeden Quartals und wird durch eine
We've slightly trimmed the long signature. Click to see the full one.

Site Timeline