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

2313 poprawny odczyt co osiem prób

03 Sie 2005 10:01 1503 14
  • Poziom 16  
    Napisałem poniższy program, który zamienia ciąg bitów na paczki danych do wysłania rs232. (monitorowanie danych karta-czytnik). Problem polega na tym ze po resecie dane przesłane na PC są błedne. Gdy włoże kartę drugi raz otrzymuje dumpa, który jest w 100% poprawny, potem przy kolejnych 6 próbach dostaje znowu za każdym razem inne dane.
    Przykład (dane w hex):

    Code:
     
    
     45 27 20 22 c3 ... - 1-sze włożenie karty (dane niepoprawne)
     bf e8 04 44 64 ... - 2-gie włożenie karty (dane  poprawne)
     17 9d 80 88 0c ... - 3-cie włożenie karty (dane niepoprawne)
     ff a2 13 10 91 ... - 4-te włożenie karty (dane niepoprawne)
     5f 74 02 22 32 ... - 5-te włożenie karty (dane niepoprawne)
     8b 4e 40 44 86 ... - 6-te włożenie karty (dane niepoprawne)
     7f d1 09 88 c8 ... - 7-me włożenie karty (dane niepoprawne)
     27 3a 01 11 19 ... - 8-me włożenie karty (dane niepoprawne)

     45 27 20 22 c3 ... - 9-te włożenie karty (dane niepoprawne)
     bf e8 04 44 64 ... - 10-te włożenie karty (dane poprawne)
     ...

    w przykładzie napisałem tylko pierszsze pięć bajtów dumpa.
    Próby są za każdym razem powtarzalne i po każdym resecie uP zaczynam od 45 27 20 22...

    Code:

    #include "avr\io.h"

    #define CARD_CLK  PINB & _BV(0)
    #define CARD_DATA PINB & _BV(1)

    //------------------------------------------------------------------------
    int main(void)
    //------------------------------------------------------------------------
    {
      register char BitCnt;
      volatile register char ClkValOld;
      volatile register char ClkValNew;
      register char Data;

      // UART initialization: Baud rate: 38400, 8 Data, 1 Stop, No Parity
      // UART Receiver: Off, Transmitter: On
      UCR       = 0x08;
      UBRR      = 0x11;

      BitCnt    = 0x01;
      ClkValOld = 0x01;
      ClkValNew = 0x01;
      Data      = 0x00;

      do
      {
        ClkValNew = CARD_CLK;
        if(ClkValOld == ClkValNew)
          continue;
        if( (ClkValOld = ClkValNew) != 1)
          continue;
        if( CARD_DATA )   
          Data |= BitCnt;
        BitCnt <<= 1;
        if(BitCnt)
          continue;
        UDR = Data;
        BitCnt = 0x01;
        Data = 0;
      }while(1);
      return 0;
    }
     


    Muszę przyznać, że jestem zdesperowany i dla osób, które mi pomogą ofiaruję po 20pkt.
  • Poziom 19  
    Nie wiem jaka to karta i może to co napiszę nie będzie specjalnie przydatne, ale zauważylem, że nie sprawdzasz w żaden sposób, czy dane z poprzedniego bajtu już zostały wysłane (czy UDR jest pusty). Ta powtarzalność i fakt, że bajty czasem dochodzą poprawnie są dziwne, ale może spróbować nie zaszkodzi ;).
  • Poziom 16  
    sepher a czy coś takiego twoim zdamiem wystarczy?

    Code:
    if(!(_SFR_BYTE(USR) & _BV(UDRE)))
    
      continue;
    UDR = Data;


    nie chcę robić pętli while, bo zależy mi, żeby nie pogubić bitów danych, nie jestem, też pewny, czy ta negacja jest ok.

    Po dodaniu powyższych linijek program działa tak samo :-(
  • Poziom 18  
    Wiatm
    Użyj tej funkcji
    Napisana jest na ATMEGA 128 więc musisz zmienić nazwy rejestrów.

    Code:
    int uart_putchar(char c)
    
    {
    if (c == '\n')
       uart_putchar ('\r');
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
    return 0;
    }

    Pozdrawiam
  • Poziom 16  
    Zmieniłem kod tak jak sugerowałeś, ale teraz nie mam już nic na PCcie. Pewnie coś jeszcze jest nie tak. Robot_ czy mógłbyś to zweryfikować?

    Code:
    #include "avr\io.h"
    

    #define CARD_CLK  PINB & _BV(0)
    #define CARD_DATA PINB & _BV(1)

    //------------------------------------------------------------------------
    int uart_putchar(char c)
    //------------------------------------------------------------------------
    {
      if (c == '\n')
        uart_putchar('\r');
      loop_until_bit_is_set(UCR, UDRE);
      UDR = c;
      return 0;
    }


    //------------------------------------------------------------------------
    int main(void)
    //------------------------------------------------------------------------
    {
      register char BitCnt;
      register char ClkValOld;
      register char ClkValNew;
      volatile char Data;

      // UART initialization: Baud rate: 38400, 8 Data, 1 Stop, No Parity
      // UART Receiver: Off, Transmitter: On
      UCR       = 0x08;
      UBRR      = 0x11;

      BitCnt    = 0x01;
      ClkValOld = 0x01;
      ClkValNew = 0x01;
      Data      = 0x00;

      do
      {
        ClkValNew = CARD_CLK;
        if(ClkValOld == ClkValNew)
          continue;
        if( (ClkValOld = ClkValNew) != 1)
          continue;
        if( CARD_DATA )   
          Data |= BitCnt;
        BitCnt <<= 1;
        if(BitCnt)
          continue;
         
        uart_putchar (Data);
        BitCnt = 0x01;
        Data = 0;
      }while(1);
      return 0;
    }
  • Poziom 18  
    viki napisał:


    Code:

      // UART initialization: Baud rate: 38400, 8 Data, 1 Stop, No Parity
      // UART Receiver: Off, Transmitter: On
      UCR       = 0x08;
      UBRR      = 0x11;

    Używasz kwarcu 11.0592 MHz??
    viki napisał:

    Code:

        ClkValNew = CARD_CLK;
        if(ClkValOld == ClkValNew)
          continue;
        if( (ClkValOld = ClkValNew) != 1)
          continue;
        if( CARD_DATA )   
          Data |= BitCnt;
        BitCnt <<= 1;
        if(BitCnt)
          continue;
     


    Nie do końca rozumie działanie tego kodu możesz mi go wyjaśnić

    znak "=" to znak przypisania a w drugim if'ie powinien być chyba znak porównania "=="
    dołączam mój programik z dwoma działającymi funkcjami do wysyłania znaków po RS
    Testowane na ATMEGA 32

    Code:
    #include <avr/io.h>
    
    //*******************************************************************
    //funkcje
    //*******************************************************************
    void avr_init(void);
    void uart_putchar(unsigned char c);
    void USART_Transmit( unsigned char data );

    //*******************************************************************
    //funkcja glowna
    //*******************************************************************
    int main (void)
    {
    avr_init();

    uart_putchar('a');
    USART_Transmit('b');
    do
    {}
    while(1);
    }

    //*******************************************************************
    void avr_init(void) // inicjalizacja procesora
    {
    //RS kwarc 16 MHz
    UCSRB=0x18; //włączenie nadajnika i odbiornika
    UCSRC=0x06; //tryb asynchroniczny, bez bitu parzystości,
    UBRRH=0x00; //8 bitów danych, 1 bit stopu
    UBRRL=0x19; //przepływność 38,4 kb/s
    }
    //-------------------------------------------------------------------
    void uart_putchar(unsigned char c)
    {
    if (c == '\n')
      uart_putchar ('\r');
    loop_until_bit_is_set(UCSRA, UDRE);
    UDR = c;
    }
    //-------------------------------------------------------------------
    //funkcja z noty katalogowej ATMEGA32
    void USART_Transmit( unsigned char data )
    {
    while ( !( UCSRA & (1<<UDRE)) );
    UDR = data;
    }
  • Poziom 16  
    dzięki Robot_ za odpowiedź

    ad1. tak używam kwarcu 11059200

    ad2. czekam na zmiane sygnału CLK karty. Jeżeli nowa wartość jest różna od starej to stata wartość jest równa nowej wartości. (Pojedyńczy = w pętli if). Dodatkowo gdy CLK ma poziom wysoki odczytuje wartość bitu na i/o i za pomocą maski BitCnt (00000001),(00000010),(00000100) ... ustawiam Data |= BitCnt, oczywiście jeśli bit i/o ma poziom wysoki. Dalej następuje przesunięcie w lewo bitu maski aż do zera. Gdy bit maski jest zero wiem, że całą dana została odczytana. (obecnie BitCnt <<= 1; zastąpiłem BitCnt += BitCnt;);

    Obawiam się że błąd leży w tym iż nie do końca rozumiem mechanizm odczytu karty, ponieważ, gdy wkładam czystą kartę również dostaję co osiem włożeń inne dane. Wysyłane chyba przez czytnik. (inicjalizacja i2c, czy jakieś kryptowanie nie wiem). Jest więc możliwe że program działa dobrze.
  • Poziom 18  
    Napisz co to za karta.
    Załącz pdf'a z opisem transmisji może coś razem poradzimy
  • Poziom 16  
    karta to sle4442
    Opisu transmisji jako takiego nie posiadam, wiem tyle co z książki. Karta elektroniczna. Bezpieczny nośnik informacji Marian Molski, Monika Kubas
    To jednak mój program działa niepoprawnie, bo po resecie za każdym razem zaczynam od 45 27 20 22...
  • Poziom 18  
    Hej znalazlem opis transmisji tej karty
    Zastosuj się do tego, może później coś napisze na razie jestem troszke zajęty więc jak sobie nie poradzisz to może coś w weekend napisze.
    Pozdrawiam
    Załączniki:
  • Poziom 16  
    Plik sle4442 jest uszkodzony, jeśli można to jakoś poprawić, będe wdzięczny. Robot_ dzięki za zainteresowanie tematem. Myśle że może czytam, gdzieś na granicy, gdybym miał przebieg, lub jego częstotliwość może wystarczy zastosować jakieś opuźnienie. W każdym razie nadal eksperymentuje i jak bylko będą jakiś wnioski od razu coś nastukam. Acha bardzo jestem ciekawy Twojego podejścia.
  • Poziom 42  
    Wygeneruj impuls resetu, on spowoduje że licznik bitów na karcie ustawi się na adresie równym 0.
  • Poziom 16  
    ale ja nie tworze czytnika, chciałem tylko podsłuchać komunikację pomiędzy czytnikiem, który działa ok a kartą. Myślę jednak, że sygnał resetu może mi posłużyć do synchronizacj, bo mo że przez jej brak dostaje takie dziwne wyniki.
  • Poziom 18  
    Już zmieniłem
    Sorki mój bład ściągałem ten plik najpierw przez przeglądarke i on był błędny sorki za pomyłke.
    Co do transmisji to wyszytałem ze składa się z trzech bajtów więc trochę będziesz miał do przeszukania.
    Jeśli to ma być podsłuch to polecam zegar walnąć na linie przerwania zewnętrznego.
  • Poziom 16  
    Robot_ nie rozumiem o co w poniższym cytacie chodzi:

    Cytat:
    Co do transmisji to wyszytałem ze składa się z trzech bajtów więc trochę będziesz miał do przeszukania.
    Jeśli to ma być podsłuch to polecam zegar walnąć na linie przerwania zewnętrznego.


    czy mógłbyś jaśniej.

    W poprawnej odpowiedzi dostaję taki ciąg

    Code:

    bf e8 04 44 24 18 00 80 a2 13 10 91 46 0b 81 15...
                            ________

    podkreśleniem zaznaczyłem atr dalej jest data wyprodukowania, producent karty: siemens i typ karty...

    Tak jak pisałem wcześniej wszystko zdadza sie od ATR do kończa z dumpem. Nie wiem co znaczą te pierwsze osiem bajtów, i zastanawiam się czy nie będzie lepiej jeśli poczekam na opadające zbocze resetu i dopiero wtedy nie zaczne odczytywać bity tak jak sugerował elektryk. W każdym razie muszę jeszcze wczytać się w pdfa od Robota_ (dzięki)

    co do przerwania to kiedyś tak zrobilem ale forumowicze uświadomili ni że tracę wtedy niepotrzebnie czas na obsłgę przerwania

    Dodano po 25 [minuty]:

    Przy okazji wersja przed dodaniem Resetu wygląda tak:

    Code:
    #include "avr\io.h"
    

    #define CLK_PIN  _BV(PINB4)
    #define DATA_PIN _BV(PINB5)

    #define CARD_CLK  PINB & CLK_PIN
    #define CARD_DATA PINB & DATA_PIN


    //------------------------------------------------------------------------
    int main(void)
    //------------------------------------------------------------------------
    {
      register char BitCnt;
      register char ClkValOld;
      register char ClkValNew;
      register char Data;

      // UART initialization: Baud rate: 38400, 8 Data, 1 Stop, No Parity
      // UART Receiver: Off, Transmitter: On
      UCR       = 0x08;
      UBRR      = 0x11;
     
      PORTB     = 0x00;
      DDRB      = 0x00;

      BitCnt    = 0x01;
      ClkValOld = 0x00;
      ClkValNew = 0x00;
      Data      = 0x00;

      do
      {
        ClkValNew = CARD_CLK;
        if(ClkValOld == ClkValNew)
          continue;
        if( ClkValNew != CLK_PIN)
        {
          ClkValOld = ClkValNew;
          continue;
        } 
        if( CARD_DATA )   
          Data |= BitCnt;
        BitCnt += BitCnt;
        ClkValOld = ClkValNew;
        if(BitCnt != 0)
          continue;
         
        UDR = Data;
        BitCnt = 0x01;
        Data = 0;
      }while(1);
      return 0;
    }