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

Modbus kbhit() not triggering
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
webgiorgio



Joined: 02 Oct 2009
Posts: 111
Location: Denmark

View user's profile Send private message

Modbus kbhit() not triggering
PostPosted: Fri Feb 19, 2021 1:39 pm     Reply with quote

Hi,
I have a breadboard setup with a PIC16F1788 (Modbus slave) and MAX485.
Wiring was tested with simple printf().
Hardware serial port pins (C6 Tx, C7 Rx, B5 RE/DE).
On the computer (master) the program QModMaster.

At uC boot the LED blinks for 2 seconds. Ok, program is running with internal oscillator.
Then I would expect it to toggle every time there are incoming data, but it does not and the master says "timeout".

RX and REDE have 10 kOhm pull up.
REDE is low, therefore I see the data sent from the PC, with the oscilloscope, at the RX pin.
All good so far, but modbus_kbhit() isn't going to 1, and no response is sent.
Code:

////modbus slave example

#include <16F1788.h>
#fuses INTRC_IO, PUT, NOWDT, NOLVP, PROTECT, NODEBUG
#use delay(clock=8000000)
#define STATUS_LED PIN_B3


#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_BAUD 9600

#define MODBUS_SERIAL_ENABLE_PIN    PIN_B5   // Controls DE pin for RS485
//#define MODBUS_SERIAL_RX_ENABLE     PIN_B5   // Controls RE pin for RS485
#include <modbus.c>
#define MODBUS_ADDRESS 31


void main()
{

   setup_adc_ports(NO_ANALOGS);

   //flash a few times the LED
   for(int i=0; i<20; i++){
      output_toggle(STATUS_LED);
      delay_ms(100);
   }
   
   modbus_init();

   while(TRUE) {
     if(modbus_kbhit()){
      output_toggle(STATUS_LED);
     
     
      delay_us(50);

      //check address against our address, 0 is broadcast
      if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0) {
         switch(modbus_rx.func)
         {
           //////////////ex_modbus_slave.c
         }
      }
     }
  }
}
temtronic



Joined: 01 Jul 2010
Posts: 8028
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 19, 2021 1:42 pm     Reply with quote

Have you the proper terminations? pullup, bias, pulldown ?
Haven't got AB flipped to BA ??
webgiorgio



Joined: 02 Oct 2009
Posts: 111
Location: Denmark

View user's profile Send private message

PostPosted: Fri Feb 19, 2021 1:59 pm     Reply with quote

No, because with printf I receive on the computer, so, the hardware is ok.

Modbus is such a bad protocol. Mad
For some other things I used a string in JSON format...so easy to parse, and send floating point and large numbers without splitting them in bytes.
temtronic



Joined: 01 Jul 2010
Posts: 8028
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 19, 2021 6:29 pm     Reply with quote

Hmm. the program you posted doesn't enable the RDA interrupt !
Also no ISR.
PCM programmer



Joined: 06 Sep 2003
Posts: 21396

View user's profile Send private message

PostPosted: Fri Feb 19, 2021 7:46 pm     Reply with quote

temtronic,
It does those things in modbus_phy_layer_rtu.c

Code:

#if (MODBUS_SERIAL_INT_SOURCE==MODBUS_INT_RDA)
#int_rda
.
.
.
void incomming_modbus_serial()
{
char c;

c=fgetc(MODBUS_SERIAL);
.
.
.


Code:
void RCV_ON(void)
{
.
.
.
#if(MODBUS_SERIAL_INT_SOURCE==MODBUS_INT_RDA)
   enable_interrupts(INT_RDA);
.
.
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21396

View user's profile Send private message

Re: Modbus kbhit() not triggering
PostPosted: Sat Feb 20, 2021 1:31 am     Reply with quote

What happens if you increase the timeout number by 10x as shown
below in bold ? Try it, just as a test.
Quote:
#define MODBUS_SERIAL_TIMEOUT 100000 // was 10000 for RTU


#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_BAUD 9600

#define MODBUS_SERIAL_ENABLE_PIN PIN_B5 // Controls DE pin for RS485
//#define MODBUS_SERIAL_RX_ENABLE PIN_B5 // Controls RE pin for RS485
#include <modbus.c>
#define MODBUS_ADDRESS 31
Ttelmah



Joined: 11 Mar 2010
Posts: 17038

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 1:58 am     Reply with quote

Yes, it does enable the interrupt in the physical layer, but only if he has
it defined. He is not telling the driver where the interrupt is to come
from or even what serial to use,
webgiorgio



Joined: 02 Oct 2009
Posts: 111
Location: Denmark

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 3:53 am     Reply with quote

I agree that the symptom is that the PIC is missing to interrupt upon serial receive.

Isn't this like enough to tell the modbus library to use the first hardware serial port?
Code:

#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA


To make sure the hardware is ok I made a simple test program that toggle a led when there is a serial interrupt.
Code:

#use rs232(baud=.........);

#int_rda
void serial_isr(){
   output_toggle(STATUSLED);
}

void main(){
  enable_interrupts(int_rda);
  enable_interrupts(global);
  while(true){}
}

and the led flashes when in the QmodMaster program I click the button to read a register.

My compiler version is 5.034
Ttelmah



Joined: 11 Mar 2010
Posts: 17038

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 4:19 am     Reply with quote

Yes.
The thing that worries me, is that 'as shown', you have nothing defined to
turn the RS485 bus round. You have remmed out the RE define, so it
can only work with a full duplex connection. If the bus is not being set to
receive, how can it receive anything?...
You do realise that the kbhit does not go 'true' when a character is received?.
It only goes TRUE when a modbus packet is seen.
temtronic



Joined: 01 Jul 2010
Posts: 8028
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 6:02 am     Reply with quote

More curiousness...
Am I to 'assume' that the included file 'modbus.c' is from CCS and NOT been modified in any way ???
It'd be nice to see a comment at the end of the line saying WHERE it came from and the version(date) of it !
If it is the CCS version, I 'assume' it's pretty 'solid' code otherwise someone would have reported it ?? I know that CCS will update a 'driver' or 'EX_ample code, so it might be important to know the 'version'.
webgiorgio



Joined: 02 Oct 2009
Posts: 111
Location: Denmark

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 7:31 am     Reply with quote

The bus and the MAX485 is set to receive because I see on the RX pin of the uC the serial data sent from QmodMaster.
Even if I hard wire the RE-DE pins to have it always in receive, I should see the PIC responding something on the TX pin following something on the RX, but it does not.

Somewhere in the forum I read that is not good to have two #define for the same pin. I read that in case RE-DE are connected together, I should only define MODBUS_SERIAL_ENABLE_PIN.
Anyway defining also MODBUS_SERIAL_RX_ENABLE does not work either.

The example that came with the compiler is from 2013, apparently. I haven't modified it.

Quote:
You do realise that the kbhit does not go 'true' when a character is received?. It only goes TRUE when a modbus packet is seen.

Ahhh ok. I misunderstood that.
I am wondering if the packet from the PC is a valid modbus packet now...
Ttelmah



Joined: 11 Mar 2010
Posts: 17038

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 8:19 am     Reply with quote

Yes, that is the critical question...
temtronic



Joined: 01 Jul 2010
Posts: 8028
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 20, 2021 8:23 am     Reply with quote

OK, silly question...
You have the PIC set for modbus adrs #31.
Does the PC send data to adres #31 ??

I don't use MODbus and don't have time to decode what it's doing perhaps others have. I would not expect anything from the PIC if you're not sending #31 with the 'data packet' or whatever it's called....
Ttelmah



Joined: 11 Mar 2010
Posts: 17038

View user's profile Send private message

PostPosted: Mon Feb 22, 2021 8:08 am     Reply with quote

and one little extra 'caveat' on that. Some of the PC packages default to using
hex for address.
webgiorgio



Joined: 02 Oct 2009
Posts: 111
Location: Denmark

View user's profile Send private message

PostPosted: Mon Feb 22, 2021 11:29 am     Reply with quote

Yes the address is correct.
So, I've tied both Re and DE to GND so the MAX485 is always on receive.

I've hooked the scope with signal decoding to the RX pin (inverted).
I see a packed that is correct (haven't checked the CRC).

I've changed the address to 2 on both C program and QmodMaster.

So, my QModMaster program is set to read 1 holding register (FC=3) starting at 1, from slave 2, at 9600 bps.

On the oscilloscope's decoder I get:
02 - 03 - 00 01 - 00 01 - D5 F9
Address - FunctionCode - start address - how many bytes to read - CRC
https://www.modbustools.com/modbus.html#function03

It seems all right.
On the TX pin however I see no answer from the uC.

Do I have a buggy library? At this point probably CCS knows what to do.

Here is my program, which is basically the CCS example with minimal changes. I removed some proprietary CCS code in the switch-case statements.

Code:

////modbus slave example

#include <16F1788.h>
#fuses INTRC_IO, PUT, NOWDT, NOLVP, PROTECT, NODEBUG //INTRC_IO to be able to use A7 and A6 as GPIO
#use delay(clock=8000000)
#define STATUS_LED PIN_B3

#define MODBUS_SERIAL_TIMEOUT 100000
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_BAUD 9600

#define MODBUS_SERIAL_ENABLE_PIN    PIN_B4   // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_ENABLE     PIN_B5   // Controls RE pin for RS485
#include <modbus.c>
#define MODBUS_ADDRESS 2


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);
   for(int i=0; i<20; i++){
      output_toggle(STATUS_LED);
      delay_ms(100);
   }
   
   modbus_init();

   while(TRUE)
   {
     if(modbus_kbhit()){
      output_toggle(STATUS_LED);
     
     
      delay_us(50);

      //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
             
               break;
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
             
               break;
            case FUNC_WRITE_SINGLE_COIL:      //write coil
           
               break;
            case FUNC_WRITE_SINGLE_REGISTER:
             
               break;
            case FUNC_WRITE_MULTIPLE_COILS:
             
               break;
            case FUNC_WRITE_MULTIPLE_REGISTERS:
           
               break;
            default:    //We don't support the function, so return exception
               modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
         }
      }
     }//end of if modbus_kbhit()
  }
}
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