Forum: Mikrocontroller und Digitale Elektronik mega8, Timer resettet variable/port?


von Nik (Gast)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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.

von Nik (Gast)


Lesenswert?

(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) ;)

von Nik A. (nik_a)


Lesenswert?

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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

von Nik A. (nik_a)


Lesenswert?

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 :/

von amateur (Gast)


Lesenswert?

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.

von Spess53 (Gast)


Lesenswert?

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

von Nik A. (nik_a)


Lesenswert?

@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
Noch kein Account? Hier anmelden.