Отговори на тема  [ 8 мнения ] 
modbus crc16 mcu:pic16 
Автор Съобщение
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Авг 19, 2005 11:38 am
Мнения: 978
Местоположение: Europe -> BG
Мнение modbus crc16 mcu:pic16
Пиша си код за генериране за CRC16 за modbus и като цяло нищо сложно.
Даже за няма и 5мин написах кода, обаче нещо не се получава.

Цитат:

Generating a CRC

Step 1 Load a 16-bit register with FFFF hex (all 1's). Call this the CRC register.

Step 2 Exclusive OR the first eight-bit byte of the message with the low order byte of the 16-bit CRC register, putting the result in the CRC register.

Step 3 Shift the CRC register one bit to the right (toward the LSB), zerofilling the MSB. Extract and examine the LSB.

; Кой LSB да се чете , новият или този който "изпада" при преместването / shift-a ?

Step 4 If the LSB is 0, repeat Step 3 (another shift). If the LSB is 1, Exclusive OR the CRC register with the polynomial value A001 hex (1010 0000 0000 0001).

Step 5 Repeat Steps 3 and 4 until eight shifts have been performed. When this is done, a complete eight-bit byte will have been processed.

Step 6 Repeat Steps 2 ... 5 for the next eight-bit byte of the message. Continue doing this until all bytes have been processed.

Result The final contents of the CRC register is the CRC value.



_едит_

нарочно пиша тук след правилата веднага , и

значи изпълняват се 3-та стъпка след това 4-та и след това се брой , така го разбирам.
И относно кой LSB се проверява, това extract ме тегли повече към мисълта , че новият LSB се чете.
Кода на този вариант не съм го дал , ще го дам нарочно в нов пост, но пак не ми излизат стойностите, вярно близко

edit2: hmm дори и това ново разбиране обаче се оказва не както трябва

получавм C198 , вместо А194
а и не се връзва ... :-( защо е толкова двузначно написано е*ати.
кой shift-ваня се броят и кой не да му ***

_крайедит_


Код:

   ERRORLEVEL   -302

   LIST   p=PIC16F628A
   #include<p16f628a.inc>
   __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC & _LVP_OFF & _BODEN_OFF
   #define   RAMBASE 0x20

#define   RESET_VECTOR   0x000
#define   INT_VECTOR      0x004

   ORG   RESET_VECTOR
   goto   start
   ORG   INT_VECTOR

   goto   interrupt

   CBLOCK   RAMBASE

   CRC_HI, CRC_LO, CRC_SHIFTC

   ENDC

MODBUS_CRC_INIT MACRO

   movlw   0xFF
   movwf   CRC_HI
   movwf   CRC_LO

   ENDM

start:

   MODBUS_CRC_INIT

   movlw   0x0b
   call   modbus_crc16
   movlw   0x0f
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x01
   call   modbus_crc16

   goto   $

modbus_crc16:   

   xorwf   CRC_LO,F

   movlw   0x08
   movwf   CRC_SHIFTC   ; shiftcount

crc16_shift:

   bcf   STATUS,C
   rrf   CRC_HI,F
   rrf   CRC_LO,F
   
   decfsz   CRC_SHIFTC,F
   goto   crc16_continue
   return

crc16_continue:

   btfss   STATUS,C
   goto   crc16_shift
   
   movlw   0xA0
   xorwf   CRC_HI,F
   movlw   0x01
   xorwf   CRC_LO,F

   goto   crc16_shift
;
;

interrupt:

   return
;
;

   END



вярното CRC на горното е

CRC_LO = 94
CRC_HI = a1

а аз получавам

CRC_LO = EB
CRC_HI = 49

_________________
един факт :-)
Съжалявам , че исках да помогна ...


Нед Апр 30, 2006 1:29 pm
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Авг 19, 2005 11:38 am
Мнения: 978
Местоположение: Europe -> BG
Мнение 
http://www.embeddedrelated.com/groups/p ... w/4385.php

Код:

;-------------------------------------------------------------------------------------------------
;   ******************************  CRC16 routine  ******************************************
;-------------------------------------------------------------------------------------------------
;--CLASS REGISTERS-----------------------------------------------------------
;Temp1   
;CRC_High
;CRC_Low   
;----------------------------------------------------------------------------
CallAddCRC16M
  xorwf CRC_High,f
  movlw 8
  movwf Temp1

CRC_Loop
  bcf ALUSTA,C
  rrcf CRC_Low,f
  rrcf CRC_High,f
  btfss ALUSTA,C
  goto NoXOring
  movlw B'10100000'
  xorwf CRC_Low,f
  movlw B'0000001'
  xorwf CRC_High,f
NoXOring
  decfsz Temp1,F
   goto CRC_Loop
  return



близко съм бил ,ама с тея двузначни правила ...

едит2: просто гледам първият ми опит и разликата е , че след последният shift (8-мият не се прави една проверка на LSB и съответно се губи един евентуален XOR, поне така го виждам аз). крайедит2

едит:

Значи забелязва се къде е разковничето точно в интерпретацията на повторният shift ако LSB=0 и броенето все пак.

Не ме радва никак факта , че такива правила са написани така двузначно , вместо човек сам да си свърши работа, за да ги разбера трябваше да намеря готов код. Не ми хареса.

Код:
   ERRORLEVEL   -302

   LIST   p=PIC16F628A
   #include<p16f628a.inc>
   __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC & _LVP_OFF & _BODEN_OFF
   #define   RAMBASE 0x20

#define   RESET_VECTOR   0x000
#define   INT_VECTOR      0x004

   ORG   RESET_VECTOR
   goto   start
   ORG   INT_VECTOR
   goto   interrupt

   CBLOCK   RAMBASE

   CRC_HI, CRC_LO, CRC_SHIFTC

   ENDC

MODBUS_CRC_INIT MACRO

   movlw   0xFF
   movwf   CRC_HI
   movwf   CRC_LO

   ENDM

start:

   MODBUS_CRC_INIT

   movlw   0x0b
   call   modbus_crc16
   movlw   0x0f
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x00
   call   modbus_crc16
   movlw   0x01
   call   modbus_crc16

   goto   $

modbus_crc16:   

   xorwf   CRC_LO,F
   movlw   D'8'
   movwf   CRC_SHIFTC   ; shiftcount

crc16_shift:

   bcf   STATUS,C         ; zero the MSB
   rrf   CRC_HI,F         ; shift toward LSB
   rrf   CRC_LO,F         ; STATUS,C carry the bit frmo HI to LO

   btfss   STATUS,C      ; check LSB
   goto   crc16_end      ; if 0 -> shift again + MSB=0

   movlw   0xA0         ; if 1 -> CRC16 XOR 0xA001
   xorwf   CRC_HI,F
   movlw   0x01
   xorwf   CRC_LO,F

crc16_end:

   decfsz   CRC_SHIFTC,F
   goto   crc16_shift
   return
;
;

interrupt:

   return
;
;

   END



и всичко точно.

_________________
един факт :-)
Съжалявам , че исках да помогна ...


Нед Апр 30, 2006 10:14 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Яну 30, 2006 2:48 am
Мнения: 1248
Местоположение: София
Мнение 
Не разбирам, защо сте се втренчили в CRC. Никак не е удобно за реализация с процесор.
Модбъс има и ASCII вариант, и проверката за грешки се прави побайтово - LRC. Играчка работа.
CRC е измислен за хардуерна реализация и там върши работа наистина.


Пон Май 01, 2006 12:38 am
Профил WWW
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Авг 19, 2005 11:38 am
Мнения: 978
Местоположение: Europe -> BG
Мнение 
modbus като цяло е нещо ново за мен.
Чел съм една част от документацията на протокола и да ... има modbus RTU и modbus ASCII, обаче в моят случей се ползва RTU - това (1) . Правя master ;-)

(2) може и аз да съм се заблудил, но правилата при RTU ми се виждат по-прости, а защо ненужно да усложнявам.

При modbus ASCII всеки байт се праща с 2 байта - всяка 8бит стойност се представя в шестнайсетичният й вид чрез ASCII (ясно , че това го знаеш , но започвам мисъл :-))

1byte = 0xA1 -> 2bytes send 'A' '1'


- добавям още една задача към процесора да преобразува 8бит стойност в 2 ASCII.
отделянето на младшата и старшата тетрада не е проблема.

- генерирам двойно повече трафик.*

Не знам, но не виждам плюса :-?

Относно LRC - определено изглежда по-лесно за генериране и пак не знам дали Този + си заслужава.

Много Ви благодаря за включвате , ще го имам предвид , очевидно имате опит с Modbus.

* - сетих се и за това -> използвам двойно повече време , а знаем , че серийната комуникация е чуствителна към времената , т.е увеличавам времето през което мцу-то не може да прави друго, освен да се занимава с приемане изпращане. Не че в случея има такова нещо, но реших да го спомена.

_________________
един факт :-)
Съжалявам , че исках да помогна ...


Пон Май 01, 2006 9:46 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Яну 30, 2006 2:48 am
Мнения: 1248
Местоположение: София
Мнение 
В режим RTU даже и с UART-а ще имаш проблем - таймингите между байтовете са критични, тъй като основния рзделител между пакетите е по време.
CRC освен това ще ти харчи на порядък повече и памет и производителност. Ако и времето и ресрсите (процесора) са ограничени - дали заради 0х00 формата на данните си струва?


Пон Май 01, 2006 10:23 am
Профил WWW
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Авг 19, 2005 11:38 am
Мнения: 978
Местоположение: Europe -> BG
Мнение 
ОК. В случея при положение , че Slave у-вото е с RTU и да иска човек няма как да работи с ASCII ..., нали ?

Не виждам проблема с RTU и UART.
Master си подготовя запитването - всеки един от байтовете в съобщението и ги праща един след друг (т.е в момента , в който байт N е изпратен , се изпраща N+1 и така). Така че няма да се се достигне timeout ;-)
При получавне на отговора от страна на master-a се изисква само да слуша и евентуално да следи да не се получи timeout. Така че пак не виждам проблема с UART-a.

Относно CRC, LRC. Определено CRC е по-усложнено за изичсление - което ме подсеща ,че трябва да видя колко време отнема в най-лошият случей изчисляването за 1byte :-| Но пък 16бит стойност намалява вероятността за грешка до ...

Въпросът , който повдигаш е наистина интересен.

Доколкото те разбирам казваш, че генерирането на CRC на съобщението е повече или голяма част от време за 'преобразуването на всеки байт в два ASCII код числа за цялото съобщение + изчисляване на LRC'.

_________________
един факт :-)
Съжалявам , че исках да помогна ...


Пон Май 01, 2006 10:51 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Яну 30, 2006 2:48 am
Мнения: 1248
Местоположение: София
Мнение 
Ако Slave у-вото е с RTU и това не зависи от теб - наистина нямаш избор.
Ако по бавна линия ще пращаш големи масиви от данни (файлове?), и същевременно ще управляваш нещо в реално време - RTU е по-бързо (но само 2 пъти)
Във всички други случай RTU е по-зле на порядък (!10 пъти)


Пон Май 01, 2006 11:32 am
Профил WWW
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Пет Авг 19, 2005 11:38 am
Мнения: 978
Местоположение: Europe -> BG
Мнение 
1. У-вото е RTU.

2.Далеч съм от мисълта за файлове - просто данни (1bit access & 16bit access).
Линията е бавна - 9600bps (знам , че modbus дефинира 9600/19200 за серийна линия, а нагоре ако искаш имаше някои правила, за да се изчислят timeout закъсненията , но това не ме интересува; 9600 е скоростта)

Отделно още не мога да се представя какво е "файл" според Modbus. Май файл се ползва по-скоро като масив от данни, отколкото в смисъл на файл, но това е друга тема.

Случеят е този - бавна линия, през <1сек някъде ще се извлича информация с команди 01,02,03,04 за всички digital & analog i/o , които има Slave у-во; а Slave у-вото управлява в реално време.

Грубо(!) смятам , че имам да прочета около 50 байта.

Много благодаря за информацията относно ASCII ! Бях останал със съвсем друго впечатление :-)

едит: всъщност у-вата ще са няколко ~4 така че се получават ~200байта/сек полезна информация.

_________________
един факт :-)
Съжалявам , че исках да помогна ...


Пон Май 01, 2006 12:06 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 8 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни