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

[Rozwiązano] Kod asemblera do obliczania CRC na mikrokontrolerze 8051

Kylan 24 Wrz 2006 22:59 3959 7
  • #1 3053766
    Kylan
    Poziom 2  
    Posty: 4
    Witam!
    Mam pewnien problem, otóż próbuje napisać program na mikrokontroler kompatybilny z 8051. W zaden sposób nie potrafie napisać procedury liczacej wartosc CRC fragmentu pamieci RAM. Z komputera PC wysyłam przez łacze RS 232 plik który zapisywany jest w zewnętrznej pamięci układu. Po zapisaniu danych program ma obliczyc wartość CRC przesłanego pliku a więc obliczyc fragment danych zapisany w pamięci RAM.
    Czy moze ktos jest w posiadaniu fragmetu kodu asemblera ktory oblicza tą wartość, bądż też potrafi napisać taka procedure. Byłbym bardzo wdzięczny.

    Pozdrawiam
  • #3 3053835
    Bigfoot
    Poziom 25  
    Posty: 982
    Pomógł: 74
    Ocena: 13
    W C zrobisz to tak:
    
    
    for(i=0; i<(Size-1); i++)
            {
                    CRC16 = Tabela[(CRC16 ^ (Buffer[i])) & 0x00FF] ^ ((CRC16 & 0xFF00) >> 8);
            }
    
    
    a Tabela zdefiniowana jest tak:
    
    
    unsigned int Tabela[] = {
      0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,
      0xC741,0x0500,0xC5C1,0xC481,0x0440,0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,
      0xCE81,0x0E40,0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,0xD801,
      0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,
      0xDD01,0x1DC0,0x1C80,0xDC41,0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,
      0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,0xF001,0x30C0,
      0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,
      0x35C0,0x3480,0xF441,0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
      0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,0x2800,0xE8C1,0xE981,
      0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,
      0xEC81,0x2C40,0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,0x2200,
      0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,0xA001,0x60C0,0x6180,0xA141,
      0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,
      0xA441,0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,
      0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,0x7800,0xB8C1,0xB981,0x7940,0xBB01,
      0x7BC0,0x7A80,0xBA41,0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
      0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,0x7200,0xB2C1,0xB381,
      0x7340,0xB101,0x71C0,0x7080,0xB041,0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,
      0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,0x9C01,
      0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,
      0x9901,0x59C0,0x5880,0x9841,0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,
      0x4A40,0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,0x4400,0x84C1,
      0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,
      0x81C1,0x8081,0x4040
    
    };
    
    


    Powyzszy sposob liczenia CRC16 jest sposobem bardziej pamieciozernym (pamiec programu) ale szybszym niz sposoby inne. Jesli potrzebujesz sposob drugi (wolniejszy):

    
    
     for(i=0; i<(Size-1); i++)
                 slowCRC(Buffer[i]);
    
    
    gdzie:
    
    unsigned slowCRC(char c)
    {
       int i,j;
    
       for(i=0;i!=8;c>>=1,i++)
       {
          j=(c^CRC)&1;
          CRC>>=1;
    
          if(j)
             CRC^=0xa001;
       }
       return CRC;
    }
    


    Poczatkowa wartosc C powina byc ustawiona na 0.

    BF
  • #4 3054078
    Kylan
    Poziom 2  
    Posty: 4
    Dziękuje za szybką odpowiedz :)
    Niestety program musi byc wykonany w asemblerze, wiec nie moge skorzystac z procedury w jezyku C. Mialem za mala stycznosc z tym jezykiem programowania a wiec nie potrafie nic w nim zaprogramowac. Ale dziekuje za procedure.
    Udało sie napisac program liczacy wartosc CRC-16 ale tylko zawartości akumulatora.
    Cytat:

    mov crc_lo,#0
    mov crc_hi,#0

    mov a,#190 ;przykladowa wartosc ktorej crc oblicza

    crc16:

    mov b, #08h

    crc_get_bit:

    rrc a
    push acc
    jc crc_in_1
    mov c, crc_lo.0
    sjmp crc_cont

    crc_in_1:

    mov c, crc_lo.0
    cpl c

    crc_cont:
    jnc crc_shift
    cpl crc_hi.6
    cpl crc_lo.1

    crc_shift:
    mov a, crc_hi
    rrc a
    mov crc_hi, a
    mov a, crc_lo
    rrc a
    mov crc_lo, a
    pop acc
    djnz b, crc_get_bit

    mov dph,crc_hi
    mov dpl,crc_lo

    lcall newline ; wyswietlenie CRC na monitorze
    lcall pHex16 ; dla tej wartosci jest to 8070
    lcall newline


    Moje zadanie polega na zapisaniu pliku do pamieci RAM i obliczenie jego wartosci CRC. Powiedzmy ze blok danych ktorych CRC chce obliczyc zajmuje w pamieci zewnterznej RAM obszar od komorki 8200h do 8500h. Co nalezy zmodyfikowac w moim tym fragmecie programu aby dzialal poprawnie?
  • #5 3054596
    Bigfoot
    Poziom 25  
    Posty: 982
    Pomógł: 74
    Ocena: 13
    Liczysz CRC16 dla komorki 8200h otrzymujac powiedzmy x. Nastepnie liczysz CRC16 dla komorki 8201h wykorzystujac wartosc z poprzedniego kroku (ten x) i tak w kolko az do komorki ostatniej.
    Z pamieci zewnetrznej RAM poierasz najnormalniej w swiecie za pomoca movx. Jesli chcesz moge umiescici programik exe pod windowsa do liczenia CRC16 abys mogl sprawdzic czy liczysz dobrze.

    BF
  • #6 3055742
    Kylan
    Poziom 2  
    Posty: 4
    Przyznam sie ze troszke nie rozumie, czy to znaczy ze po obliczeniu wartosci CRC drugiej komórki mam odjac ta wartość
    movx a,@dptr
    subb a,crc_hi
    mov crc_hi,a

    movx a,@dptr
    subb a,crc_lo
    mov crc_lo,a

    czy tez do kolejnych obliczen mam uzyc:

    mov crc_hi,dph
    mov crc_lo, dpl

    Jestem laikiem w dziedzinie programowania, stad moje pytania.
    Wiem ze to moze zbyt nachalne z mojej strony ale czy moglbys napisac fragment programu ktory by realizowal ta procedure? Dokladniej to co powinno sie znalesc za fragmetem napisanym przeze mnie.

    Jezeli mozesz to wstaw ten plik, udalo mi sie znalesc tylko programy liczace crc32.
  • Pomocny post
    #7 3058244
    Dyrek
    Poziom 16  
    Posty: 129
    Pomógł: 21
    Ocena: 1
    Poniżej przedstawiam działającą procedurkę jaką sobie napisałem do obliczania CRC16 w komunikacji po ModBusie z falownikami. Nie wiem tylko pojęcia czy algorytm obliczania dla ModBus jest jednakowy np z tym dla czujników dallasa z 1-wire ale CRC to CRC :)

    ;crcl, crch - zmienne zdefiniowane w wewnętrznej RAM
    
    
    ;-----obliczanie CRC16----r0, r1, acc----
    crc16:
    	mov	dpl,#młodszy_bajt_adresu_początkowego
    	mov	dph,#starszy_bajt_adresu_początkowego
    
    	mov	crcl,#0ffh
    	mov	crch,#0ffh
    wylicz2:
    	movx	a,@dptr
    	xrl	crcl,a
    	mov	r5,#8
    wylicz:
    
    ;przesunięcie bitowe w prawo całego słowa CRC
    	mov	a,crch
    	clr	c
    	rrc	a
    	mov	crch,a
    	mov	a,crcl
    	rrc	a
    	mov	crcl,a
    
    	jnc	indeks
    ;jeśli "wyłuskany" bit w C ustawiony to XOR CRC ze stałą
    	xrl	crcl,#1
    	xrl	crch,#10100000b
    indeks:
    	djnz	r5,wylicz		;powtórzyć 8 razy dla każdej danej
    	inc	dptr
    	mov	a,dpl
    	cjne	a,#adres,wylicz2	;tu wpisać młodszy bajt adresu ostatniej danej 
    	mov	a,dph
    	cjne	a,#adres,wylicz2	;tu wpisać starszy bajt adresu ostatniej danej 
    	ret
    ;-------------------------------------
  • #8 17161951
    Kylan
    Poziom 2  
    Posty: 4
    Temat już dawno zakończony.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu napisania procedury w asemblerze dla mikrokontrolera kompatybilnego z 8051, która oblicza wartość CRC (CRC-16) dla fragmentu danych zapisanych w zewnętrznej pamięci RAM. Autor przesyła plik przez RS-232 do pamięci zewnętrznej i potrzebuje obliczyć CRC dla zakresu adresów, np. od 8200h do 8500h. W odpowiedziach podano linki do bibliotek i teorii CRC oraz przykładowy kod w języku C wykorzystujący tablicę do obliczeń CRC16. Autor wyjaśnił, że potrzebuje rozwiązania w asemblerze, gdyż nie zna dobrze języka C. Wskazano, że obliczanie CRC polega na iteracyjnym przetwarzaniu kolejnych bajtów pamięci z użyciem instrukcji movx do odczytu danych z pamięci zewnętrznej. Zaproponowano podejście, gdzie wynik CRC jest aktualizowany po każdym bajcie. Jeden z użytkowników udostępnił fragment działającej procedury asemblerowej do obliczania CRC16, stosowanej w komunikacji ModBus, z wykorzystaniem rejestrów i przesunięć bitowych oraz operacji XOR, co może być adaptowane do innych zastosowań. Temat został ostatecznie zamknięty przez autora.
Wygenerowane przez model językowy.
REKLAMA