Hallo alle :) ich steh gerade vor einer Wand und komme nicht weiter. Falls irgendwem unklar ist, was ich im folgenden Text meinen könnte, dann bitte nachfragen ^^ Ich habe einen mega8, der mittels Timer-Interrupt sehr genau die Zeit hochzählt. Jede Sekunde wird dieser ausgelöst. Nach x Minuten wird der Wert auf einen EEPROM geschrieben, das passiert alles in der Interrupt-Routine. Der mega8 wertet zusätzlich noch ein paar Ports aus und kommuniziert ganz simpel über 2 Ports mit einem anderen mega8. Diese 2 Ports sind PB.4 und PB.5 (SCK und MISO). PB.5 vom 1. mega8 wird auf PB.4 vom 2. mega8 ausgewertet. Und andersrum genauso. Kommt also auf PB.4 ein high, wird so lange in eine Programmschleife gesprungen, bis das ganze wieder low ist. Das ganze habe ich mit einer Variablen gelöst (if port high -> variable = 1, else port low -> variable = 0) in der hauptschleife steht dann etwa: if variable = 1, dann LED1 an, else LED2 an Das Problem ist, es wird zwar erkannt, dass die Variable = 1 ist, aber irgendwie bleibt immer LED1 an und LED2 leuchtet (nur im dunkeln sichtbar) für einen sehr kurzen Moment auf Das ganze passiert nicht mehr sobald ich den timer rausnehme. Laut Datenblatt haben PB.4 und PB.5 nichts mit dem Timer bzw Interrupts bzw COMPARE1A zu tun. Aber es muss irgendwie am Timer liegen. Kann mir da jemand helfen? Ich seh gerade nicht mehr durch ... :( (Ich schreibe alles in BASCOM, mit C/asm kenne ich mich nicht aus) Vielen Dank für Hilfe! PS: zur allgemeinen Verwirrung aller: ich habe auch probiert, zur Portauswertung hinzuzufügen, dass Interrupts und COMPARE1A disabled werden, sobald ein hi da ist (und enabled, sobald wieder ein lo da ist), aber der Timer bleibt nicht stehen, genau wie die LED nicht umschaltet.
Reduziere die Interrupt Routine. Ich vermute, dass sie mehr tut, als beabsichtigt war. Wenn Du Schrittweise Code entfernst, wirst DU irgendwann an den Puntk kommen, wo das Reset-Problem verschwindet. Der gerade entfernet Code ist dann warscheinlich die Problemursache. Wie hast DU das mit dem 1 Sekunden-Takt gemacht? Soweit ich weiß ist keiner der Timer imstande, einen Interrupt pro Sekunde auszulösen (mit einer Taktfrequenz im Mhz Bereich). Vermutlich zahlst Du die Interrupt, und wenn genug zusammengekommen sind, dass eine Minute rum sein müsste, dann fängst DU an zu speichern und zu kommunizieren. bedenke, dass der Interrupt während dieser Zeit nicht ausgeführt wird. Wenn die Interruptroutine länger dauert, als das Intervall zwischen zwei Interrupts., wird die Uhr ungenau laufen. Aber das ist momentan wohl nicht deine Haupt-Sorge.
(ich hab meine login-Daten gerade nicht im Kopf, deswegen schon wieder als Gast ...) Hallo Stefan! So sieht der Timer aus: (der code ist nicht 100% exakt, z.b. bei den LEDs und auch die DIMs für die Variablen fehlen, sollte aber dennoch erkennbar sein)
1 | config timer1 = timer, prescale = 256, compare a = disconnect, clear timer = 1 |
2 | compare1a = 62500 |
3 | on compare1a sec_cnt |
4 | enable compare1a |
5 | enable interrupts |
dann die hauptschleife:
1 | do |
2 | |
3 | u2com |
4 | |
5 | if u2_stop_error = 1 then |
6 | led2 on |
7 | disable compare1a |
8 | disable interrupts |
9 | else |
10 | led2 off |
11 | enable compare1a |
12 | enable interrupts |
13 | end if |
14 | |
15 | loop |
16 | end |
die sub für u2com (ist als integer definiert):
1 | sub u2com |
2 | if pinb.5 = 1 then |
3 | u2_stop_error = 1 |
4 | else |
5 | u2_stop_error = 0 |
6 | end if |
7 | end sub |
die sub für den interrupt sieht so aus (ebenfalls als integer definiert):
1 | sec_cnt: |
2 | incr time_measure |
3 | |
4 | if time_measure = 1 then |
5 | time_measure = 0 |
6 | toggle LED1 'LED blinkt wenn interrupt auslöst |
7 | end if |
so. nun passiert folgendes: die LED1 blinkt LED 2 geht an, wenn ich pinb.5 hi setze aber der timer bleibt nicht "stehen", bzw es werden weiter interrupts ausgelöst der timer sollte ziemlich exakt jede sekunde auslösen später werden innerhalb sec_cnt dann noch die minuten gezählt und bei 5 vollen minuten werden wieder compare1a und die interrupts disabled und auf den eeprom geschrieben, danach werden die beiden sachen wieder enabled. auf meiner bisherigen schaltung funktioniert das bisher bestens. dort wurden lediglich 2 ADC-Ports ausgelesen und sobald ein wert unterschritten wurde, wurden keine sekunden mehr gezählt und es gingen 2 rote LEDs an. Die wurden grün und es wurde weitergezählt, sobald der wert für den ADC wieder überschritten wurde. diesmal habe ich noch ein paar mehr ports auszuwerten, einmal ist es ein taster, und der rest sind hi/low-signale. ich verstehe nicht, warum die interrupts weiter auslösen. müssen die in sec_cnt disabled werden und nicht in der hauptschleife? das hatte ich gestern auch probiert, hat aber irgendwie keinen unterschied gemacht ... :/ danke für hilfe! (achja, meine shift-taste ist nicht defekt, lol) ;)
so, also wie es scheint, darf in der hauptschleife keine Auswertung stehen, die variablen ändert bei mir funktioniert es nur, wenn die variablen in der vom Interrupt ausgelösten sub geändert werden und in der hauptschleife die auswertung geschieht (z.b. wenn variable = 1 -> LED an) ich weiss nicht, ob das tatsächlich so ist, aber nachdem ich die variablen in sec_cnt setze und dort die ports abfrage, klappt alles wieder ... die interrupts und compare1a zu disablen hab ich bisher nicht probiert, aber da es im alten projekt geklappt hat, müsste es auch hier funkionieren
Nik schrieb: > und bei 5 > vollen minuten werden wieder compare1a und die interrupts disabled und > auf den eeprom geschrieben Diese Strategie musst du noch mal überdenken. Wenn du immer die gleiche Stelle im EEPROM beschreibst, ist nach 347 Tagen der 100000ste Schreibvorgang - damit endet die garantierte Anzahl der möglichen Schreibzyklen lt. Datenblatt.
hey Matthias :) ja, da gibt's 2 Möglichkeiten ... entweder wird der EEPROM regelmässig getauscht (das Ding zählt Betriebsstunden von Lampen, die dann ebenfalls getauscht werden müssen) oder man schreibt's an eine andere Stelle im EEPROM. Da ich aber nicht weiss, wie ich das realisieren könnte, vorallem beim Einschalten des Gerätes weiss der mega8 ja erst mal nicht, welchen EEPROM er nun vor sich hat (z.B. nach Tausch) und ab welcher Stelle er lesen müsste, seh ich noch keine Lösung und da hab ich auch keine Vorstellung :/
Vorsicht beim automatisierten Schreiben ins EEPROM. Ein kleiner Fehler, schon beim Systemtest und das Teil ist hinüber. Überlege mal, ob es wirklich nötig ist 1 Mal pro Sekunde ins EEPROM zu schreiben. Wenn ich ein System programmiere, das unbedingt "nachtragend" sein muss, so spendiere ich dem Prozessor einfach einen großen Kondensator mit verlustarmer Diode und eine Spannungsüberwachung. Das ist recht einfach, allerdings geht dabei ein Pin drauf. Dann kann ich meinen Kram im RAM machen und sichere nur im "Notfall". Restauration natürlich immer beim Einschalten. Der Strom, der den Prozessor stützen tut ist nicht sonderlich hoch, weshalb sich die Größe des Stützkondensators auch in Grenzen hält.
Hi >oder man schreibt's an eine andere Stelle im EEPROM. >Da ich aber nicht weiss, wie ich das realisieren könnte, Da gibt es eine AppNote von ATMEL: http://www.atmel.com/Images/doc2526.pdf http://www.atmel.com/Images/AVR101.zip MfG Spess
@Spess: ah danke, da guck ich mal rein :) @amateur: es wird auch nicht jede Sekunde geschrieben, sondern das geschieht alle 5 Minuten bisher :) Pro Sekunde zähle ich den Sekundenzähler 1 hoch und mach dann die Port-Abfragen. Bei 300 wird dann angehalten und geschrieben. Die "Lebensdauer" wäre also irgendwo bei 345 Tage, wenn ich von 100k Zyklen ausgehe. über diese Spannungsüberwachung hab ich auch schon nachgedacht, aber leider hab ich auch nirgends mehr Pins frei an den beiden mega8 wie gesagt, ich bin kein studierter Entwickler, muss es aber trotzdem irgendwie schaffen ^^;
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.