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

quick Help with RS232

 
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

quick Help with RS232
PostPosted: Sun Apr 25, 2010 1:11 am     Reply with quote

The following code gets stuck in the 'System' function, before it ever reaches any of the 'output_high(pin_xx); commands. I'm basically trying to read the RS232 only when there's an available byte, in the simplest form possible. I've tested and my input is receiving bytes correctly, but when I use kbhit() and getc, the code gets stuck. I'm programming a PIC16f684 using compiler version 4.022

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)

int16 var=0;
int16 frame2=0;
int8 state=0;
int16 speed=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;
int16 timer2=0;
int16 timer3=0;

void system()
{
      if(kbhit());
      {
         var=getc();
      }
     
      if(var==10) //++
      {
         output_high(pin_c4);
      }
           
      if(var==20) //--
      {
         output_high(pin_c5);
      }
}

void main()
{
   while(1)
   {
      delay_ms(100);
      output_low(pin_c4);
      output_low(pin_c5);
      system();
   }
}

_________________
Vinnie Ryan
arunb



Joined: 08 Sep 2003
Posts: 492
Location: India

View user's profile Send private message Send e-mail

RE
PostPosted: Sun Apr 25, 2010 1:31 am     Reply with quote

Use RDA interrupt to get the data instead of polling for received characters.
Ttelmah



Joined: 11 Mar 2010
Posts: 19401

View user's profile Send private message

PostPosted: Sun Apr 25, 2010 4:55 am     Reply with quote

What you are doing, is basically right, _except_ for the testing for changes, and what you test 'for', and a critical 'timing' issue.

Remember 'var' is a global variable. Once it receives a value, it'll keep holding it. You really only want to change the pins, if a 'new' value has arrived.


If you are using a terminal package to send the charcaters, 'enter', will send CR (13), and LF(10). So 'var' may well contain 10, and continuously set C4 high.

Code 20, is a 'DC4' control code, so unless you are deliberately sending this with the alt key, and the numeric code, this is never going to be seen. You have a remark '++', and '--', the codes for the +, and - signs, are 46, and 48 respectively is these are what you are trying to see.
Using interrupts does become 'better' if there are delays in the main code, but for a simple operation as shown, are not needed. However judging by the number of variables you are declaring, suggecting that a lot more is wanted in the future, may well be the batter way to go.
As a 'comment', you may well be 'wiser' to avoid using standard names like 'timer3', which is the name of a standard system timer, in your variable declarations.
The main reason for problems though is mentioned after the updated code.

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 var=0; //Why use a 16 bit variable for a max 8bit value.....

void system()
{
      if(kbhit());
      {
         var=getc();
         if(var=='+') //+
         {
            output_high(pin_c4);
         }
           
         if(var=='-') //-
         {
            output_high(pin_c5);
         }
      }
}

void main()
{
   while(1)
   {
      delay_ms(100);
      output_low(pin_c4);
      output_low(pin_c5);
      system();
   }
}

Now, with a hardware UART, this will work.
_But_ with a software UART, it probably won't. All 'kbhit' does, is tests if the input serial line is low at the moment of the call. This will happen for just 1uSec, every 100mSec. Unless you just happen to send the 'start' bit, at _exactly_ this moment in time, the character will _not_ be seen.
With a software UART, you _must_ poll the input no less frequently than about 1/3rd a bit time (in your case about 7000 times a second), if data is not going to be missed.
To do what you want, you _must_ use the hardware UART.

Best Wishes
vinniewryan



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

View user's profile Send private message MSN Messenger

PostPosted: Sun Apr 25, 2010 10:57 am     Reply with quote

Thanks for the replies. I will try using an RDA interrupt.

Ttelmah,

I want the variable 'var' to change constantly, because it's receiving a constant signal of data from a transmitter. I assumed that when there is no byte available, it will set var to 0? Or perhaps will crash the code causing my problem? I've been able to successfully receive data from the transmitter and respectively turn on and off the output pins, but when I add this code to the rest of my code, the rest of the code doesn't run because it all gets stuck in a loop of checking getc and setting outputs high. It never runs past that point.

If it would help I can post the rest of my code, but I'm going to try using the RDA interrupt first. My PIC does not have an onboard UART, or any form of communication. I do however have an I2C compatible PIC which may better suit my needs if I can't get this working correctly.

A third method I found was posted by PCM a while ago, and it includes using a PICBASIC snippet to count pulse width on an input. If I use this method, I can basically create my own type of serial encryption, as I'm only working with two different transmitted values.

I've created a timer system that allows me to generate delays without pausing the other running code, and without using a WDT or any hardware functions. It's a general timer code used for any section of the code, which is the reason for the general variable names like 'timer2'.
_________________
Vinnie Ryan
Ttelmah



Joined: 11 Mar 2010
Posts: 19401

View user's profile Send private message

PostPosted: Sun Apr 25, 2010 2:48 pm     Reply with quote

No, when no byte is available, var will sit holding what was last received.
to set it to zero when nothing is available, you would need:
Code:

if (kbhit()) {
   var=getc();
}
else {
   var=0;
}


However, why not just put the code that changes pins inside the character receive routine, then it doesn't matter what var holds the rest of the time, and saves _time_ (no testing of var, or unecessary outputs)....

Best Wishes
vinniewryan



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

View user's profile Send private message MSN Messenger

PostPosted: Mon Apr 26, 2010 12:12 am     Reply with quote

Thanks for all the help! Here's the final *working* code. I haven't yet, but will make the change you last suggested about nesting the "if(var=)" statements within the"if(kbhit())" function.

The code breakdown:

Receive an input from the RX pin, the value at the RX pin will either read 10 or 20. Park that. The code has a constant timing system that allows unlimited timers and functions to run without pausing or desynching anything else, which is necessary for the proper function of this code. Basically the PIC controls output to 3 motors, and constantly pulses them on and off really fast to give emulated speed control similar to a PWM. The RX input receives either a 10 (+), which increases the intensity of the VIBRATING motors, or 20 (-), which decreases the intensity. There is an LED connected to pin C3, one on C4, and one on A1, these simply indicate where the code is. A1 LED indicates that info is being received on the RS232, C2 and C3 determine whether it's a 10(+) or a 20(-).

This timer system can be used with any other code or pic, doesn't require interrupts, WDT's, or delays, and is very handy and easy to program. If requested, I'll post just the timer code so anyone out there can use it and easily get it working. It can accurately measure any timeframe, ns, ms, s, min, h, even days and months. All in a few lines. It's not really that exciting to the world of PICs, but it is to me because I use it so often and I made it.
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)

int16 var=0;
int16 frame2=0;
int8 state=0;
int16 O=500; //OUTPUT time

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;
int16 timer2=0;
int16 timer3=0;

void output()
{
   timer++;
   
   if(timer1<O)
   {
      if(timer>4000)
      {
      timer=0;
      }
     
      else if(timer>3000)
      {
         output_high(pin_c2);
      }
      else if(timer>2000)
      {
         output_high(pin_c1);
      }
     
      else if(timer>1000)
      {
         output_high(pin_c0);
      }
     
      timer1++;
   }
     
   if(timer1>=O)
   {
      timer2++;
      output_low(pin_c2);
      output_low(pin_c1);
      output_low(pin_c0);
   }
     
   if(timer2>=200)
   {
      output_low(pin_c3);
      output_low(pin_c4);
      state=0;
      timer1=0;
      timer2=0;
   }
}

void system()
{
   if(state==0)
   {
      if(kbhit())
      {
         output_high(pin_a1);
         var=getc();
      }
      else
      {
         var=0;
      }
         
      if(var==10) //++
      {
         output_high(pin_c3);
         O+=(O/10);
         state=1;
      }
           
      if(var==20) //--
      {
         output_high(pin_c4);
         O-=(O/10);
         state=1;
      }
     
      if(O>900)
      {
         O=900;
      }
     
      if(O<50)
      {
         O=50;
      }
     
      output_low(pin_a1);
   }
   
   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
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