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 CCS Technical Support

loop problem :(
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
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

loop problem :(
PostPosted: Thu Jan 08, 2009 5:21 pm     Reply with quote

Hi guys I'm having problem with something that to you might be very simple, I'm using the pickit2 with the ccs compiler and I just wanted to know how can I jump from one loop to the other. I created this simple program but it won't let me. The compiler gives me the error because it won't jump unless the loop I want to go is on top, I hope this makes sense to you. Thank you.
Code:
#include <16F887.h>             // header file for the PIC16F887
                                // includes built-in functions and constants
                                // for arguments/returns.
#FUSES NOWDT               
#FUSES NOMCLR
#FUSES NOCPD
#FUSES NOBROWNOUT            
#FUSES XT 

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
/////////////////////////////////////////////////////////////////////////////////


void firstloop()      
{
while(1){
output_d(0xf0);
if (getc()=='2')secondloop(); 
}
}


void secondloop()
{
while(1){
output_d(0x0f);
if (getc()=='1')firstloop(); 
}
}


void main()
{

while(true)
  {
   printf("Welcome:,\n\r");
   printf(" \n\r");
      printf("Press 1 for first loop\r");
   printf("Press 2 for second loop\r");
if (getc()=='1')firstloop();
if (getc()=='2')secondloop();     

  }
 
}
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Thu Jan 08, 2009 5:33 pm     Reply with quote

you just need a prototype to show what the function looks like.
But then you have recursive problem.
try something more like this
Code:
#include <16F887.h>             // header file for the PIC16F887
// includes built-in functions and constants
// for arguments/returns.
#FUSES NOWDT
#FUSES NOMCLR
#FUSES NOCPD
#FUSES NOBROWNOUT
#FUSES XT

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//prototypes//
void firstloop();
void secondloop();
//funtions
void firstloop()
{
    output_d(0xf0);
}


void secondloop()
{
    output_d(0x0f);
}

//main//
void main()
{
  int8 getc_val;   
  printf("Welcome:,\n\r");
  printf(" \n\r");
  printf("Press 1 for first loop\r");
  printf("Press 2 for second loop\r");

  while(true)
  {
    getc_val=getc();
    if (getc_val=='1')firstloop();
    if (getc_val=='2')secondloop();

  }

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 08, 2009 5:36 pm     Reply with quote

You can't do recursion. That's what you're attempting to do. You'll
get this error message:
Quote:
*** Error 69 "pcm_test.c" Line 58(0,1): Recursion not permitted [firstloop]
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Jan 08, 2009 5:41 pm     Reply with quote

THANK YOU SO MUCH!!!!!!!!!!!!!!!!!!!!! IT WORKS!!!!!!!!!!!!!!!!!!!
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Jan 08, 2009 9:07 pm     Reply with quote

it worked but is not what I was trying to do but thanx...this what I'm trying to do, I have a robot that I need it to work in remote and autonomous mode, so when I send a command it has to stay in the remote loop with all the features, and when I hit another command it has to stay in the autonomous mode with diferent features, thats why I'm trying to do 2 diferent loops. make sence??
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Thu Jan 08, 2009 10:13 pm     Reply with quote

IceMetal wrote:
...when I send a command it has to stay in the remote loop with all the features, and when I hit another command it has to stay in the autonomous mode with diferent features, thats why I'm trying to do 2 diferent loops. make sense??


Yes, but don't use getc() because it is blocking. Use kbhit() to check for a new command without blocking. If you want to use a function for loop 1 and another function for loop 2, then just have those functions return whenever kbhit() is true. Then let the main command dispatcher loop in main decide which loop to call based on a reading of getc(), which you can do without blocking after kbhit() returns true.
_________________
Robert Scott
Real-Time Specialties
Embedded Systems Consulting
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Jan 08, 2009 10:16 pm     Reply with quote

but how do I go to the loop that is at the bottom when I'm on the top loop? cuz when I'm trying to do that I get an error
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Jan 09, 2009 12:18 am     Reply with quote

If you advance from the present very simple example to a real application, you most likely notice, that there are more things to do than stay in mutual exclusive loops representing different machine states.

To my opinion, it's more suitable to have a variable representing the different states, perform conditional code depending on the variable value, e. g. in a switch construct, and change the variable value to transit to another state. The technique is called finite state machine (FSM). In contrast to your loop example, you can divide the total system state into several substates, each representec by a FSM.

If this sounds too complex for your application, keep your intial loop example, place all loops in one function block and transit by C goto statements. This works without causing recursion issues. As a basic disadvantage, you can't perform other actions at the main program level while staying in the loop.
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

PostPosted: Fri Jan 09, 2009 2:09 am     Reply with quote

well this is what I'm trying to do I mean I will replace the printf with output commands but just to give you an idea why I want to stay in the same loop,

Code:
#include <16F887.h>             // header file for the PIC16F887
                                // includes built-in functions and constants
                                // for arguments/returns.
#FUSES NOWDT               
#FUSES NOMCLR
#FUSES NOCPD
#FUSES NOBROWNOUT            
#FUSES XT 

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
/////////////////////////////////////////////////////////////////////////////////

//remote loop
void remote()
{
while(1){
    if (getc()=='4')printf("go foward\r");
    if (getc()=='5')printf("go left\r");
   if (getc()=='6')printf("go right\r");
if (getc()=='2')autonomous();
}
}

//autonomous loop
void autonomous()
{
while(1){
     printf("go foward\r");
   while(Input(PIN_A1))printf("go left\r");
   while(Input(PIN_A2))printf("go right\r");
if (getc()=='1')remote();
}
}

//main//
void main()
{
  printf("Welcome:,\n\r");
  printf(" \n\r");
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");

  while(true)
  {
    if (getc()=='1')remote();
    if (getc()=='2')autonomous();

  }

}
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Jan 09, 2009 3:53 am     Reply with quote

I can't believe FvM sugested using goto to fix your problem!

You have 2 options, The first requires very little change to the way your are doing it but will limit you to only the 2 loops. And is basically a really silly way to do it.

The break instruction will exit a while loop!

Code:

//remote loop
void remote()
{
while(1){
    if (getc()=='4')printf("go foward\r");
    if (getc()=='5')printf("go left\r");
   if (getc()=='6')printf("go right\r");
if (getc()=='2')break;
}
}

//autonomous loop
void autonomous()
{
while(1){
     printf("go foward\r");
   while(Input(PIN_A1))printf("go left\r");
   while(Input(PIN_A2))printf("go right\r");
if (getc()=='1')break;
}
}

//main//
void main()
{
  printf("Welcome:,\n\r");
  printf(" \n\r");
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");

  while(true)
  {
    if (getc()=='1') {
      while(true) {
         remote();
         autonomous();
      }
    if (getc()=='2') {
     while(true) {
         autonomous();
         remote();
      }
  }
}


I was just going to try and show you the second way but before I do that there are really big problems with your code. As pointed out, by using getc you code will stop and wait for a keypress before continuing, it may appear to be working ok but you should have noticed that you need to send the same value several times for it to perform the correct action!
Also by fixing this you will simplify your code:-

Code:



//remote loop
void remote(int key)
{
    if (key=='4')printf("go foward\r");
    if (key=='5')printf("go left\r");
   if (key=='6')printf("go right\r");
}

//autonomous loop
void autonomous()
{
     printf("go foward\r");
   while(Input(PIN_A1))printf("go left\r");
   while(Input(PIN_A2))printf("go right\r");
}

//main//
void main()
{
  int mode = 0
  int key;

  printf("Welcome:,\n\r");
  printf(" \n\r");
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");

  while(true)
  {
      if (kbhit())  // If a key has been pressed
        key = getc();  // Save the key
      else
        key = 0;

    if (key == '1')
      mode = 1;
    else if (key == '2')
       mode = 2;

    if (mode==1)remote(key);
    if (mode==2)autonomous();

  }

}


This will make it work the same way where you have to hold a key down to make it perform that action continously, but if you want it to continue the same action even if you let go of the key then just remove the

else
key = 0;

lines.
IceMetal



Joined: 20 Nov 2008
Posts: 79
Location: white Plains, NY

View user's profile Send private message Yahoo Messenger

PostPosted: Fri Jan 09, 2009 12:35 pm     Reply with quote

thank you so much Wayne that really helped me alot!!!!!!!!!!!!!!!!!!!!
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Jan 09, 2009 12:45 pm     Reply with quote

Quote:
I can't believe FvM sugested using goto to fix your problem!

Believe it or not! Basically, I mentioned why staying in a loop most likely isn't a solution for a real application. But if it would be, goto is a suitable solution, you can use a lot of others too. It's legal C code.

Code:
void main()
{
  char c;
  printf("Welcome:,\n\r");
  printf(" \n\r");
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");

  while(true)
  {
   c=getc();
   if (c =='1')
   while(1){
remote:   
      c=getc();
      if (c =='4')printf("go foward\r");
      if (c =='5')printf("go left\r");
      if (c =='6')printf("go right\r");
      if (c =='2') goto  autonomous;
   }
   if (c =='2')
   while(1){
autonomous:
     printf("go foward\r");
     while(Input(PIN_A1))printf("go left\r");
     while(Input(PIN_A2))printf("go right\r");
     if (kbhit() && getc()=='1') goto remote;
   }
  }
}
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Jan 09, 2009 9:29 pm     Reply with quote

Gotos really should be avoided, particularly for such a simple loop. My first take was:
Code:
void main()
{
  int1 remote = TRUE;
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");
  for (;;)
  {
    if (kbhit())
    {
      switch (getc())
      {
        case '1':
          remote = TRUE;
          break;
        case '2':
          remote = FALSE;
          break;
        case '4':
          if (remote) printf("go forward\r");
          break;
        case '5':
          if (remote) printf("go left\r");
          break;
        case '6':
          if (remote) printf("go right\r");
          break;
      }
    }
    if (!remote)
    {
      printf("go forward\r");
      if (input(PIN_A1)) printf("go left\r");
      if (input(PIN_A2)) printf("go right\r");
    }
  }
}
but I didn't like the duplicate code for left/right/forwards. So then I came up with:
Code:
void main()
{
  int1 remote = TRUE;
  printf("Press 1 for remote\r");
  printf("Press 2 for autonomous\r");
  for (;;)
  {
    int8 c = 0;
    if (kbhit())
    {
      c = getc();
      if (!remote && c >= '4') c = 0; // no remote control in autonomous mode
    }
    else if (!remote)
    {
      c = '4';
      if (input(PIN_A1)) c = '5';
      if (input(PIN_A2)) c = '6';
    }

    switch (c)
    {
      case '1':
        remote = TRUE;
        break;
      case '2':
        remote = FALSE;
        break;
      case '4':
        printf("go forward\r");
        break;
      case '5':
        printf("go left\r");
        break;
      case '6':
        printf("go right\r");
        break;
    }
  }
}
All the previous code examples suffer from the potential problem in autonomous mode where if the inputs stay high, you'll never be able to switch to remote mode.
_________________
Andrew
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Jan 10, 2009 3:43 am     Reply with quote

Quote:
Gotos really should be avoided
Any arguments?

To my opinion,you really should avoid to code state machines in an unstructurized way. For this reason, any of the suggested examples is effectively bad coding style (at least from an embedded application point of view). My goto version simply emphasizes this bad style instead of hiding it. You immediately see, that you're stuck in a loop, as apparently intended.

To find a better coding style, you should analyze the application purpose first and define a meaningful behaviour. The original post indicates, that this hasn't been done yet. It's generally difficult to apply improvements to an inconsistent code.
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Sat Jan 10, 2009 7:59 pm     Reply with quote

Speaking of coding style, something I meant to mention before relates to the first two code samples provided by IceMetal:

http://www.ccsinfo.com/forum/viewtopic.php?p=109099#109099
http://www.ccsinfo.com/forum/viewtopic.php?p=109115#109115

They are just plain wrong under all circumstances, from embedded systems to supercomputers. The problem is that firstloop() and secondloop() are always calling each other and never returning. This will eventually cause any computer to run out of memory and crash. Embedded systems will just get there first due to less memory. Smile
_________________
Andrew
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