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

Komunikacja AVR <-> RS232 <-> Delphi

silvanjk 18 Maj 2010 12:11 10000 71
  • #1 8089715
    silvanjk
    Poziom 12  
    Witam. Mam zapytanie, jak w temacie, choć podobnych jest sporo, to wszędzie piszą ludzie... No cóż, tak, że początkującemu trudno zrozumieć :P
    W każdym razie - chciałbym zrobić póki co najbanalniejszą komunikację, jak w temacie.
    Kupiłem konwerter USB RS232, model AVT MOD09, oparty na FT232RL. Ma on wyjścia tylko TxD i RxD.
    Dostałem niedawno Delphi 7 (nigdy nie programowałem w niej, ale coś tam ogarniam, póki co chodzi mi o banał), ściągnąłem też komponent do portu COM.
    I mam wielki problem z jego zainstalowaniem.
    Początek instrukcji:
    Cytat:

    Remove all previously installed files of ComPort Library (TComPort
    component). Create a new folder under Delphi directory and extract
    Sources zip file into new folder. Add to the Library Path the new
    ComPort folder (Tools-Environment Options-Library-Library Path).


    Ponieważ żadnych innych nie instalowałem, więc nie mam co usuwać, prawda?
    Dalej, kiedy wchodzę w to Tools-Environment Options-Library-Library Path - to przycisk 'Add' jest nieaktywny, że tak powiem: disabled ;\
    I już koniec wycieczki, nie wiem, jak to dodać, a to dopiero początek instrukcji do tego ;\

    A inne pytanie mam - jak się obsługuje taki port com?
    Mam jakiś tam układ zrobiony, uP ATmega, diody, przyciski. Powiedzmy, że chciałbym, aby po wciśnięciu przycisku przy uP zapaliła się dioda, i póki trzymam przycisk, to aby w jakimś labelu mieć '1', a jak puszczę przycisk, dioda gaśnie, w labelu zaś wraca wartość 0.
    Albo w 2gą stronę. Na formie tworzę przycisk, i póki go trzymam, to świeci jakaś dioda przy uP. Jak puszczam, to gaśnie. Cokolwiek, coś prostego, co pomogłoby mi zrozumieć obsługę tego, bo póki co nie za bardzo mi to idzie...

    Coś czytałem o jakimś otwieraniu portu com, jego zamykaniu, ale nie znam się wybitnie...
    Za wszelką pomoc z góry dziękuję.
  • Pomocny post
    #2 8089845
    utak3r
    Poziom 25  
    silvanjk napisał:
    Dalej, kiedy wchodzę w to Tools-Environment Options-Library-Library Path - to przycisk 'Add' jest nieaktywny, że tak powiem: disabled ;\


    Najpierw przyciskiem z 3 kropeczkami wybierz ścieżkę, jak się pojawi w tym dolnym okienku, uaktywni się klawisz "Add".

    Dodano po 1 [minuty]:

    silvanjk napisał:
    Coś czytałem o jakimś otwieraniu portu com, jego zamykaniu, ale nie znam się wybitnie...


    oj oj.... będzie ciężko. Proponuję zacząć poszukiwania od tekstów, co to w ogóle jest port szeregowy - inaczej tzw. kicha.
  • #3 8089873
    silvanjk
    Poziom 12  
    O, dzięki!
    Kurczę, jakie to na opak ;\
    Myślałem, że najpierw chcę coś dodać, a później wybieram co...
    Pomogłeś ;)

    Co do dalszej części, wiesz, ja tam trochę się znam. Jestem elektrykiem, nie elektronikiem, ale jakieś proste rzeczy w ASM pisałem dla AVR.
    A to chyba nie jest jakieś wybitnie trudne, tylko ciężko znaleźć coś konkretnego.
    Ot, mi chodzi o wysłanie jakiegoś pojedynczego bajtu z Delphii do uP.
    Tak, abym mógł wysterować port z dołączonymi diodami.
    Tyle. Chodzi mi o jakiś kawałek kodu, który pokazuje jak wysyła jakiś bajt (niech będzie 0b00000011), a drugi kawałek - jak przyjmuje i wpisuje go do jakiegoś labela. Cokolwiek.
  • #5 8090028
    silvanjk
    Poziom 12  
    Hm, mam jeszcze jedno pytanie. Po dodaniu na formę kontrolki ComPort1 klikam sobie na nią 2x i mam tam opcje. Ustawiony jest COM nr 1. Nie mogę tego tu zmienić - tylko on jest do wyboru.
    Mój konwerter usb \ rs232 jest zainstalowany jako com 4.
    Jak mogę dojść do jakiegoś 'porozumienia' między nimi?
  • #6 8090036
    utak3r
    Poziom 25  
    No a jak we właściwościach kontrolki (w tym szarym okienku z długą listą różnych właściwości aktualnie wybranego komponentu) nie możesz wpisać ręcznie?
    Ponadto, można również w kodzie przypisać wartość, np. mojport.COMPort := "COM3";
  • #7 8090113
    silvanjk
    Poziom 12  
    Hm, próbuję np czegoś takiego:

    procedure TForm1.Button1Click(Sender: TObject);
    var a:string;
    begin
                 a:= 'abc';
                 comport1.Open;
                 comport1.WriteStr(a);
                 comport1.Close;
    
    end;
    
    end.

    W różnych momentach mierzę napięcie w każdym możliwym miejscu na wyjściu tego konwertera rs232\usb. Są tam: gnd, +5V, Rx i Tx.
    Poza gnd wszystko jest na tym samym potencjale. Między gnd, a każdym innym pinem jest +5V.

    Czy w ogóle to ma sens takie sprawdzanie?
    A może chodzi o czas? Może to przesłanie trwa tak krótko (jakiś ułamek sekundy), że woltomierz tego nie wyłapuje?
    Jak można sprawdzić, czy zmienią się jakkolwiek wartości napięć na liniach Tx i Rx?

    Tak wygląda ten konwerter:
    Link


    -------------------

    Dobra, to miało sens. Ale musiałem wstawić ten kod nie pod przycisk, ale do timera na 1ms. Wtedy miernik bez problemu wyłapywał zmianę napięcia.

    To może coś innego. Jak w Delphi wygenerować coś, hm, w rodzaju przerwania?
    Inaczej - skąd mam wiedzieć, że NADCHODZI transmisja?

    Mógłbym wstawić jakiś warunek np też w timerze, który sprawdza powiedzmy 100 razy na sekundę, czy transmisja nadchodzi, wtedy coś się dzieje.
    Ale jak to sprawdzić?

    If 'nadchodzi transmisja' = true then coś tam.
    comport1.connected?
    A może coś innego?
  • #8 8090244
    utak3r
    Poziom 25  
    W tym szarym okienku ;) przejdź na listę zdarzeń. Powinno być tam m.in. coś w stylu "OnDataReceived" albo "OnDataReady".
  • #10 8090356
    utak3r
    Poziom 25  
    Jak się dokładnie powinna nazywać, to nie wiem - ale brzmi ok ;)

    silvanjk napisał:
    If comport1.OnRxFlag = 1 then coś tam


    Nie, to jest zdarzenie. Robisz to dokładnie tak samo, jak w buttonie czy timerze - dblclick na tym i dostajesz metodę, która będzie wywoływana w momencie wystąpienia tego zdarzenia.
  • #11 8090552
    silvanjk
    Poziom 12  
    A jak w Delphi zrobić z liczby stringa?
    W VB robiło się to np tak:

    dim a as string
    b as integer
    b = 10012

    a = cstr(b)

    A tu? Jest jakaś gotowa funkcja?
  • #13 8090667
    utak3r
    Poziom 25  
    Klawisz F1 też nie gryzie....
  • #14 8090689
    mirekk36
    Poziom 42  
    utak3r napisał:
    Klawisz F1 też nie gryzie....


    No tak... ale co po klawiszu F1 komuś kto, stawia pierwsze kroki w jakimś zaawansowanym środowisku programistycznym na PC. Widać miliony różnych funkcji czy procedur ale ciężko od razu i na szybko wyłapać to co potrzebne w danej chwili - chociaż tak hasłowo. Sam wiem bo podobnie walczę z kobyłami typu MS Visual C++ albo MS Visual C# ;)
  • #15 8093207
    silvanjk
    Poziom 12  
    Właśnie ;\
    To na początku nie jest takie proste.
    Może dla niektórych nie zabrzmi to szaleńczo, ale udało mi się zapalać diody (raz jedną, raz drugą, w zależności od przycisku), a także je gasić.
    Kombinowałem w drugą stronę, ale nie wychodziło za bardzo.
    Chciałem z procka przesłać póki co dowolną wartość, aby mi się w labelu wyświetliła.
    Niestety - brak jakiejkolwiek reakcji.

    .include "m16def.inc"
    
    ldi R16, 0xFF
    out DDRA, R16
    
    ldi R16, 0b00000000
    out DDRD, R16
    
    
    ldi R16, 0xFF
    out PORTD, R16
    
    
    ;inicjacja USARTu
    cli       ;wyłącz obsluge przerwan
    ldi R17, high(25)    ;prędkość transm ustawiamy na 2400
    ldi R16, low(25)
    out UBRRH, R17
    out UBRRL, R16
    ldi R18, 0b10000110  ;asynchr, bez bitu parzyst, 1 bit stopu, dlugosc 8 bitow
    out UCSRC, R18
    
    ldi R18, 0b00001000
    out UCSRB, R18
    
    sei          ;wlacz obsl przerwan
    
    
    
    
    ldi R17, 0b00000010  
    ldi R18, 0b00000000
    ldi R19, 0b00000001
    
                          ; wart pomocnicze dla diod
    
    
    
    Calosc1:
    
    
    NieMa1:
       out PORTA, R18
       sbic PIND, PIND5
    rjmp NieMa2
    rjmp Jeest1
    
    NieMa2:                    ;sprawdzenie czy klaw1 lub klaw2 wcisniety
       out PORTA, R18
       sbic PIND, PIND4
    rjmp NieMa1
    rjmp Jeest2
    
    
    
    Jeest1:                     
       
       rcall Transm_1
    Po_Transm1:
       out PORTA, R17
       sbis PIND, PIND4
       rjmp SaOba
    
       sbis PIND, PIND5
    rjmp Jeest1
    
    
    
    Jeest2:                    ;jezeli ktorys wcisniety, zapala odpowiednia 
       out PORTA, R19
       sbis PIND, PIND5        ;diode, oraz sprawdza czy wcisniety jest
       rjmp SaOba              ;tez drugi klawisz, lub czy pierwszy zostal
                               ;puszoczny
    
       sbis PIND, PIND4
    rjmp Jeest2
    
    
    
    rjmp Calosc1
    
    
    SaOba:                      ;jezeli wcisniete oba, swieca obie diody
    	ldi R22, 0b00000011
    	out PortA, R22
        
    	sbic PIND, pind4        ;sprawdza, czy ktorykolwiek zostal puszczony
    	rjmp Jeest1
    	sbic pind, pind5        
    	rjmp Jeest2
    rjmp SaOba
    
    rjmp Calosc1
    
    
    Transm_1:
    	sbis UCSRA, UDRE        ;sprawdza gotowosc do nadawania
    	rjmp Transm_1
    	
    	ldi R20, 24             ;wartosc przykladowa do wyslania
    
    	out UDR, R20
    
    rjmp Po_Transm1


    Po wciśnięciu klawisza nr 1 (drugi póki co zbędny) ładowałem R24 wartością 24, po czym ładowałem to do UDR'a. Tu raczej powinno być dobrze.

    Więc chyba tu coś jest nie tak:

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, CPort;
    
    type
      TForm1 = class(TForm)
        ComPort1: TComPort;
        Label1: TLabel;
        procedure ComPort1RxBuf(Sender: TObject; const Buffer; Count: Integer);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.ComPort1RxBuf(Sender: TObject; const Buffer;
      Count: Integer);
      var a:string;
    
    begin
     comport1.Open;
     comport1.ReadStr(a, count);
     comport1.Close;
    label1.Caption:=a;
    
    end;
    
    end.
    


    Próbowałem różne eventy.
    OnRxFlag, OnRxChar, OnRxBuf, niestety, nic z tego. W labelu jak było 0, tak dalej jest... ;\
    Nie wiem, czy dobrze odbieram dane, nie wiem, do czego jest ten 'Count', nie wiem, jak sprawdzić gotowość odbioru - czyli, że nadchodzi transmisja.
    W ASM to wygląda prosto, bo albowiem:

    
    czekaj:
    sbis UCSRA, RXC
    rjmp czekaj


    Jak nadchodzi transmisja, RXC ustawia się na 1, co sprawia, że rjmp zostaje przeskoczone - i program idzie dalej.
    A w Delphi - no ideas ;\

    BTW - wszystkie parametry transmisji (prędkosc, ilosc bitów, itd) mam ustawione bezpośrednio w kontrolce, a nie w kodzie.
  • #16 8093367
    utak3r
    Poziom 25  
    Count w tym zdarzeniu wskazuje, ile znaków czeka w buforze.
    No i... robisz jeden kardynalny błąd: w procedurze zdarzenia odbioru otwierasz i zamykasz port??... nieee.....

    W głównym programie otwórz port przed rozpoczęciem nasłuchu - no bop jak inaczej chcesz odebrać dane? Wtedy w procedurze odbioru już tylko sprawdzasz jeszcze, czy Count > 0 i wtedy ReadStr albo cokolwiek innego.

    Dodano po 1 [minuty]:

    PS.
    "Na początku programu" oznacza albo jakiś klawisz "Start", albo też w zdarzeniu OnCreate całej formy.
  • #17 8093433
    mirekk36
    Poziom 42  
    A ja dodam tylko, że jak zassałeś sobie z netu ten komponent ComPort to nie mogło tam nie być kilku przykładowych prostych jak drut programików dla Delphi. Wystarczy do nich zajrzeć, żeby załapać podstawy obsługi tego komponentu. Masz tam prawidłowe przykłady np procedury obsługi zdarzenia OnRx.....
  • #19 8093476
    mirekk36
    Poziom 42  
    Poza tym twoim największym problemem jest to, że ty nie potrafisz napisać poprawnie programu do procka odnośnie komunikacji UART. Zatem jak chcesz to wszstko razem testować???? skoro i tu program ma błędy (poważne) i na PC tak samo (poważne błędy)

    Spróbuj wyeliminować w prosty sposób najpierw jedno źródło swoich problemów. Więc albo korzystaj ze zwykłego gotowego terminala na PC i naucz się dobrze pisać program do mikrokontrolera żeby w 100% działał z terminalem albo ....... albo zacznij pisać program w Delphi ale do komunikacji z jakimś już działającym gotowym urządzeniem, które komunikuje się przez RS232 z komputerem - np jakiś telefon komórkowy/modem. Wtdy z kolei podszkolisz się z obsługi RS232 na komputerze - a nie tak jak teraz - wielkie buuum, nic nie działa a ty zadajesz wyrywkowe pytania, które w zasadzie mają mały związek z tym, że to w całości nie działa.

    Jeśli chodzi o program do procka - to skoro nie masz doświadczenia w programowaniu w asemblerze - a widać, że nie masz - to spróbuj sobie napisać kilka linijek kodu w darmowej wersji BASCOMA na początek, żeby mieć to urządzenie podłączone do PC, które na pewno dobrze działa. W Bascomie 99% programu dla ciebie do testwó sprowadzi się do kilku linijek, np:

    Dim licznik As Byte
    licznik = 0
    
    Do
      PRINT "test - " ; licznik
      incr licznik
      Wait 1
    Loop


    i musisz wtedy tak pisać program w Delphi żeby poprawnie odbierał napis test i kolejny numerek licznika wysyłany co sekundę przez procek do PC.

    Dlaczego twierdzę, że w asemblerze będziesz miał duże kłopoty? bo np uruchamiasz przerwania - polecenie sei ...... a nie wiesz co to jest inicjalizacja stosu w pamięci RAM a po drugie nie wiesz co to są wektory przerwań i jak się je inicjalizuje w kodzie w asemblerze. A to podstawy podstaw. Więc tutaj to raczej zaczynasz wszystko od tyłu.

    Dlatego tylko sugeruję użycie przejściowo Bascoma żeby wyeliminować na szybko jeden problem w procku i żeby się szybciej nauczyć programować RS232 na PC.

    A potem to polecam ci albo pozostać dalej w Bascomie albo zdecydowanie lepiej zacząć uczyć się języka C dla procków.
  • #21 8094976
    silvanjk
    Poziom 12  
    Heh, dzięki wszystkim.
    Za pomoc, oraz za konstruktywną krytykę.
    Lepsza taka, niż "To już było tu 100 razy, poszukaj".
    Fakt, uczę się dopiero. Wszyscy wszędzie pisali, aby uP zaczynać od ASM, bo wtedy rozumie się podstawy. Btw - akurat mam pewien wymóg, aby działać w ASM, ale do nauki sięgnę kiedyś po Bascoma.
    @mirekk36
    Co do przerwań, to tak, wiem wszystko, co napisałeś. W bieżącym programie to nie było niezbędne. Maił być prosty, szybki test, wiadomo, że chodzi o odpowiednie nawyki, ale obyło się bez tego, gdyż działało.
    Raz jeszcze dzięki wszystkim ;)
  • #22 8095304
    mirekk36
    Poziom 42  
    silvanjk --> ależ ja nie mam nic przeciwko asemblerowi a swoje uwagi nie mówiłem tylko dlatego że chodziło o nawyki, tylko niestety o stadko błędów w programie. I wcale to nie działało bo co jakiś czas po prostu się resetowało ale nawet tego nie zauważałeś.

    Ustawianie stosu nie należy do dobrego zwyczaju to konieczność ;)

    druga sprawa, jak już nie używasz wektorów przerwań i w ogóle przerwań to zrozumiałe jest, że teoretycznie nie musisz definiować tychże wektorów - no ale to już należy do poprawnych zasad programowania w asemblerze, z tym, że zasady te nie zostały wymyślone po to żeby sobie ot tak były . Programując w asemblerze już od samego początku najlepiej wyrabiać sobie właściwe nawyki i reżim programowania - to nie jest trudne. Główne ciało programu wraz ze startem to można nawet sobie na zasadzie kopiuj wklej robić z innego projektu. A nie pomijać bo tu akurat niepotrzebne

    ..... ale ok - właśnie przez taką niefrasobliwość - popełniasz kolejny błąd bo skoro nie używasz pan przerwań ;) to po co "wachlujesz" poleceniami



    albo



    przy czym co gorsza na końcu inicjalizacji zostawiasz je włączone sei

    ale to jeszcze nie taki wielki babol w twoim kodzie ;)

    Największy dotyczy jednak braku ustawionego stosu oraz zastosowania przez ciebie totalnie niestety bez pojęcia instruckji skoków, np:

    rcall Transm_1 


    być może nie wiesz, ale jeśli nie wiesz to szybko doczytaj, że właśnie m.inn te instrukcje potrzebują stosu by odłożyć sobie na nim adres powrotu.

    A tu kolejny ZONK ;) .... twoja procedura Transm_1: nie kończy się rozkazem ret - tylko gdzieś na jej końcu znowu przeskakujesz zwykłym skokiem bezwarunkowym rjmp

    uwierz mi, że twój program czy chcesz czy nie chcesz co jakiś czas się resetuje a ty nawet tego nie dostrzegasz. Stos się po prostu przepełnia.

    Reasumując, mam nadzieję, że zrozumiesz, że to co piszę to nie po to żeby ci dogryźć tylko zwrócić uwagę na to, że to "omijanie" dobrych nawyków, szczególnie w asemblerze to zła droga i nie doprowadzi cię do nikąd, albo stracisz hetolitry dodatkowego czasu zanim zrozumiesz, że trzeba to żmudnie pisać w asemblerze. Nie ma że boli.

    I być może też kiedyś dojdziesz do wniosku, że lepiej pisać w C - bo nauka C dla procków da ci tyle samo co programowanie w asemblerze - powiem więcej - programowanie w C bardzo się wiąże z asemblerem ;)

    ot wszystko
  • #23 8096035
    silvanjk
    Poziom 12  
    Jasne :)
    Przecież pisałem o konstruktywnej krytyce :)
    Masz rację, a właściwie wiele racji.
    ret nie działał mi prawidłowo (mam JTAG, więc sprawdzałem krok po kroku, gdzie to sobie wędruje), dlatego użyłem skoku bezwarunkowego. O poprawnym ustawianiu stosu, itd dowiedziałem się kilka godzin po wklejeniu tamtych kodów. (EDIT: może raczej o tym, jak bardzo są potrzebne, bo widziałem to wcześniej w różnych programach).
    Użyłem cli oraz sei, ponieważ gdzieś wyczytałem, że nastawy USATR'u mają się odbywać między tymi poleceniami.
    Wiesz, assemblerem zajmuję się kilka tygodni.
    I to nie jakoś pioruńsko mocno. Ciężko o dobre nawyki po takim czasie :)
    Ale z czasem się wyrobią i myślę, że będzie lepiej :)
  • #24 8114321
    silvanjk
    Poziom 12  
    Hm, czy to normalne, że przy wysyłaniu z Delphi do uP liczb od 1 do 6 (zależnie, który klawisz w Dph wcisnę) otrzymuję je inne?
    1: 0x31 = 49
    2: 0x32 = 50
    :
    :
    6: 0x36 = 54

    Samo odebranie danych:
    
    Calosc:
    	sbis UCSRA, RXC
    	rjmp Calosc
    	in R18, UDR


    I w tym R18 dostaję powyższe wartości. Od strony Dph wygląda to następująco (załóżmy dla klawisza 2):

    
    procedure TForm1.Button1Click(Sender: TObject);
    var a:string;
    begin
      comport1.Open;
      a:='2';
      comport1.WriteStr(a);
    end;


    Wcześniej, w innym programie robiłem tak samo, wartość R18 dawałem bezpośrednio do PortaA (gdzie są diody) - świeciły jak należy. To znaczy, że otrzymałem 2 (0b00000010), a nie 50 (0b00110010).
  • Pomocny post
    #25 8114335
    mirekk36
    Poziom 42  
    Jak byś pisał program do procka w C, to byś w prosty sposób sobie to "naprawił" ;)

    wynik = UDR - '0';

    po prostu wysyłasz z delphi przecież panie kolego nie liczbę a znak ASCII - nie prawdaż ??? Zatem znak ASCII w postaci cyfry np "2" będzie miał wartość 50, znak cyfry "1" będzie miał wartość 49 - to chyba normalne.

    Zatem musisz od odebranej liczby (znaku ASCII) odjąć wartość znaku ASCII jakim jest "0" o kodzie 48 i wtedy dopiero da ci to twoją cyfrę binarnie ;) Jak widzisz w C robi się to prosto i bardzo intuicyjnie, a w innych językach jak np asm - musisz sobie od rejestru R18 do którego wpisałeś zawartość UDR jeszcze odjąć 48

    teraz jaśniej ? ;)
  • #26 8114345
    silvanjk
    Poziom 12  
    Jaśniej ;)
    Myślałem o czymś takim, ale hm... Wydawało mi się, że wcześniej mi działało.
    Więc nie wiedziałem dlaczego teraz jest inaczej.

    Wracając do kwestii ASM vs C - wykonuję na zajęcia pewien projekt i prowadzący WYMAGA ASM.
    Dlatego, przynajmniej póki co, nie bardzo mogę się przerzucić...
  • #27 8114434
    mirekk36
    Poziom 42  
    silvanjk napisał:

    Wracając do kwestii ASM vs C - wykonuję na zajęcia pewien projekt i prowadzący WYMAGA ASM.
    Dlatego, przynajmniej póki co, nie bardzo mogę się przerzucić...


    A to rozumiem, zresztą ćwiczenia w asemblerze też się przydadzą później do C. Jak znalazł ;)
  • #28 8119183
    silvanjk
    Poziom 12  
    Eh, opornie to idzie. Próbuję obsłużyć przerwanie.
    Że tak powiem - moje pierwsze w życiu :P
    Póki co nie idzie za bardzo.
    Przypuszczam, że coś źle robię z ustawieniami pamięci (.org coś tam).
    W każdym razie - mam podłączony klawisz do pinu INT0 (ATmega16).
    Program ogólnie komunikuje się z Delphi, ale chciałem, aby przy naciśnięciu tego klawisza wyszło przerwanie, które:
    - będzie reagować na zbocze opadające. (Słusznie chyba, prawda? Pin domyślnie jest wejściem - czyli jest na potencjale 5V, a przez przycisk łączę go z masą - czyli zbocze opada).
    - zapali mi 2 diody.

    Zapalenie diod działa elegancko - tylko że to przerwanie, hm, trwa cały czas jakby. Co chwila jest wywoływane. Przypuszczam, że przez błędy w programie ;)

    .include "m16def.inc"
    
    
    .org 0x00
    		jmp RESET
    
    
    		jmp Klawisz_plytka
    
    
    
    RESET:
    		ldi r16,low(RAMEND)
    		out SPL,r16
    		ldi r16,high(RAMEND)
    		out SPH,r16
    
    		ldi R16, 0xFF
    		out DDRA, R16        ;portA jako wyjscie
    
    ;inicjacja USARTu
    
    ;Ustawienia UART
    		ldi r16,0x18
    		out UCSRB,r16
    		ldi r16,0b10000110
    		out UCSRC,r16
    		ldi r16,0x00
    		out UBRRH,r16
    		ldi r16,25		;2400
    		out UBRRL,r16	
    
    
    		ldi R27, 0          
    		out PortA, R27      ;poczatkowe zgaszenie diod
    		ldi R18, 0          ;poczatkowe wyzerowanie R18
    
     		
    
        	in R29, MCUCR
    		cbr R29, 1<<ISC00
    		sbr R29, 1<<ISC01     ;ustawienie zbocza opadajacego
    		out MCUCR, R29
    
    		ldi R29, 1<<INTF0
    		out GIFR, R29
    
    	
    		in R29, GICR        ;zezwolenie na przerwanie INT0
    		sbr R29, 1<<INT0
    		out GICR, R29
    
    	
    rjmp Calosc                 ;koniec przerwania RESET
    
    
    
    
    
    Klawisz_plytka:             ;przerwanie dla klawisza
    	
    	ldi R28, 3
    	out PORTA, R28
    reti
    
    
    
    
    Calosc:
    	sei
    	sbis UCSRA, RXC
    	rjmp Calosc
    	in R18, UDR
            :
            : reszta podprogramu
            :
    rjmp Calosc


    Nie do końca rozumiem te wektory przerwań, nie wiem, czy przed jmp Klawisz_plytka
    nie powinno być .org 0x002. Próbowałem 100 innych rzeczy. Ciągle coś źle ;\

    EDIT:
    Debugując - jak tylko dochodzi do 'sei' - od razu wskakuje w przerwanie...

    EDIT 2:
    ^%$^$%^@#!@#@@&.......................

    EDIT 3:
    Jeśli kogoś to interesuje, czy komuś pomoże - znalazłem błąd. Pod przyciskiem nie było włączonego pull-up'a. Dziękuję.
  • #29 8171620
    silvanjk
    Poziom 12  
    Witam.
    Po dłuższym czasie się odzywam, gdyż nauczony powyższymi przykładami, że jak się przyłożę, to sobie poradzę sam - no ale znowu utknąłem.
    Zrobiłem duże postępy, jeśli chodzi o ASM, konstrukcje programu, itd ;)

    No ale do rzeczy:
    W przyszłości niedalekiej mam w planie używać przetwornika ADC w ATmedze16 i próbki wysyłać do Delphi po RS'ie.
    I tak, teoretycznie niby nie problem, ponieważ wysyłam po bajcie, zapisuję w tablicy, przetwarzam do formatu, jakiego chcę - i charakterystyka sobie czasowa powiedzmy.
    No ale przetwornik ma być używany z dokładnością 10 bit. I tu zaczynają się schody. Wartość próbki będzie więc przechowywana w 2óch bajtach (ADCL i ADCH) - czyli w młodszym i starszym.
    O ile młodszy będzie (w pewnym sensie) wypełniony cały zerami i jedynkami, to starszy może (ale nie musi - w zależności od wartości zmierzonej) będzie miał zajęte góra dwa najmłodsze bity (00, 01, 10, 11).
    No ok - dalej nic strasznego, pakujemy obie wartości do pomocniczych rejestrów, wysyłamy po kolei do delphi, zbieramy w tablicę.
    I teraz.
    Jak ja mam to skleić?
    Przecież z ComPortu dostaję albo char, albo string, w zależności od konwersji, mogę zrobić integer.
    Ale to nigdy nie wyjdzie tyle samo.
    Żeby przykładowo pokazać - mamy starszy bajt (10) i młodszy (00010001).
    Nasz 10bitowy wynik to 1000010001 = 529 dziesiętnie.
    Po kolei zaś znaczą: 2 oraz 17.
    Ani to dodać, ani zlepić (19? 217?), ani nie wiem już sam :(

    Może ktoś ma jakiś pomysł? Próbowałem już zlepiać znaki ascii, zmienne string, konwertować na integer znowu, ale nic nie wychodzi sensownego...
  • Pomocny post
    #30 8171737
    utak3r
    Poziom 25  
    Aby zlepić bajt młodszy ze starszym w dwubajtowe słowo, będziesz musiał użyć operatora "shl":

    
    slowo := (starszy shl 8) + mlodszy;
    
REKLAMA