logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Bascom - jak zrealizować wybór programu za pomocą przerwań?

majcher1 08 Lut 2006 00:45 2055 19
  • #1 2274369
    majcher1
    Poziom 11  
    Posty: 40
    Witam.

    Zaczynam zabawe z uC i Bascomem. Chcialbym napisac program, ktory bedzie sterowal np.3 portami - wlaczal je w roznych kompinacjach na jakis czas. Kompinacji ma byc kilka - w ponizszym programie sa przykladowe dwie jako Prog1 i Prog2. Sęk w tym, że nie bardzo wiem jak zrealizowac ich wybor. Musi byc dostepny w kazdej chwili- bez czekania, az dany program sie zakonczy (wiec wymyslilem, ze bedzie potrzebne przerwanie;) ) Zadawalajace by bylo np, zeby "Numer" byl inkrementowany przez przerwanie i wplywalby na wybor programu np. (start prog- 0 , przerwanie-1, przerwanie-2, przerwanie znow 0 itd.) co by zadzialalo gdyby po zakonczeniu przerwania wrocil na poczatek programu glownego (dokonywanie wyboru podprogramu), a nie np do 10-cio sek. Wait'a :/.

    Ps. Da sie w BascomAvr jakos usprawnic ta symulacje, zeby reagowala na przyciski sama - nie czekala na kolejne tykniecie zegara. Ustawiam wejscia i musze zmienic cos, zeby miec rezultat...

    Help. ;)

    $sim

    Config Lcd = 16 * 2
    Cls
    Dim Numer As Byte
    On Int0 Przycisk0
    Enable Interrupts
    Enable Int0

    Numer = 0


    Cls : Lcd "xxx" : Waitms 300
    Lowerline : Lcd "xxx" : Waitms 300


    Do

    'tu ma byc program ;)

    Loop


    Prog1:

    Cls
    Lcd "Program #1"

    Do

    Set Portd.0
    Reset Portd.1
    Set Portd.2

    Wait 5

    Reset Portd.0
    Set Portd.1
    Reset Portd.2

    Wait 5

    Loop
    Return

    Prog2:

    Cls
    Lcd "Program #2"

    Do

    Set Portd.0
    Reset Portd.1
    Reset Portd.2

    Wait 5

    Reset Portd.0
    Set Portd.1
    Reset Portd.2

    Wait 5

    Reset Portd.0
    Reset Portd.1
    Set Portd.2

    Wait 5

    Loop
    Return

    Przycisk0:

    Return
  • Pomocny post
    #2 2275379
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Witam.

    W petli glownej programu musisz sobie napiac jakas procedurke wyboru podprogramow. Np mozesz uzyc do tego 3 przyciskow - jeden do zwiekszana zmiennej np wybor , drugi do jej zmniejszania atrzeci przycisk do potwierdzenia "enter" .

    Nie pamietam juz dokaldnie skladni w Bascomie ale moze to byc np tak:


    DDRB=&b11111000 // - piny 0 1 i 2 portu B jako wejscia
    PORTB=&b00000111 // - podciagniete do plusa zasilania, nie pamietam czy tak mozna konfigurowac porty w bascomie
    dim a as byte
    a=0;


    // petla glowna
    do



    cls
    lcd "progr:"; a


    if PINB.0 = 0 then
    waitms 100 // opznienie wymagane by wyeliminowac drgania stykow
    incr a ;
    if a >=5 then // 5 - ilosc kombinacji
    a=5;
    end if
    end if

    if PINB.1 = 0 then
    waitms 100 // opznienie wymagane by wyeliminowac drgania stykow
    decr a;
    if a <=0 then // 5 - ilosc kombinacji
    a=0;
    end if
    end if

    if PINB.2 =0 then
    cls
    lcd "wybrano progr:"; a
    waitms 100

    case select a
    case 0 : Gosub Prog1
    case 1 : Gosub Prog2
    case 2 : Gosub Prog3
    case 3 : Gosub Prog4
    case 4 : Gosub Prog5
    case 5 : Gosub Prog6
    end select
    end if
    loop
    aha do eliminacji drgan stykow mozna wykozystac poloecenie debounce czy jakos tak

    Co do wychodzenia z podprogramu bez czekania... musial bys zastosowac zewnetrzne przerwanie np INT0 , jednak sprawa nie jest taka prosta bo po rzerwaniu nastepuje podwrot w miejsce programu gdzie zostalo ono przerwane. Trzeba zastosowac pare sztuczek, musisz poszukac na forum niedawno byl post gdzie kolega mial podobny problem z wychodzeniem z procedury po przerwaniu.
  • #3 2276067
    majcher1
    Poziom 11  
    Posty: 40
    Dzieki za odp. Bedzie napewno bardzo przydatna, lecz nadal nie wiem najwazniejszego :/ Chodzi pewnie o zmiane adresu powrotu - ale jak na poczatek Bascoma to chyba chwilowo za trudne :p. Czekam na dalsze rady z Waszej strony.

    Znalazlem przed chwila taki kod:
    on int0 guzik nosave

    do
    etykieta:
    SREG.7=1
    ...
    CALL procedura1
    CALL procedura2
    ...
    loop

    guzik:
    IF ma_byc_wyskok THEN
    SPL=&HDF
    GOTO etykieta
    END IF
    return

    Ponoc dziala, co oznacza SREG.7=1 i SPL=&HDF ?
  • #4 2277674
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Cos takiego powinno działac , musisz pokombinować.


    SP to stack pointer czyli wskaźnik stosu,a stos to chyba wiesz co to jest :)
    SPL określa młodszy bajt SP.

    Instrukjca nosave powoduje że na stos nie beda wrzucane zadne rejestry robocze.

    SREG to głowny rejestr kontrolny . Proponuje zajrzeć do pdfa z opisem układu.
    SREG.7 wskazuje na 7 bit w tym rejestrze. Bit ten jest odpowiedzialny za włączenie bądz wyłączenie globalnej obsługi przerwań. Gdy jest =1 przerwania sa odblokowane. To działa tak samo jak być napisał w BASCOMIE "enable interrupts ", lub "disable interrupts"

    Jak to działa... no więc w momencie wykrycia przerwania na stosie jako pierwszy jest umieszczany adres miejsca z którego nastąpił wyskok do procedury przerwania.
    Normalnie po zakończeniu przerwania odczytywany jest adres powrotu i następuje powrót do miejsca w którym program aktualnie wykonywał instrukcje. W twoim przypadku mogą to być te podprogramy.

    Ty nie chcesz zeby po przerwaniu nastepował tam powrót, tylko chcesz wracać do pętli głównej. Tak więc musisz podmienic adres powrotu znajdujący sie na stosie. Podmieniony adres musi wskazywać na adres początkowy stosu .
  • #5 2278671
    majcher1
    Poziom 11  
    Posty: 40
    Enable Interrupts -trzeba bylo tak odrazu ;)

    Nadal nie do konca jednak rozumiem SPL=&HDF
    Co to dokladnie oznacza?
  • #6 2279931
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    SP to rejestr 16 bitowy, podzielony na 2 częsci , młodszy bajt oznaczony SPL i starszy bajt oznaczony SPH.

    inaczej mozna by zapisać SP jako SP=SPL + 255*SPH

    SPL=&HDF, oznaca ze młodszy bajt wskaźnika stosu zostanie ustawiony na wartość &hDF, czyli na DF w zapisie hexadecymalnym (szesnastkowym ) Odpowiada to wartosci dziesietnej 223.
  • #7 2280791
    majcher1
    Poziom 11  
    Posty: 40
    '$sim


    Config Lcd = 16 * 2
    Dim A As Byte
    A = 1
    On Int0 Przycisk0 Nosave

    Cls : Lcd "linia 1" : Waitms 300
    Lowerline : Lcd "linia 2" : Waitms 300



    Do
    Poczatek:
    Enable Interrupts
    Enable Int0

    Select Case A
    Case 1 : Gosub Prog1
    Case 2 : Gosub Prog2
    Case 3 : Gosub Prog3
    Case 4 : Gosub Prog4
    Case 5 : Gosub Prog5
    Case 6 : Gosub Prog6
    End Select

    Loop



    Przycisk0:
    Spl = &HDF
    Incr A
    If A >= 7 Then A = 1
    Goto Poczatek

    Return

    Prog1:

    Cls
    Lcd "Program 1"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    Prog2:
    Cls
    Lcd "Program 2"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    Prog3:
    Cls
    Lcd "Program 3"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    Prog4:
    Cls
    Lcd "Program 4"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    Prog5:
    Cls
    Lcd "Program 5"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    Prog6:
    Cls
    Lcd "Program 6"
    Waitms 100
    Do
    Cls
    Lcd "--**--TEST--**--"
    Waitms 100
    Cls
    Waitms 100
    Loop
    Return

    W symulatorze na poczatku dzialalo, pozniej zaczal wyswietlac jaies krzaki, aktualnie dobrze skacze po kodzie, ale jak wlacze symulacje LCD to sa albo krzaki, albo jakas zwiecha na wyswietlaczu... Nie mam jeszcze ukladu na ktorym moglbym to przetestowac niestety. Moze ktos zechce to sprawdzic... ? ;)
  • #8 2280866
    Jaca
    Poziom 32  
    Posty: 1332
    Pomógł: 239
    Ocena: 217
    Czy nie lepiej wykonać obsługę sekwencji w procedurze obsługi przerwania timer'a ? Co należałoby zrobić ?:
    - zdefiniować przerwanie np co 50 ms
    - dodać programowy dzielnik /100 w przerwaniu (5s)
    - wykonać tablicę sekwencji w pamięci programu
    - każde przepełnienie dzielnika powoduje odczyt danej z tablicy (w zależności od numeru sekwencji i numeru kroku) i przekazanie jej na port uC
    - ustawienia numeru sekwencji, start/stop umieślić w pętli głównej programu

    W ten sposób mamy "z głowy" jakieś kombinacje ze stosem, kod staje się bardziej czytelny i mniejszy, nie ma problemów ze zmianą numeru sekwencji ponieważ czas oczekiwania (5 s) jest podzielony na mniejsze kawałki (50 ms). Takie jest moje zdanie.

    Pozdrawiam...
  • #9 2280902
    Mirek D
    Poziom 15  
    Posty: 120
    Pomógł: 8
    Ocena: 12
    Za krótkie opuźnienie WAITMS. Muszą być krzaczki bo wyświetlacz zwyczajnie nie zdąży wyświetlić tego co powinien.
    Pozdro
  • #10 2281228
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Instrukcja goto poczatek chyba nie jest juz potrzeba ..
  • #11 2281829
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    adamusx napisał:
    Instrukcja goto poczatek chyba nie jest juz potrzeba ..

    A to niby dlaczego :?:
    Zresztą cała ta dysputa , przypomina mi dyskusję praktykantów , o operacji na otwartym sercu (wybaczcie) ;) W tym przykładzie , nawet gdybyśmy z przerwania wskoczyli pod adres 0 (reset) , to i tak na LCD pojawią się krzaki , bo układ obsługujący matrcę w wyświetlaczu , nic nie wie o naszych niecnych zamiarach ;) Takie przypadki , można by mnożyć w nieskończoność.Przecież takie urządzenie to nie tylko procek , ale współpracujące z nim peryferia itd.Ja bym się przychylił do propozycji Jaca Nie mówię , że TO jest niemożliwe , ale ktoś kto nie wie co to jest wskaźnik stosu , takiego numeru nie może robić bezkarnie :(
    To chciałem Wam przekazać.

    Pozdrawiam
    Piotrek
  • #12 2281871
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    No pewnie ze to nie jest prosta spawa, jak sie robi takie sztuczki tym bardiej jak sie kombinuje cos z licznikiem programu :) Operacja na otwartymsercu todobre określenie :D

    Co do tego ze instrukcja goto poczatek nie jest potrzebna ...tak mi sie wydaje,bo:
    skoro ustawilismy recznie juz po wejsciu do obslugi przerwania adres stosu na okreslone miejsce to po zakonczeniu obslugi przerwania w (bascomie Return) jest instrukcja reti ktora powoduje odczytanie ze stosu licznika programu i skok w to miejsce . Tak więc w tym przypadku niezależnie od tego w ktory miejscu programu nastąpiło przerwanie, powrot z niego nastąpi w miejsce ktore zostało ustawione przez wskaznik stosu... zgadza sie ?
  • #13 2281955
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Majcher - Faktycznie program wykona GOTO POCZATEK zawsze. Nie potrzebne to chyba? W moim zastosowaniu taki sposób wyskoku z procedury potrzebny mi był własnie do NATYCHMIASTOWEGO przerywania wykonywaniania jakichś procedur (akurat ja miałem je w petli głównej). Jeśli użyjesz przycisku program wyskoczy z procedury np. między CLS a LCD i co wtedy? Nic nie pokaże. Niepotrzebnie też chyba ciągle robisz petle w procedurach. Ja bym dal raczej np. tak:
    Prog1:
    Cls
    Lcd "Program 1"
    Wait 1
    Cls
    Lcd "--**--TEST--**--"
    Do
    waitms 100
    Loop
    Return
  • #14 2282108
    majcher1
    Poziom 11  
    Posty: 40
    Poszczegolne procedury ProgX sa tylko do testow, ale masz racje.

    Problemem jest u mnie jeszcze brak uC :/ wiec nie moge tego sprawdzic na ukladzie. Zbudowalem juz programator, teraz musze skas wziac jakiegos avr'ka. Narazie to symuluje w BascomAvr, ale niestety nie dziala !

    Po wcisnieciu przerwania program staje. Cos w ogole jest nie tak podczas symulacji - hardware emulation... moze ten BascomAvr jest zle skonfigurowany, albo cos z nim nie tak skoro program jest "w miare" poprawny.

    SPL=&HDF - tez powinno dzialac w symulatorze ?!
  • #15 2282187
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    wicy napisał:
    Majcher - Faktycznie program wykona GOTO POCZATEK zawsze.
    ...

    Nie GOTO POCZATEK tylko po ...

    ... do licznika rozkazów(PC) zostanie załadowana wartość 0x0000 czyli adressoft reset.Dlaczego , ano dla tego , że np. w 90s2313 &HDF jest najwyższym adresem pamięci RAM , a procek po powyższej sekwencji rozkazów , załaduje do PC dane spod adresu &HE0 i &HE1 , a tam NIC NIE MA.Dla np. 90s8535 , to już wogóle katastrofa , bo pamięć RAM kończy się na &H025F , a program zmieni tylko młodszy bajt PC , więc wskaźnik stosu przyjmie wartość &H02DF :( i tak dalej i tym podobnie .

    Zawiedziony ;)
    Piotrek
  • #16 2282368
    majcher1
    Poziom 11  
    Posty: 40
    Do
    Poczatek:
    Cls 'to w celu poznania zawartosci SPL
    Lcd Spl
    Wait 1

    Enable Interrupts
    Enable Int0

    Select Case A
    Case 1 : Gosub Prog1
    Case 2 : Gosub Prog2
    Case 3 : Gosub Prog3
    Case 4 : Gosub Prog4
    Case 5 : Gosub Prog5
    Case 6 : Gosub Prog6
    End Select

    Loop

    Przycisk0:
    Spl = 93
    Incr A
    If A >= 7 Then A = 1

    Return

    Lopatologicznie zrobilem jak wyzej, nawet dziala w symulacji, ale mam duze obawy co do slusznosci mej idei ;) Na kompie dziala - bedzie tez dzialac na np ATMega8?

    Jest jeszcze jedna sprawa - jak zaczne klikac szybko INT0 to po chwili program glupieje- na ekranie pojawiaja sie "krzaki", dopiero po ponownym uruchomieniu Bascom'a zaczyna dzialac. Co to moze byc ?

    Pozyslalem, ze robi wtedy przerwanie w przerwaniu, ale napisalem na poczatku przerwania:
    Disable Interrupts
    Disable INt0

    i jest tak samo ;/
  • #17 2282876
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    majcher1 napisał:

    ...
    i jest tak samo ;/

    Bo nie słuchasz o czym mówię :(
    Potestuj poniższe - skrobnąłem dla Ciebie ;) :
    
    '$map
    
    $regfile = "m32def.dat"
    '$crystal = 11059200
    'ATMega32  adres rej SPL+&H20
    Const Lowsp = &H5D
    
    Dim A As Byte , Lab_adr As Word
    Dim Alow As Byte At Lab_adr Overlay , Ahi As Byte At Lab_adr + 1 Overlay
    Dim Tspl As Byte
    On Int0 Int0_intr Nosave
    Config Int0 = Falling
    Lab_adr = Loadlabel(petla)
    Lab_adr = Lab_adr / 2
    $asm
    lds r24,{alow}
    push r24
    lds r24,{ahi}
    push r24
    $end Asm
    Tspl = Inp(lowsp)
    Enable Int0
    A = 0
    Petla:
    Spl = Tspl
    'enable interrupts
    sei
    Do
       On A Gosub Prog1 , Prog2 , Prog3 , Prog4 , Prog5 , Prog6 , Idz_w_krzaki
    Loop
    Int0_intr:
    Incr A
    '************If A > 5 Then A = 0
    Spl = Tspl
    Return
    
    Prog1:
    Do
    'blokujemu przerwania przed każdą operacją na LCD
       cli
       Cls
       Lcd "Prog1"
    'włączamy przerwania , byśmy mogli przerwać tę nieskończoną pętlę
       sei
       Waitms 100
       nop
    Loop
    'Return -jest zbędny , bo i tak nie opuścimy tej pętli w "normalny" sposób ; -)
    Prog2:
    Do
       cli
       Cls
       Lcd "Prog2"
       sei
       Waitms 100
       nop
    Loop
    Prog3:
    Do
       cli
       Cls
       Lcd "Prog3"
       sei
       Waitms 100
       nop
    Loop
    Prog4:
    Do
       cli
       Cls
       Lcd "Prog4"
       sei
       Waitms 100
       nop
    Loop
    Prog5:
    Do
       cli
       Cls
       Lcd "Prog5"
       sei
       Waitms 100
       nop
    Loop
    Prog6:
    nop
    A = 0
    Spl = Tspl
    Return
    
    Idz_w_krzaki:
    Goto Idz_w_krzaki
    

    Możesz skoczyć do "Petla:" z przerwania lub z dowolnego miejsca w programie.
    Piotrek
  • #18 2283568
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Zumek - Masz rację pewnie co do stosów i nawet nie chcę rozpoczynać tutaj polemik. Ja w swoim programie użyłem SPL=223 bo akurat taką wartość mi wskazywał tuż po rozpoczęciu pętli głównej, czyli wskaźnik stosu "początkowy" ustawiony już po wszystkich konfiguracjach na początku programu. Wartość ta pewnie się zmienia np. przy wykorzystaniu LCD albo przy zmianach konfiguracyjnych w samym Bascom'ie, ale juz w trakcie wykonywania programu i pętli głównej przy prostych instrukcjach nie używających stosu pozostaje niezmienna. W symulacji trzebaby sprawdzić jaką wartość ma SPL przed pierwszym "przejsciem" przez etykiete POCZATEK i taka wartośc ustawiać potem w przerwaniu.
  • #19 2283759
    majcher1
    Poziom 11  
    Posty: 40
    No to spoko. Czyli w takim razie to co napisalem powinno dzialac.
    Zablokowalem tez prezrwania przed kazda operacja na LCD i juz sie krzaki nie pojawiaja. Narazie wszytsko tylko w symulacji, ale moze juz niedlugo uda mi sie to sprawdzic.

    Dzieks.
  • #20 2284239
    Jaca
    Poziom 32  
    Posty: 1332
    Pomógł: 239
    Ocena: 217
    Zerknij jeszcze na to co napisałem "na szybkiego".
    Załączniki:
    • uC.zip (1.01 KB) Musisz być zalogowany, aby pobrać ten załącznik.

Podsumowanie tematu

✨ Dyskusja dotyczy realizacji wyboru programu w Bascom AVR za pomocą przerwań, tak aby możliwa była natychmiastowa zmiana aktywnego podprogramu bez oczekiwania na zakończenie aktualnie wykonywanego kodu. Proponowane rozwiązania obejmują inkrementację zmiennej sterującej numerem programu w procedurze obsługi przerwania INT0 oraz manipulację wskaźnikiem stosu (SPL) w celu wymuszenia powrotu do początku pętli głównej po przerwaniu. Omówiono znaczenie rejestru SREG i bitu globalnej obsługi przerwań (SREG.7), a także rolę wskaźnika stosu (SP, SPL, SPH) w kontekście adresowania powrotu z przerwania. Zwrócono uwagę na ryzyko nieprawidłowego ustawienia SPL, które może prowadzić do błędów adresowania i niestabilności programu, szczególnie na różnych modelach mikrokontrolerów AVR. Wskazano, że w praktyce lepszym rozwiązaniem jest obsługa sekwencji w przerwaniu timera z podziałem czasu na krótsze odcinki i wykorzystaniem tablicy sekwencji w pamięci programu, co zwiększa czytelność i stabilność kodu. W trakcie symulacji w Bascom AVR pojawiały się problemy z wyświetlaniem i stabilnością, które zostały częściowo rozwiązane przez blokowanie przerwań podczas operacji na LCD. Dyskutowano także o ograniczeniach symulatora i konieczności testów na rzeczywistym sprzęcie, np. ATMega8. Przykładowy kod pokazuje implementację wyboru programu przez przerwanie INT0, inkrementację zmiennej wyboru, oraz wywoływanie podprogramów w pętli głównej z obsługą przerwań i manipulacją wskaźnikiem stosu.
Wygenerowane przez model językowy.
REKLAMA