Forum: Mikrocontroller und Digitale Elektronik Timer Interrupt am Tiny13


von Christoph B. (elgigo)


Lesenswert?

Mahlzeit!

Ich suche seit fast ner Woche im Net, hab auch einiges gefunden.
Leider funzt nichts wirklich der Interrupt wird nie ausgelöst :-(
Ich wollte mir eigentlich nen 10ms Impuls ausprogrammieren, aber ich 
bekomms einfach nicht hin.

Hab den Code jetzt etwas vereinfacht und wollte nur ne Led ansteuern.
Ich ersuche einen von euch Wissenden kurz mal drüber zu schauen und mir 
zu sagen wo der Fehler liegt.
Danke!!
1
$regfile = "ATTiny13.dat"
2
$crystal = 1000000 '1MHz
3
4
5
6
7
Tccr0 = &H0D                                                'This will replace Config Timer1 = Timer , Prescale = 4096
8
9
10
On Timer0 Timer_int
11
Enable Timer0
12
13
Config Pinb.0 = Output                                      'LED
14
Led1 Alias Portb.0
15
Dim Count As Iram Byte
16
Dim Imp As Iram Bit
17
18
Enable Interrupts
19
20
Do
21
  If Imp = 1 Then
22
    Count = Count + 1
23
      If Count = 255 Then
24
         Toggle Led1
25
          Count = 0
26
      End If
27
  End If
28
Loop
29
30
End
31
32
Isr
33
Timer_int:
34
   Imp = 1
35
Return

von Karl H. (kbuchegg)


Lesenswert?

> Tccr0 = &H0D                                                'This will replace 
Config Timer1 = Timer , Prescale = 4096


Laut Datenblatt gibt es beim Tiny13 kein Tccr0 Register. Wohl gibt es 
aber ein TCCR0A und ein TCCR0B Register.

Ich weiss jetzt nicht, auf welches Register zugegriffen wird, wenn du in 
BASCOM einfach nur TCCR0 schreibst. Aber es wird wohl
* enteder überhaupt nichts mit TCCR0A oder TCCR0B zu tun haben
* oder aber das falsche sein

ABer selbst wenn es das richtige ist, solltest du überprüfen, was du mit 
der Zuweisung von 0x0D anrichtest

von Christoph B. (elgigo)


Lesenswert?

Danke für die schnelle Antwort!

Hab den Code jetzt auf die Zeilen geändert die man beim Googeln immer 
findet, ist aber noch das selbe, der Interrupt wird niemals ausgelöst
1
$regfile = "ATTiny13.dat"
2
$crystal = 1000000                                          '1MHz
3
4
Config Timer0 = Timer , Prescale = 64
5
6
7
On Timer0 Timer_int
8
Enable Timer0
9
10
Config Pinb.0 = Output                                      'LED
11
Led1 Alias Portb.0
12
Dim Count As Iram Byte
13
Dim Imp As Iram Bit
14
15
Enable Interrupts
16
17
Do
18
  If Imp = 1 Then
19
    Count = Count + 1
20
      If Count = 255 Then
21
         Toggle Led1
22
          Count = 0
23
      End If
24
  End If
25
Loop
26
27
End
28
29
30
Timer_int:
31
   Imp = 1
32
Return

von Karl H. (kbuchegg)


Lesenswert?

Christoph Baumgartner schrieb:
> Danke für die schnelle Antwort!
>
> Hab den Code jetzt auf die Zeilen geändert die man beim Googeln immer
> findet, ist aber noch das selbe, der Interrupt wird niemals ausgelöst

Woher weißt du das?
PS: Deine LED wird ungefähr alle 4 Sekunden getoggelt.

Edit. Korrektur.
Deine Led wird viel schneller getoggelt, da du Imp nie wieder auf 0 
zurücksetzt.

Schalte doch einfach mal dein Led im Timer_int wahlweise ein oder aus, 
dann weißt du ob der Interrupt ausgelöst wird. Je komplizierter du 
deinen Nachweis für den Aufruf gestaltest (das ganze HäckMäck mit Imp 
und Counter), desto größer wird die Gefahr, dass du dir genau in diesem 
HäckMäck zusätzliche Fehler einhandelst.

von Christoph B. (elgigo)


Lesenswert?

Ah ja stimmt! Imp wird nicht zurück gesetzt.

Das is aber nicht so schlimm da es gar nicht gesetzt wird!
Genau das is ja mein Problem.....

von MWS (Gast)


Lesenswert?

Ein paar kleine Hinweise:
1
$crystal = 1000000

geht nicht, denn der R/C Oszillator läuft mit 9.6MHz und der Teiler ist 
8 im Lieferzustand = 1200000.

Wobei das hier wurscht sein sollte, denn es wird kein Wait und auch kein 
UART verwandt, wofür der Compiler die Frequenz genau wissen muss. Ist 
also von mir nur der Vollständigkeit halber erwähnt.

Die Variablen als IRam zu definieren ist recht sinnfrei, solange Du die 
PUSH/POP Orgie in der Interrupt Routine hast, die 26 Register auf den 
Stack schiebt und wieder runterholt. Wenn's schnell gehen soll, dann 
NOSAVE verwenden und Register selbst sichern.

Unter einer aktuellen Bascom Version läuft Dein Code, auch im AVR Studio 
getestet.

Solltest Du eine gaaaanz alte Bascom Version besitzen, so musst Du auch 
noch:
1
Start Timer0

schreiben, damit der startet.

Das hier:
1
Tccr0 = &H0D

hätte versucht den Timer0 in einen Modus zu versetzen, den es nicht 
gibt. Genausowenig gibt es einen Prescaler von 4096 dafür.

TCCR0 kann ersatzweise für TCCR0B verwendet werden.

Wenn Du den Timer über Register konfigurieren willst, dann würde der 
Timer0 mit Prescaler 64 starten mit:
1
TCCR0 = 3

Oder leserlicher:
1
TCCR0 = Bits(CS01, CS00)

von Christoph B. (elgigo)


Lesenswert?

Also,

entweder liegt es an der Demo oder ich bin zu doof. In der Simulation 
geht nix und auf dem Tiny auch nix.
mir fällt nix mehr ein...

danke trotzdem....

von MWS (Gast)


Lesenswert?

Wie alt ist die Demo ? Version ?

Pack doch mal die erzeugten Files, sollten 8 Stück inklusive der .bas 
sein, in ein Zip und stell sie hier rein. Heut' kann ich sie evtl. noch 
anschauen, morgen bin ich verreist.

von Christoph B. (elgigo)


Angehängte Dateien:

Lesenswert?

Guten Morgen!

Bin gestern leider nicht mehr online gekommen weil sich mein Laptop 
geschrottet hat. Poste das File aber trotzdem, vll findets ja jemand 
anders raus

Danke!
MFG

von Christoph B. (elgigo)


Lesenswert?

Hat niemand eine Idee?

von Karl H. (kbuchegg)


Lesenswert?

Ich kann mich nur wiederholen

[quote]
Schalte doch einfach mal dein Led im Timer_int wahlweise ein oder aus,
dann weißt du ob der Interrupt ausgelöst wird. Je komplizierter du
deinen Nachweis für den Aufruf gestaltest (das ganze HäckMäck mit Imp
und Counter), desto größer wird die Gefahr, dass du dir genau in diesem
HäckMäck zusätzliche Fehler einhandelst.
[/quote]

Du hast dir schon wieder einen Fehler in der Hauptschleife eingehandelt!
Wenn du eine Funktionalität testen willst, dann mach den Code so einfach 
wie möglich. Je weniger Spielraum du dir für Fehler lässt, umso besser. 
Je umfangreicher der Code, desto mehr Möglichkeiten für Fehler.

So einfach ist das.

-> Du willst wissen, ob die Timer_int aufgerufen wird.
Dann mach dir den verdammten Nachweis dafür auch in die Timer_int 
hinein. Und zwar direkt und nicht über 25 Ecken.


PS: Ich weiß nicht, ob die Timer_int überhaupt aufgerufen wird. Ich hab 
weder einen Tiny13 noch BASCOM hier. Aber das erste was ich täte ist: in 
der Timer_int irgendetwas ein/ausschalten um zu sehen, ob die überhaupt 
aufgerufen wird.

von Wolfgang H. (frickelkram)


Lesenswert?

Hallo,

das Programm ist ja übersichtlich ;-) Auf jeden Fall mal die LED aus der 
IRQ-Routine ansteuern, das erhellt ungemein ...

Der ATTiny13 hat einen umfangreicheren Timer als die anderen, kleinen 
Atmel Prozessoren. Es gibt zusätzliche Steuerbits um den Modus fest zu 
legen. Ich habe mich schon einige Zeit mit dem Teil herum geschlagen, 
weil der Timer nicht das gemacht hat was ich wollte. Hier ein Auszug aus 
einem meiner Programme. Damit läuft der Timer im Interrrupt.
1
/* timer0 */
2
ISR (TIM0_COMPA_vect)
3
{
4
  PORTB ^= (1<<SPEAKER); 
5
}
6
7
.. snip ..
8
9
int main(void)
10
{
11
12
.. snip ..
13
14
  /* Init timers */
15
  /* phase correct PWM until TOP */
16
  /* timer generating square wave with 1kHz */
17
  TCCR0B |= T0div8;
18
  TCNT0 = 0;
19
  OCR0A = FRQADJ;
20
  TIFR0 = 0;
21
  TCCR0A |= (1<<COM0A0)|(1<<WGM01);
22
23
  
24
   /* switch on the IRQ handling */
25
   TIMSK0 |= (1<<OCIE0A);
26
   sei();
27
28
.. snip() ..
29
30
}

Wichtig: Im Datasheet die Steuerbits genau nachlesen.

Andere Lösungen:
http://www.bitartist.org/2008/07/timer-interrupt-on-tiny13.html
http://www.franzis.de/elo-das-magazin/mikrocontroller-und-programmierung/avr-anwendungen/tiny13-steuert-rgb-led
http://www.bitartist.org/2008/07/ctc-mode-on-tiny13.html

von Wolfgang H. (frickelkram)


Lesenswert?

Ach, noch was ...
Wie sieht die verwendete "ATTiny13.dat" aus? Ich habe mal eine verwendet 
die in Wirklichkeit für den ATTiny12 geschrieben war und im Bereich der 
Timer nicht 100%ig richtig war ...
Prüfe mal die Register Definitionen für die Timer Register gegen die 
Angaben im Datasheet.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:

> PS: Ich weiß nicht, ob die Timer_int überhaupt aufgerufen wird. Ich hab
> weder einen Tiny13 noch BASCOM hier. Aber das erste was ich täte ist: in
> der Timer_int irgendetwas ein/ausschalten um zu sehen, ob die überhaupt
> aufgerufen wird.

Ich hab mir jetzt BASCOM geholt und installiert.
Die Timer_int wird laut Simulation aufgerufen.

Allerdings dauerte es rund 230 ms bis Count den Wert 6 erreicht hat. 
Hochgerechnet auf 255 (wenn die Led toggelt) würde es daher rund 9 
Sekunden dauern, bis sich der Zustand der LED ändert.

von Christoph B. (elgigo)


Lesenswert?

Wolfgang Heinemann schrieb:
> Ach, noch was ...
> Wie sieht die verwendete "ATTiny13.dat" aus? Ich habe mal eine verwendet
> die in Wirklichkeit für den ATTiny12 geschrieben war und im Bereich der
> Timer nicht 100%ig richtig war ...
> Prüfe mal die Register Definitionen für die Timer Register gegen die
> Angaben im Datasheet.

Ich glaube du hast recht. Ich hab das nur das regfile auf m8def.dat 
geändert und in der Simu funzt es. Ist aber seltsam, hab mir die demo 
erst vor 2 Wochen geladen. Kann mal jemand sein File für den Tiny13 
posten bitte?

MFG
Christoph

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.