Zkusil jsem udělat jednoduchý program v bascomu, jenž využívá přerušení. Problém je v tom, že první část (kontrolní zablikání ledkami) proběhne, ale vlastní přerušení nefunguje. Díky přerušení by měl program vyskočit každých 3,5sekundy z hlavní smyčky a 3x bliknout červenou led na portu B.2. Přitom by neustále měla téměř neustále blikat zelená led dioda na portu B1. To se však neděje.
Napadají mě tyto příčiny:
a) Špatné definování a spuštění časovače
b) Špatný dělící poměr v podmínce v podprogramu
Podprogram musí být navštíven 27500x aby se vykompenzovalo přerušení, jenž je 7812,5x za sekundu
Sám si myslím, že by to takto mělo fugovat, avšak evidentně to tak není, jelikož to takto nedělá.
' Preuseni
$regfile = "m48def.dat"
$crystal = 8000000
Dim A As Byte
Dim B As Integer
Config Portb = Output
Config Timer0 = Timer , Prescale = 1024
On Ovf0 Prerus
Enable Timer0
Enable Interrupts
Start Timer0
B = 0
Portb.1 = 1 ' Zelena led
Portb.2 = 1 ' Cervena led
For A = 1 To 5 ' Zablikej Ledkami
Portb.1 = 0
Portb.2 = 1
Waitms 300
Portb.1 = 1
Portb.2 = 0
Waitms 300
Next
Portb.1 = 1
Portb.2 = 1
Do ' Hlavni cyklus
Portb.1 = 0 ' Blikni zelenu led
Waitms 150
Portb.1 = 0
Waitms 300 ' Konec hlavniho cyklu
Loop
' Podprogram
Prerus: ' Podprogram vzkonavany pri preruseni
' Zvys B o jednu
Incr B ' Pokud uplynuko cca 3.5 sek blikni cervenou led
' 8000000/1024 = 7812.5Hz
' Kmitocet zakladni / preddelicka
' = vysledny pocet preruseni za sekundu
' 27500 / 7812.5 = 3.52 sek
If B > 27500 Then
For A = 1 To 3
Portb.2 = 0
Waitms 100
Portb.2 = 1
Waitms 300
Next
Else
B = 0
End If
Return
P.S. Doufám, že tento kód na přímé zveřejnění není ještě příliš dlouhý.
administrator: přejmenováno z "Přerušení nějak funguje, ač to mám špatně napsané"
If B > 27500 Then
For A = 1 To 3
Portb.2 = 0
Waitms 100
Portb.2 = 1
Waitms 300
Next
Else
B = 0
End If
Return
Tak jsem zjistil, že příkaz **else **je tam naprosto navíc a tak jsem ho smazal. Bohužel teď po proběhnutí kontrolního blikání na úvod svítí trvale červená dioda (portb.2) a zelená nereaguje.
Upravený kód podprogramu nyní vypadá takto:
If B > 27500 Then
For A = 1 To 3
Portb.2 = 0
Waitms 100
Portb.2 = 1
Waitms 300
Next
B = 0
End If
Return
P.S. Překladač chybu nikde nehlásí. Z tohoto důvodu jsem přesvědčen, že se jedná o chybu spíše logickou, než chybu v příkazu.
Nechápu co jsi vyřešil tím, že místo přerušení od přetečení čítače0 použiješ externí přerušení.
Podívej se do helpu ENABLE jaké jsou názvy přerušení.
Pro přetečení timer0 můžeš použít OVF0,TIMER0, COUNTER0.
Tvůj původní kód má tyto chyby:
Do ' Hlavni cyklus
Portb.1 = 0 ' Blikni zelenu led
Waitms 150
Portb.1 = 0
Waitms 300 ' Konec hlavniho cyklu
Loop
S tímto ledka blikat nebude.
If B > 27500 Then
To odpovídá intervalu asi 900 vteřin, ne 3,5.
Zkus hodnotu 100.
Edit:
A samozřejmě vynechat ELSE v obsluze přerušení.
Přerušení jsem se pokusil použít poprvé a tak to podle toho vypadá.
Když jsem zkoušel použít přetečení (viz původní kód), tak se nic nedělo. Proto jsem zkusil kód z příkladu z manuálu k bascomu a tofungovalo. Když se člověk zadívá, tak asi ne úplně správně. Spíš to tak na první pohled vypadá. I když, pokud je to externí přerušení, tak nevím, podle čeho funguje. Nejspíš díky neošetřenému pinu, kde se cosi indukuje.
Aha, chyba se vloudila. Tak proto prvni zelena led sviti. Ale ta druhá (červená, ovládaná přerušením) kupodivu bliká.
Aha já sice spočítal, že 8MHz/1024 je 7812.5, ale zapoměl jsem to vydělit 256.
Vnější přerušení INT0 je vyvoláno hranou nebo nízkou úrovní na pinu INT0 (PD2).
Způsob spuštění se nastavuje příkazem CONFIG INT0.
Nezapojený vstupní pin bez pull-up má vysokou vstupní impedanci takže je velmi citlivý na rušení.
Projeví se to tak, že neustále náhodně mění stav.
Proto, pokud za tohoto stavu povolíš přerušení INT0, bude spouštěno neustále jedno za druhým.
Tak jsem trochu poupravil časy původního programu, ale stále se to chová jinak, než bych chtěl. Na začátku má zablikat nastřídačku zelená led na portu B1 nastřídačku s červenou led na portu B.2 Poté má blikat zelená led a zhruba 1x za 3,5sekundy by měla 3x bliknout červená led. První fáze proběhne, ale pak bliká jen zelená led a červená led, jíž by mělo ovládat přerušení jen svítí. A vůbec nevím proč.
Portb.1 = 1 ’ Zelena led
Portb.2 = 1 ’ Cervena led
For A = 1 To 10 ’ Zablikej Ledkami
Portb.1 = 0
Portb.2 = 1
Waitms 15
Portb.1 = 1
Portb.2 = 0
Waitms 15
Next
Portb.1 = 1
Portb.2 = 1
Do ’ Hlavni cyklus
Portb.1 = 0 ’ Blikni zelenu led
Waitms 20
Portb.1 = 1
Waitms 20 ’ Konec hlavniho cyklu
Loop
’ Podprogram
Prerus: ’ Podprogram vzkonavany pri preruseni
’ Zvys B o jednu
Incr B ’ Pokud uplynuko cca 3.5 sek blikni cervenou led
’ 8000000/1024 = 7812.5Hz
’ Kmitocet zakladni / preddelicka
’ = vysledny pocet preruseni za sekundu
’ 27500 / 7812.5 = 3.52 sek
If B > 50 Then
For A = 1 To 3
Portb.2 = 0
Waitms 20
Portb.2 = 1
Waitms 30
Next
Else
B = 0
End If
Return[/code]
Je pravda, že jsem snížil čas na 1/2, takže místo 1x za 3,5sek by mělo blikání červené led proběhnout 2x. Celý cyklus blikání trvá 150ms a to by i při čase pro přerušení 612,5ms nemělo vadit. Nebo se pletu? Čemu vadí, že b bude maximálně 50? Kromě toho, že čas bude poloviční, než u hodnoty 100?
Asi si sedím na vedení, jelikož nevím, co jsem měl špatně, opravil jsem to na správně a pak zas opravil na špatně.
Máš v kódu napsáno, že když B je větší než 50 tak ledka zabliká.
Tudíž když B bude maximálně 50, tak ledka nezabliká nikdy.
Ostatně v tvém kódu dokonce B nebude nikdy větší než 1.
[code]Prerus: ’ Podprogram vzkonavany pri preruseni
Incr B
If B > 50 Then 'jestliže B je větší než 50, proveď smyčku "for-next" (tj. zablikej ledkou)
For A = 1 To 3
Portb.2 = 0
Waitms 20
Portb.2 = 1
Waitms 30
Next
Else 'jinak (tj. jestliže B není větší než 50)
B = 0 'vynuluj B (a smyčku for-next samozřejmě vynech)