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

RS-232 interrupt fails
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
dDelage



Joined: 10 Sep 2022
Posts: 20

View user's profile Send private message

RS-232 interrupt fails
PostPosted: Sun Oct 16, 2022 12:01 am     Reply with quote

This is code (simplified) that has worked previously with PIC16F876A, now being used with PIC16F18855. I know that the WIN11 and Prolific USB/Serial adapter work because they work with the previous revision. Here's the code with two choices, neither of them work. Ideas?

Code:
/*RS-232 Test*/

// PICK ONE
#define SerIntr   //uses serial interrupt
//#define SerPoll   //uses kbhit()

//////////// CHIP SETUP
#include  <16F18855.H>     //includes #device spec rev5
#id CHECKSUM   //stores the checksum, doesn't affect program
#use delay (INTERNAL=4MHZ)   //Says INTERNAL OSCILLATOR is 4MHz rev5
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)

// PORTB ASSIGNMENTS
#define StatusLed  PIN_B1             
#define ReadyLed   PIN_B2 

//other
void serial_in();
void initialize();
void main();

#INT_RDA // interrupt on serial data receive
void serial_in()
{
   INT iSerCnt;
   CHAR cSerialParam;
   CHAR cSerialValue;
   CHAR sSerialData[10]; //upto 10 characters from race manager, max is 8
   
   gets (sSerialData); //get the incoming data
   output_toggle (ReadyLed);
   iSerCnt = 0;

   WHILE ((sSerialData[iSerCnt] != 13)&& (iSerCnt < 10) )
   {
      //get this param and value until out of data
      cSerialParam = sSerialData[iSerCnt]; //get first CHAR that identifies param
      iSerCnt++;
      cSerialValue = sSerialData[iSerCnt] - 64; //get second CHAR value, 64 got us out of lf, cr, bksp
      iSerCnt++; //increment to next
      SWITCH (cSerialParam)
      {
         // decide what to DO
         CASE 'U' : // UUUUc
         IF (cSerialValue == 21)
         {
            puts ("UUUUt"); //tell RM we are here
            iSerCnt += 3; //skip past rest of characters in sSerialData
         }

         BREAK;

         CASE '0' : //report values bck to RM
         putc (5 + 64);
         putc (10 + 64);
         putc (0x1f + 64);
         putc (3 + 64);
         putc (65);
         putc (66);
         putc (67);
         BREAK;
      } //SWITCH
   } // WHILE iSerialCntr[x] > 0
}  //end serial interrupt handler

VOID initialize  ()
   {
   // set up initial interrupt conditions
   #ifdef SerIntr
   enable_interrupts (INT_RDA); //SERIAL ReceiveDataAvailable
   #endif
   enable_interrupts (GLOBAL); //interrupt
   } // end initialize

   // MAIN
VOID main()
   {
   initialize (); //initialize the hardware
   WHILE (1)
   {
      #ifdef SerPoll
      IF (kbhit () )
      {
         serial_in ();
         output_toggle (StatusLed);
      }
      #endif
      delay_ms (10);
      output_toggle (StatusLed);
   }
   } //end main  ()
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Oct 16, 2022 1:02 am     Reply with quote

The problem is you are not using the UART!......
Hence no INT_RDA.... Sad

Look at the sticky at the top of the forum about PIN_SELECT.

The new chip is a PPS chip. The peripherals are relocatable to different
pins.
The syntax you need to use is:
Code:

#PIN_SELECT U1RX=PIN_C7
#PIN_SELECT U1TX=PIN_C6
#USE RS232 (UART1, BAUD=9600, parity=N, bits=8, ERRORS)
//You should always use 'ERRORS' unless you are adding code to
//handle hardware ERRORS yourself
dDelage



Joined: 10 Sep 2022
Posts: 20

View user's profile Send private message

RS-232 interrupt fails
PostPosted: Sun Oct 16, 2022 6:22 am     Reply with quote

Thank you, thank you. I woke up this morning to a message that makes me feel so dumb, but happy! You made my day. On to the next!
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Oct 16, 2022 8:17 am     Reply with quote

It is one of those things that until you have 'met it', is not immediately
obvious. So don't feel too bad. Very Happy
Just add it to your internal knowledge-base, to check if a chip has
PPS.

Have a great day.
dyeatman



Joined: 06 Sep 2003
Posts: 1910
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Oct 16, 2022 3:33 pm     Reply with quote

I find it interesting it is working previously using gets() for a single char input
unless it spends a loooong time in the ISR and has the potential to hang.....
_________________
Google and Forum Search are some of your best tools!!!!
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Oct 16, 2022 5:52 pm     Reply with quote

Quote:

unless it spends a loooong time in the ISR and has the potential to hang.....


Well, I hate to spend any significant time in any ISR. As for the UART, there are so far only two ways I approach it. Either fill a buffer starting from some known start sequence till an "end_of_data" sequence and than raising a flag for main to handle the data or by directly decoding the incoming message via a state machine inside the ISR. In latter case, if the task that needs to be done after receiving the message is simple (like a LED on or off), it is done inside the ISR. Otherwise, flag for the main. Since messages usually don't come directly one after another, I've never encountered a situation where main wasn't able to handle the data before the next arrived.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Oct 17, 2022 5:38 am     Reply with quote

Yes.
Using gets in an RDA interrupt, will 'work', but completely wastes the
actual point of the interrupt. It means that nothing else happens in the
code all the time serial is being received. The whole 'point' of having
interrupt driven serial is so that other things can be done while serial data
is being handled.... Sad

Generally, except when working with very fast serials, as PrinceNai says
it is really worth getting your head round just how slow normal serial 'is'
in processor terms, and so how easy it is to handle data between packets.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Mon Oct 17, 2022 1:53 pm     Reply with quote

To illustrate the point of Mr. Ttelmah. With a clock of 32MHz each machine instruction cycle takes 0,000125ms. With a serial set to 19.200 each byte (10 bits) comes in every 0,52083ms. That means you have 4.177 (4177, not four point 177) instruction cycles available for each byte received. Messages are seldom (never) 1byte long. + Carriage return and Newline take the same time. An eternity.

Last edited by PrinceNai on Mon Oct 17, 2022 7:47 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 17, 2022 5:23 pm     Reply with quote

Note that you are using a decimal point as a thousands separator, and a
comma as a decimal point. Some countries do this, some do the opposite.
So you mean 4177 instruction cycles.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Mon Oct 17, 2022 7:16 pm     Reply with quote

Dear PCM, 4177 cycles it is. Please don't hold it against me for using European way of writing numbers, since I'm from there. It has already caused me no end of grief with SQL. But the point is well taken. How could people know? I edited the response, leaving the original there.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 17, 2022 11:27 pm     Reply with quote

My intention was to indicate it to others if they weren't aware of it,
not to chastise you.
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Tue Oct 18, 2022 6:03 am     Reply with quote

It was never ever taken that way :-). You pointed out how numbers can be interpreted in a totally different way, based on how one is trained to see them. A very good point, in fact, that can save someone a lot of time scratching his head and wondering about the result.

As I mentioned, I already had problems with precisely the same thing and lost days with an SQL database where the same client program spitted out different results on different computers. Different locale, different way of interpreting the numbers and dates. So once again, your comment was very well taken and I hope I'll remember it next time.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Oct 19, 2022 1:09 am     Reply with quote

Yes.
I must admit when I read the original post, it took me perhaps half a
second to suddenly reaiise that the decimal here was the thousands
separator. However I've dealt with so many variants of this over the years
that it is very much second nature (the apostrophe in Switzerland was one
that drove me mad!). Remembering when programming to make sure that
you have the 'national' options selected to deal with this has become
standard practice in databases, spreadsheets etc., that remembering
standard text does not deal with this, is important. I think PriceNai's
change to point it out in his post was the brilliant way to handle this. Very Happy
dDelage



Joined: 10 Sep 2022
Posts: 20

View user's profile Send private message

PostPosted: Wed Feb 14, 2024 9:45 pm     Reply with quote

Greetings, all. I am resurrecting this thread from a year and a half ago. I am the son of the OP. I'm picking this project up where he left off.

I see that after Dad got his answer and left the conversation, that a lot of good points were brought up.

Regarding the serial interrupt: in this particular application, when we get serial messages, there isn't a lot of other stuff going on, so waiting for the full string seems to work.

However, I have taken the advice about not wasting CPU cycles to heart, and am looking to improve the serial interrupt handler. Unfortunately, in this case, our serial messages do not have a specific end character, so we can't wait for, say, a CRLF and then signal main() to process the serial data buffer.

I'm considering using one of the 8-bit timers on the PIC to do a timer-based serial capture. Serial strings into the PIC are never more than 10 characters long and are always sent in one stream from the computer. We're running at 9600 baud, which tells me that each character arrives in just under 1mS, putting us at ~10mS for the worst-case string.

The plan is to start the timer when we receive the first serial character, and then signal main() to process the serial data buffer 15mS or so later, giving plenty of time for the remainder of the characters to arrive.

So now here's the question: has anyone here done anything like this before, and if so, does this approach make sense? I'm leaving lots of details out--like incrementing indices and clearing out the serial buffer--in the interest of brevity. When I get this coded, I'll be sure to post the source, but in the meantime, I'm hoping to see if anyone has any tips.

And the best solution is probably to put a message terminator at the end of the serial messages, but we have thousands of devices in the wild that can't be updated, so we'll probably have to deal with this issue for the foreseeable future.

Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Feb 15, 2024 1:46 am     Reply with quote

Whoa a second.

gets, waits for a carriage return.

If gets works, then you can simply have the ISR set a flag when the
carriage return arrives.

The original approach, won't work unless there _is_ a carriage return... Sad
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