Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

AT Tiny26L i Bascom AVR - nadajnik RC5 - problem

tomsyty 23 Aug 2005 15:06 3555 6
  • #1
    tomsyty

    Level 26  
    Witam. Mam pewien problem. Próbuję zrobić nadajnik kodu RC5 z użyciem mikrokontrolera AT Tiny26L SMD w Bascomie AVR 1.11.7.0. Niestety, polecenie RC5Send nie działa na tym układzie (Assignment Error [Timer1: 0 0: 112] i Assignment Error [Compare1a: 0 111: 112]).
    Próbowałem więc zastosować procedurę opisaną na stronie http://www.mcselec.com/an_105.htm która działa poprawnie dla 90s2313 (testowałem). Jednak dla AT Tiny już nie chce.
    Zmieniłem typ procesora, próbowałem z różnymi kwarcami (ustawiłem zewnętrzny rezonator).
    Zastąpiłem polecenie Compare1a odwołaniem do rejestru Ocr1a i polecenie Timer1=0 poprzez Tcnt1=0 ponieważ bez tego nie było poprawnej kompilacji. Próbowałem zmieniać trochę wartość T_oc1 w górę i w dół ale dalej nic.
    Oto kod, który stosuję (trochę przerobiony, zaremowałem kilka niepotrzebnych linii)
    Dim Rc5_address As Byte
    Dim Rc5_command As Byte
    'Dim Key As Byte
    'Dim Key_prev As Byte
    Dim Rc5_bit_nr As Byte
    Dim Toggle_bit As Boolean
    ' 36kHz carrier reload value
    'Const T_oc1 = 55                         'value for 4MHz crystal
    Const T_oc1 = 110                         'value for 8MHz crystal
    'Const T_oc1 = 138                        'value for 10MHz crystal
    Const Carrier_on = &B01000000     'IR 36kHz carrier on
    Const Carrier_off = &B11000000    'IR 36kHz carrier off
    'Config Kbd = Portb                        'keyboard connected at Port b
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
    'Timer1 = 0 - to zastąpiłem poleceniem:
    Tcnt1=0
    'Compare1a = T_oc1 - to zastąpiłem poleceniem:    'Pb.3 = OC1 = IR carrier output 36 kHz
    Ocr1a=T_oc1
    Declare Sub Logic_0
    Declare Sub Logic_1
    Tccr1a = Carrier_off
    Toggle_bit = 0
    '---[ set RC-5 System Address ]-------------------------------------------------
    'Pracuję na stałej komendzie i adresie:
    Rc5_address = 20
    Rc5_command = 63
    'Rc5_address = 0                           'TV = 0
    'Rc5_address = 5                          'VCR = 5
    'Rc5_address = 20                         'CD = 20
    '---[ main program loop ]-------------------------------------------------------
    Do
      'Key = Getkbd()                          'get keyboard value
      Waitms 1                                'small delay
      'If Key <> 16 Then                       'test if key is pressed else key = 16
        'If Key_prev <> Key Then Toggle_bit = Not Toggle_bit       'set toggle bit
        'Rc5_command = Lookup(key , Rc5_commands)       'get RC-5 command
    '---[ transmit Address and Command as 14 bit RC-5 code ]------------------------
        'Ddrb.3 = 1     'set OC1 (Pb.3) = IR carrier output - zastąpiłem zgodnie z rozkładem pinów:
        Ddrb.1 = 1
        Logic_1                               'first start bit
        Logic_1                               'second start bit
        If Toggle_bit = 0 Then Logic_0 Else Logic_1       'toggle bit
        For Rc5_bit_nr = 4 To 0 STEP -1           '5 bit address, msb first
          If Rc5_address.rc5_bit_nr = 0 Then Logic_0 Else Logic_1
        Next
        For Rc5_bit_nr = 5 To 0 STEP -1           '6 bit command, msb first
          If Rc5_command.rc5_bit_nr = 0 Then Logic_0 Else Logic_1
        Next
        Tccr1a = Carrier_off
        Waitms 87                             'frame gap delay
      'End If
      'Key_prev = Key                      'save last key value
    Loop
    End
    '-------------------------------------------------------------------------------
    Sub Logic_0
      Tccr1a = Carrier_on
      Waitus 883
      Tccr1a = Carrier_off
      Waitus 884
    End Sub
    Sub Logic_1
      Tccr1a = Carrier_off
      Waitus 883
      Tccr1a = Carrier_on
      Waitus 884
    End Sub
    'Rc5_commands:
    'Data 1 , 2 , 3 , 0                        'column 4 not used  (3x4 keypad)
    'Data 4 , 5 , 6 , 0
    'Data 7 , 8 , 9 , 0
    'Data 10 , 11 , 12 , 0
    
    

    Kod ten działa dla 90s2313 (oczywiście przy pinie Pb.3 i normalnych poleceniach Timer1 i Compare1a). Zbudowałem odbiornik RC5 na płytce testowej AVT2500, mam pilota Philips, czyli na pewno RC5, sygnał z pilota dekoduje poprawnie, nadajnik zbudowany na 90s2313 działa (ten kod akurat włącza CD w wieży). Zauważyłem za to, że na AT Tiny sygnał nie jest dekodowany i jest on jakby słabszy (po podłączeniu wyjścia TFMS5360 do diody LED reaguje ona na pilota i nadajnik na 90s2313 z dużej odległości, natomiast na AT Tiny z kilku centymetrów i to ledwo ledwo, przez kilka sekund a później jakby coraz słabiej). Podłączenie przez ULN2803 diody nadawczej nic nie dało, wydaje się że układ nie generuje sygnału na częstotliwości 36kHz, ale odbiornik jak wyżej opisałem jako tako chwyta, poza tym próbowałem zmieniać wartość T_oc1 co ma chyba wpływ na częstotliwość (mogę się mylić) ale nie zauważyłem żadnej poprawy.
    Co może być przyczyną że akurat na tym mikrokontrolerze nie działa? Czy fakt że w 90s2313 Timer1 jest 16-biotwy a w AT Tiny 8-bitowy może tu mieć jakieś znaczenie, skoro zliczanie i tak mieści się z obrębie 8 bitów (do 110). Ponadto wyjście OC1A jest także wejściem programującym MISO ale nawet odłączenie od programatora nic nie daje. Jeszcze jedno - przebieg w symulacji dla 90s2313 i AT Tiny jest identyczny.
    A może ktoś zaproponuje jakiś kod w Assemblerze (nie znam się na nim, ale jako wstawkę mogę zastosować).
  • #2
    tiger.krak
    Level 12  
    Ja dopiero co prawda zaczynam z AVR'ami ale mogę poradzić co ja bym zrobił z takim fantem.

    Po pierwsze wydrukował bym sobie dokumentację do Tiny'ego i do 2313 i zaczął szukać różnic między nimi (być może Tiny czegoś nie ma w osprzęcie wewn.)

    Po drugie zastosował bym analogie między nimi. Jeżeli W 2313 jest wykorzystany pierwszy 16bitowy timer to w Tiny'm też bym wpisał pierwszy 16 bitowy chyba że dokumentacja mówi o różnicach w ich budowie. Tak więc jeżeli w Tiny'm 16 bitowy ma inny numer to zmienił bym numery w programie.

    Pozdrawiam!! I POWODZENIA ;)
  • #3
    tomsyty

    Level 26  
    AT Tiny nie ma 16-bitowego timera, tylko dwa 8-bitowe. Akurat Timer1 spełnia te same funkcje w obydwu mikrokontrolerach, różnią się tylko pojemnością i trochę większym rozbudowaniem (AT Tiny, ma np. 3 komparatowy cyfrowe, próbowałem też na komparatorze B z użyciem pinu OC1B ale to samo...) Dokumentację przeglądam już kilka dni i na nic nowego nie wpadłem... Aha, dodałem brakujące procedury w listingu na stronie, bo zapomniałem ich wcześniej dokleić).
  • Helpful post
    #4
    tiger.krak
    Level 12  
    Tomsyty zobacz w dokumentacji do Tinny26 (kompletną) na stronę 23 pierwszy akapit. Tam Jest prawdopodobna przyczyna Twojego problemu. Timer T1 pracuje z zegarem mnożonym przez 64 względem zegara rdzenia!! Więc Twój układ dostał na preskaler Timera1 nie 8MHz jak chciałeś tylko 512 MHz !! Znaczy się zamiast 36kHz za preskalerem masz około 2,3 MHz !! Sprawdź i daj znać czy pomogłem ;)

    Powodzenia :)

    Dodano po 4 [minuty]:

    Poprawka :) W drugim akapicie piszą że max zegar przed preskalerem jest ograniczony do 70 MHz. Czyli będzie około 315kHz ;)
  • #5
    tomsyty

    Level 26  
    Gdyby procesory AVR cudownie mnożyły częstotliwość to pewnie w moim kompie byłby taki jeden, pod wiatraczkiem:) Tak wracając do tematu, to piszesz o wewnętrznym zegarze dla peryferiów (m.in. Timer1). Mikrokontroler nie mnoży 64-krotnie zewnętrznego sygnalu zegarowego, tylko sygnał z wewnętrznego oscylatora RC o częstotliwości 1MHz. Ja stosuję zewnętrzny kwarc, więc od razu odpada stosowanie PLL, poza tym standardowo bit odpowiedzialny za włączenie tego szybkiego zegara jest nieaktywny. Powiem ci że poradziłem przed chwilą sobie z moim problemem stosując się do informacji zawartych na stronie http://www.ustr.net/infrared/infrared1.shtml. Po prostu napisałem swoje procedury odpowiedzialne za wysyłanie bitu 0 i 1 - każdy bit składa się z 64 impulsów, z których każdy ma 27us. Pierwsza połowa bitu może mieć 32 impulsy a druga połowa to 32 impulsy przerwy lub na odwrót - ot i cała filozofia.
    Sub Logic_1
    For A = 1 To 32
      Portb.1 = 0
      Waitus 24
    Next
    For A = 1 To 32
      Portb.1 = 1
      Waitus 12
      Portb.1 = 0
      Waitus 12
    Next
    End Sub
    
    Sub Logic_0
    For A = 1 To 32
      Portb.1 = 1
      Waitus 12
      Portb.1 = 0
      Waitus 12
    Next
    For A = 1 To 32
      Portb.1 = 0
      Waitus 24
    Next
    End Sub

    Ale i tak należą ci się podziękowania za grzebanie w serwisówce. Aha, jakby mimo wszystko ktoś znalazł jakiś kod w Assemblerze (wiadomo, na pewno dużo lepiej jest zoptymalizowany, mniej zajmuje itp) to niech zamieści, przyda się. Jak zwykle ujawnia się potrzeba nauki Assemblera, bo na Bascomie daleko nie zajadę... No cóż, trzeba się będzie wkrótce wziąść do roboty.
  • #6
    tiger.krak
    Level 12  
    Cieszę się że udało Ci się odpalić tą IRdę :) Dzięki
  • #7
    tomsyty

    Level 26  
    Tak więc sprawa załatwiona - potrzeba było napisać swoją własną procedurę generującą ciąg sygnałów oznaczający logiczne 0 i 1. Temat zamykam.