Forum: Mikrocontroller und Digitale Elektronik Timer0 oder 2 im sekundentakt (bascom)


von Peter K. (pker)


Lesenswert?

Hallo!
Ich als blutjunger Anfänger habe mal wieder ein Problem mit einem Timer
Ich benötige timer1 für die PWM.
Möchte aber noch ne Drehzahl von einem Lüfter messen.
Dazu benötige ich ja noch einen timer (hier 0 oder 2)

Ist es möglich den Timer0 oder Timer2 so zu programmieren das er mir 
eine isr jede Sekunde durchläuft?

Oder irgend wie anders zb. so
1
$regfile = "m16def.dat"                    
2
$crystal = 8000000
3
                       
4
Config Timer0 = Timer, Prescale= 8 
5
On  Timer0  Isr_Timer0  
6
Enable Timer0
7
Enable Interrupts
8
9
dim timerx as integer
10
11
do
12
'macht irgend etwas
13
loop
14
15
isr_timer0:
16
timerx = timerx + timer0
17
 
18
if timerx = ??? then
19
 'mach etwas
20
 timer = 0
21
 end if
22
23
return
24
25
end

Gruß Peter

von Hannes L. (hannes)


Lesenswert?

Peter K. schrieb:
> Ist es möglich den Timer0 oder Timer2 so zu programmieren das er mir
> eine isr jede Sekunde durchläuft?

Dann rechne doch mal.

Du willst mit 8 MHz Controllertakt arbeiten.
Der maximal mögliche Vorteiler ist 1:1024.
Der max. Zählumfang des Timer0 oder Timer2 (beide 8 Bit breit) ist 256.

8000000 Hz durch 1024 ist 7812,5 Hz
7812,5 Hz durch 256 ist 30,5... Hz, also 1/30 Sekunde.
Es reicht also nicht vorn und nicht hinten...

Abhilfe wäre das Erzeugen von 50 oder 100 Hz (20 oder 10 ms) und das 
Verwenden eines Nachteilers.

...

von Oliver J. (skriptkiddy)


Lesenswert?

Peter K. schrieb:
> Ist es möglich den Timer0 oder Timer2 so zu programmieren das er mir
> eine isr jede Sekunde durchläuft?
Nein mit einem 8-Bit-Timer ist es bei 8MHz nicht möglich unter 30Hz zu 
kommen.

Peter K. schrieb:
> Oder irgend wie anders zb. so
Ich kann Bascom nicht, aber irgendwie kommt mir das so vor, als willst 
du einen Software-Timer implementieren. Das ist auf jeden Fall möglich. 
Mann könnte das mit folgendem Konzept lösen:
Den Prescaler auf 1024 stellen und dann einfach den Overflow-Interrupt 
nutzen. Das hat pro Sekunde 8000000/1024/256 = 30.5175 Durchläufe zur 
Folge.
Mann geht jetzt einfach davon aus, dass nach 30 Interrupts eine Sekunde 
vergangen ist. Die so ermittelte Drehzahl muss dann allerdings noch mit 
einem Faktor von 30/30.5175 = 0.98304 nach unten korrigiert werden, weil 
eben noch keine Sekunde vergangen ist. Eventuell Kannst du auch mit den 
2% Fehler leben.

Dein Code ist aber irgendwie Murks. Ich würde das so versuchen:
1
$regfile = "m16def.dat"                    
2
$crystal = 8000000
3
                       
4
Config Timer0 = Timer, Prescale = 1024 
5
On  Timer0  Isr_Timer0  
6
Enable Timer0
7
Enable Interrupts
8
9
dim soft_timer as integer
10
dim Drehzahl as single
11
12
do
13
  'macht irgend etwas
14
loop
15
16
isr_timer0: 'aller 1/30.5175 Sekunden
17
  soft_timer = soft_timer + 1
18
 
19
  if soft_timer = 30 then
20
    'berechne Drehzahl (Deine Berechnung)
21
    '...
22
23
    'Korrigiere Drehzahl
24
    Drehzahl = Drehzahl*0.98304
25
    
26
    'Software-Timer zurücksetzen
27
    soft_timer = 0
28
  end if
29
return
30
31
end

Gruß Oliver

von Oliver J. (skriptkiddy)


Lesenswert?

Mir fällt gerad ein, dass man auch den CTC-Modus nutzen könnte:

Prescaler:256
Compare:  250 - 1
------------------
8000000/256/250 = 125

Damit hätte man exakt 125 Hz ISR-Frequenz und müsste nix korrigeren. 
Einfach den Software-Timer bis 125 Zählen lassen und es ist exakt eine 
Sekunde vergangen, wenn 125 ISR-Aufrufe geschehen sind.

Warum machst du übrigens nicht deine PWM mit TIMER0 oder TIMER2. Da 
könntest du den 16-Bittimer so einstellen, dass er 1Hz ISR-Takt hat. Mit 
einen Prescaler von 256 und einem Compare-Wert von 31250-1 kommt exakt 1 
Sekunde im CTC-Modus heraus.

Gruß Oliver

von Peter K. (pker)


Lesenswert?

Oliver J. schrieb:
> Mir fällt gerad ein, dass man auch den CTC-Modus nutzen könnte:
>
> Prescaler:256
> Compare:  250 - 1
> ------------------
> 8000000/256/250 = 125
>
> Damit hätte man exakt 125 Hz ISR-Frequenz und müsste nix korrigeren.
> Einfach den Software-Timer bis 125 Zählen lassen und es ist exakt eine
> Sekunde vergangen, wenn 125 ISR-Aufrufe geschehen sind.

Das hört sich schon mal gut an!

> Warum machst du übrigens nicht deine PWM mit TIMER0 oder TIMER2.

Ich habe gelesen das PWM nur mit timer1 geht.
Wen ich die PWM mit timer0 oder 1 programmieren kann wäre das auch ok!
aber wie?


Gruß Peter

von Hannes L. (hannes)


Lesenswert?

Peter K. schrieb:
> Ich habe gelesen das PWM nur mit timer1 geht.

Wo hast Du das gelesen?

Schau doch einfach mal ins Datenblatt des Mega16, Seite 2, da ist die 
Skizze des Pinout mit der Bezeichnung der Anschlüsse. Da gibt es neben 
OC1A und OC1B (Pin 19 und Pin 18, Hardware-PWM-Pins des Timer1) auch die 
Pins OC0 (Pin 4, Timer0) und OC2 (Pin 21, Timer2). Die Pins wurden 
sicher nicht ohne Grund so genannt... ;-))

Dieses Pinout ist immer die erste Anlaufstelle, um zu sehen, welche 
Hardware-Features der jeweilige AVR hat. Als nächstes schaut man sich 
dann die Registerbeschreibung an, da sieht man dann, welche 
Möglichkeiten die jeweilige Hardwarekomponente bietet.

...

von ThomasH (Gast)


Lesenswert?

Peter K. schrieb:
> Möchte aber noch ne Drehzahl von einem Lüfter messen.
> Dazu benötige ich ja noch einen timer

Das war die Aufgabenstellung. Lösungsansatz ist die Zeit zwischen zwei 
Interrupt-isr zu messen. Du brauchst dazu keinen Timer der im 
Sekundentakt läuft.
Also, Tachosignal an int-Pin (keine Ahnung wo der bei diesem Controller 
ist), einen Timer zum Messen der Zeit, einen für die PWM (den jetzt mal 
vergessen).
In der Interrupt-isr schaust du wieviele Timerüberläufe es seit der 
letzten isr gab und setzt den Zähler wieder auf null. Im Hauptprogramm 
rechnest du diesen Wert in U/min oder was auch immer um.

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.