Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

I2C w przerwaniach

14 Wrz 2004 09:25 3402 18
  • Poziom 10  
    Drodzy koledzy, procesorami AVR od bardzo niedawna się zajmuję i w związku z tym zadam jedno małe pytanko.
    Otóż czy obsługa magistrali I2C może być bez zakłoceń wykonywana w w przerwaniach procesora. Pytanie może jest naiwne ale widzę że system potrafi mi całkowicie zgłupieć.
    INT0 zajmuje się u mnie obsługą przerwania zegara czasu rzeczywistego PCF8583.
    TIMER0 obsługuje klawiaturę wykonaną na (PCF8574) zapisując w odpowiednim rejestrze kod ostatnio wcisnietego klawisza.
    Już przy takim prostym ustawieniu okazuje się że przerwanie zakłóca pracę I2C poprzez zmianę rejestrów zegara, gdy tymczasem w programie nie mam funkcji zapisu danych do zegara (jeszcze jej po prostu nie napisałem :D). Ponieważ oba scalaki obsługiwane są przez I2C domyslam się że przerwanie Timera wchodzi w paradę protokółowi transmisji która wykonuje się podczas obsługi przerwania zegara.
    W związku z tym następujące pytania:
    1) czy AVR-y mają kolejkowanie przerwań na poziomie konstrukcji procesora ? (jakoś się tego nigdzie nie doczytałem)
    2) czy obsługa I2C nie jest na tyle wolnym procesem aby być obsługiwaną przez przerwania timerów ?
    3) czy koledzy mają jakieś własne propozycje zapanowania nad hierarchią przerwań w sytuacji kiedy program musi obsłużyć "na raz" kilka przerwań procesora w dodatku pracując z wyświetlaczem LCD.
    Problem dotyczy Atmega32 oraz programu pisanego w C więc kwestie pamięci i szybkości programu możemy pominąć milczeniem :D
    Póki co bawię się tym testując kolejne przerwania ale docelowo wszystkie układy we-wy czyli klawisze, wyświetlacz,LED-y,oraz pamięć danych będę musiał obsłużyć za pomocą I2C w dodatku używając przynajmniej czterech przerwań procesora, w związku z tym proszę o ew. spostrzeżenia,
    PZDR.
  • Poziom 29  
    A nie lepiej odpytywać na przerwaniu timera i klawiaturę i PCF8535? Do programu wstawić semafor ustawiany przerwaniem INT0 i kasowany przy odczycie wskazania zegara. To samo dotyczy innych peryferiów przyłączanych na I2C - dostęp do szyny niech ma tylko jeden wątek.

    Myślę, że ułatwiłoby to sprawę i to znacznie.
  • Poziom 33  
    Kiepskim pomysłem jest wykorzystywanie transmisji IIC w obsłudze przerwania. Protokół IIC jest stosunkowo wolny, a może być jeszcze wolniejszy bo przytrzymanie sygnału zegara niczemu nie szkodzi. Nie do końca rozume to co napisałeś ale wydaje mi się, że problem polega na tym, że uC nie wyrabia się z tymi przerwaniami bo zajmują mu za dużo czasu i wszystko się rozłazi.
    Ewentualnie zapodaj tu źródło programu i schemat układu.
  • Poziom 10  
    lelekx napisał:
    A nie lepiej odpytywać na przerwaniu timera i klawiaturę i PCF8535?

    Ja też tak myślę i dziwne że na to nie wpadłem wcześniej, Dzieki za wsparcie mojego know how :D
    Choć niestety nie uniknę przesyłania "wielowątkowego", póki co na tzw biegu posłużyłem się zatrzymywaniem innych przerwań podczas trwania przerwania timera, chyba pomogło ale nie wiem czy to dobre rozwiązanie?
  • Poziom 32  
    Też mam nie mały programik na ATmega32 i urzywam multum przerwań:
    • Timer0
      Timer1
      USART nadawanie i odbiór
      Comparator

    i jak narazie zero problemów. Przerwania mają jedną zasadniczą zaletę, elestyczniej wykożystują zasoby systemowe. Oczywiście należy przeliczyć zależności czasowe, bo jak przerwania będą się zbyt długo nakładać to system będzie musiał paść.
  • Poziom 15  
    jesli przerwanie zakloca ci transmisje i2c to masz cos nie tak bo to transmisja synchorniczna i nawet jesli dana przestanie sie wysylac na kilka minut a potem sie wznowi to bedzie ok.
  • Poziom 10  
    gummis napisał:
    jesli przerwanie zakloca ci transmisje i2c to masz cos nie tak bo to transmisja synchorniczna i nawet jesli dana przestanie się wysylac na kilka minut a potem się wznowi to bedzie ok.

    może przybliżę problem ponieważ wiem że coś jest nie tak :D tylko co ?
    1)przerwanie timera w okreslonym interwale czasowym sprawdza stan klawiatury i jesli jakis klawisz zostal wcisniety zapisuje jego kod w zmiennej globalnej oraz ustawia flagę wcisniecia klawisza i w zasadzie na tym kończy się obsługa przerwania Timera. Ponieważ klawiatura jest podłaczona do ekspandera PCF8574 obsługa jest realizowana za posrednictwem I2C.
    Zmienną z kodem wcisnietego klawisza odczytuje z kolei funkcja odczytu klawiatury ktora przy okazji kasuje flagę.
    2)drugie prerwanie INT0 jest przeznaczone dla zegara czasu rzeczywistego, ktore w zasadzie nic innego nie robi z wyjatkiem ustawienia flagi odczyt czasu z zegara.
    Program głowny dzialajac w petli odczytuje flage zegara, w zaleznosci od jej stanu pobiera czas zegara i wyświetla go na LCD. Dalej wykonuje sprawdzenie nacisniecia klawisza (na podstawie flagi ustawionej przez przerwanie timera) i w zaleznosci o stanu klawiatury podejmuje dalszą akcję. Takie jest z grubsza założenie.
    Nestety okazuje się że jakiegoś nieznanego powodu, przy okazji czas segara zostaje zmieniony ! i to na dodatek jakąś dziką wartością z poza zakresu 24godzinnego czasu. Na przykład godziny przyjmują wartość 30 !
    Sądzę że może być tak że w czasie kiedy program głowny pobiera czas w tym momencie wchodzi mu w paradę przerwanie i zaczyna czytać ekspander przez co głupieje całe I2C. Nie mogę zrezygnować z przerwania zegara INT0 ponieważ potrzebuję dokładnie odmierzanych impulsów czasowych 1 sek, tak naprawdę do innego celu a czas wyświetlany jest niejako przy okazji. A z drugiej strony inne przerwania muszą mieć mozliwość transmisji po I2C ponieważ i klawiatura i LCD czy też LED będą znacznie oddalonene od płyty z procesorem więc podłaczenie ich pod porty odpada.
    Może wprowadzić flagę zajętości magistrali I2C i wtedy uniknę kłopotów. W kazdym razie dziękuję za rady, kombinuję cały czas :D
  • Poziom 33  
    Co ile masz przerwanie od timera bo jak się domyślam stan klawiatury odczytujesz kilkadziesiąt razy na sekundę??
    Napisze to po raz kolejny:
    Wywal odczyt po IIC klawiatury z obsługi przerwania!!! I rób to tak samo jak odczyt czasu w programie głównym na podstawie flagi.
    Po drugie po co odczytujesz za każdym razem czas z PCF'a???
    Skoro masz przerwanie INT0 co 1s to zrób w obsłudze tego przerwania licznik czasu tzn. licz sekundy jak dojdą do 60 to minuty (sekundy zerujesz) itd. Czas z PCF odczytuj tylko przy starcie systemu i powiedzmy raz na 12 godzin żeby zniwelować ewentualne różnice (jak dobrze napiszesz program to powinno wystarczyć korygowanie raz na tydzień czy raz na miesiąc). W ten sposób odciążysz IIC.
  • Poziom 10  
    Tdv napisał:
    Co ile masz przerwanie od timera bo jak się domyślam stan klawiatury odczytujesz kilkadziesiąt razy na sekundę??
    Napisze to po raz kolejny:
    Wywal odczyt po IIC klawiatury z obsługi przerwania!!! I rób to tak samo jak odczyt czasu w programie głównym na podstawie flagi.
    Po drugie po co odczytujesz za każdym razem czas z PCF'a???
    Skoro masz przerwanie INT0 co 1s to zrób w obsłudze tego przerwania licznik czasu tzn. licz sekundy jak dojdą do 60 to minuty (sekundy zerujesz) itd. Czas z PCF odczytuj tylko przy starcie systemu i powiedzmy raz na 12 godzin żeby zniwelować ewentualne różnice (jak dobrze napiszesz program to powinno wystarczyć korygowanie raz na tydzień czy raz na miesiąc). W ten sposób odciążysz IIC.


    Timer ustawiłem tak aby 8 x w ciągu sekundy odczytywał klawiature. Z nim akurat sobie własnie poradziłem zastepując go przerwaniem INT1 pochodzącym od PCF8574. Z czasem istotnie mozna sobie dać spokój i zrobić wg twojej rady. Odczyt czasu wpakowalem w zasadzie po to aby testowac program. Muszę stwierdzić że mimo wszystko nie uniknę odczytu magistrali I2C w przerwaniach bo nie mogę sobie pozwolić na korzystanie z portów procesora z racji sporej długości kabli łaczących urzadzenia we-wy z płyta procesora no i tym samym mam kłopot :D
    Chodzi o to że robię taki mini-komputer pokładowy do motocykla, tzn obrotomierz, licznik kilometrów dziennego przebiegu, całkowitego, szybkościomierz cyfrowy ale także z analogowym obrazowaniem na linijce LED, obrotomierz także z cyfrowym i analogowym odczytem a jeszcze w dodatku alarm a w tym wszystkim i obrazowanie części informacji na LCD oraz 16 znakowa klawiatura matrycowa . W efekcie przynajmniej 4 a moze 5 przerwań będę musiał obskoczyć. I jak tu uniknąć I2C w tym wszystkim kiedy płyta jest w jednym miejscu a wskazniki oddalone o jakieś 1,5 m w długości kabli ? No chyba że dołoże jakieś równoległe porty wejścia wprost do procesora i połaczę to potężną "pytą" kabli, hehehe.
    Rozumiem że nadrzędna zasada jest taka, przerwanie a zwłaszcza te krytyczne czasowo jak np. timera nie może posługiwac się I2C wewnatrz swojej procedury i tego się nalezy trzymać . Mam rację ?
    W kazdym razie dzięki za ray bo się przydały, PZDR :?
  • Poziom 15  
    ogolnie jest zasada tak ze w przerwaniach nie powinno byc jakis procedur opozniajacych, przerwanie powinno sie wykonac , obliczyc i wylaczyc jak najszybciej,glowny program jest od czasowek , komunikacji i2c itp.
    przynajmniej ja sie staram trzymac tych zasad.czasami mozna je nagiac oczywiscie.to zalezy od zlozonosci projektu.
    ja PCF8583 obsluguje zawsze tak jak to opisal TDV
    przy starcie odczytujesz czas a potem inkrementujesz w przerwaniu.nie trzeba nic uaktualniac po kilku godz bo nadanie przerwania przez PCF8583 jest rownoznaczne ze zinkrementowaniem czasu w nim.
    oczywistym jest ze jesli wykonuje sie transmisja i2c i w srodku zostanie przerwana i nowa transmisja idzie to bedzie tak sie dzialo.
    zrob normalnie tak przy starcie:
    wylacz przerwanie od PCF
    wyzeruj flage wywlujaca przerwanie od PCFa
    odczytaj dane z PCFa
    sprawdz czy flaga wywolujaca przerwanie nie ustawila sie
    jesli nie tzn ze w momencie odczytu czasu nie nastapila inkrementacja czasu w pcfie
    jesli ni to wlacz przerwanie i masz dobry czas
    jeslisie ustawila to powtorz wszyko od kroku 2.
    potem tylko za kazdym przerwaniam od PCF zmieniasz czas w procesorze
    ni pisze na avr moge ci podac jak to zrobilem na 51 .moze se przetlumaczysz


    ; ************ G L O W N A P R O C E D U R A Z E G A R O W A *********
    intpcf:
    push psw
    push acc
    mov PSW,#pcfRB
    ; =========================== AKTUALIZACJA WSKAZAN ZEGAROW
    ; ----------- ZLICZANIE CZASU GLOWNEGO
    mov a,ZEGs
    add a,#1
    da a
    mov ZEGs,a
    cjne a,#60h,czasOK
    mov ZEGs,#00h
    mov a,ZEGmn
    add a,#1
    da a
    mov ZEGmn,a
    cjne a,#60h,czasOK
    mov ZEGmn,#00h
    mov a,ZEGg
    add a,#1
    da a
    mov ZEGg,a
    cjne a,#24h,czasOK
    mov ZEGg,#00h
    ; ----- NOWY DZIEN TYGODNIA
    mov a,ZEGmc
    add a,#40h
    jc SetDzTy
    subb a,#20h
    SetDzTy:mov ZEGmc,a
    ; ----- WYLICZENIE OSTATNIEGO DNIA MIESIACA
    anl a,#1fh
    mov rck1,a
    add a,#-8
    addc a,#0
    anl a,#1
    orl a,#30h
    cjne rck1,#2,SetMxMc
    mov a,ZEGd
    add a,#0c0h
    mov a,#29h
    subb a,#0
    SetMxMc:cpl a
    mov rck2,a
    ; ----- NOWY DZIEN MIESIACA
    mov a,ZEGd
    anl ZEGd,#0c0h
    anl a,#3fh
    add a,#1
    da a
    orl ZEGd,a
    add a,rck2
    jnc czasOK
    anl ZEGd,#0c0h
    inc ZEGd
    ; ----- NOWY MIESIAC
    mov a,rck1
    anl ZEGmc,#0e0h
    add a,#1
    da a
    orl ZEGmc,a
    cjne a,#13h,czasOK
    anl ZEGmc,#0e1h
    ; ----- NOWY ROK
    mov a,ZEGd
    add a,#40h
    mov ZEGd,a
    mov a,ZEGr
    add a,#1
    da a
    mov ZEGr,a
    czasOK:
    ;-------------------------------
    ;tu mozna wstawic czesc kodu specyficzna dla
    ;aplikacji
    ;-------------------------------
    ExitClk:
    pop acc
    pop psw
    reti
  • Poziom 33  
    gummis: kolega pisał wyraźnie o uC AVR, a nie o '51 ;-D.
  • Poziom 10  
    Tdv napisał:
    gummis: kolega pisał wyraźnie o uC AVR, a nie o '51 ;-D.

    ale kumam czacze :) wszysko OK. mimo ze wolę C niż jezyk maszynowy z tymi wszystkim jego cyferkami :D
    Osobiście muszę się z Wami zgodzić że macie rację w kwestii przerwań tylko ze jest jedno ale.
    Chodzi o tę klawiaturę. Z portów nie da się zrobic użytku z ww. opisanych powodów. Pozostaja ekspandery i co z tym począć. Wprawdzie do 8 znaków klawiatury mozna użyć przerwania zewnetrznego bo ekspander takie coś generuje. Tylko że klawiatura jest matrycowa bo ma więcej niż 8 znaków. O ile mi dobrze wiadomo :-), procedura obsługi takiej klawiatury wymaga cyklicznego wpisywania zer na linii wierszy i sprawdzania stanu linii kolumn a tutaj juz potrzebna jest dwukierunkowa wymiana danych. W takim razie zadanie to zlecić głownemu programowi ? Czy nie jest to zbyt duża "ofiara krwi" dla procesora. Przerwanie timera wydaje sie byc tutaj idelane, bo z jednej strony ładuje i odczytuje dane do rejestu we-wy i ustawia sobie flage wpisania znaku wraz z jego kodem. Główny program tylko odczytuje znak i kasuje flage o ile nastapilo w ogole nacisniecie klawisza. Chyba jedynym wyjsciem jest zrobienia sprzetowego dekodera klawiatury i o ile wiem jest takie cos o nazwie MM74C922 tylko poki co nigdzie tego kupic nie moge a załatwiłby sprawe cyklicznego zapisu-odczytu portu.
  • Poziom 33  
    No nie do końca bo przeniesienie całej obsługi do klawiatury powoduje robienie długich procedur w przerwaniu, czyli jeszcze gorzej niż jak je zrobisz w poprogramie głównym.
    Ja bym to rozwiązał nieco inaczej, tzn zamiast expandera IIC dałbym uC jakiś mały (ATtiny2313, 89C2051 itp.) i znaki bym wysylał UARTEM albo nawet po tym IIC (zrobienie programowego slave na IIC w 2051 może byc trudne). Koszt porównywalny (2051 chyba jest nawet znacznie tańszy niż ten PCF), a w sumie do wysłania będziesz miał tylko kod znaku i nic więcej bo całe operacje na matrycy klawiatury zrobi drugi procek, czyli znacznie mniej operacji na magistrali IIC, czy UARTcie. Dodatkowo zrobienie jednej lini przerwania od kalwiatur spowoduje, że zamiast obsługiwać klawisze 8 razy na sekunde, odczytujesz jej stan tylko wtedy, kiedy zgłosi ona, że zostałna ciśnięty przycisk. Zresztą nie wiem czy IIC sobie poradzi z zakłóceniami na motorze bo w sumie to nie jest magistarala zbyt odporna...
  • Poziom 15  
    Tdv napisał:
    gummis: kolega pisał wyraźnie o uC AVR, a nie o '51 ;-D.


    przeciez wyraznie napisalem ze moze sobie przetlumaczyc.

    jedna transmisja i2c w przerwaniu zostala wyeleminowana ta gdy nastepuje zmiana 1s.
    jesli nic wiecej nie musisz obslugiwac w i2c poza tym exponderem wprzerwaniu to juz nie bedzie sie to klocic.w przeciwnym wypadku proponuje ustawiac w glownym programie flage o nazwie np. i2c_busy
    i sprawdzac w przerwaniu czy jest zajeta i2c i zwieksz wtedy czestotliwosc pobierania klawiatury , ja standardowo pobieram co 20ms.wtedy nawet jak przerwanie trafi w moment w ktorym glowny program uzywa i2c to juz to nie bedziw istotne tak.no chyba ze w tym glownym porgramie tez duzo idzie danych i2c.wtedy jest troche problem.
    mozna tez zrobic procedurke ktora biezaco pobiera stan klawiatury w programie glownym.wiadomo ze program glowny sklada sie z petl.i w tych petlach mozna sprawdzac klawiature.
    dobre tez rozwiazanie jest zrbic z drugiego procesorka dekoder klawiatury.nie tylko by mogl spelniac role dekodera, ale rowniez filtru eleminujacego drganie stykow.
  • Poziom 10  
    Namierzyłem właśnie swojego scalaka 74C922 więc odpada zapis do ekspandera :D Dzieki za rady a pomysł z flagą zajętości I2C tez mi wpadł do głowy trzeba będzie tego spróbować, Dzieki za rady ,PZDR
  • Poziom 14  
    Witam.
    Prosiłbym o pomoc w niżej opisanej sprawie.
    Napisałem własną procedurę do obsługi wyświetlacza LCD z Opla Astry F. Sterowanie odbywa się przez magistrale I2C. Program ma działać na procku 89c4051. Problem tkwi w tym, że gdy w pętli głównej - bo tylko w niej używam transmisji I2C - wysyłam dane do LCD, a w tym czasie włączy się przerwanie np. zliczania czasu trwania wtrysku benzyny, to po jego zakończeniu nawet jeśli transmisja zostanie dokończona na wyświetlaczu nic nie pokazuje, albo zapala przypadkowe segmenty wyświetlacza. Wynikiem tego jest przeważnie pusty wyświetlacz. Czy jest jakiś sposób na poprawienie tej sytuacji? Do obsługi wymagane są 3linie SCL,SDA i MRQ (też musi być bo bez tego LCD nawet nie drgnie).
    Jestem początkujący w tej dziedzinie więc prosiłbym o tłumaczenie raczej "łopatologiczne".

    Wcześniej ktoś pisał o wykorzystaniu oddzielnego procka jako "sterownika", może w ostateczności coś takiego można by wykombinować. Tylko czy procki muszą być taktowane taką samą częstotliwością?
    No i będzie większy pobór prądu ,bo będą dwa procki :(
  • Poziom 15  
    moze zle konczysz przerwanie i tak naprawde ona sie nie konczy.przyczyn moze byc wiele.jesli uzyjesz rozkazu ret zamiast reti to przerwanie bedzie ciagle trwalo.jesli robiles cos ze stosem to tez istneieje grozba ze po wysjciu z przerwania procesor nie trafi juz tam skad przyszedl.moze byc wiele przyczyn ale napewno samo w sobie przerwanie nie powinno zaklocac i2c gdycz to trasmisja synchroiczna.Najprawdopodniej przerwanie sie albo nie konczy albo po przerwani cos sie stalo.Acha i jeszcze jedno.Czy po wywolani zapamietujesz akumulatror i psw? bo jesli nie to masz odpoweidz co jest nie tak.musisz wrzuci na stos te rejestry i akumulator ktore wykorzystujesz w przerwaniu a ktre moga byc tez wykirzystywane w programie glownym.sorki za literowki.
  • Poziom 13  
    Cytat:
    Nestety okazuje się że jakiegoś nieznanego powodu, przy okazji czas segara zostaje zmieniony ! i to na dodatek jakąś dziką wartością z poza zakresu 24godzinnego czasu. Na przykład godziny przyjmują wartość 30 !
    Rozwiązanie jest bardzo proste!!! Układ PCF8583 dane w rejestrach koduje w sposób BCD . Tzn: pierwsze cztery bity w bajcie liczą dziesiątki, a cztery młodsze bity liczą jednostki. Np godz. 24, po zakodowaniu binarnym to: b0001 1000 a po zakodowaniu BCD będzie to:b0010 0100 (24 zakodowane BCD a odczytane jako dana kodowana binarnie da błędnie wynik:dec36). Musisz zrobić konwersję :) Ten sposób kodowania miał ułatwić współpracę PCF8583 z układami cyfrowymi wśród których są właśnie liczniki 4bit +dekoder i sterownik 7segm.

    Obsługa I2C w przerwaniu to niezbyt dobre miejsce, chociaż AVR nie mają wyskakiwania z przerwania do przerwania o wyższym priorytecie (jak '51) czyli transmisja się zakończy, bo przerwanie rozciągnie się na cały czas transmisji. Z tego jednak może wyniknąć problem ,bo zbyt długie przerwanie przyblokuje kolejne.
    W Atmegach jest sprzętowy I2C (opisany jako Two wires serial) i korzystanie z niego to sama przyjemność, polecam :)
  • Poziom 14  
    nie wiem czy jest ret czy reti bo akurat obsługę przerwania mam napisaną w Bascomie, a wysylanie tekstu przez I2C w ASM.

    Obsluga_przerwania:
    'coś co ma robić
    Return

    U mnie tak wygląda w Bascomie obsluga przerwania. Co do Akumulatora i Psw to fakt ,że ich nie zapamiętuje.No chyba ,że tym zajmuje się sam Bascom.
    W przerwani nie będę używał i2c bo za długo to trwa. Około 200ms, traciłbym większość informacji które mają docierać do procka.