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

Jak zbudować detektor alfabetu Morsa z LPC 1114 i wyświetlaczem 7-segmentowym?

gumis12444 05 Lut 2013 00:11 2862 20
REKLAMA
  • #1 11890013
    gumis12444
    Poziom 11  
    Posty: 22
    Szukam pomocy.
    Mam do użycia siedmiosegmetowy wyświetlacz oraz przycisk.
    I za pomocą tego mam stworzyć detektor alfabetu morsa.
    Czyli jak rozumiem musi być reakcja na długość wciśnietego przycisku by odróżnić kropke od kreski.
    Jest tylko problem, że jestem początkującym i niewiem jak się do tego zabrać.
    Poprosił bym o pomoc i jakieś sugestie.
  • REKLAMA
  • #2 11890021
    alagner
    Poziom 26  
    Posty: 768
    Pomógł: 85
    Ocena: 29
    Poczytaj o trybie capture timera.
  • #3 11890756
    snnaap
    Poziom 25  
    Posty: 677
    Pomógł: 83
    Ocena: 10
    Szkoda tylko że nie napisałeś więcej szczegółów bo temat ciekawy i dosyć rozwojowy.
    Nie wiadomo jaką formę będzie miał sygnał - sygnał elektryczny, dzwiękowy czy świetlny.
    Jak wygląda nadajnik?
    Czy masz określoną długość sygnałów kropki i kreski?
  • #4 11890941
    gumis12444
    Poziom 11  
    Posty: 22
    Zrealizować dekoder alfabetu Morse'a w oparciu o wyświetlacz siedmiosegmentowy i pojedynczy przycisk. Użytkownik odpowiednio klika na przycisk, a na wyświetlaczu pojawiają się odpowiednie znaki.

    Chodzi o to, że przycisku używasz jak telegrafu, a na wyświetlaczu pokazuje się wystukana cyfra, litera.
  • #5 11891200
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Nie do konca jest tak ;]
    Po kazdym puszczeniu przycisku (czyli skonczeniu symbolu - kropki lub kreski) musi lecieć licznik timeouta na znak. Zeby dało się rozpoznać kiedy skonczył sie znak...

    W skrócie mówiąc, weź uruchom timer w trybie capture z przerwaniem na capture event, podłącz przycisk pod TMRx_CAP0, capture skonfiguruj na oba zbocza i edge sensitive + reset timera. W efekcie czego ISR timera wykona sie co zmiana stanu przycisku.

    Przycisk ma stan aktywny niski.

    Jeden z MATCHów timera wykorzystujesz do timeouta znaku - uzbrajasz go co zbocze narastające.

    W ISRrze rozpoznajesz czas trwania stanu niskiego (czyli czas wcisnietego przycisku) miedzy opadajacym a narastającym zboczem, i na podstawie tego klasyfikujesz symbol.

    Ustal sobie np. kropka=0,kreska=1, i co zbocze narastajace wykonuj operacje: { bierzZnak|=symbol; bierzZnak<<=1; symbole++; }

    Na timeout (czyli wystąpienie MATCHa) w bierzZnak masz sekwencje kropek/kresek a w 'symbole' sumaryczna ich ilosc.

    Rozpoznawanie najwydajniej zrobić lookupem 64pisowym +ifem do obsługi cyfr: jeden znak nie-cyfra nie ma wiecej niz 4 symbole, więc:
    index=bierzZnak|((symbole-1)<<4);
    znak=lookup[index];

    Lookupa trzeba zbudowac tak, żeby np. index 0x11 ('A': dot-dash, len=2, =0010 0001) wskazywał na znak ASCII 'A'...
  • #6 11891326
    sp3ots
    Poziom 38  
    Posty: 3065
    Pomógł: 523
    Ocena: 673
    Witam !
    Gumis12444, jak na wyświetlaczu siedmiosegmentowym chcesz wyświetlać LITERY.
    Nsvinc, cyfry mają 5 ( długich/krótkich ).
    Pozdrawiam. Stefan
    ps. Interesuje mnie to zagadnienie ale nie w tym języku, za wysokie progi na moje nogi.
  • REKLAMA
  • #7 11891398
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    sp3ots napisał:
    Nsvinc, cyfry mają 5 ( długich/krótkich ).

    Oczywiscie, że mają, gdyż
    myself napisał:

    +ifem do obsługi cyfr: jeden znak nie-cyfra nie ma wiecej niz 4 symbole

    ;)
    if(symbole<5) znak=Lookup[index]; else TuJestKilkaSposobowNaRealizacjeRozpoznawaniaCyfry(bierzZnak);

    sp3ots napisał:
    Gumis12444, jak na wyświetlaczu siedmiosegmentowym chcesz wyświetlać LITERY

    Dobre pytanie ;] Ale różne są zboczenia...
    Chyba prościej niz jakikolwiek inny wyświetlacz byłoby popychanie danych UARTem do komputera. A jak już wyświetlacz, to może 1x8 alfanumeryczny zgodny z HD44780? Lub wersja dla masochistów wyświetlacz 16segmentowy LED...
  • #8 11891611
    gumis12444
    Poziom 11  
    Posty: 22
    nie to ma byc wyświetlacz taki jak napisałem ma wyświetlac tylko jeden znak
    Tyle co sam rozkminiłem


    Dekoder morsa:
    Dekodowanie znaków:
    1. ustawić kody od najkrótszego do najdłuższego
    2. zliczanie długości:
    kropka (.) - 1 jednostka (~60 ms ciągłego sygnału)
    kreska (-) - 3 jednostki (3 kropki)
    przerwa między kropką/kreską - 1 kropka
    odstęp między literami - 3 kropki
    odstęp między słowami - 7 kropek

    3. Algorytm
    3.1 Ustalić czas trwania jednej jednostki
    3.2 Nasłuch (wersja o stałej prędkości wprowadzania):
    3.2.1 Mierzyć wypełnienie impulsu w ustalonym czasie jednostki
    jeżeli był wciśnięty przez 75-90% założonego czasu zapisać jako 1 do łańcucha tekstowego morsa (ma to na celu wyeliminowanie drgań przycisku i eliminację "przeciągniętej 3 jednostki")
    jeżeli nie był wciśnięty przez 75-90% założonego czasu zapisać jako 0 do łańcucha tekstowego morsa
    jeżeli 3 ostatnie znaki w łańcuchu tekstowym morsa to "0" przerwać nasłuch i rozpocząć dekodowanie znaku (przejdź do 3.3)
    przejdź do 3.2.1

    3.3 Przygotować łańcuch do dekodowania
    Usunąć zera poprzedzające pierwsze wystąpienie "1" w łańcuchu
    Usunąć 3 zera które znalazły się na końcu łańcucha
    (Przykład: łańcuch przed dekodowaniem: "0010101000" -> po przygotowaniu -> "10101")
    Po przygotowaniu łańcucha przejść do dekodowania
    3.4 Dekodowanie
    Jeżeli łańcuch jest pusty nie rób nic i pozostaw ostatnią znaną literę na wyświetlaczu
    Jeżeli łańcuch nie jest pusty:
    Porównaj z tabelą zero-jedynkową (pkt. 4) i znajdź pasujący ciąg
    Jeżeli wyszukiwanie się powiedzie wyświetl na wyświetlaczu literę lub cyfrę przypisaną do ciągu
    Jeżeli wyszukiwanie się nie powiedzie wyczyść wyświetlacz.
    3.5 Przejdź do 3.2 (Nasłuch)

    4. Tabela kodów zero/jeden (nie mylić z binarną)
    A:10111
    B:111010101
    C:11101011101
    D:1110101
    E:1
    F:101011101
    G:111011101
    H:1010101
    I:101
    J:10111
    itd. resztę sam sobie przygotuj na podstawie: http://upload.wikimedia.org/wikipedia/commons...e.svg/2000px-International_Morse_Code.svg.png

    Tabelę należy posortować od najkrótszego kodu do najdłuższego (czyli "E" teoretycznie powinno być pierwsze w tabeli, potem "I" i wszystko "E-podobne" potem "T" (111) i wszystko "T-podobne" itd...)

    5. Prosty test
    zakładając że przyjmiemy jednostkę na poziomie 60 ms wciskając przycisk krótko jednokrotnie po ok. 180 ms powinna pojawić się litera "E", znowu przytrzymując przycisk przez 180ms po ok. 360ms powinna pojawić się litera "T"


    Ale nie potrafię zapisać tego timera do zliczania tych cykli.
    W sumie to dopiero zacznam mieć z tym jakąś styczność.
  • #9 11895515
    Konto nie istnieje
    Konto nie istnieje  
  • #10 12000682
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Zacznij od wstawienia kodu w czytelnej postaci oraz deklaracji z atrybutem volatile dla zmiennych modyfikowanych w przerwaniach i sprawdzanych poza nimi. Potem zapisz stałe tak, żeby było wiadomo, o co chodzi, np. wygaszenie przez zais 1023 wygląda dość magicznie. Po tych czynnościach zostanie już tylko 98% pracy do wykonania. ;)

    Właśnie odpowiedziałem na post, który Autor skasował...
  • #11 12000765
    gumis12444
    Poziom 11  
    Posty: 22
    #include "lpc11xx_syscon.h"
    #include "lpc11xx_gpio.h"

    #define OUT 1
    #define IN 0


    // a b c d e f g h i j k l m n o p r s t u w y z
    // _ _ _ _ _ _ _ _ _
    //|_| |_ | _| |_ |_ | |_| | | |_ | | | _ _ |_| _ |_ |_ | | |_| _|
    //| | |_| |_ |_| |_ | |_| | | | _| | |_ | | | | |_| | | _| |_ |_| |_| _| |_ 1 2 3 4 5 6 7 8 9 0

    char out[]={8,3,70,33,6,14,66,9,121,113,15,71,72,43,35,12,47,18,7,99,65,17,36,121,36,48,25,18,2,120,0,16,64};
    int ms0=0; //mili sekundy (odmierzane przez TIMER0)
    int ms1 =0; //mili sekundy (odmierzane przez TIMER1)
    char wsk=0;
    char tab[];

    void init();
    void dekoduj();

    int main(void)
    {
    init();
    int p;
    for(p=0;p<5;p++){
    tab[p]=2;
    }
    int delay
    =2000;
    while(1){
    while(LPC_GPIO3->DATA & (1<<2));
    while(delay>0){delay--; }
    if((LPC_GPIO3->DATA & (1<<2)) == 0){
    LPC_TMR16B0->TCR = 2; // timer reset
    LPC_TMR16B0->TCR = 1; // timer start
    LPC_TMR16B1->TCR = 2; // timer reset
    LPC_TMR16B1->TCR = 1; // timer start
    while(!(LPC_GPIO3->DATA & (1<<2)));
    }
    LPC_TMR16B0->TCR = 0;
    delay=2000;
    while(delay>0){delay--; }
    if (ms0<=200){ //kropka
    LPC_GPIO2->DATA = out[14];
    tab[wsk]=0;
    wsk++;
    }else{ //kreska
    LPC_GPIO2->DATA = 63;
    tab[wsk]=1;
    wsk++;
    }
    ms0=0;
    }
    }

    void init(){
    GPIOInit();
    GPIOSetDir(PORT2, 0, OUT);
    GPIOSetDir(PORT2, 1, OUT);
    GPIOSetDir(PORT2, 2, OUT);
    GPIOSetDir(PORT2, 3, OUT);
    GPIOSetDir(PORT2, 8, OUT);
    GPIOSetDir(PORT2, 9, OUT);
    GPIOSetDir(PORT2, 6, OUT);
    LPC_GPIO2->DATA = 1023; //wygaszenie
    LPC_GPIO3->DIR &= ~(1<<2); //wejscie, przycisk

    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7)|(1<<8);
    LPC_TMR16B0->PR = 12000 - 1;
    LPC_TMR16B0->MR0 = 1;
    LPC_TMR16B0->MCR = 1 << 0 | 1 << 1;
    LPC_TMR16B0->TCR = 1;

    LPC_TMR16B1->PR = 12000 - 1;
    LPC_TMR16B1->MR0 = 5; //czas
    LPC_TMR16B1->MCR = 1 << 0 | 1 << 1;
    LPC_TMR16B1->TCR = 1;
    NVIC_EnableIRQ(TIMER_16_0_IRQn);
    NVIC_EnableIRQ(TIMER_16_1_IRQn);

    }

    void dekoduj(){
    if ( tab[0]==0 & tab[1]==1 & tab[2]==2 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[0];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==0 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[1];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==1 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[2];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==0 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[3];}
    if ( tab[0]==0 & tab[1]==2 & tab[2]==2 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[4];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==1 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[5];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==0 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[6];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==0 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[7];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==2 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[8];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==1 & tab[3]==1 & tab[4]==2) {LPC_GPIO2->DATA=out[9];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==1 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[10];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==0 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[11];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==2 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[12];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==2 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[13];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==1 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[14];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==1 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[15];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==0 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[16];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==0 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[17];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==0 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[18];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==1 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[19];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==1 & tab[3]==2 & tab[4]==2) {LPC_GPIO2->DATA=out[20];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==1 & tab[3]==1 & tab[4]==2) {LPC_GPIO2->DATA=out[21];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==0 & tab[3]==0 & tab[4]==2) {LPC_GPIO2->DATA=out[22];}
    if ( tab[0]==0 & tab[1]==1 & tab[2]==1 & tab[3]==1 & tab[4]==1) {LPC_GPIO2->DATA=out[23];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==1 & tab[3]==1 & tab[4]==1) {LPC_GPIO2->DATA=out[24];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==0 & tab[3]==1 & tab[4]==1) {LPC_GPIO2->DATA=out[25];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==0 & tab[3]==0 & tab[4]==1) {LPC_GPIO2->DATA=out[26];}
    if ( tab[0]==0 & tab[1]==0 & tab[2]==0 & tab[3]==0 & tab[4]==0) {LPC_GPIO2->DATA=out[27];}
    if ( tab[0]==1 & tab[1]==0 & tab[2]==0 & tab[3]==0 & tab[4]==0) {LPC_GPIO2->DATA=out[28];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==0 & tab[3]==0 & tab[4]==0) {LPC_GPIO2->DATA=out[29];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==1 & tab[3]==0 & tab[4]==0) {LPC_GPIO2->DATA=out[30];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==1 & tab[3]==1 & tab[4]==0) {LPC_GPIO2->DATA=out[31];}
    if ( tab[0]==1 & tab[1]==1 & tab[2]==1 & tab[3]==1 & tab[4]==1) {LPC_GPIO2->DATA=out[32];}
    wsk=0;
    int w;
    for(w=0;w<5;w++){ // error: 'for' loop initial declarations are only allowed in C99 mode
    tab[w]=2;
    }
    }



    void TIMER16_0_IRQHandler(void)
    {
    ms0++;
    LPC_TMR16B0->IR = 0x1f; // clear interrupt flag
    }


    void TIMER16_1_IRQHandler(void)
    {
    ms1++;
    if(ms1>5000){
    ms1=0;
    LPC_TMR16B1->TCR = 0;
    LPC_GPIO2->DATA = 1023; //wygaszenie
    dekoduj();
    }
    LPC_TMR16B1->IR = 0x1f; // clear interrupt flag
    }




    Z tym volatile jak to zdeklarować?
    Chodzi o to??


    volatile int timer_counter = 0;
  • #12 12000801
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Najpierw poprawnie użyj tagów Syntax.
    Tak, chodzi o to, że zmienne modyfikowane w przerwaniach powinny mieć atrybut volatile. Raz już to napisałem.
  • REKLAMA
  • #13 12000848
    gumis12444
    Poziom 11  
    Posty: 22
    niepotrafie połać z tymi tagami.
    Byłbym wdzieczny jakbys mi troche pomógł z tym o naprawde niemam pojecia jak to w tym przypadku zdeklarować.
  • REKLAMA
  • #14 12000905
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Bierzesz w blok kod i z menu tuż powyżej okienka, w którym piszesz wybierasz Syntax C.
  • #15 12000930
    gumis12444
    Poziom 11  
    Posty: 22
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Byłbym bardzo wdzieczny gdybyś pomógł mi z tym volatine
  • #16 12000969
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    1. Jak jeszcze mam Ci pomóc z volatile? Co jest niejasne?

    2. Co to jest char tab[]; ?

    3. Po co napisałeś:
    void init();
    void dekoduj();
    i dlaczego ignorujesz ostrzeżenie kompilatora?

    4. Dlaczego restetujesz timer 2 razy pod rząd?

    To tak na początek...
  • #17 12000988
    gumis12444
    Poziom 11  
    Posty: 22
    do tab[] wpisywana jest wartość 0 lub 1 wzależności od długości przytrzymanego przycisku. 0 kropka 1 kreska. Dopiero zaczynam mieć z tym styczność z tym i niemam pojęcia jak ją zdeklrować przy dwóch przerwaniach. z tym resetem to przeoczenie widocznie. Zresztą używane są dwa timery.
    void dekoduj myślałem że jest potrzebne
  • #18 12001026
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Do tab[] nie da się nic wpisać, bo tab[] ma zero elementów. Pisząc do tab zamazujesz inne zmienne.

    Zacznij czytać ostrzeżenia kompilatora i usuwać ich przyczyny.
  • #19 12001036
    gumis12444
    Poziom 11  
    Posty: 22
    no dobra dzięki.
    A według ciebie jak powinna wygladać cała ta deklaracja przerwań w moim przypadku?
  • #20 12001058
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Według mnie powinno być jedno przerwanie zgłaszane z częstotliwością np. 100 Hz, w którym programowo testujesz przycisk z ignorowaniem drgań. Inaczej to nie ma szans zadziałać.

    Pokazywałem niedawno taki przykład obsługi przycisku na STM32F0.
  • #21 12007689
    gumis12444
    Poziom 11  
    Posty: 22
    Problem rozwiązany program był dobrze napisany brakowało tylko kondensatora by zniwelować drgania styków. Głupie przeoczenie
    Pozdrawiam

Podsumowanie tematu

✨ Użytkownik poszukuje pomocy w budowie detektora alfabetu Morsa z wykorzystaniem mikrokontrolera LPC 1114 oraz wyświetlacza 7-segmentowego. Kluczowym elementem projektu jest przycisk, który będzie używany do wprowadzania sygnałów, gdzie długość wciśnięcia przycisku będzie rozróżniać kropki i kreski. W dyskusji poruszono kwestie dotyczące konfiguracji timera w trybie capture, obsługi przerwań oraz algorytmu dekodowania sygnałów Morsa. Ustalono, że kropka odpowiada 1 jednostce czasu (~60 ms), a kreska 3 jednostkom. Użytkownik napotkał problemy z drganiami styków, które zostały rozwiązane poprzez dodanie kondensatora.
Wygenerowane przez model językowy.
REKLAMA