Hallo Gemeinde
möchte an einem AT 1284p / 16 M einen Timer0 (8 bit) mit 1 ms
programmieren
Komme aber nicht ganz klar. Habe den folgenden Code dazu:
1
TCCR0A=(1<<WGM01);// CTC Modus
2
TCCR0B|=(1<<CS01)|(1<<CS00);// Prescaler 64
3
OCR0A=249;
4
TIMSK0|=(1<<OCIE0A);
Nach dem Datenblatt müsste das 1 ms ergeben.
Problem ist aber die ISR:
1
ISR(TIMER0_COMPB_vect)
2
{
3
if(wait<=9)
4
{
5
wait++;
6
}
7
else
8
{
9
wait=0;
10
wait10=0xff;
11
}
12
}
In einem Stück Code möchte ich _delay_ms(1) durch den Timer ersetzen.
Der Timer soll genau so 1 ms warten (ohne delay)
Irgendwie habe ich ein Brett vor dem Kopf.
achim
Bitflüsterer schrieb:> Schön. Was aber ist nun genau Deine Frage?
Vermutlich, wie er den Timer zu einem bestimmten Zeitpunkt anwerfen
kann. Er will ja wohl kaum alle ms wieder einen Programmunterbruch,
sondern vermutlich nur an einer Stelle.
Wird die Variable wait lediglich innerhalb der ISR benötigt? Wenn ja,
dann definiere sie innerhalb der ISR (und nicht global) mit:
static uint8_t wait;
und nicht außerhalb.
Wenn nein, definiere sie global mit
volatile uint8_t wait;
Oder wenn nur innerhalb einer C-Datei benötigt:
static volatile uint8_t wait;
Dasselbe gilt für wait10.
sorry, übersehen.
- möchte permanent einen unterbruch von jeweils 1 ms.
Soll in einer Blinkschleife verwendet werden. Diese hat 2 x 500 ms mit
delay, also 500 x 1 ms an und 500 x 1 ms aus
Achim Seeger schrieb:> Soll in einer Blinkschleife verwendet werden. Diese hat 2 x 500 ms mit> delay, also 500 x 1 ms an und 500 x 1 ms aus
Dann schreib den An- und Aus-Befehl noch mit in die ISR. Ob Du gerade
an- oder ausschalten musst, kannst Du mittels flag, welches Du toggelst,
testen.
Oder Du togglest direkt den Port-Pin. Das wäre das sparsamste Vorgehen.
Warum willst du delayms ersetzen?
Wenn es daruf hinaus läuft, dass du an einer Stelle im Programm so lange
wartest, bis ein Timer-Interrupt eine Variable gesetzt hat, kannst du
auch genausogut delayms weiterbenutzen.
Wenn du mehrere Dinge parallel (ereignisgesteuert) abarbeiten willst,
sind schon größere Änderungen am Programmablauf nötig als nur delayms
durch etwas selbstgebautes zu ersetzten.
Delay schrieb:> Wenn du mehrere Dinge parallel (ereignisgesteuert) abarbeiten willst,> sind schon größere Änderungen am Programmablauf nötig als nur delayms> durch etwas selbstgebautes zu ersetzten.
Naja... Mit einem Timer wäre es immerhin schon mal möglich das Blinken
Parallel zum Rest laufen zu lassen. Pin Toggle in die ISR und das
wars... sehe da nicht, was für andere Änderungen noch nötig wären in
diesem Fall.
Kommen da andere Interrupts usw hinzu, dann stimme ich dir zu. Dann
wirds irgendwann etwas komplizierter.
So ähnlich könnte das aussehen:
ISR (TIMER0_COMPB_vect)
{
static uint16_t cnt;
cnt++;
if (cnt == 500)
{
cnt = 0;
PORTX ^= (1<<PINXY);
}
}
Wenn der TO es schafft, dass die ISR nur alle 2ms aufgerufen wird,
könnte er auch bis 250 zählen und cnt käme mit einem uint8_t aus.
Hallo Frank
das Problem ist es etwas grösser und länger. Versuche es mal zu erklären
Im grund sieht es so aus
Timer
ISR
int main
.....
while
Unterprogramm 1
Unterprogramm 1
...
Unterprogramm 5
delay 1ms
Jedes Unterprogramm verwendet kein delay und keiner Verzögerung. Dadurch
wird die gesamtlaufzeit des Programmes nur durch die 1 ms bestimmt. Die
1 ms muss aber relativ konstant sein, da in den Unterprogrammen Zähler
sind, die bei jedem Durchlauf um eins erhöht werden. Bei der LED 500 x
1ms, dann LED an, nochmal 500 x 1 ms dann LED aus.
Brauche also einen Timer mit 1 ms. Die ISR dazu muss mein Programm bei
jedem Durchlauf 1 ms stoppen.
Kommt alles aus dem Bereich Multitasking
achim
Okay, die letzten Antworten hatte ich vor dem Absenden nicht gesehen.
Wenn ein Ausgang alle 500ms getogglet werden soll, ist es natürlich
sinnvoll, einen ms-Counter zu bauen, der bei jedem Durchlaf der
main-Schleife geprüft wird (und bei jedem Aufruf der Timer-ISR erhöht
wird mit Überlauf bei 1000).
Je nachdem, was der Timer sonst noch so steuern soll, kann es natürlich
auch sinvoll sein (oder gerade nicht) den Ausgang direkt in der
Timer-ISR zu togglen.
Es geht eigentlich nicht darum eine LED unabhängig blinken zu lassen,
sondern 5 Stück und dazu noch 3 Taster abzufragen und dazu noch 4
Bodensensoren und die Tasterabfrage nach Peter und Karl Heinz.
Nur eine Timer mit fester zeit. alles andere wird da von abgeleitet.
Das wichtigste daran sind die Unterprogramme. Es darf keinerlei
Verzögerung eintreten.
Habe das alles auf einem AT 128 zu laufen. Leider mit anderen Libs und
einem anderen Timer. Möchte es jetz einfach auf dem 1284p anpassen.
@ Achim Seeger (achims)
>Brauche also einen Timer mit 1 ms.
Wo liegt das Problem? Stell ihn richtig ein und los!
> Die ISR dazu muss mein Programm bei>jedem Durchlauf 1 ms stoppen.
Nö, dein Programm, genauer die FUNKTIONEN, müssen darauf passen
reagieren, dass sie im 1ms Raster aufgerufen werden! Siehe
Statemachine.
>Kommt alles aus dem Bereich Multitasking
Mensch Meier, und warum nimmst du nicht einfach das gottverdammte
Beispiel? Hast du das Thema nicht schon vor vielen Monaten bearbeitet?
Mir scheint, dein Langzeit- und Lerngedächtnis ist nicht das Beste.
http://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR
@ Achim Seeger (achims)
>Es geht eigentlich nicht darum eine LED unabhängig blinken zu lassen,>sondern 5 Stück und dazu noch 3 Taster abzufragen und dazu noch 4>Bodensensoren und die Tasterabfrage nach Peter und Karl Heinz.
Einfachster Krümelkram.
>Nur eine Timer mit fester zeit. alles andere wird da von abgeleitet.
Richtig!
>Das wichtigste daran sind die Unterprogramme. Es darf keinerlei>Verzögerung eintreten.
Genau!
>Habe das alles auf einem AT 128 zu laufen. Leider mit anderen Libs und>einem anderen Timer. Möchte es jetz einfach auf dem 1284p anpassen.
Muss ich das verstehen? Wo ist denn da das Problem?
Hallo Falk
stimmt genau
Habe es schon vor einiger Zeit gemacht. Damals war ich so blöd, die
Pause richtig kompliziert zu machen. Habe neulich was kurzes gesehen,
weiss leider nicht mehr wo.
Genau, zur Statemaschine will ich kommen, aber nicht sofort. Da muss ich
erst noch einiges lernen.
Hatte es damals für den nib.. programmiert. Leider verwendet der
Hersteller viel eigene Sachen. Da Nib.. nur noch als Ausstellungsstück
dient, mache ich einiges neu.
Hast du schon mal versucht I2C Bus und Multitasking zu kreuzen?
Wenn der Timer so stimmt, eine kurzes Stück Code zur Verzögerung.
Habe die Datenblätter vom 128 und 1284 gelesen. Sind doch ein paar
Unterschiede drin
Solche Problembeschreibungen solltest Du wirklich von Anfang an posten.
Man weiss sonst einfach nicht, worum es geht.
1. Du hast also innerhalb einer while-Schleife mehrere Unterprogramme.
2. Die while-Schleife soll alle 1ms einmal durchlaufen werden.
2.a. Dazu gehört die Bedingung, dass die Laufzeit aller Unterprogramme
zusammen weniger als 1ms beträgt (mit ein wenig Reserve). Ist das
gegeben?
3. Zusätzlich soll eine LED alle 500ms getoggelt werden.
Das wäre jetzt mal so ein Ansatz, den ich mir von Dir gewünscht hätte.
Darauf kann man Fragen beziehen.
Du solltest Dir angewöhnen Dir mal so ein grundsätzliche
Ablaufbeschreibung zu entwerfen. Und wenn sie noch so falsch ist.
Wenn Du immer nur irgendwelche Schnippsel hinlegst und darauf starrst
und das als Ausgangspunkt einer Frage nimmst, dann müssen wir immer die
Entwürfe für Dich machen. Davon lernst Du nichts und wirst immer von uns
abhängig sein.
- Init
1. Timer initialisieren
2. Flag initialisieren
- main
1. Timer starten
2. while(1)
3. up1();
4. up2();
5. Warten bis Zähler 1ms abgelaufen - Flag variable zurücksetzen
6. 500ms Zähler inkrementieren
7. 500ms Zähler abgelaufen?
8. Wenn ja, LED toggeln - Zähler zurücksetzen
9. } /* while */
- Timer-Int
1. Flag setzen
Hallo Falk
habe dein Stück gleich gezogen.
Vieles ist aus der anderen Version.
War der Timer schon immer dadrin? Wenn ja, habe ich noch was anderes,
oder total verschlafen.
Danke dir
achim
P.S.
Paket ist angekommen. Noch mal meine Dummheit gesucht. Sorry hatte es
ganz vergessen
Hallo Gast
du hast vollkommen Recht. Deine Beschreibung stimmt genau.
Leider ist maches schwer auszudrücken. Wollte es eigentlich nicht zu
kompliziert machen. Im Netz steht von Falk und anderen ein extra Artikel
drin, der alles beschreibt, Multitasking. Ist ein sehr guter Artikel der
alles sehr einfach beschreibt. Ansonsten stimmt dein Ansatz genau.
achim
Sorry, habe es erst jetzt gesehen. Innerhalb der Unterprogramme laufen
die Zähler. Können durchaus 5 bis 10 Stück sein. 6, 7, 8 nicht in der
while Schleife
@ Achim Seeger (achims)
>War der Timer schon immer dadrin?
Nein, der kam etwas später rein.
Ist am 11. NOvember 2012 reingekommen (doch schon ne Weile her)
>Sorry, habe es erst jetzt gesehen. Innerhalb der Unterprogramme laufen>die Zähler. Können durchaus 5 bis 10 Stück sein.
10 kleine Unterprogramme und darin jeweils ein Zähler oder gar eine
Statemachine bringen den AVR noch nicht ins Schwitzen]].
@ Achim Seeger (achims)
>Hast du schon mal versucht I2C Bus und Multitasking zu kreuzen?
Jain, ich hab mal vor langer Zeit einen kleinen Zähler mit I2C gemacht.
Wenn gleich sich dort das Multitasking in Grenzen hielt.
>Habe die Datenblätter vom 128 und 1284 gelesen. Sind doch ein paar>Unterschiede drin
Ja, aber die sind eher klein. So ein Timer hat beim AVR bestenfalls drei
Register, das sollte schon drin sein, die richtig einzustellen.
Im Grunde wollen wir das gleiche. Habe jetzt so ziemlich alles
exportiert auf das neue system. Hattest ja mitbekommen, das ich viel mit
dem Bus mache. Dazu jetzt noch Multitasking und später Statemaschine.
Das kann ganz neue Sachen bringen.
Du hast auch eine Sicherheitskontrolle drin. War mir ganz neu. Da habe
ich doch wieder was zu lesen und kann getrost auf das blöde Fernsehen
verzichten. Informiere dich über die Ergebnisse.
achim
Muss noch nachfragen.
Habe ein Problem den AT1284p / 16MHz der Timer 0 in Betrieb zu nehmen.
Habe nach Datenblatt die folgenden Einstellungen gemacht. Es soll 1 ms
kommen
Es geht aber nicht. Was mach ich falsch?
// Timer 0 konfigurieren
TCCR0A = (1<<WGM01); // CTC Modus
TCCR0B |= (1<<CS01)|(1<<CS00); // Prescaler 64
OCR0A=249;
// Compare Interrupt erlauben
TIMSK0|= (1<<OCIE0A);
// Global Interrupts aktivieren
sei();
@ Achim Seeger (achims)
>Habe ein Problem den AT1284p / 16MHz der Timer 0 in Betrieb zu nehmen.>Habe nach Datenblatt die folgenden Einstellungen gemacht. Es soll 1 ms>kommen>Es geht aber nicht. Was mach ich falsch?
Dass du konsequent nur sinnlose Quelltextfragmente postest!
Was soll das? Poste VOLLSTÄNDIGE Quelltexte als Anhang!
Es fehlt MINDESTENS die ISR!
>// Timer 0 konfigurieren>TCCR0A = (1<<WGM01); // CTC Modus>TCCR0B |= (1<<CS01)|(1<<CS00); // Prescaler 64>OCR0A=249;>// Compare Interrupt erlauben>TIMSK0|= (1<<OCIE0A);
Die Registereinstellungen sehen OK aus.
Da sind sie. Kennst du aber
ISR (TIMER0_COMPB_vect)
{
flag_1ms=1;
}
Im Programmm steht das noch:
volatile uint8_t flag_1ms;
...
if(flag_1ms)
{
flag_1ms=0;
Unter 1..
Unter 2 ..
Unter 3 ...
}
Der ganze Code besteht im Moment nur aus diesen paar Zeilen. Die
Unterprg habe ich vollständig rausgelassen.
@ Achim Seeger (achims)
>Danke dir Steffan. Das war es. Keine Ahnung warum ich das nicht gesehen>habe.>Da muss wohl doch eine Brille her.
Erkennst du JETZT, warum man VOLLSTÄNDIGEN Quelltext posten MUSS?!
Ja das erkenne ich. Stelle aber auch fest, das ich noch viel lernen
muss. Aus Fehlern lernt man.
Egal, danke für deine Hilfe.
Dein Programm läuft sofort richtig.
Der Sinn deiner überwachung ist mir nicht ganz klar.
Wenn flag noch 1 ist > Anzeige - ok
und das andere??
@Achim Seeger (achims)
>Der Sinn deiner überwachung ist mir nicht ganz klar.
Steht das nicht sonnenklar im Text? Damit kann man live im Programm
prüfen, ob deine Tasks schnell genug abgearbeitet werden können oder
nicht. Also eine Echtzeitfehlerüberwachung.