Hallo, Ich habe eine STK500, der Tiny läst sich ansprechen und programieren nur leider funzt mein Code nicht. Die LEDs blinken aber die LED an PB0 wird nicht durchgeschaltet auch wenn S1 mehrmals gedrückt wurde. Der TimerA/Counter ist auf Vergleich eingestellt und soll nach 5 mal S1 drücken T0A/PB0 durchschalten. Die LED soll dann 0,5 sec brennen und dan zurückgesetzt werden. Wo liegt der Fehler, kann mir einer freundlicherweise weiter helfen? Gruß Olli
Musst du Kulitinte sparen? Die Pins hättest du doch angeben können, oder? http://www.atmel.com/dyn/resources/prod_documents/doc2535.pdf Schalter ist active-high an PB2 (T0). LEDs sind active-high an PB0, PB1 und PB4 > PORTB |= (1 << PB3); // LED an PB3 einschalten > if (PB0 == 1) // wenn der Counter PB0 eingeschaltet hat Passt nicht zu Schaltplan/Datenblatt
> if (PB0 == 1) // wenn der Counter PB0 eingeschaltet hat
Ist auch unsinnig. Nach dem C-Präprozessor steht da: if (0 == 1). Da
sollte eine Warnung beim Kompilieren kommen.
@Oliver PB0 einfach nur als Zahl 0 definiert und nicht an einen Pin gebunden. Um zu prüfen, ob ein Bit 1 ist, muss man diesen ausmaskieren und den Ausdruck nach einem Wert ungleich 0 überprüfen.
1 | |
2 | if (PINB & (1<<PB0)) // wenn der Counter PB0 eingeschaltet hat |
3 | // dann nach 500ms zur�cksetzen
|
4 | {
|
5 | _delay_ms (500); // 500 ms warten |
6 | PORTB &= ~(1 << PB0); // PB0 aus, ist OC0A |
7 | }
|
Siehe http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29 MfG Mark
Hier noch das Layout mit den zuordnungen der Pins beim ATtiny13.
Ich habe keine Warnungen.
Das erste Problem muß auch schon weiter oben liegen weil der
Timervergleich schon nicht funktioniert.
in der If Schleife wird ja nur das vom Timer gesetzet Bit am Ausgang
wieder gelöscht.
> if (PB0 == 1);
kann ich damit nicht auch den Zustand von PB0 abfragen und auswerten?
Gruß Olli
> TCCR0A |= (1 << CS00) | (1 << CS01) | (1 << CS02);
Falsches Register, müsste TCCR0B sein.
Initialisierung von TCCR0A kommt mir auch Spanisch vor. Ich vermisse den CTC Modus.
> if (PB0 == 1); > kann ich damit nicht auch den Zustand von PB0 abfragen und auswerten? Abfragen kannst du nur die Register PORTB oder PINB, PB0 ist bloß ein #define für die Pinnummer in diesen Registern.
Warum soll ich TCCR0B nehmen? Sind A und B nicht gleichwertige 8-Bit Timer? Wenn ich mich für Timer A entscheide muss ich doch alle Register für A benutzen? > OCR0A = 4; // Vergleichswert (-1) einstellen, 5xTaster dr�cken das dürfte doch richtig sein, im Output Compare Register eine vier eintragen, dann wird beim darauffolgenden Takt der Signalzustand geändert. > TCCR0A |= (1 << COM0A0) | (1 << COM0A1); // OC0A ein bei Vergleichswert Im Datenblatt steht das COM0A0 und COM0A1 auf 1 gesetzt im Vergleichsmodus bedeutet. > TCCR0A |= (1 << CS00) | (1 << CS01) | (1 << CS02); // Externe Clock an T0, steigende Flanke CS00, CS01, CS02 auf 1 bedeutet steigende Flanke auswerten. Was ist denn jetzt noch falsch bei der Ini des Timers? Die If Bedingung habe ich jetzt so wie von Mark vorgeschagen geändert: if (PINB & (1<<PB0)) // wenn der Counter PB0 eingeschaltet hat // dann nach 500ms zur�cksetzen { _delay_ms (500); // 500 ms warten PORTB &= ~(1 << PB0); // PB0 aus, ist OC0A }
Hallo. >Warum soll ich TCCR0B nehmen? Sind A und B nicht gleichwertige 8-Bit >Timer? >Wenn ich mich für Timer A entscheide muss ich doch alle Register für A >benutzen? Es gibt keine Timer A oder B; es gibt nur einen Timer0. Und die Register TCCR0A und TCCR0B gehören beide zum Timer0 und haben verschiedene Funktionen. Was du meinst, sind die Compare-Einheiten mit Registern "OCR0A" und "OCR0B" sowie den Ausgängen OC0A und OC0B. Das sind aber keine Timer ...
> TCCR0A |= (1 << COM0A0) | (1 << COM0A1); // OC0A ein bei > Vergleichswert > Im Datenblatt steht das COM0A0 und COM0A1 auf 1 gesetzt im > Vergleichsmodus bedeutet. Richtig, das definiert die Aktion, die bei zutreffendem Vergleich durchzuführen ist. Du brauchst noch die Definition dafrü, was verglichen wird, also TCNT0 gegen OCR0A, damit dann die Aktion durchgeführt wird. Ich halte den CTC-Modus für geeignet, den man mit dem WGM00, WGM01, WGM02 Bits einstellen kann. Leider scheint mein AVR Simulator hier buggy zu sein, so dass ich deine Source nicht im Simulator nachvollziehen kann. Daher auch kein Codevorschlag.
Im Datenblatt steht dass der Timer/Counter 0 TCNT0 ständig mit den
Output Compare Registern OCR0A und OCR0B verglichen wird. Das muss ich
also nicht extra einstellen, der Vergleich findet automatisch statt.
Bei Übereinstimmung wird dann das Output Compare Flag OCF0A oder OCF0B
gesetzt. Falls der Interrupt aktiv ist wird dieser ausgelöst und das
Flag gelöscht, sonst muß es per Software gelöscht werden.
Da ich mit:
> TCCR0A |= (1 << CS00) | (1 << CS01) | (1 << CS02);
// Externe Clock an T0, steigende Flanke
eingestellt habe dass ein externes clock Signal mit steigender Fanke
ausgewertet werden soll muß doch eigentlich bei Übereinstimmung Pin5 =
PB0 = OC0A gesetzt werden?
Ohne an WGM00 oder WGM01 etwas einzustellen?
Gleichzeitig soll doch nach dem Tutorial mit TCCR0A |= (1 << CS00) | (1 << CS01) | (1 << CS02); auch der Timer gestartet werden?
Gibts hier denn heute keinen der mir mit dem Timer weiter helfen kann und den Fehler in meinem Code findet? Hier nochmal der aktuelle Code....
Oliver Henrichsen schrieb: > Der TimerA/Counter ist auf Vergleich eingestellt und soll nach 5 mal S1 > drücken T0A/PB0 durchschalten. Das wird so nicht klappen, Tasten müssen entprellt werden. Du solltest den Timer besser dazu nehmen, die Tasten zu entprellen und die Flanke zu erkennen. Und dann zählst Du einfach ganz profan die Drücke mit einer Variable. Peter
Oliver Henrichsen schrieb: > Gibts hier denn heute keinen der mir mit dem Timer weiter helfen kann > und den Fehler in meinem Code findet? Ein Fehler wurde schon klipp und klar benannt. Aber trotz einer kleinen Diskussion darüber, hast du dich anscheinend entschlossen, einfach zu ignorieren, dass TCCR0A das falsche Register ist.
Ich denke, daß die Kollegen hier die Lust verlieren, da Du nur wild rumbastelst, Deine Sachen nicht lernst und die Hinweise ignorierst. Spezi hat Dir geschrieben, Du sollst TCCR0B nehmen, das ist Dir aber egal. Dem µC dagegen nicht, denn Dein Code:
1 | TCCR0A |= (1 << CS00) | (1 << CS01) | (1 << CS02); |
passt nicht, denn CS00..02 stehen nun mal im TCCR0B. OC0A kann bei Dir gar nix schalten, da er nicht als Output Compare Ausgang definiert ist, das dagegen würde man über COM00..01 auf TCCR0A einstellen. Wenn man den OC0A eingeschaltet hat, dann kann man den Portpin nicht mehr selbst setzen oder löschen, das steht z.B. im ATT13 DB, hier 2535I–AVR–05/08, S.70 Weiter, obwohl Du weist, daß ein Compare Match das OCF0A setzt, übersiehst Du das dies hier in Verbindung mit CTC die Lösung wäre. Hier ignorierst Du noch den Rat von Stefan eben den CTC Modus zu nutzen, das würde dafür sorgen, daß der Zähler bei 4 zurücksetzt und Du nicht 256 mal den Taster drücken musst, um wieder eine Reaktion zu erhalten. Wenn Du fragst, aber dann die Antworten ignorierst, brauchst Du Dich über mangelndes Feedback nicht zu beschweren. Also die Antwort auf Deine Frage: diejenigen die helfen können, gibt's hier schon, nur irgendwann wollen die nicht mehr.
Sorry und Danke, Leider versteht man als Anfänger bzw. gelegenheits Bastler manche Hinweise nicht gleich, insbesondere wenn sie zu knapp formuliert sind und für jemanden der in der Materie steckt alles enthalten was man zur Lösung eines Problems braucht. Ich habe die Hinweise nicht ignoriert sondern versucht nachzulesen und zu verstehen. Als Anfänger experimentiere ich nun mal...zwischen Steckboard, Buch und Datenblatt Wie auch immer, jedenfalls hat mir die ausführliche Hilfe von MWS weitergeholfen und ich habe die richtigen Register gefunden, jetzt entprelle ich noch den Schalter mittels flipflop.
Hallo, ich habe mir gerade diesen Beitrag durchgelesen und auch versucht meinen Tiny nach meinen Anforderungen zu programmieren. Ich würde mich freuen, wenn mir jemand kurz sagen kann ob meine Anstrengungen richtig waren. So wie ich die Register gesetzt habe müsste eigentlich alle 5ms mein Programm durchlaufen werden. Aber die Pins PB0, PB1, PB2 und PB3 kann ich als noramale I/O-Ports nutzen. Vielen Dank für Eure Hilfe! mfg pal Meine main.c lautet:
1 | #include "main.h" |
2 | |
3 | |
4 | ISR(TIM0_COMPA_vect) { |
5 | event++; // Erzeuge event in Software |
6 | }
|
7 | |
8 | |
9 | void init() { |
10 | DDRB = 0x00 | (1 << PINB0) | (1 << PINB1); |
11 | PORTB &= ~((1 << PINB0) | (1 << PINB1)); // Ausgänge erstmal AUS |
12 | |
13 | TCCR0A = (1 << WGM01); // CTC |
14 | TCCR0B = (1 << CS02); // Prozessortakt / 256 --> 9,6MHz / 256 = 37,5kHz --> 0,0000026666 sec |
15 | OCR0A = 200; // Vergleichsregister --> alle 0,000002666 sec * 200 = 0,00053332 sec |
16 | TIMSK0 = (1 << OCIE0A); |
17 | |
18 | sei(); |
19 | }
|
20 | |
21 | |
22 | int main(void) { |
23 | init(); |
24 | |
25 | |
26 | for (;;) { |
27 | |
28 | if(event >= 10) { // Alle 5ms (10 x 0,00053332 sec) |
29 | event = 0; |
30 | // TODO: Mein Programm
|
31 | }
|
32 | }
|
33 | }
|
und die entsprechende main.h:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <util/delay.h> |
4 | |
5 | volatile uint8_t event; |
pal ... schrieb: > ich habe mir gerade diesen Beitrag durchgelesen und auch versucht meinen > Tiny nach meinen Anforderungen zu programmieren. Schön. Trotzdem würden wir es hier begrüßen, wenn du keine Leichenfledderei betreiben würdest. Das Original hier stammt aus 2009 und ist für dein 'Problem' nicht wirklich relevant. Fang in so einem Fall einen neuen Thread an, und alle sind glücklich. (Und vor allen Dingen liest niemand alte Beiträge und überlegt sich Antworten ehe er drauf kommt, dass der Thread 4 Jahre alt ist.) > Ich würde mich freuen, wenn mir jemand kurz sagen kann ob meine > Anstrengungen richtig waren. Warum probierst du es nicht einfach aus. Dein µC sagt dir am Allerbesten, ob es richtig ist oder nicht. Entweder eine LED blinkt oder sie blinkt nicht. > So wie ich die Register gesetzt habe müsste MÜSSTE? In der Programmierung gibt es kein müsste. Entweder es tut oder es tut nicht. Das nennt man testen. > eigentlich alle 5ms mein > Programm durchlaufen werden. Und, tut es das auch? Dazu gleich noch mehr > Aber die Pins PB0, PB1, PB2 und PB3 kann > ich als noramale I/O-Ports nutzen. Ja natürlich. Das eine hat ja mit dem anderen erst mal nichts zu tun. > if(event >= 10) { // Alle 5ms (10 x > 0,00053332 sec) Du fragst hier ab, ob event größer gleich 10 ist. Laut deiner Rechnerei müsste das 5ms ergeben (ich hab nicht nachgerechnet). Jetzt wird es dir wahrscheinlich auch so gehen wie mir: Wie kontrolliert man das ohne Oszi? > event = 0; > // TODO: Mein Programm so jedenfalls nicht. Wenn man nichts anderes hat, dann ist eine LED an einem Portpin ein mächtiges Werkzeug. Kabel dir eine LED an einen Pin ran und jedesmal wenn event größer gleich 10 ist, setzt du nicht nur event um, sondern schaltest auch die LED in den jeweils anderen Zustand. D.h. deine LED blinkt. Blinkt die LED, dann weißt du, dass event tatsächlich erhöht wird, was aber nur passieren kann, wenn der Timer arbeitet und die Interrupts uaslöst, die zum Aufruf der ISR führen. D.h. alleine dadurch, dass die LED blinkt hast du einen Test ob eine relativ komplexe Kette von Ereignissen tatsächlich so abläuft wie vorgesehen. Jetzt erhebt sich noch eine 2. Frage. Wenn die LED blinkt, tut sie es dann auch in der richtigen Geschwindigkeit? 5ms sind nicht viel. Durch das umschalten der LED blinkt sie mit der halben Geschwindigkeit, was einer Zykluszeit von 10ms entspricht, und das sind wiederrum (f=1/t) gleich 100Hz. 100Hz siehst du aber mit freiem Auge nicht mehr. AAAAAber: Du musst ja nicht das Blinken auslösen, wenn event größer gleich 10 ist. Du kannst ja für deine Tests auch erst mal 100 hinschreiben. Dadurch wird alles um einen Faktor 10 langsamer, was bedeutet, dass die LED jetzt mit 10Hz blinkt. Und das sieht man dann schon. Aber warum bei 100 stehen bleiben? 200 bringt dir nochmal einen Faktor 2 und somit sind wir bei 5Hz. D.h. die LED blinkt in einer Sekunde 5 mal auf. Und das kann man schon ganz gut und zuverlässig schätzen. D.h. Ändere zu Testzwecken dein Programm wie vorgeschlagen um und sieh nach, ob eine LED an einem Portpin pro Sekunde 5 mal aufblinkt. Tut sie das, dann funktioniert dein Programm wie vorgesehen. Tut sie es nicht, dann gibt es 2 Möglichkeiten * entweder sie blinkt überhaupt nicht Dann hast du entweder einen Fehler beim LED_Blinken oder die ganze Timer-Einstellung stimmt nicht * oder aber sie blinkt, aber mit der falschen Geschwindigkeit Dann stimmt zwar die grundsätzliche Timereinstellung, aber du hast dich irgendwo verrechnet und die Steuerkonstanten in den Registern stimmen nicht. Zum Programmieren gehört auch, dass man selber seine Programme testen kann und sich überlegt, wie man einen Test inszenieren kann, der einem verrät, was man wissen möchte. Dann gibt es auch kein 'müsste' mehr. Entweder es tut oder es tut nicht. Dein µC ist geduldig. Der führt auch stundenlang den immer gleichen Code aus, während du dir überlegst, wie du mit einer Programmänderung die Dinge in Erfahrung bringen kannst, die du wissen willst.
Hallo, vielen Dank für deine Antwort. Ja das Problem ist tatsächlich, dass ich kein Oszi habe. Das Programm läuft auf jeden Fall wie ich jetzt festgestellt habe. Nur bei der Geschwindigkeit bin ich mir nicht sicher. Aber auch hier noch mal danke für den Tip - ich werde einfach mal eine LED blinken lassen und zählen. > Schön. > Trotzdem würden wir es hier begrüßen, wenn du keine Leichenfledderei > betreiben würdest. Sorry, hier wusste ich einfach nicht was besser ist. In Zukunft werde ich einen neuen Thread eröffnen. lg pal
Eines noch
Das hier
> Tut sie das, dann funktioniert dein Programm wie vorgesehen.
ist nicht ganz richtig.
Denn es gilt:
Durch Testen kann man immer nur die Anwesenheit von Fehlern feststellen,
nicht die Abwesenheit.
D.h. wenn scheinbar das Programm genau das tut was es soll, heißt das
noch lange nicht, dass es fehlerfrei ist. Es kann auch sein, dass man
einfach nur noch nicht den Test gefunden hat, der den Fehler zeigen
würde.
D.h. mit solchen Dingen wie "ist getestet, muss also funktionieren"
immer ein wenig vorsichtig sein.
Hallo, also evtl. kann mir jemand bei meiner Fehlersuche helfen, Ich Bekomme es ohne Probleme hin auf ein ATtiny85 IR Infrared Obstacle Sensor Modul das wenn ich über den Sensor meine Hand halte das die LED angeht und wieder aus. ich Möchte jetzt gern das selbe Prinzip nur mit 2 Sende Module auf einen ATtiny85 Bringen, Natülich pro Modul eine LED. unten mal den Code für ein IR Infrared Obstacle was müsste ich denn ändern damit es geht? sorry auf dem Gebit kenne ich mich noch nicht besonders gut aus, denoch hoffe ich auf eure Hilfe LG int LED = 4; // Use the onboard Uno LED int isObstaclePin = 1; // This is our input pin int isObstacle = HIGH; // HIGH MEANS NO OBSTACLE void setup() { pinMode(LED, OUTPUT); pinMode(isObstaclePin, INPUT); } void loop() { isObstacle= digitalRead(isObstaclePin); if (isObstacle == LOW) { digitalWrite(LED, HIGH); } else { digitalWrite(LED, LOW); } delay(1); }
:
Bearbeitet durch User
Es ist nicht gut einen alten Tread zu verwenden. Der von dir gezeigte Code ist für einen Arduino Uno, passt daher nicht für einen Tiny85. Ändern muss man bei dem Code sonst nichts wesentliches, nur etwas dazuschreiben.
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.