![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
CRC_calculate Help... |
Posted: Sat Sep 25, 2010 5:09 pm |
|
|
Hi Developers..
I've problem with calculation of specific CRC. I'll put simple test program for calculating CRC with example packet (data).
Code: | ////////////////////////////////////////////////////////////////////////////////////////////
#include <16F628A.h> //
#device *=16 //
#fuses HS, NOWDT,PROTECT,BROWNOUT,PUT,NOLVP,MCLR ///////////////////////////////////////////
#use delay(clock=10 000 000) //
#use rs232(baud=9600,rcv=PIN_B1,xmit=PIN_B2,errors,enable=PIN_B3,STREAM=rs_485) //
//
////////////////////////////////////////////////////////////////////////////////////////////
char buffer_485_tx []={0xF2,0x94,0x02,0x00,0x37,0x38,0x30,0x30,0x30,0x33,0x32,0x30,0x36,0x31};
char pc_crc_tx ()
{
unsigned int16 hlp;
int1 cary;
int byte_counter;
char CHEKSUM=0x00;
printf ("START CRC CALC\n\r");
for (byte_counter=0;byte_counter<=13;byte_counter++)
{
printf ("For byte No:******************************* %d \n\r",byte_counter);
printf ("INPUT_BYTE %X\n\r",buffer_485_tx[byte_counter]);
printf ("CHEKSUM: %X\n\r",CHEKSUM);
printf ("HLP: %4X\n\r",hlp);
//////////////////////////////////////////////////////////////////
hlp = buffer_485_tx[byte_counter] + CHEKSUM;
printf ("HLP_0: %4X\n\r",hlp);
if (hlp > 0xFF)
{
cary = 1;
}else cary=0;
printf ("Cary___________1: %d\n\r",cary);
hlp=hlp & 0xFF;
printf ("HLP_1: %4X\n\r",hlp);
hlp=hlp+hlp;
printf ("HLP_2: %4X\n\r",hlp);
if (cary)
{
hlp++;
}
printf ("HLP_3: %4X\n\r",hlp);
if(hlp>0xFF)
{
cary=1;
}else cary=0;
printf ("Cary___________2: %d\n\r",cary);
hlp=hlp & 0xFF;
printf ("HLP_4: %4X\n\r",hlp);
if (!cary)
{
hlp=hlp ^ 0xDD;
}
printf ("HLP_5: %4X\n\r",hlp);
if (hlp >=0xE0)
{
hlp=hlp-0xE0;
}
printf ("HLP_6: %4X\n\r",hlp);
CHEKSUM = hlp;
// fputc (CHEKSUM,rs_485);
}
printf ("CRC_byte_LAST: %X\n\r",CHEKSUM);
return CHEKSUM;
}
void main (){
while (TRUE)
{
delay_ms(1000);
pc_crc_tx ();
delay_ms(1000);
}
}
|
The Calculated CRC is 0x18, but it's Wrong. Correct CRC is 0x12.
Also I make test program with Visual C++ and Source work with little change of data type.
Any idea...??
Thanks before:) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Sep 25, 2010 9:54 pm |
|
|
Quote: | Also I make test program with Visual C++. |
Did you get the algorithm from the internet ? If so, post a link to a
working version of the code that is written in C (not C++). |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Sun Sep 26, 2010 12:17 am |
|
|
PCM programmer wrote: | Quote: | Also I make test program with Visual C++. |
Did you get the algorithm from the internet ? If so, post a link to a
working version of the code that is written in C (not C++). |
Hi PCM:) I got the algorithm from Delphi working code. Also I've assembler code for 8086 CPU...
Code: |
ADDCHECK: PUSH AX
ADD AL,CHECKSUM
RCL AL,1
JC ADCK3
XOR AL,11011101b
ADCK3: MOV CHECKSUM,AL
SUB AL,224
JC ADCK4
MOV CHECKSUM,AL
ADCK4: POP AX
RET
|
My Compiler version is v.4.104 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Sep 26, 2010 5:24 pm |
|
|
For me, it's far easier to translate the Intel x86 ASM code into PIC ASM
than to try to convert it to C, so that's what I did below. I also cleaned
up your function interface. I created a function called get_checksum()
with accepts a pointer to an array of bytes and also the size of the array,
and then it calculates the checksum on that array and returns the result.
Now, unlike your code, it's a self-contained function. You give it
parameters and it gives you a result.
Running it in MPLAB simulator with compiler vs. 4.112 gives 0x12, which
you said is the expected result, so it's probably working.
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
char buffer_485_tx[]={0xF2,0x94,0x02,0x00,0x37,0x38,0x30,0x30,0x30,0x33,0x32,0x30,0x36,0x31};
int8 get_checksum(int8 *buffer, int8 bufsize)
{
int8 i;
int8 AL;
int8 checksum;
if(bufsize == 0) // Safety check. Is the count = 0 ?
return(0); // Just return if so
checksum = 0;
for(i = 0; i < bufsize; i++)
{
AL = buffer[i];
#asm
; ADD AL,CHECKSUM // Add checksum to AL, update Cy
movf checksum, W
addwf AL,F
; RCL AL,1 // Rotate AL left, thru Cy
rlcf AL,F
; JC ADCK3 // Jump on Cy to ADCK3
bc ADCK3
; XOR AL,11011101b // XOR AL with 0xDD
movlw 0xDD
xorwf AL,F
ADCK3:
; MOV CHECKSUM,AL // Put AL in Checksum
movff AL,checksum
; MOV CHECKSUM,AL // Put AL in Checksum
; SUB AL,224
movlw 224
subwf AL,F
; JC ADCK4
bnc ADCK4 // Cy is opposite with subwf so use bnc
; MOV CHECKSUM,AL // Put AL in Checksum
movff AL, checksum
ADCK4:
#endasm
}
return(checksum);
}
/*
// Original x86 source code
ADDCHECK:
PUSH AX
ADD AL,CHECKSUM // Add Checksum to AL, update Cy
RCL AL,1 // Rotate AL left, thru Cy
JC ADCK3 // Jump on Cy to ADCK3
XOR AL,11011101b // XOR AL with 0xDD
ADCK3:
MOV CHECKSUM,AL // Put AL in Checksum
SUB AL,224
JC ADCK4
MOV CHECKSUM,AL
ADCK4:
POP AX
RET
*/
//======================================
void main()
{
int8 result;
result = get_checksum(buffer_485_tx, sizeof(buffer_485_tx));
printf("Checksum = %x\r", result);
while(1);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Sep 27, 2010 4:39 am |
|
|
PCM programmer wrote: | For me, it's far easier to translate the Intel x86 ASM code into PIC ASM
than to try to convert it to C, so that's what I did below. I also cleaned
up your function interface. I created a function called get_checksum()
with accepts a pointer to an array of bytes and also the size of the array,
and then it calculates the checksum on that array and returns the result.
Now, unlike your code, it's a self-contained function. You give it
parameters and it gives you a result.
Running it in MPLAB simulator with compiler vs. 4.112 gives 0x12, which
you said is the expected result, so it's probably working.
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
char buffer_485_tx[]={0xF2,0x94,0x02,0x00,0x37,0x38,0x30,0x30,0x30,0x33,0x32,0x30,0x36,0x31};
int8 get_checksum(int8 *buffer, int8 bufsize)
{
int8 i;
int8 AL;
int8 checksum;
if(bufsize == 0) // Safety check. Is the count = 0 ?
return(0); // Just return if so
checksum = 0;
for(i = 0; i < bufsize; i++)
{
AL = buffer[i];
#asm
; ADD AL,CHECKSUM // Add checksum to AL, update Cy
movf checksum, W
addwf AL,F
; RCL AL,1 // Rotate AL left, thru Cy
rlcf AL,F
; JC ADCK3 // Jump on Cy to ADCK3
bc ADCK3
; XOR AL,11011101b // XOR AL with 0xDD
movlw 0xDD
xorwf AL,F
ADCK3:
; MOV CHECKSUM,AL // Put AL in Checksum
movff AL,checksum
; MOV CHECKSUM,AL // Put AL in Checksum
; SUB AL,224
movlw 224
subwf AL,F
; JC ADCK4
bnc ADCK4 // Cy is opposite with subwf so use bnc
; MOV CHECKSUM,AL // Put AL in Checksum
movff AL, checksum
ADCK4:
#endasm
}
return(checksum);
}
/*
// Original x86 source code
ADDCHECK:
PUSH AX
ADD AL,CHECKSUM // Add Checksum to AL, update Cy
RCL AL,1 // Rotate AL left, thru Cy
JC ADCK3 // Jump on Cy to ADCK3
XOR AL,11011101b // XOR AL with 0xDD
ADCK3:
MOV CHECKSUM,AL // Put AL in Checksum
SUB AL,224
JC ADCK4
MOV CHECKSUM,AL
ADCK4:
POP AX
RET
*/
//======================================
void main()
{
int8 result;
result = get_checksum(buffer_485_tx, sizeof(buffer_485_tx));
printf("Checksum = %x\r", result);
while(1);
}
|
| Thanks again . PCM , but it dosn't work with PCM devices (14bit Parts), and return error from compilations "rlcf AL,F--->Expecting an opcode mnemonic" |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Mon Sep 27, 2010 4:53 am |
|
|
Just change RLCF to RLF.
On the PIC16, the only rotation does it through the carry, so there is just one instruction (fortunately the one we want!). On the PIC18's, other versions were added, so the instruction became 'RLCF' to say 'through the carry'.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Sep 27, 2010 5:18 am |
|
|
Ttelmah wrote: | Just change RLCF to RLF.
On the PIC16, the only rotation does it through the carry, so there is just one instruction (fortunately the one we want!). On the PIC18's, other versions were added, so the instruction became 'RLCF' to say 'through the carry'.
Best Wishes |
Hi Ttelmah
I saw this , but have other ASM different instruction set ..
I have err on line : "bc ADCK3" What is "bc"?? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Mon Sep 27, 2010 7:05 am |
|
|
Branch if carry. Jumps to ADCK3, if the carry bit is set.
On the PIC16, this has to be done as:
#byte STATUS=3
Then in the assembler:
BTFSC STATUS,0
GOTO ADCK3
So you test the 'carry' bit in the status register, and if it is 'set' (carry), then execute the next instruction, which is the jump to ADCK3, otherwise skip this.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Mon Sep 27, 2010 7:26 am |
|
|
Ttelmah wrote: | Branch if carry. Jumps to ADCK3, if the carry bit is set.
On the PIC16, this has to be done as:
#byte STATUS=3
Then in the assembler:
BTFSC STATUS,0
GOTO ADCK3
So you test the 'carry' bit in the status register, and if it is 'set' (carry), then execute the next instruction, which is the jump to ADCK3, otherwise skip this.
Best Wishes |
Hi Ttelmah I made up this for BC --> BTFSC 3,0
goto ADCK3
and for bnc --> BTFSS 3,0
goto ADCK4
but still have a errors and diferent from MOVFF instruction
![Question](images/smiles/icon_question.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Mon Sep 27, 2010 9:09 am |
|
|
To 'put you out of your misery', I have done what PCM didn't want to, and changed the routine into C.
Code: |
int8 get_checksum(int8 *buffer, int8 bufsize) {
int8 i;
int16 AL;
int8 checksum,temp;
int1 carry;
if(bufsize == 0) // Safety check. Is the count = 0 ?
return(0); // Just return if so
checksum = 0;
for(i = 0; i < bufsize; i++) {
AL = buffer[i];
AL+=checksum;
if (AL & 0x100)
//Here have carry, so rotate one into the byte
carry=shift_left(&AL,1,1);
else
//Else zero
carry=shift_left(&AL,1,0);
//Carry is now the bit that came out the bottom
if (carry==0)
AL^=0xDD;
temp=make8(AL,0); //Get LSB
if (temp<224)
checksum=temp;
else
checksum=temp-224;
}
return checksum;
}
|
I think this is 'right', and should work identically with PIC16 or PIC18 chips.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
kmp84
Joined: 02 Feb 2010 Posts: 345
|
|
Posted: Tue Sep 28, 2010 9:04 am |
|
|
Hi Ttelmah ! Thanks for your help. Your 'C' CRC calc. routine work. I've never done programing in assembler, but with little reading data sheet - PIC instruction set summary and your help this also work:
Code: |
int8 get_checksum(int8 *buffer, int8 bufsize)
{
int8 i;
int8 AL;
int8 checksum;
//#byte STATUS=3
if(bufsize == 0) // Safety check. Is the count = 0 ?
return(0); // Just return if so
checksum = 0;
for(i = 0; i < bufsize; i++)
{
AL = buffer[i];
#asm
movf checksum, W
addwf AL,F
rlf AL,F
BTFSC 3,0
goto ADCK3
movlw 0xDD
xorwf AL,F
ADCK3:
movf AL ,W
movwf checksum
movlw 224
subwf AL,F //demo
BTFSS 3,0
goto ADCK4
movf AL,W
movwf checksum
ADCK4:
#endasm
}
return(checksum);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|