CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Modbus over usb

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
elogicca



Joined: 09 Dec 2006
Posts: 2

View user's profile Send private message

Modbus over usb
PostPosted: Wed Sep 12, 2007 5:12 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Sep 12, 2007 10:16 pm     Reply with quote

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








PostPosted: Thu Sep 13, 2007 8:23 am     Reply with quote

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();
        }
      }
    }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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