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

kbhit problem with 16f684

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



Joined: 29 Jul 2009
Posts: 154
Location: at work

View user's profile Send private message MSN Messenger

kbhit problem with 16f684
PostPosted: Fri Apr 30, 2010 9:25 pm     Reply with quote

I am using a 16f684, compiler version 4.03, and I'm having a problem with the KBHIT function.

Currently my RX pin is pin_a0, and I am able to receive values perfectly fine through this pin, until I try using kbhit. To be more specific, here's an example:

This WORKS:
Code:

void main()
{
   if(state==0)
   {
      var=getc();
      state=1;
   }
}

'var' successfully equals whatever I send over the rs232, but it's constantly checking kbhit which slows down the cycle time by too much.

This does NOT WORK:
Code:

void main()
{
   if(state==0)
   {
      if(kbhit())
      {
         var=getc();
         state=1;
      }
}


The code runs perfectly fast and fine, but never checks kbhit or executes 'getc()', and therefore 'var' never changes.

My question I suppose is, for one is there any reason this problem is occurring, and second, is there a function other than kbhit that I can use to check if a value is available via rs232 pin_a0? Below is the actual code that runs just fine, other than the above mentioned malfunction.


Code:
#include "16f684.h"
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOMCLR,BROWNOUT,CPD,NOPUT,IESO,INTRC_IO,NOWDT
#use rs232(FORCE_SW, baud=2400, rcv=PIN_a0)

int8 A=0;
int8 var=0;
int8 state=0;
int16 O=500; //OUTPUT time
int8 ON=1;
int16 OT=0;
int16 frame=0;
int16 fpms=25; //frames per milisecond
int16 milisecond=0;
int1 milisecondspassed=0;
int8 second=0;
int1 secondspassed=0;
int1 minutespassed=0;
int16 timer=0;
int16 timer1=0;

void output()
{
   if(ON==1)
   {
      timer++;
     
      if(timer1<O)
      {
         if(timer>3000)
         {
         timer=0;
         }
         
         else if(timer>2000)
         {
            output_high(pin_c1);
         }
         else if(timer>1000)
         {
            output_high(pin_c0);
         }
         
         else if(timer>0)
         {
            output_high(pin_a2);
         }
         
         timer1++;
      }
         
      if(timer1>=O)
      {
         output_low(pin_c1);
         output_low(pin_c0);
         output_low(pin_a2);
         state=0;
         timer1=0;
      }
   }
   
   if(ON==0)
   {
      state=0;
      output_low(pin_a2);
      output_low(pin_c0);
      output_low(pin_c1);
   }
}

void system()
{
   if(state==0)
   {
      if(kbhit())
      {
         getc();
         var=getc();
      }
      else
      {
         var=0;
      }
     
      if(var!=0)
      {
         if(var!=10)
         {
            if(var!=20)
            {
               var=0;
            }
         }
      }
      else
      {
         A++;
         if(A>200)
         {
         OT=0;
         }
      }
     
      if(var==10) //++
      {
         output_high(pin_c2); //LED
         O+=(O/10);
         state=1;
         OT++;
         A=0;
         var=0;
         
         if(OT>40)
         {
            OT=0;
            if(ON==0)
            {
               ON=1;
            } 
         
            if(ON==1)
            { 
               ON=0;
            } 
         } 
      }
           
      if(var==20) //--
      {
         output_high(pin_c2); //LED
         ON=1;
         OT=0;
         O-=(O/10);
         state=1;
         var=0;
      }
     
      if(O>900)
      {
         O=900;
      }
     
      if(O<50)
      {
         O=50;
      }
      output_low(pin_c2); //LED
   }
   output();
}

void main()
{
   while(1)
   {
      milisecondspassed=0;
      secondspassed=0;
      minutespassed=0;
      frame++;

      if(frame==fpms)
      {
         frame=0;
         milisecondspassed=1;
         milisecond++;
      }
     
      if(milisecond==1000)
      {
         milisecond=0;
         secondspassed=1;
         second++;
      }
     
      if(second==60)
      {
         second=0;
         minutespassed=1;
      }
     
      system();
   }
}

_________________
Vinnie Ryan
vinniewryan



Joined: 29 Jul 2009
Posts: 154
Location: at work

View user's profile Send private message MSN Messenger

PostPosted: Sat May 01, 2010 12:35 pm     Reply with quote

After more testing, I've found that when I use PIN_A1 instead, I get a similar problem, but slightly different. When using kbhit and pin_a1, the code runs just fine when there is a byte ready in the rs232, but when no byte is available, the code suddenly runs extremely slow.
_________________
Vinnie Ryan
Ttelmah



Joined: 11 Mar 2010
Posts: 19329

View user's profile Send private message

PostPosted: Sat May 01, 2010 12:55 pm     Reply with quote

The problem is using software RS232.
With software RS232, 'kbhit', simply checks is the serial input line is low at the _instant_ you call kbhit.....
Miss the start bit, and you have missed the character.

Best Wishes
vinniewryan



Joined: 29 Jul 2009
Posts: 154
Location: at work

View user's profile Send private message MSN Messenger

PostPosted: Sat May 01, 2010 1:36 pm     Reply with quote

I see what you mean. So a workaround might be to check Khbit, and if it IS high (active), to use getc maybe 5 times in a row with a function that's looking for a certain value, and if that value is met, then it can be considered a successful read. Like this?

Code:

//TX is sending the number '10' via rs232 when I press a button
void main()
{
   if(state==0)
   {
      if(kbhit()) //IF line is active
      {
         state=1;
      }
   }

   if(state==1)
   {
      if(counter<5) //check getc() 5 times
      {
         var=getc();
         counter++;

         if(var==10) //IF 10 is successfully read
         {
            //do something;
            var=0;
            counter=0;
            state=0;
         }
         else //IF 10 is NOT read, reset var
         {
            var=0;
         }
      }

      else if(counter==5) //IF 10 is not read after 5 times, reset everything
      {
         counter=0;
         var=0;
         state=0;
      }
   }
}

_________________
Vinnie Ryan
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 01, 2010 10:16 pm     Reply with quote

Another possible solution is to use the External interrupts pin (INT)
with the Ex_sisr.c example. Then you will get an interrupt on the leading
edge of the start bit, and the byte will be read in the #int_ext interrupt
routine, and put into a circular buffer. Then your main code can all
bkbhit() to see if the buffer holds any characters. If so, then you can
get them with bgetc(). The example file is here:
Quote:
c:\program files\picc\examples\ex_sisr.c

You would need to change that code so it uses #int_ext instead of #int_rda.
This code would have to be added near the start of main(), to enable
the #int_ext interrupts to detect the leading edge of the start bit.
Code:

ext_int_edge( H_TO_L );
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);


This thread has some sample code. It has some other stuff in it
related to getting a float as a string, but you don't need that part.
http://www.ccsinfo.com/forum/viewtopic.php?t=36039&start=4

I didn't try to understand what your code is doing, so it's up to you to
decide if the delay caused by the interrupt routine reading the incoming
byte is acceptable. This delay could occur at any time during your code
execution (if a character comes in), and it would be about 4 ms per haracter.
vinniewryan



Joined: 29 Jul 2009
Posts: 154
Location: at work

View user's profile Send private message MSN Messenger

PostPosted: Wed May 05, 2010 4:05 pm     Reply with quote

Thanks for the info and suggestion PCM, I tried it out and it worked, but the delay was slightly too much.

To get around the problem I simply used a second MCU to strictly receive the serial data, and send high and low signals to input pins on my main MCU. Given more time I could have probably come up with a better fix, but time is always my enemy at my job.

If anyone's curious about the code I used, here it is. This PIC simply receives serial data from an RF receiver and outputs high and low signals to another pic for communication. There are a lot of counters which help the code determine the difference between a serial byte, or RF noise.

Code:
#include "16f684.h"
#use delay(clock=4000000)
#Fuses NOFCMEN,NOPROTECT,NOMCLR,BROWNOUT,CPD,NOPUT,IESO,INTRC_IO,NOWDT
#use rs232(FORCE_SW, baud=2400, rcv=PIN_a1)

//Copyright ©2010 Vincent Westly Ryan
//ALL RIGHTS RESERVED

int8 var=0;
int8 state=0;
int8 counter=0;
int8 counter2=0;
int8 counter1=0;

void system()
{
   if(state==0)
   {
      if(kbhit())
      {
         var=getc();
         state=1;
      }
      else
      {
         if(counter2<50)
         {
            counter2++;
         }
         else
         {
            counter=0;
            counter1=0;
            var=0;
         }
      }
   }
   
   if(state==1)
   {
      if(var==10)
      {
         counter2=0;
         if(counter<5)
         {
            counter++;
            state=0;
         }
         else
         {
            counter=0;
            output_high(pin_c0);
            state=2;
            var=0;
         }
      }
     
      else if(var==20)
      {
         counter2=0;
         if(counter1<5)
         {
            counter1++;
            state=0;
         }
         else
         {
            counter1=0;
            output_high(pin_a2);
            state=2;
            var=0;
         }
      }
     
      else
      {
         var=0;
         state=0;
      }
   }
   
   if(state==2)
   {
      if(input(pin_a0))
      {
         output_low(pin_c0);
         output_low(pin_a2);
         state=0;
      }
   }
}

void main()
{
   while(1)
   {
      system();
   }
}

_________________
Vinnie Ryan
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