Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

PIC 16F84 "kodowanie znaku rs232"

kolgreen 18 Lut 2010 22:28 2046 10
  • #1 18 Lut 2010 22:28
    kolgreen
    Poziom 14  

    Programuje PIC 16F84 w języku C. Problem, który rozwiązuje
    można w skrócie opisać tak:
    Do uC wysyłany zostaje znak przez port COM

    Code:

    #use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1,bits=8)


    odbieram dane - to mam zrobione.
    Odebrałem znak char i jest on zapisany w zmiennej np. znak.
    uC szyfruje znak (np. dodaje do niej jakąś stałą liczbę)
    Następnie chciałbym go "przekazać dalej" np. na PIN_A1.

    Odebrać drugim uC na PIN_A2 zapisać do zmiennej znak
    i przekazać po "zdekodowaniu" na port COM.

    PIN_A1 - tx szyfrowane
    PIN_A2 - rx szyfrowane

    PIN_B0 - tx jawny
    PIN_B1 - rx jawny

    Przyznam, że nie mam wprawy w programowaniu uC i troszkę się "zafiksowałem".
    Bo skoro funkcja:
    printf();
    wysyła mi na COM (PIN_B0) to jak przesłać na PIN_A1 ?!
    Z góry dziękuję za wskazówki ;)

  • #2 19 Lut 2010 00:18
    nenpa8lo
    Poziom 17  

    Nie jestem expertem w PICach, ale PIC 16F84 nie ma UARTu, więc o jakim COMie piszesz?

  • #3 19 Lut 2010 00:27
    CDMaster
    Poziom 14  

    Tak z ciekawości... Jaki masz kompilator??;D Bo jak się kiedyś bawiłem PIC16, to ciężko było dorwać coś sensownego:D
    A co do pytania... Czytanie masz opanowane... Spoko... Zapis... Hmmm... Skoro Ci ten printf nie działa, to może czas zajrzeć do dokumentacji?? Generalnie wysłanie czegoś, to po prostu przypisanie wartości zmiennej do rejestru TXREG, co przynajmniej w C18 wyglada tak:
    TXREG = zmienna;
    Potem tylko się martwisz o bit busy (chyba TRMT, dawno nie używałem USART'u:D), czy przy próbie następnego wysłania nie jest ustawiony;D

  • #4 19 Lut 2010 09:29
    kolgreen
    Poziom 14  

    Wysyłanie i odbieranie działa bez problemu z tym, że mam tylko jedną parę:
    -pin tx
    -pin rx
    A potrzebuję jeszcze jedną taką parę :] Wydaje mi się jednak, że bez głębszej przeróbki funkcji obsługujących UART się nie obejdzie :(
    No tak... PIC 16F84 nie ma sprzętowego UART'a, ale można rozwiązać to programowo. Używam kompilatora PCWH Compiler. Ma on już wiele gotowych funkcji,
    obsługę LCD itd. w tym też obsługę standardu RS232.
    Przykładowy kod odbierający i nadający znak:

    Code:

    #include <16F84.h>
    #use delay(clock=4000000)
    #fuses NOWDT,XT, NOPUT, NOPROTECT
    #use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1,bits=8)

      #include <stdio.h>
      #include <stddef.h>
      #include <stdlib.h>
      #include <stdlibm.h>
      #include <string.h>
      #include <input.c>

    void main()
    {
       //komenda
       char command;

       //wyslanie czegoś
       printf("Hello");

       //petla glowna
       while(true){
          //odebranie czegos
          command = getc();
      }
    }


    I wszystko działa pięknie. Tylko że to jest obsługa tylko jednego portu.
    Teraz gdy mam coś w zmiennej command to chciałbym to "wysłać dalej".
    printf wyśle mi na zdefiniowany port
    Code:

    #use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1,bits=8)

    Pytanie jak obsłużyć port kolejny?

  • Pomocny post
    #5 19 Lut 2010 10:16
    94075
    Usunięty  
  • #6 20 Lut 2010 16:49
    kolgreen
    Poziom 14  

    Dzięki albertb, nie wiem dlaczego nie wpadłem na to by manuala poszukać :] Link się przydał, znalazłem to co potrzebowałem.

  • #7 27 Lut 2010 21:57
    kolgreen
    Poziom 14  

    Pojawił się niestety problem z aplikacją dla uC.

    Przykład z dokumentacji:

    Code:

    #USE RS232(BAUD=9600, XMIT=PIN_B0, RCV=PIN_B1, STREAM=COM_A)
    #USE RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B3, STREAM=COM_B)
    main() {
    char c;
    fprintf(COM_A,"Online\n\r");
    fprintf(COM_B,"Online\n\r");
    while(TRUE) {
    c = fgetc(COM_A);
    fputc(c, COM_A);
    fputc(c, COM_B);
    }
    }


    Działa - brak jakichkolwiek problemów.
    Ja natomiast rozbudowałem (to chyba zbyt dużo powiedziane) program o coś w stylu loopback.

    Oczekuję, że program:

    Code:

    #include <16F84.h>
    #use delay(clock=4000000)
    #fuses NOWDT,XT, NOPUT, NOPROTECT

    //----Oznaczenia portu----
    //xmit - out
    //rcv  - in

    //---Komputer----------
    // wyjscie PIN_B1 pin7 (2pin rs232 odbieranie)
    // wejscie PIN_B2 pin8 (3pin rs232 nadawanie)
    #use rs232(baud=9600,parity=N,xmit=PIN_B1,rcv=PIN_B2,bits=8,stream=COM_A)

    //---Transceiver-------
    // wejscie PIN_B3 pin9
    // wyjscie PIN_B5 pin11
    #use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B3,bits=8,stream=COM_B)


      #include <stdio.h>
      #include <stddef.h>
      #include <stdlibm.h>
      #include <string.h>



    void main(){

    char a;
    char b;

       //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

    fprintf(COM_A, "Online\n\r");
    fprintf(COM_B, "Online\n\r");

       while(TRUE) {
          a = fgetc(COM_A);
          fputc(a, COM_B);
         
          b = fgetc(COM_B);
          fputc(b, COM_A);
         
       }

    }


    Będzie wysyłał na port COM_A to co otrzyma na COM_B i na odwrót,
    to oczywiście nie ma większego sensu, ale jest to dopiero szkielet programu.
    By sprawdzić czy to działa złączyłem B3 (pin9) z B5 (pin11).
    Czy moje myślenie jest poprawne? Bo działać to, to niestety nie działa...

    Poszedłem więc na całość... Napisałem kod:
    Code:

    #include <16F84.h>
    #use delay(clock=4000000)
    #fuses NOWDT,XT, NOPUT, NOPROTECT

    //----Oznaczenia portu----
    //xmit - out
    //rcv  - in

    //---Komputer----------
    // wyjscie PIN_B1 pin7 (2pin rs232 odbieranie)




    // wejscie PIN_B2 pin8 (3pin rs232 nadawanie)
    #use rs232(baud=9600,parity=N,xmit=PIN_B1,rcv=PIN_B2,bits=8,stream=COM_A)

    //---Transceiver-------
    // wejscie PIN_B3 pin9
    // wyjscie PIN_B5 pin11
    #use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B3,bits=8,stream=COM_B)


      #include <stdio.h>
      #include <stddef.h>
      #include <stdlibm.h>
      #include <string.h>



    void main(){

    char a=NULL;
    char b=NULL;

       //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

    fprintf(COM_A, "Online\n\r");
    fprintf(COM_B, "Online\n\r");

       while(TRUE) {
       
          a = fgetc(COM_A);
         

          //z kompa (COM A) rozkaz sprawdzenia COM A, na COM A wysłanie czy jest ok
          if (a=='a'){
             fprintf(COM_A, "COM_A OK");
             a=NULL;
          }
          //z kompa (COM A) rozkaz sprawdzenia COM B, na COM B wysłanie czy jest ok
          if (a=='b'){
             fprintf(COM_B, "COM_B OK");
             a=NULL;
          }
         
         
          //LOOPBACK
          if (a!=NULL){
             fprintf(COM_B, a);
             a=NULL;
          }
         
          b = fgetc(COM_B);
         
          if (b!=NULL){     
             fprintf(COM_A, b);
             b=NULL;
          }
         
       }

    }


    Spodziewałem się, że "coś się pojawi". Program ładnie wypisuje na porty "Online"
    po wysłaniu znaku "a" wypisuje "COM_A OK". Wszystko niby fajnie... ale
    to już koniec... ponowne wysłanie "a" nie skutkuje wypisaniem "COM_A OK".
    Procesor się "wiesza". Dodam, że te NULL, to już tak przekombinowałem...
    Wcześniej było bez if'ów, NULL'i i też był ten sam problem.

  • Pomocny post
    #8 27 Lut 2010 22:28
    94075
    Usunięty  
  • #9 27 Lut 2010 23:58
    kolgreen
    Poziom 14  

    Fakt :)
    Nie wiem dlaczego spodziewałem się, że dostane NULL skąd to wynalazłem nie wiem. Myślałem, że program wykonuje następną instrukcję a funkcja fgetc() nic nie zwraca. Mój błąd, głupi błąd ! :]
    Z tym, że w chwili gdy nie wiemy czy pojawi znak czy nie to rozwiązujemy to
    za pomocą (np. dla COM_B) tak jak w przykładzie poniżej?

    Code:

    if (kbhit(COM_B)){
        //tutaj instrukcje gdy coś przyszło
    }


    Dobrze rozumiem ?

    Skleciłem zatem kod:
    Code:

    #include <16F84.h>
    #use delay(clock=4000000)
    #fuses NOWDT,XT, NOPUT, NOPROTECT

    //----Oznaczenia portu----
    //xmit - out
    //rcv  - in

    //---Komputer----------
    // wyjscie PIN_B1 pin7 (2pin rs232 odbieranie)
    // wejscie PIN_B2 pin8 (3pin rs232 nadawanie)
    #use rs232(baud=9600,parity=N,xmit=PIN_B1,rcv=PIN_B2,bits=8,stream=COM_A)

    //---Transceiver-------
    // wejscie PIN_B3 pin9
    // wyjscie PIN_B5 pin11
    #use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B3,bits=8,stream=COM_B)


      #include <stdio.h>
      #include <stddef.h>
      #include <stdlibm.h>
      #include <string.h>



    main() {

    char c;

    fprintf(COM_A,"Online COM_A\n\r");
    fprintf(COM_B,"Online COM_B\n\r");

       while(TRUE) {
       
          //Gdy pojawi się znak na COM_A
          if (kbhit(COM_A)){
             
             c = fgetc(COM_A);
             
             if (c=='a'){
                fprintf(COM_A,"COM A OK\n\r");
             }
             else if (c=='b'){
                fprintf(COM_B,"COM B OK\n\r");
             }
             //przekazanie znaku z COM_A na COM_B
             else {
                  fprintf(COM_B,c);
                  }
          }
         
          //Gdy pojawi się znak na COM_B
          if (kbhit(COM_B)){
             
             c = fgetc(COM_B);
             
             if (c=='a'){
                fprintf(COM_A,"COM A OK\n\r");
             }
             else if (c=='b'){
                fprintf(COM_B,"COM B OK\n\r");
             }
             //przekazanie znaku z COM_B na COM_A
             else {
                  fprintf(COM_A,c);
                  }
          }
         
       }
    }


    Mam nadzieje, że merytorycznie jest to poprawne i zadziała...
    Wstępnie sprawdzałem kbhit(), co prawda jeszcze nie na tym powyższym kodzie, a na bardziej okrojonym i wszystko było ok. Mam nadzieje, że przykład powyższy będzie przekazywał znaki (za wyjątkiem "a" i "b") między portami...

    Jeśli popełniam błąd, będę wdzięczny za wskazówki.

  • #10 28 Lut 2010 16:44
    94075
    Usunięty  
  • #11 28 Lut 2010 19:27
    kolgreen
    Poziom 14  

    Code:

    fputc(c, COM_B);


    czy tak powinno być ?

TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo