www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PORTA setzen und wieder zurücksetzten


Autor: Carsten Köditz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich habs jetzt hingekriegt des ich den µC (atmel Atmega128)
programmieren kann . Jetzt wollt ich einfach mal zum test eine LED
blinken lassen dafür hab ich einfach den PORTA = 0x01 gesetzt ne for
Schleife reingemacht und wieder zurückgesetzt die LED blinkt zwar aber
immer im gleichen Rythmus egal wie lang ich die for Schleife mach kann
mir jemand sagen woran des liegt wäre super !
Vielen Dank schonmal !

Gruß
Carsten

Autor: Frank Linde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne Deinen Sourecode gesehen zu haben, wird Dir das wohl niemand sagen
können. Aber raten kann man ja mal: Vielleicht optimiert der verwendete
Compiler die Schleife immer weg? => Compileroptionen prüfen. Es ist
jedenfalls erwiesen, dass man Zeitschleifen unterschiedlicher Länge für
die AVR programmieren kann. ;-)

Gruß, Frank

Autor: Carsten Köditz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok mein Source Code is

while (1)
{

if (PORTA == 0x00)
{
PORTA = 0x01;
for (i=0;i>=10000;i++)
{;}
}
else
{
PORTA = 0x00;
for (i=0;i>=10000;i++)
{;}
}
}

Autor: Frank Linde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hhm, bin ja nicht gerade ein C-Freak, aber IMHO ist das soweit in
Ordnung. Mit welcher Taktfrequenz läuft denn Dein Chip und welche Werte
für die Schleife hast Du ausprobiert? Und wie schnell blinkt die LED
mit dem Schleifenwert 10000 ungefähr?

Gruß, Frank

Autor: Carsten Köditz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Controller läuft mit 16 MHz.

Ich habe schon 10 000, 100 000, 1 mio, 2 mio ausprobiert,
aber da ändert sich nichts...

Die LED blinkt etwa 10 mal in der sek. habe die Frequenz nicht
gemessen.

Gruß

Carsten

Autor: Fritz Ganter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du weisst schon dass das ein 8bit Prozessor ist, oder?
Also wenn i ein int ist, dann hat er nur 16bit, dh. bei 32667 ist
schluss.

Autor: Daniel Jelkmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Carsten,

Dein Code ist nicht ganz richtig.
Die For-Schleife wird kein einziges Mal durchlaufen, weil die
Abbruchbedingung "verkehrt rum" ist.
Anstatt
 for (i=0;i>=10000;i++)
hast Du wohl
 for (i=0; i < 10000; i++)
gemeint. Ich denke Du möchtest, dass er die Schleife 10.000 mal
durchläuft.

Und der zweite Punkt:
Ich vermute ganz stark, dass Frank recht hat und die Schleife komplett
wegoptimiert wird. Der Compiler erkennt, dass eine solche Schleife
keinen Sinn macht und entfernt sie...
Probier mal das folgende:
for (i=0; i < 10000; i++)
 asm volatile ("nop");

Das volatile verhindert, dass der Compiler das NOP (=no operation)
wegoptimiert.

Was mir noch einfällt: Ich weiss nicht, wie die Pins standardmässig
geschaltet sind, also ob als Ausgang oder als Eingang. Daher würde ich
vor der while()-Schleife sicherheitshalber den Pin mit der LED als
Ausgang schalten.

Bye
  Daniel Jelkmann

Autor: Frank Linde (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Daniel: Aua! Stimmt natürlich, habe ich aber auch nicht gesehen.
<schnarch> Aber egal, ob die Schleife nun wegoptimiert oder sowieso
nicht ausgeführt wird, warum blinkt die LED dann mit so einer niedrigen
Frequenz? Soooooooooooooooooooooo langsam kann C gegenüber ASM doch nun
wirklich nicht sein. ;-)

Gruß, Frank

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
könnte ein geweckter Wachhund sein, der zubeisst.

Autor: Divison (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs doch mal damit!

#include <avr/io.h>


unsigned short waittime=1000;

#define AVR_CLK (8000000)
#define LOOPS_PER_US (AVR_CLK/4)
#define LOOPS_PER_MS (AVR_CLK/1000/4)

void delay_ms(unsigned short ms)
{
        if (!ms)
                return;

        /* the inner loop takes 4 cycles per iteration */
        _asm__ __volatile_ (
                "1:                     \n"
                "       ldi r26, %3     \n"
                "       ldi r27, %2     \n"
                "2:     sbiw r26, 1     \n"
                "       brne 2b         \n"
                "       sbiw %0, 1      \n"
                "       brne 1b         \n"
                : "=w" (ms)
                : "w" (ms), "i" (LOOPS_PER_MS >> 8), "i" (0xff &
LOOPS_PER_MS)
                );
}

void blink(){
  sbi(PORTB,1);
  delay_ms(waittime);
  cbi(PORTB,1);
  delay_ms(waittime);
  return 0;
}

int main(void){

PORTB = 0x00;
DDRB = 0xFF;

while(1){

  blink();

}

return 0;

}

Autor: Carsten Köditz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen!

Danke euch für eure Mühe!

Ich hab nun noch nen Ansatz. Ich hab versucht das über ein
"Unterprogramm" zu lösen.

while(1){

  if (PORTA = 0x01)
  { PORTA = 0x00;
    pause();
     }

     else
     { PORTA = 0x01;
       pause();
        }

}

}

void pause (void)

  {
  unsigned char i;
  for (i=0;i>=32667;i++);
  }

Kann mir einer von euch sagen wie ich die for-Schleife verschachteln
kann, so das ich doppelte oder dreifache oder x-fache Zeit raus
bekommen?

Benutze nach wie vor den ATmega128 von Atmel!

Gruß

Carsten

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
deine Abbruchbedingung ist wieder falsch :-)
Und was ist mit dem watchdog? Wenn dein 1. Programm geblinkt hat, ist
eigentlich die einzige Erklärung ein watchdogreset.
Schleifenzeit erhöhen ist keine grosse Sache, du kannst den Prozessor
innerhalb der Schleife mit irgendwas beschäfigen, jeder Behehl kostet
Zeit. Alternativ keine Int, sondern eine long-Variable verwenden.
Der bessere Weg wäre, einen Timer einzusetzen.
z.B. Timer0, erzeugt jede 1ms einen Timerinterrupt (Timer mit passendem
Vorteiler im CTC-Modus starten, passenden Wert ins OCR-Register
schreiben, in der ISR zählst du nur eine globale Variable hoch.)
im Hauptprogramm kannst du die Variable abfragen und somit definierte
Verzögerungen erzeugen.

Autor: Daniel Jelkmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi nochmal...

Ich war gestern wohl halb blind ;)

if (PORTA = 0x01)
geht so nicht. Erstens ist das keine Abfrage auf Gleichheit, sondern
eine simple Zuweisung. Vom Sinn her war wohl eher PORTA == 0x01
gemeint.
Und zweitens geht das mit der Abfrage von PORTA nicht auf diese Weise,
wenn ich nicht irre. Ich würde mir da ne Variable nehmen, deren Zustand
sich abwechselnd von 1 auf 0 bzw von 0 auf 1 ändert und damit den Wert
der LED am Port wiederspiegelt.

DDRA = 0xFF;   // alle Pins als Ausgänge schalten
int toggle = 0;
while(1)
{
  if (toggle)
  {
    PORTA = 0x00;
    toggle = 0;
  }
  else
  {
    PORTA = 0x01;
    toggle = 1;
  }
  pause();
}

Hab das jetzt nicht probiert sondern einfach mal runtergeschrieben, ich
hoffe das läuft so ;)

Zum Thema Pause: es dürfte doch genug Delay-Routinen geben, die im Netz
rumschwirren oder sogar mit dem Compiler mitgeliefert werden. Warum das
Rad immer neu erfinden?

Bye
  Daniel Jelkmann

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.