Timer0 oder 2 im sekundentakt (bascom)

OP #2854264
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
#2854300
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.

...
#2854328
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
#2854348
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
OP #2854476
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
#2854528
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.

...
Gast #2854635
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren