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 support@ccsinfo.com

Is modbus working with new compiler [SOLVED]
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Is modbus working with new compiler [SOLVED]
PostPosted: Thu Aug 17, 2017 9:30 am     Reply with quote

HI All,

I had lost all access to the machine that I had to CCS, and all my projects including this forum.

Long story short, I was using a very old compiler Version 4ish. One of my friend offered me his laptop with CCS 5.ish to help me try complete my waterpump project before I fly to Canada. But to my surprise the existing working code that I had is not working with the new version.

Any additional steps that I need to do? or is it broken? Entire code that was working before is pasted below.

Code:

#include <16F727.h>
#device ADC=16
#use delay(internal=8000000)


#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_RX_PIN PIN_c7                    //Valid pin for serial receive               
#define MODBUS_SERIAL_TX_PIN PIN_c6                   //Valid pin for serial transmit     
#define MODBUS_SERIAL_ENABLE_PIN PIN_c0              //Valid pin for serial enable, rs485 only
#define MODBUS_SERIAL_RX_ENABLE PIN_c0              //Valid pin for serial rcv enable, rs485 only   
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA 
#define MODBUS_TIMER_USED MODBUS_TIMER_T2
#include "modbus.c"                   
#define MODBUS_ADDRESS 0x9


int8 swap_bits(int8 c)
{
   return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
          |((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}



void main() {

   int8 coils = 0b00000101;
   int8 inputs = 0b00001001;
   int16 hold_regs[] = {0x8800,0x7700,0x6600,0x5500,0x4400,0x3300,0x2200,0x1100};
   int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800};
   int16 event_count = 0;
   setup_adc_ports(NO_ANALOGS);
   enable_interrupts(GLOBAL);

   modbus_init();
   int8 i;
   for(i=0; i<8; i++) { hold_regs[i] = 0;} // initializing all zeros.
   while(TRUE){
      //TODO: User Code
     
      if( hold_Regs[7] == 1) {output_high(PIN_C2);} else {output_low(PIN_C2);}
           //modbus starts here //
     
         if(modbus_kbhit())
      {           
      //check address against our address, 0 is broadcast
      if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
      {
         switch(modbus_rx.func)
         {
            case FUNC_READ_COILS:    //read coils
            case FUNC_READ_DISCRETE_INPUT:    //read inputs
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int8 data;
                 
                  if(modbus_rx.func == FUNC_READ_COILS)
                     data = coils>>(modbus_rx.data[1]);      //move to the starting coil
                  else
                     data = inputs>>(modbus_rx.data[1]);      //move to the starting input

                  data = data & (0xFF>>(8-modbus_rx.data[3]));  //0 out values after quantity

                  if(modbus_rx.func == FUNC_READ_COILS)
                     modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
                  else
                     modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
                     
                  event_count++;
               }
               break;
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
                     modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
                  else
                     modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_SINGLE_COIL:      //write coil
               if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
               else
               {
                  //coils are stored msb->lsb so we must use 7-address
                  if(modbus_rx.data[2] == 0xFF)
                     bit_set(coils,modbus_rx.data[1]);
                  else
                     bit_clear(coils,modbus_rx.data[1]);

                  modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_SINGLE_REGISTER:
               if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  //the registers are stored in little endian format
                  hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[3],modbus_rx.data[2]);

                  modbus_write_single_register_rsp(MODBUS_ADDRESS,
                               make16(modbus_rx.data[0],modbus_rx.data[1]),
                               make16(modbus_rx.data[2],modbus_rx.data[3]));
               }
                 //initialize the values received from master
                 
               break;
            case FUNC_WRITE_MULTIPLE_COILS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int i,j;

                  modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);

                  for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
                  { 
                     if(bit_test(modbus_rx.data[5],j))
                        bit_set(coils,7-i);
                     else
                        bit_clear(coils,7-i);
                  }

                  modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
                                 make16(modbus_rx.data[0],modbus_rx.data[1]),
                                 make16(modbus_rx.data[2],modbus_rx.data[3]));
                 
                  event_count++;
               }
               break;
            case FUNC_WRITE_MULTIPLE_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  int i,j;

                  for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
                     hold_regs[i] = make16(modbus_rx.data[j+1],modbus_rx.data[j]);

                  modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
                                 make16(modbus_rx.data[0],modbus_rx.data[1]),
                                 make16(modbus_rx.data[2],modbus_rx.data[3]));
               
                  event_count++;
               } 
                 //initialize the values received from master
                           
               break;           
            default:    //We don't support the function, so return exception
               modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
         }
      }
     
      } 
      // modbus ends here.
     


   }

}


_________________
Regards,
Devil


Last edited by devilfrmheaven on Sat Aug 19, 2017 11:31 pm; edited 3 times in total
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Apologies in advance
PostPosted: Thu Aug 17, 2017 9:35 am     Reply with quote

Apologies in Advance, did not come here just to ask for question, I am in the process of migrating to Canada, and working day and night to make cash to migrate to Canada.

I almost worked with my friend's laptop for 2 days but modbus did not workout. I do not have much time after my work to spend more time with it. But I would really like to complete what I started. :(

Hope you guys understand my situation.
_________________
Regards,
Devil
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 17, 2017 9:47 am     Reply with quote

If you want help, you will post the exact compiler version.
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Please let me know where I can find it?
PostPosted: Thu Aug 17, 2017 9:56 am     Reply with quote

Please let me know where I can find it?

The current interface is very much confusing, I dont see an about button for the app.

I was informed it was 5.45 or 5.49 I am not sure, probably I would be able to answer it only tomorrow once I get his laptop.
_________________
Regards,
Devil
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 17, 2017 10:16 am     Reply with quote

Those are not compiler version numbers. Look at the CCS versions page
to inform yourself of what version numbers look like:
http://www.ccsinfo.com/devices.php?page=versioninfo

Here is a list of ways to find the CCS compiler version:

1. Compile a test file, and look at the top of the .LST file, which will
be in your project folder. It will show the version. However, to get
the .LST file to be generated, the source file must compile with no errors.

2. Click on the Start button in Windows, then go to Programs, and then
find the entry for CCS, which will be called "PIC-C". Then click on the icon
for "Compiler Version". It will display a box which shows the compiler
version.

3. Open a Command Prompt window and go to c:\Program Files\Picc
(or wherever the compiler is installed on your PC) and run this command line:
Quote:
CCSC.exe +v
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

CCS PCM C Compiler, Version 5.049, 5967
PostPosted: Thu Aug 17, 2017 12:04 pm     Reply with quote

CCS PCM C Compiler, Version 5.049, 5967

Looks like this is the info you are looking for.
_________________
Regards,
Devil
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 17, 2017 4:58 pm     Reply with quote

Quote:
I was using a very old compiler Version 4ish.

Also post your exact version of your version 4 compiler. The version
number consists of 4-digits in this format: 4.xxx and no other numbers.

With both versions, I can compile your posted program and compare
the .LST files. Of course, you could do this too. But post your version
and I'll do it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri Aug 18, 2017 1:11 am     Reply with quote

There were four major things that did change, that I know of:

1) Default fuses. CCS5, altered the way that the fuses behave in some cases, when they are not specified. If you don't have the .lst file for the 'working' code, and don't know the V4 compiler number, then it'd be worth loading the .hex file into a programmer, noting the fuses, and explicitly setting them in the code to match.
2) Interrupt handling. This should not make any difference unless you are doing some sneaky things with interrupts. No sign of this in the code posted.
3) Pointer handling. Again no sign in the posted code of anything that would be affected by this. CCS switched to handling pointer arithmetic the 'right way', incrementing by the size of the addressed element. This was happening already on the later V4 compilers.
4) Bit handling. Again this pre-dates V5, but this was an update of the changes in bit handling from CCS2, made in the late V4 versions.

There were also some major 'migratory' changes around 4.100, so details of the version number involved do become important.

However the V4 cannot be that old. At the start of main, he has 'int8 i' declared after setup_adc_ports, enable_interrupts, and modbus_init. Now early V4 compilers won't allow this. This was one of the changes that came in around 4.100ish.

Big question is whether he is really sure this code was the code that worked?.

Looking at modbus.c, the 'revision history' on the 5.049 one, shows changes in 2011, that were done during the later V4 compilers. Perhaps around 4.120. I'd perhaps be suspicious that it was something in these changes that is causing the problem, rather than V5. I know the functions did get more complex at this point, and I'd expect the code size to be significantly larger. This was when TCP/IP support was added.

Just tried the experiment, of compiling with 4.114, and then with 5.049. Size goes up by about 100bytes. Then recompiled, with 5.049, but use the modbus.c from 4.114, and the code shrinks back to the 4.114 size.

I suspect it is the changes in modbus.c, introduced in the late V4 version, not the V5 compiler that is causing his problems. I notice that he has ENABLE and RX _ENABLE set to the same pin. This is not right.

The system is able to control multiple 'enable' pins. The 'ENABLE' pin, is meant to be to drive a pin to physically enable the buffer 'driver enable'. The 'RX_ENABLE' is meant to be to drive a pin to enable receive 'receive enable'. Normally if the buffer is permanently wired 'on', you only need to define RX_ENABLE' to switch the direction to receive, and set 'enable' to 0, so it is not operated. The later code did tighten up on how these are handled, and this might be causing problems.


Last edited by Ttelmah on Fri Aug 18, 2017 1:38 am; edited 1 time in total
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Version 4.140
PostPosted: Fri Aug 18, 2017 1:26 am     Reply with quote

I searched my project folders from the backup and I found it was Version 4.140
Looks like the last compiled date was Nov 19, 2016 Cool that was a long time ago.

CCS PCM C Compiler, Version 4.140, 31805 19-Nov-16 12:58
_________________
Regards,
Devil
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Following changes found in the header file as well.
PostPosted: Fri Aug 18, 2017 1:32 am     Reply with quote

From Version 4.140
Code:
#include <16F727.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset

#use delay(int=8000000)



From Version 5.049

Code:
#include <16F727.h>
#device ADC=16
#use delay(internal=8000000)

_________________
Regards,
Devil
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri Aug 18, 2017 2:27 am     Reply with quote

OK.

So add those fuses to the new project, and then try changing the enable pin settings. I'm assuming you have a RS485 transceiver, that is actually permanently enabled and only need to control the RX enable. So:
Code:

#include <16F727.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset

#use delay(internal=8MHz)

#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_PROTOCOL MODBUS_PROTOCOL_SERIAL
//Add this ensures setup for serial not TCP/IP

#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_RX_PIN PIN_c7             //Valid pin for serial receive               
#define MODBUS_SERIAL_TX_PIN PIN_c6             //Valid pin for serial transmit     
#define MODBUS_SERIAL_ENABLE_PIN 0              //No enable pin
#define MODBUS_SERIAL_RX_ENABLE PIN_c0       //Valid pin for serial rcv enable, rs485 only   
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_TIMER_USED MODBUS_TIMER_T2
#include "modbus.c"                   
#define MODBUS_ADDRESS 0x9

See if this then works.
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

no it did not MR T
PostPosted: Fri Aug 18, 2017 3:55 am     Reply with quote

No it did not Mr T, the modscan32.exe is not displaying the slave device with device ID 9.

I can see the RX Led blink when modscan32.exe pings but TX don't.
_________________
Regards,
Devil
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Did some more testing today.
PostPosted: Fri Aug 18, 2017 10:19 am     Reply with quote

Did some more testing today. Seems like Modbus is broken even the example don't work.



This is the circuit of Max485 I have printed on a PCB. I know the board works but placing it for your reference. It has pretty good protection as well may be others can try the same.

PIN 1 = RX = Goes to PIN C7 in PIC16F727
PIN 4 = TX = Goes to PIN C6 in PIC16F727
PIN 2 & 3 = Transmission Enable = Goes to PIN C0 in PIC16F727
_________________
Regards,
Devil
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri Aug 18, 2017 12:56 pm     Reply with quote

Your bus is not biased, and what biasing there is, is in the wrong direction.
Some RS485 transceivers are designed to treat an unbiased bus as idle, but technically the A line needs to be biased to at least 200mV above the B line when the bus is undriven.

<http://www.ni.com/support/serial/resinfo.htm>
devilfrmheaven



Joined: 09 Feb 2016
Posts: 53

View user's profile Send private message

Mr T
PostPosted: Fri Aug 18, 2017 1:19 pm     Reply with quote

Mr T, The hardware is working fine, if I burn the old hex it works. If I burn the new hex with Compile 5.049 it will not.

I do not know how to reproduce it again since I only have the one 5.049 version in this Laptop.

MrT, Please check you PM.
_________________
Regards,
Devil
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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