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

lpc 1114 - detektor alfabetu morsa

05 Lut 2013 00:11 2613 20
  • Poziom 10  
    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.
  • Poziom 26  
    Poczytaj o trybie capture timera.
  • Poziom 25  
    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?
  • Poziom 10  
    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.
  • Poziom 35  
    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'...
  • Poziom 36  
    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.
  • Poziom 35  
    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...
  • Poziom 10  
    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ść.
  • Użytkownik usunął konto  
  • Specjalista - Mikrokontrolery
    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ł...
  • Poziom 10  
    #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;
  • Specjalista - Mikrokontrolery
    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.
  • Poziom 10  
    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ć.
  • Specjalista - Mikrokontrolery
    Bierzesz w blok kod i z menu tuż powyżej okienka, w którym piszesz wybierasz Syntax C.
  • Poziom 10  
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Byłbym bardzo wdzieczny gdybyś pomógł mi z tym volatine
  • Specjalista - Mikrokontrolery
    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...
  • Poziom 10  
    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
  • Specjalista - Mikrokontrolery
    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.
  • Poziom 10  
    no dobra dzięki.
    A według ciebie jak powinna wygladać cała ta deklaracja przerwań w moim przypadku?
  • Specjalista - Mikrokontrolery
    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.
  • Poziom 10  
    Problem rozwiązany program był dobrze napisany brakowało tylko kondensatora by zniwelować drgania styków. Głupie przeoczenie
    Pozdrawiam