|
|
View previous topic :: View next topic |
Author |
Message |
elogicca
Joined: 09 Dec 2006 Posts: 2
|
Modbus over usb |
Posted: Wed Sep 12, 2007 5:12 pm |
|
|
Trying to figure this out, incoming is fine but on outgoing my crc is apparently wrong... the sample only contains holding regs
[code]
#include <18F4455.h>
#device adc=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#define MODBUS_SERIAL_RX_BUFFER_SIZE 32
#define MODBUS_OUR_ADDRESS 1
#include<usb_cdc.h>
int1 modbus_serial_new=0;
int8 data_buf[MODBUS_SERIAL_RX_BUFFER_SIZE];
const int8 modbus_serial_wait=50;
enum {MODBUS_GETSLAVE, MODBUS_GETFUNC, MODBUS_GETADDRESS_HIGH,MODBUS_GETADDRESS_LOW,MODBUS_GETQTY_HIGH,MODBUS_GETQTY_LOW, MODBUS_GETDATA, MODBUS_DONE}
modbus_serial_state = 0;
struct
{
int8 slave;
int8 address_high;
int8 address_low;
int8 qty_high;
int8 qty_low;
int16 qty;
int8 len; //number of bytes in the message received
int8 func; //the function of the message received
int8 data[MODBUS_SERIAL_RX_BUFFER_SIZE]; //data of the message received
} modbus_rx;
int16 modbus_serial_crc;
void response(void);
void Clear_Incoming_Buffer(void)
{
while(usb_cdc_kbhit())
{
usb_cdc_getc();
}
}
void Calc_CRC(int8 data)
{
int16 crc;
int16 x;
x = make8(modbus_serial_crc,1) ^ data;
x ^= x>>4;
crc = (modbus_serial_crc << 8) ^ (x << 12) ^ (x <<5) ^ x;
crc &= 0xffff;
modbus_serial_crc = crc;
}
void modbus_serial_putc(int8 c)
{
usb_cdc_putc(c);
Calc_CRC(c);
delay_us(4000);
}
void MODBUS_ENABLE_TIMEOUT(int1 enable)
{
disable_interrupts(INT_TIMER2);
if (enable)
{
set_timer2(0);
clear_interrupt(INT_TIMER2);
enable_interrupts(INT_TIMER2);
}
}
#int_timer2
void modbus_timeout_now(void)
{
if((modbus_serial_state == MODBUS_GETDATA) && (modbus_serial_crc == 0x0000) && (!modbus_serial_new))
{
modbus_rx.len-=2;
modbus_serial_new=TRUE;
}
else
{
modbus_serial_new=FALSE;
modbus_serial_crc = 0xFFFF;
modbus_serial_state=MODBUS_GETSLAVE;
MODBUS_ENABLE_TIMEOUT(FALSE);
response();
}
}
void modbus_send(int8 to, int8 func, int8* data, int8 len)
{
int8 i;
int8 crc_low, crc_high;
modbus_serial_crc =0xFFFF;
modbus_serial_new=FALSE;
Clear_Incoming_Buffer();
delay_us(4000);
modbus_serial_putc(to);
modbus_serial_putc(func);
modbus_serial_putc(len);
for (i=0;i<len;i++)
{
modbus_serial_putc(*data);
data++;
}
crc_high = make8(modbus_serial_crc,1);
crc_low = make8(modbus_serial_crc,0);
modbus_serial_putc(crc_high);
modbus_serial_putc(crc_low);
delay_us(4000);
}
void read_holding_registers_rsp(int8 address, int8 register_count, int8 *reg_data)
{
int8 i;
for(i=0; i < register_count; i++)
{
data_buf[i] = *reg_data;
reg_data++;
}
modbus_send(address, 0x03, &(data_buf[0]), register_count);
}
void response()
{
int8 PendantStatus[4];
switch(modbus_rx.func)
{
case 0x01:
break;
case 0x02:
break;
case 0x03:
PendantStatus[0] = 0x10;
PendantStatus[1] = 0x01;
read_holding_registers_rsp(MODBUS_OUR_ADDRESS,modbus_rx.qty,&(PendantStatus[0]));
break;
case 0x04:
break;
case 0x05:
break;
case 0x06:
break;
case 0x07:
break;
case 0x08:
break;
case 0x10:
break;
case 0x11:
break;
}
}
void getusbdata()
{
char c;
c=usb_cdc_getc();
if (!modbus_serial_new)
{
if(modbus_serial_state == MODBUS_GETSLAVE)
{
modbus_serial_crc = 0xFFFF;
modbus_rx.slave = c;
modbus_serial_state++;
modbus_rx.len = 0;
}
else if(modbus_serial_state == MODBUS_GETFUNC)
{
modbus_rx.func = c;
modbus_serial_state++;
}
else if(modbus_serial_state == MODBUS_GETADDRESS_HIGH)
{
modbus_rx.address_high = c;
modbus_serial_state++;
}
else if(modbus_serial_state == MODBUS_GETADDRESS_LOW)
{
modbus_rx.address_low = c;
modbus_serial_state++;
}
else if(modbus_serial_state == MODBUS_GETQTY_HIGH)
{
modbus_rx.qty_high = c;
modbus_serial_state++;
}
else if(modbus_serial_state == MODBUS_GETQTY_LOW)
{
modbus_rx.qty_low = c;
modbus_rx.qty = make16(modbus_rx.qty_high,modbus_rx.qty_low);
modbus_serial_state++;
}
else if(modbus_serial_state == MODBUS_GETDATA)
{
if (modbus_rx.len>=MODBUS_SERIAL_RX_BUFFER_SIZE) {modbus_rx.len=MODBUS_SERIAL_RX_BUFFER_SIZE-1;}
modbus_rx.data[modbus_rx.len]=c;
modbus_rx.len++;
}
Calc_CRC(c);
MODBUS_ENABLE_TIMEOUT(TRUE);
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,249,5);
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}
Clear_Incoming_Buffer();
for(;;)
{
usb_task();
if (usb_enumerated())
{
if(usb_cdc_kbhit())
{
getusbdata();
}
}
}
}
[/code]
any suggestions? |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Wed Sep 12, 2007 10:16 pm |
|
|
This might help.
Its not based on a USB connection but it does meet MODBUS specs for a few functions and it compiles well.
This is a good document to develop from.
At a quick glance I saw several things that are a problem in the code you posted.
I don't think your CRC formula is right. Modicon Modbus Protocol Reference Guide PI–MBUS–300 Rev. J page 112 has an example of the bit shift method.
MODBUS and CCS do not store Int16 variables in the same byte order. When decoding and encoding packets the byte order needs to be swapped when coping registers. |
|
|
Guest
|
|
Posted: Thu Sep 13, 2007 8:23 am |
|
|
Ok so it's running now, i accept and process the holding regs crc chechs ok, input data is 010300000001840A
so slave 1 function 3 address 0000 count 0001, the response sent back is 01030100f048 so slave 1 function 3 1 count 00 data and chksum, the chksums ae correct but i get a response back invalid checksum...... fom the master
Code: | #include <18F4455.h>
#device adc=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#define MODBUS_BUFFER_SIZE 32
#define MODBUS_OUR_ADDRESS 1
#include<usb_cdc.h>
int1 modbus_sending=0;
int1 modbus_serial_new=0;
int8 data_buf[MODBUS_BUFFER_SIZE];
int16 modbus_serial_crc;
/* Table of CRC values for high–order byte */
const char modbus_auchCRCHi[] = {
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 char modbus_auchCRCLo[] = {
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
};
enum
{
MODBUS_GETSLAVE,
MODBUS_GETFUNC,
MODBUS_GETADDRESS_HIGH,
MODBUS_GETADDRESS_LOW,
MODBUS_GETQTY_HIGH,
MODBUS_GETQTY_LOW,
MODBUS_GETDATA,
MODBUS_DONE
}
modbus_serial_state = 0;
struct
{
int8 slave;
int8 address;
int16 qty;
int8 len; //number of bytes in the message received
int8 func; //the function of the message received
int8 data[MODBUS_BUFFER_SIZE]; //data of the message received
}
modbus_rx;
void response(void);
void Calc_CRC(int8 data)
{
int8 uIndex ; // will index into CRC lookup table
int8 t1;
int8 t2;
t1 = make8(modbus_serial_crc,0);
t2 = make8(modbus_serial_crc,1);
uIndex = t2 ^ data; // calculate the CRC
t2 = t1 ^ modbus_auchCRCHi[uIndex];
t1 = modbus_auchCRCLo[uIndex];
modbus_serial_crc = make16(t2,t1);
}
void modbus_serial_putc(int8 c)
{
usb_cdc_putc(c);
Calc_CRC(c);
delay_us(780);
}
void MODBUS_ENABLE_TIMEOUT(int1 enable)
{
disable_interrupts(INT_TIMER2);
if (enable)
{
set_timer2(0);
clear_interrupt(INT_TIMER2);
enable_interrupts(INT_TIMER2);
}
}
void modbus_send(int8 to, int8 func, int8* data, int8 len)
{
int8 i;
int8 crc_low, crc_high;
modbus_serial_crc =0xFFFF;
modbus_serial_new=FALSE;
modbus_serial_putc(to);
modbus_serial_putc(func);
modbus_serial_putc(len);
for (i=0;i<len;i++)
{
modbus_serial_putc(*data);
data++;
}
crc_low = make8(modbus_serial_crc,0);
usb_cdc_putc(crc_low);
delay_us(780);
crc_high = make8(modbus_serial_crc,1);
usb_cdc_putc(crc_high);
delay_us(780);
delay_us(2320);
}
void read_holding_registers_rsp(int8 address, int8 register_count, int8 *reg_data)
{
int8 i;
for(i=0; i <register_count>=MODBUS_BUFFER_SIZE) {modbus_rx.len=MODBUS_BUFFER_SIZE-1;}
modbus_rx.data[modbus_rx.len]=c;
modbus_rx.len++;
}
Calc_CRC(c);
MODBUS_ENABLE_TIMEOUT(TRUE);
}
}
#int_timer2
void modbus_timeout_now(void)
{
if((modbus_serial_state == MODBUS_GETDATA) && (modbus_serial_crc == 0x0000) && (!modbus_serial_new) && (!modbus_sending))
{
modbus_rx.len-=2;
modbus_serial_new=FALSE;
modbus_serial_crc = 0xFFFF;
modbus_serial_state=MODBUS_GETSLAVE;
response();
}
else if(!modbus_sending)
{
modbus_serial_new=FALSE;
modbus_serial_crc = 0xFFFF;
modbus_serial_state=MODBUS_GETSLAVE;
MODBUS_ENABLE_TIMEOUT(FALSE);
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,200,5);
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}
for(;;)
{
usb_task();
if (usb_enumerated())
{
if(usb_cdc_kbhit() && !modbus_sending)
{
getusbdata();
}
}
}
} |
|
|
|
|
|
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
|