|
Tài trợ cho PIC Vietnam |
Giao tiếp USB, CAN, I2C, SPI, USART... Những giao tiếp được tích hợp trên PIC |
|
Ðiều Chỉnh | Xếp Bài |
|
26-04-2012, 02:49 PM | #1 |
Đệ tử 6 túi
Tham gia ngày: Feb 2009
Bài gửi: 127
: |
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 ạ |
26-04-2012, 02:50 PM | #2 |
Đệ tử 6 túi
Tham gia ngày: Feb 2009
Bài gửi: 127
: |
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); } |
25-11-2012, 02:02 AM | #3 |
Nhập môn đệ tử
Tham gia ngày: Mar 2010
Bài gửi: 5
: |
không ai trả lời cả!
|
01-02-2015, 10:43 PM | #4 |
Nhập môn đệ tử
Tham gia ngày: Jun 2012
Bài gửi: 3
: |
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; |
|
|