Forum: Mikrocontroller und Digitale Elektronik genaues Timing mit ATMEGA8 unter C


von Tobi (Gast)


Lesenswert?

Hallo zusammen,

ich versuche mit einem ATMEGA8 eine Multiplexansteuerung zu bauen. Je 6 
Sende und Empfangskanäle sollen betrieben werden. Hierzu habe ich 
folgenden Code Programmiert:

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{int i,j,x,y;
PORTC = 0b00000000;
PORTD = 0b00000000;
DDRC  = 0xff;
DDRD  = 0xff;

for (;;)
   {x = 32;
     for (i=0; i<6; i++)
      {PORTC = x;
    x = x/2;
    y = 32;
     for (j=0; j<6; j++)
      {PORTD = y;
       y=y/2;
       _delay_us(25);}
      }
   }
}

Ist da was sehr dumm? Oder wie kann ich den Ablauf präziser gestalten? 
Vielen Dank für eure Antworten!

Grüße Tobi

von Falk B. (falk)


Lesenswert?

@ Tobi (Gast)

>ich versuche mit einem ATMEGA8 eine Multiplexansteuerung zu bauen. Je 6
>Sende und Empfangskanäle sollen betrieben werden.

Was für Kanäle? Du sprichst in Rätseln.

MFG
Falk

von Durchblicker (Gast)


Lesenswert?

Nö. Dumm ist das nicht. Wenn Du auf der C-Schiene bleiben willst, geht 
es nicht viel genauer.

Allerdings sieht Dein Code ein wenig nach Gefahrensucher aus, da Du zum 
Bitschieben die Division einsetzt. Somit verlässt Du Dich implizit auf 
die Optimierungsfähigkeiten des Compilers. Wenn der gerade seine Tage 
hat, ruft er Dir die Divisionsroutine auf und dann geht Dein Timing den 
Bach runter.

Schreibe einfach hin, was Du willst:

x >>= 1;
y >>= 1;

Weiterhin spannend bleibt, was Du da multiplext...!?

von Tobi (Gast)


Lesenswert?

Guten Abend zusammen,

da muss ich jetzt doch bisschen ausholen. Geplante ist eine Erweiterung 
des Elektroglottographie Verfahrens, wo durch die Impedanzänderung des 
Halses auf Höhe der Stimmlippen ein Rückschluss auf deren momentane 
Öffnungsphase möglich ist.

http://de.wikipedia.org/wiki/Elektroglottograph

Idee in meiner Dipl. Arbeit war es, das auf mehrere Messkanäle zu 
erweitern und so neben dem Öffnungsgrad noch eine Ortsinformation vom 
Kehlkopf zu bekommen.

http://www.ukaachen.de/go/show?NAVDV=0&ID=4364732&DV=0&NAVID=1022836&COMP=project

Im Moment will ich meinen Aufbau rationalisieren und habe ihn deswegen 
verschlankt und mit dem ATMEGA8 in der Ansteuerung ausgestattet.

Meine zugegebenermaßen unschöne Lösung ist es nun, die Portzustände in 
einer Endlosschleife alle untereinander zu schreiben und jeweils ein 
_delay_us dazwischen zu schreiben. Sehr präzise!!!

1.) Sonnst wär mir nur eingefallen an der Arbeitstaktfrequenz zu spielen 
und ihn schneller arbeiten zu lassen und die Pausen relativ zu 
verlängern....
2.) Oder mit Timern und Interrups zu arbeiten!?!?

Aber es funktioniert nun auch so, nur der Sprung am Ende zum Anfang 
benötigt Zeit, die ich aber habe, da zu Beginn eines Zyklusses jeweils 
ein Sync. mit dem Auswerterechner erfolgt.

Grüße aus der Phoniatrie, Tobi

von Hannes L. (hannes)


Lesenswert?

Ich persönlich würde das mit Timer-Interrupt machen. Da nur ein 
Intervall benötigt wird, bietet sich der CTC-Mode an. Aus Gewohnheit 
würde ich es aber in ASM machen, C ist nicht mein Ding.

Wenn das Programm weiter nix tun soll, schafft es das Multiplexing im 
Zeitraster von 25µs bereits mit 1MHz Takt.

Ein Tiny2313 wäre dafür aber auch ausreichend.

...

von Falk B. (falk)


Lesenswert?

@ Tobi (Gast)

>Meine zugegebenermaßen unschöne Lösung ist es nun, die Portzustände in
>einer Endlosschleife alle untereinander zu schreiben und jeweils ein
>_delay_us dazwischen zu schreiben. Sehr präzise!!!

Also du willst die Ports in serh regelmässigen Abständen einlesen und 
speichern. Das hat mit Multiplexing so ziemlich gar nichts zu tun.
Aber wo wird in deinem Code ein Port eingelesen?

>2.) Oder mit Timern und Interrups zu arbeiten!?!?

Bei 25 us lohnt das fast nicht.

MfG
Falk

von Durchblicker (Gast)


Lesenswert?

Kompaktere Version Deines Codes:

int main(void)
    {
    int x,y;
    DDRC = 0xff;
    DDRD = 0xff;
    for (;;)
        {
        for (x=32; x>0; x >>= 1)
            {
            PORTC = x;
            for (y=32; y>0; y >>= 1)
                {
                PORTD = y;
                _delay_us(25);
                }
            }
        }
    }

Damit sind zwei Variablen eliminiert und Du erreichst "härtere" 
Echtzeit.

Wahrscheinlich täte sogar

int main(void)
    {
    DDRC = 0xff;
    DDRD = 0xff;
    for (;;)
        {
        for (PORTC=32; PORTC>0; PORTC >>= 1)
            for (PORTD=32; PORTD>0; PORTD >>= 1)
                _delay_us(25);
        }
    }

funzen, aber das sollte man testen.

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.