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
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
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++) {;} } }
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
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
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.
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
@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
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; }
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.