Mein erster Code auf dem Mega 32: Lauflicht
Servus
Ich habe heute mal die Zeit gefunden mir ein kleines Lauflicht zu Programmieren. Ich hab zwar keine Experimentierplatine, macht aber auch nix weil das AVRStudio mir ja erlaubt fröhlich zu Simulieren.
Erstmal der Code, dann meine Fragen:
Code:
#include <avr/io.h>
#ifndef F_CPU
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert
(z.B. durch Übergabe als Parameter zum Compiler innerhalb
des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
"nachträgliche" Definition hinweist */
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
#define F_CPU 16UL /* Quarz mit 3.6864 Mhz */
#endif
#include <stdint.h>
#include <util/delay.h>
struct s_bPORTB{
uint8_t PIN;
}bPORTB[8];
int main (void) {
DDRB = 0xff;
DDRA = 0x00;
bPORTB[0].PIN=PINB0;
bPORTB[1].PIN=PINB1;
bPORTB[2].PIN=PINB2;
bPORTB[3].PIN=PINB3;
bPORTB[4].PIN=PINB4;
bPORTB[5].PIN=PINB5;
bPORTB[6].PIN=PINB6;
bPORTB[7].PIN=PINB7;
while(1) {
if(PINA & (1<<PINA1)){
for(int i=0; i<8; i++){
PORTB &= (1<<bPORTB[i].PIN);
PORTB |= (1<<bPORTB[i].PIN);
_delay_ms(10);
}
}
}
/* wird nie erreicht */
return 0;
}
Sooo, das läuft auch alles soweit. Dennoch macht es zwei drei Problemchen... 1. macht _delay_ms(10); nicht das was es soll^^ die angabe in den Klammern sollte eigentlich eine Verzögerung in Millisekunden darstellen. Ergo: Wenig wert, wenig Pause, viel Wert, viel Pause. Ist der Wert allerdings größer als 10 springt er in der delay.h rum macht aber sonst nix mehr. Und bei 10 ist die Pause ziemlich genau eine Sekunde => Sehr komisch.
2. Wie kann ich einen Timer Interrupt abfragen? Sprich: Timer Initialisieren, Timer so laufen lassen das zum Beispiel 10Takte/sekunde (sollten dann 100mHz sein oder?) habe und schluss endlich immer dann PINB eins Hochzählen wenn der Timer hochgezählt wird.
3. Finde ich meine Lösung die Pins an Port B hoch zu zählen nicht sooo Elegant. Ginge das Eleganter?
4. AVR Studio sagt unter "Prozessor" 4MHz - in den Controller Optionen habe ich 16000000Hz eingestellt ... finde ich etwas Merkwürdig ^^
Achja, laufen lassen tu ich das immer so:
Build -> Start Debugging -> AutoStep
Und dann entsprechen PinA1 anklicken und so auf 1 setzen (was nich wirklich gut funktioniert wie ich finde, das reagiert arg blöd (oder brauch ich auch da einen debounce?)
So ich hoffe das ist soweit verständlich. Danke fürs lesen und helfen :)
edit: die lösung mit der ForSchleife ist auch nicht so schön, einfach der Tatsache wegen das das ganze nicht an Ort und Stelle Stoppt sondern immer bis zum Ende durchläuft (logisch). Die Lösung könnte eine While Schleife sein oder? Also
Code:
while(PINA1==1){
PINB.i=1;
i++;
}
i=0;
So als halber Pseudocode....
Oder?
grüße
Liste der Anhänge anzeigen (Anzahl: 2)
Re: Mein erster Code auf dem Mega 32: Lauflicht
Hi,
es ist wichtig, dass Du im AVRStudio die Parameter richtig einstellst. Einmal unter "Project|Configuration Options|Frequency" (siehe erste Anlage) und dann unter "Debug"AVR SimulatorOptions" oder direkt im Frequenzfenster des Simulators. Ich habe Deinen Code simuliert und komme auf knapp über 10ms (siehe Anlage 2). Nimm die ganze FCPU-Sache aus Deinem Code und stelle alles im AVRStudio wie oben gesagt ein. In meinem Beispiel (1. Anlage) habe ich "keine Optimierung (=-O0)" gewählt; typischerweise nimmt man mindestens "-O1".
Dein Code ist etwas holprig: Statt
Code:
PORTB &= (1<<bPORTB[i].PIN);
PORTB |= (1<<bPORTB[i].PIN);
kannst Du z.B. direkt (1<<i) verwenden. Übrigens: Beim ATmega32 kann man die einzelnen Ausgangspins nicht mit Hilfe von PINx |= PINx "togglen" (20:04 editiert: verkehrt -- muss heißen: "PINx |= KONSTANTE;"), aber bei den neueren ATmegas geht das!
Hier eine Lösung für Deine Schleife:
Code:
while(!(PINA & (1<<PINA1))){
for(int i=0; i<8; i++){
blablabla();
}
}
Viel Erfolg und Spaß bei der Weiterentwicklung!
Gruß
Fred
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
Zitat:
Zitat von sternst
...Wenn man die Funktionen aus util/delay.h verwenden will, ist es sehr wichtig, die Optimierungen einzuschalten.
Stimmt -- das hätte ich besser dazuschreiben sollen! Mein Beispiel war also nicht 100% treffend, obwohl ich erwähnt habe, dass man eine Optimierungsstufe >0 einschalten sollte!
Zitat:
Zitat:
Beim ATmega32 kann man die einzelnen Ausgangspins nicht mit Hilfe von PINx |= PINx "togglen", aber bei den neueren ATmegas geht das!
Auch bei neueren ATmegas klappt das so nicht. Mit "PINx |= PINx" bekommt man den Ausgang nur von 1 auf 0, aber nicht wieder zurück.
Dass das Toggeln so nicht geht, ist nicht korrekt: siehe Anlage (Datenblatt Atmega3290P); viele andere der neueren AVRs können das auch!
Hier ein Beispiel zum Ausprobieren im Simulator (Atmega3290P einstellen!):
Code:
#include <avr/io.h>
int main (void) {
while(1) {
DDRB = 1;
PORTB=1;
for (uint8_t i=0;i<10;i++)
asm volatile("sbi 3,0"); // = sbi PINB, 0
}
return 0;
}
// -O0, Breakpoint auf die Zeile mit "asm volatile..." setzen;
Gruß
Fred