PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Giao tiếp USB, CAN, I2C, SPI, USART... (http://www.picvietnam.com/forum/forumdisplay.php?f=45)
-   -   modbus RTU với pic cần giúp đỡ (http://www.picvietnam.com/forum/showthread.php?t=16123)

hoc_picpicpic 26-04-2012 02:49 PM

modbus RTU với pic cần giúp đỡ
 
chào các huynh, em viết chương trình modbus RTU slave trên pic16f877a nhưng crc gửi đi ko đúng, em có tham khảo cách tính crc trong tài liệu http://forums.ni.com/attachments/ni/...I_MBUS_300.pdf .

huynh nao làm rồi giúp em xem sai ở đâu.

trình tự em test như sau :


Modbus Master send:

0x01 address Slave
0x04 function 4
0x00 address start byte hight
0x01 address start byte low
0x00
0x04 quantity
0xA0 crc hight
0x09 crc low



Modbus Sleve Respond: (pic16f877a)

01 04 08 00 00 00 00 00 00 00 00 40 0B


huynh nào có cách tính crc khác chỉ giúp em với ạ

hoc_picpicpic 26-04-2012 02:50 PM

còn đây là chương trình:


#include <16F877A.h>
#fuses HS, NOWDT ,PROTECT ,NOBROWNOUT ,NOPUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7,bits=8, stop=2, parity=N)





int1 modbus_flag_status;

int8 modbus_index = 0;
int8 modbus_data_transmit[10];
int8 modbus_data_reciever[10];

//---------------------------------------
int16 modbus_calcu_crc(int8 *puchMsg, int16 usDataLen);
//---------------------------------------
void main()
{
int8 i ;
int8 quantity ;
int16 modbus_crc ;


enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

for(i=0;i<10;i++ )
{
modbus_data_transmit[i] = 0;
};


while(TRUE)
{

if( modbus_flag_status == 1 ) // test function 4
{
modbus_flag_status = 0;


putchar( modbus_data_reciever[0]); // adress slave
putchar( modbus_data_reciever[1]); // function

quantity = modbus_data_reciever[5]*2 ;

putchar(quantity); // byte count

for(i=0;i<quantity;i++)
{
putchar( modbus_data_transmit[i] ); // data byte
};


modbus_crc = modbus_calcu_crc(modbus_data_transmit, quantity); // crc calculate

putchar( modbus_crc >> 8 ); // crc hight byte
putchar( modbus_crc); // crc low byte

};


}
}
//-----------------------------------------------------------
int16 modbus_calcu_crc(int8 *puchMsg, int16 usDataLen)
{


//---------------------------------------
/* Table of CRC values for high–order byte */
const unsigned char modbus_CRCHi[] = {
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00, 0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01, 0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80, 0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,
0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,
0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81, 0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,
0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00, 0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,
0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81, 0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,
0x40
};

/* Table of CRC values for low–order byte */
const unsigned char modbus_CRCLo[] = {
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06, 0x07,0xC7,0x05,0xC5,0xC4,
0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A, 0xCA,0xCB,0x0B,0xC9,0x09,
0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A, 0x1E,0xDE,0xDF,0x1F,0xDD,
0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16, 0xD6,0xD2,0x12,0x13,0xD3,
0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3, 0xF2,0x32,0x36,0xF6,0xF7,
0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF, 0x3F,0x3E,0xFE,0xFA,0x3A,
0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29, 0xEB,0x2B,0x2A,0xEA,0xEE,
0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25, 0xE5,0x27,0xE7,0xE6,0x26,
0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60, 0x61,0xA1,0x63,0xA3,0xA2,
0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C, 0xAC,0xAD,0x6D,0xAF,0x6F,
0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68, 0x78,0xB8,0xB9,0x79,0xBB,
0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC, 0x7C,0xB4,0x74,0x75,0xB5,
0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71, 0x70,0xB0,0x50,0x90,0x91,
0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55, 0x95,0x94,0x54,0x9C,0x5C,
0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B, 0x99,0x59,0x58,0x98,0x88,
0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F, 0x4F,0x8D,0x4D,0x4C,0x8C,
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42, 0x43,0x83,0x41,0x81,0x80,
0x40
};


int8 uchCRCHi, uchCRCLo ;
int16 uIndex ;
int16 i ;


uchCRCHi = 0xFF ;
uchCRCLo = 0xFF ;

for(i=0;i < usDataLen ;i++ )
{
uIndex = uchCRCHi ^ *puchMsg++ ;
uchCRCHi = uchCRCLo ^ modbus_CRCHi[uIndex];
uchCRCLo = modbus_CRCLo[uIndex] ;
};

i = uchCRCHi ;
i = (i<<8) | uchCRCLo ;


return(i);


}
//-----------------------------------------------------------
#INT_RDA
void interrupt_rs232(void)
{
char data ;

data = getchar();

modbus_data_reciever[modbus_index] = data;

modbus_index++ ;
if( modbus_index >= 8 )
{
modbus_flag_status = 1;
modbus_index = 0;

};

//putchar(data);


}

lovedt 25-11-2012 02:02 AM

không ai trả lời cả!

SLPRV 01-02-2015 10:43 PM

Có 1 ví dụ khi viết trên C#:
Với chuỗi "01 03 00 01 00 04". Ta khai báo 1 mảng byte mang[];
Hãy gán giá trị cho mảng như sau: mang[0] = Convert.ToByte("01",16) ....và tiếp tục với
các giá trị còn lại còn lại.
chuỗi truyền có 6 byte nên "len = 6";
Khi sử dụng thì hãy gọi hàm ModRTU_CRC(mang,len);


Code:

UInt16 ModRTU_CRC(byte[] buf, int len)
{
UInt16 crc = 0xFFFF;

for (int pos = 0; pos < len; pos++) {
crc ^= (UInt16)buf[pos]; // XOR byte into least sig. byte of crc

for (int i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
// Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
return crc;



Múi giờ GMT. Hiện tại là 05:00 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam