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

I got a problem about my Code. I can not figure out...
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
Need Help
Guest







I got a problem about my Code. I can not figure out...
PostPosted: Wed Aug 27, 2008 2:18 am     Reply with quote

Dear Folks,

I got a problem about my Code.

I am communicating between two PIC 16f877.

I hope that PIC A send "2" to PIC B and PIC B add 1 to 2 (it will become 3) and then PIC B send 3 to PIC A. When PIC A get the number which is from PIC B, PIC A will add 1 again and send the number (it will be 4) back.

I am using the 7-segment to display these numbers. My problem is that the 7-segment show nothing but 0.

Any help will be appreciate.
Thank you very much.
Sincerely,

The following is my code. Could you tell me where is the problem?
PIC B part:
Code:

#include<16F877.h>
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

int a,b,e,f,i;

void main()
{
set_tris_b(0xFF);
set_tris_d(0x00);

       
while(1)
  {
 .............. // I ignore the hardware communication
 .............. //  code.
 ..............
 ..............
         
           a=getc();
           if(a==1)
           {
           
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
           }
           else
           {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
               
           }
                         
           delay_ms(100);
           b=a+1;
           delay_ms(30);
           puts("b");
           delay_ms(100);
           e=getc();
           if(e==3)
            {
             
                output_high(PIN_D0);
                output_high(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
            }
            else  // this mean if the do not get the number, show "0"-->"9"-->"0"
            {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
               
              }     
           delay_ms(100);
           f=e+1;
           delay_ms(3);
           puts("f");
           
           i=getc();
           if(i==5)
           {
             
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_high(PIN_D2);
                output_low(PIN_D3);
           }   
           else
           {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
               
           }     
         
           }
        }
}


PIC A :
Code:

#include<16F877.h>
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)


int c,d,g,h;



void main()
{
    delay_ms(1000);
    puts("1");
    delay_ms(1000);
   
   
    c=getc();
    if(c==2)
    {
    delay_ms(100);
    d=c+1;
    delay_ms(30);
    puts("d");
    delay_ms(100);
    }
   
   
    g=getc();
    if(c==4)
    {
    delay_ms(100);
    h=g+1;
    puts("h");
    delay_ms(100);
    }
   
}
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Aug 27, 2008 8:37 am     Reply with quote

Start by seeing if A sends what it should. Then see if B receives it properly. The do the same for B to A. Also check that your display routine works.

Why do you have so many delays?

Code:
    c=getc();
    if(c==2)
    {
    delay_ms(100);
    d=c+1;
    delay_ms(30);
    puts("d");
    delay_ms(100);
    }
 


Why not just use
Code:
    c=getc();
    if(c==2)
    {
    delay_ms(230);
    d=c+1;
    puts("d");
    }
 

_________________
The search for better is endless. Instead simply find very good and get the job done.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Aug 27, 2008 8:45 am     Reply with quote

First of all, if you're going to communicate with other devices via the serial port then it's best to use the hardware built into the PIC. It's easiest to use the interrupt to detect data coming in.

Next, in your puts() routines, you're not sending a number but rather the character. When you entered puts("b") what is happening is you're sending the _character_ b and not it's value. If you want to send the _value_ of the variable 'b' then you need to use printf(). For instance:

printf("%d", b);// prints the value of b

or

printf("%d", 1);// prints the number 1 and not the character "1" which is hex 31

That will send whatever value 'b' happens to be.

Look through the forum and see how others use ISRs to send and receive data. Simply placing a getc() in the main code is not an effective way to doing things. That, effectively, forces the PIC to hault on that line until something comes along the serial port.

Also, setting the TRIS does nothing unless used with FAST_IO. Remove these commands and allow the compiler to control the direcion of the ports for you.

You might want to add ERRORS to your #use rs232 to keep the port from locking up.

Ronald
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Wed Aug 27, 2008 8:56 am     Reply with quote

rnielsen is not entirely correct.

If you use the printf as he has stated you will send the ascii equivilent of the variable so

b = 1;
printf("%d", b); // will send "1" (ascii)
b = 12;
printf("%d", b); // will send "12" (ascii)

When you recieve the char you are treating it as if you have recieved the value 1 and not an ascii char '1' which is actualy decimal value 49.

What you need to be doing is just sending the value of b so

putc(b);

No quotes, no printf, this will simply put the value of b (1) on the serial line.

Also use
putc(1);
NOT
putc("1"); as this will put the value 49 (0x31 hex) on the serial line.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Aug 27, 2008 10:02 am     Reply with quote

There might be a problem with your oscillator setup. Post your #fuses line so we can check.

You have a lot of delays in the code. This makes it possible the UART is receivng more data then it can buffer (3 characters max.). If this happens the UART will stop receiving. To prevent the UART from stalling add the ERRORS keyword to the #rs232 line, you still miss data but at least the UART wil not stop.
Need Help
Guest







I got a problem about my Code. I can not figure out...
PostPosted: Thu Aug 28, 2008 12:12 am     Reply with quote

Hello,

Thank you for you guys' suggestion. I am using USART to TX and RC the numbers.

To Wayne_:

Thank you for your reply and suggestion.

I tried your suggestion. I changed all puts to puc and putc("b") to putc(b) but the result is the same. The 7-segment show "9"-->"0"-->"9" so it look like that the PIC B do not get the 1 from PIC A. When I try the same way like transmitting a word which is " Hello ", it can be shown on my Hyper terminal window. I mean when I use the sample command while (1), it keep showing the word on the Hyper terminal.

Do you have other suggetions?

To rnielsen:

Thank you for your reply and suggestion.
I set the TRIS is for my 7-segment to display the numbers which I hope that I can get.


To ckielstra:

I am beginner for this field. I do not know what the #fuses line is. Could you explain it to me? Thanks a lot.

I am also confused about delay. I think that the delay is to allow the USART to get time to deal with the data which USART get. Is it correct?
If it is correct, what do you mean stop receiving?

I also do not understand what is the the ERRORS keyword and how to add the ERRORS keyword?



Again, Thank you for your guys help and reply. Could you explain my questions and give me some suggestions about my problem.




Any help will be appreciated. Thank you so much.



Sincerely.
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Aug 28, 2008 2:34 am     Reply with quote

getc will wait for a char to come in so you don't need a delay before it, remove them.

You must turn PIC B on first and then PIC A for your code to work otherwise it will be in a deadlock situation with both pics waiting for a char to come in.

Because you are using values below 32 (0x20) space these will not be printable on hyperterminal so you will not see a 1 displayed for a putc(1); You may notice strange chars or the cursor move with some values but I wouldn't count on it with the values you are using.

If you want to see the values on hyperterminal you would have to convert the value to ascii using printf("%d", a);

Once you have made these changes, re-post your code which should now be alot smaller Smile
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Aug 28, 2008 2:48 am     Reply with quote

There are also some other problems with your code.

The first is a bug

Code:

  g=getc();
    if(c==4)  // <-------------This should be if (g == 4)
 


This bug means PIC A will never send h, i recieve the value 1 then both PICs will wait for chars A at c = getc() and B at a=getc() (deadlock)

The second is this
PIC A ---------- PIC B
put(1) ---> a = getc()
c = getc() <--- put(b)
if (c == 2)
put (d) ---> e = getc()
g = getc() <--- put(f)
if (c == 4)
put (h) ---> i = getc()

If PIC B does not recieve the initial 1 but gets some other value instead then when it puts(b) this value will not be == 2, PIC A will NOT then send a value back so PIC B will wait at e=getc() for a char, PIC A will then wait at g=getc() for a char and you will be in a deadlock situation.

1 last thing, when it displays "9" - "0" - "9" does it stop at "9" or does it continue to alternate "0" - "9" - "0" etc... ?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Aug 28, 2008 5:31 am     Reply with quote

The #fuses line is code for configuring the PIC Configuration bits (see chapter 12.1 in the PIC16F877 data sheet). Without specifying these fuses the compiler will choose a default setting which most likely is not correct for your hardware setup.
The most important fuses are:
    - Clock configuration: XT for an external crystal <= 4MHz, HS for an external crystal >= 4MHz. For more options check the data sheet and the top of the header file for your chip.
    - NOLVP: disables the Low Voltage Programming mode. Nobody uses these type of programmers. Disabling the feature makes pin B3 available and prevents some difficult to find problems.
    - NOWDT disables the watchdog


Quote:
I also do not understand what is the the ERRORS keyword and how to add the ERRORS keyword?
The hardware UART is designed to stop receiving when it's receive buffer is full (3 characters). To start the UART again you have to reset some error flags in the UART. By adding the ERRORS keyword the compiler will add some extra code for clearing these error flags.
Your code has a lot of delays, so maybe the receive buffer never overflows, but it doesn't hurt and is a good habit to always add the ERRORS keyword.

Code:
#include<16F877.h>
#fuses HS, NOLVP, NOWDT            // added
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)   // Added ERRORS to reset error flags.
Need Help
Guest







I got a problem about my Code. I can not figure out...
PostPosted: Fri Aug 29, 2008 12:33 am     Reply with quote

Hello,

Thank you for you guys' suggestion and explain again. I really appreciate it.

Now I am out of town so I can't change my code and test you guys' suggestion right now.

I will do that tomorrow and let you guys know the result as soon as possible.


To Wayne:

Thank you again. I got several questions. First of all, why do I need to turn the PIC B on first. How different if I turn the PIC A first?

Secondly, you are correct. I saw some strange chars on Hyper terminal but I am not sure what that is. I do not need to see these numbers (1,3,5) on the Hyper terminal. I hope that they can be shown on the 7-segment so does it mean that I do not need to change the code from putc() to printf ("%d", a)?

Thirdly, My 7-segment is located in PIC B. On the 7-segment, I just saw "9"-->"0"-->"9" and finally it stop at "9" so what does it mean?

Thank you again, Wayne. Thank you answer my question and help me. Do you have any suggestion for the code? Which part I should change?


To ckielstra:

Thank you for your reply. You explain it very clearly. I will test it again and let you know the result as soon as possible.

I got a question about NOLVP. You mention ==> "Disabling the feature makes pin B3 available and prevents some difficult to find problems." Why do we need to make B3 available and how to make it available? Does it mean that we have to avoid using PIN B3?
Thank you, ckielstra. I learned a lot of new knowledge from your explain.

Thank you guys again. Thank you for your reply and suggestion.

By the way, I also post the part of code about PIC communication. I hope that it is help to answer my question.

the hardware code is following:

Code:
if(input(PIN_B4))
           {
           .............................. //Because the hardware commucation do all
           ..............................//right, I ignore part of the communication
           ..............................//code.
           delay_ms(1000);
           puts("g!");               //this is for the development board.
           delay_ms(1000);
Ttelmah
Guest







PostPosted: Fri Aug 29, 2008 2:15 am     Reply with quote

If LVP is enabled, pin B3, becomes permanently used for programming, and can't be used for anything else. Hence it is 'not available'. If you don't need the pin, then this in itself doesn't matter. _However_, if LVP is enabled, you then have to make absolutely sure, that this pin cannot 'float'. Unconnected input pins are always a problem. The internal 'diode' structures in the chip, tend to act so that if there is any interference floating about (there will be...), these pins will often get noticeable voltages developed on them. On 'normal' pins, this can result in the chip drawing extra power (a pin sitting in the 'indeterminate' region between a logic high, and a logic low, results in internal gates drawing extra power...), hence it is always 'bad practice' to leave pins floating in general. On the programming pin though, if the pin floats high, the chip can 'accidentally' enter programming mode, resulting in destruction of the contents of the program memory, which is rather worse.... So, if LVP is enabled, you can't use RB3, and _must_ add a resistor to this line, pulling it to 0v. Since most people never use LVP, it is better, safer, and easier, to ensure this fuse is not selected.

Best Wishes
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Aug 29, 2008 2:28 am     Reply with quote

This is your message state for your pics

PIC A ---------- PIC B
put(1) ---> a = getc()
c = getc() <--- put(b)
if (c == 2)
put (d) ---> e = getc()
g = getc() <--- put(f)
if (c == 4)
put (h) ---> i = getc()

As you can see, as soon as you turn on PIC A it will output the value 1. As you are not using flow control PIC A will just send the value of 1 out of the serial port even if PIC B is not on. PIC A will then continue to the line c=getc() and wait for a char.
You now turn PIC B on and PIC B waits for a char, PIC A has already sent it and because PIC B was not on it missed it. PIC B is now waiting for a char at line a=getc();
As they are both waiting this will be a deadlock and will not do anything.

With your curent setup you cannot use hyper terminal to monitor the data between the 2 pics. If you try to just change the putc to printf your code will not work.
The only ways you can see what is going on is to:
1. Use a second serial port for debug
2. Change your code to work with values
'1' (49), '2' (50), '3' (51) Ascii char (decimal value).
You would need to change your code as in if (c=='1') which is the same as if (c==49).
3. Just rely on the 7-segment output.

I would opt for option 3 as the display appears to be working corectly.

But saying this, you have actually seen something on hyperterminal, even though it is not recognisable this implies that some form of serial communication is going on.

The display of "9" --> "0" --> "9" and then stops means that your code has stopped. Unfortunately your choice of output for the 7-segment does not indicate where this has happened.
Change your code so it displays a different output at each stage of the code, make sure this does not match any other value you are trying to display.
When it stops you will know where it has stopped.

If you are feeling really enthusiastic you could write an interrupt routine to display the recieved value by alternating the display between the upper HEX value and the lower HEX value. This would show you the actual values being recieved.

Or you could just leave the hyperterminal connected and put a printf("---%d---\r\n", a); after the a=getc();
This will display the value recieved but will cause the program to fail. If the value is correct, remove this printf and put one after the c=getc(); making sure you change the var in the printf. Again this will cause the program to fail but you will see what is happening and if it actually gets to that point.
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Fri Aug 29, 2008 2:31 am     Reply with quote

Actually, just change it so that the first block shows
"9" -- "0" -- "7"
The second
"9" -- "0" -- "8"
and the third
"9" -- "0" -- "9"

And post the results along with your latest code.
Need Help
Guest







I got a problem about my Code. I can not figure out...
PostPosted: Sat Aug 30, 2008 4:06 am     Reply with quote

Hello,

Thank you guys reply again. I try the ways which you guys told me but the result is the same.

To Wayne:

Thank you for offering so many suggestions. I really appreciate it. I changed the "else block" to "9"-->"0"-->"7" , "9"-->"0"-->"8", "9"-->"0"-->"9". I found that the 7-segment will run these block once and finally stop at "9". I think that it mean PIC A do not get "1" from PIC B. As you said, I use
while(1){
printf("1");
printf("2");
}
to show the number. I pretty sure that the PIC B send these two number to PIC A. The Hyper terminal can show the 12121212121212.........ans so on but I do not why it does not work to use putc(1).


To ckielstra:

Thank you for your suggestion. I tried to add #fuses HS, NOLVP, NOWDT but there are something weird. When I added #fuses HS, NOLVP, NOWDT, I can not download code to the microcontroller success. I tried lots of times but the result is the same. Could you know why?


To Ttelmah:

Thank you for explain it to me. Thank you so much. Do you know why I can not download the code to the microcontroller after adding the #fuses HS, NOLVP, NOWDT?


Thank you guys' suggestion again. Do you guys have any suggestion for my new test and my new code. I really appreciate you guys' suggestion. Thank you so much.

The follwing is the new code but I do not change to much. Because I do not know where I should changed, I do not change too much.


PIC B:
Code:
#include<16F877.h>
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)

int a,b,e,f,i;



void main()
{
   set_tris_b(0xFF);
                set_tris_d(0x00);

       
   while(1)
       {
      if(input(PIN_B4))
           {
           
           delay_ms(10);
           ................................... // ignore
           ...................................//
           ...................................//
           puts("g!");
           delay_ms(100);
             
      while(1)
{   
           a=getc();
           if(a==1)
           {
           
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
           }
           else
           {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_high(PIN_D1);
                output_high(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
               
           }     
           
                         
           
           b=a+1;
         
           putc(b);
         
           e=getc();
           if(e==3)
            {
             
                output_high(PIN_D0);
                output_high(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_high(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
            }
            else
            {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
               
           }     
                   
           
           f=e+1;
           
           putc(f);
           
           i=getc();
           if(i==5)
           {
             
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_high(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_high(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
           }   
           else
           {
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
                output_low(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_low(PIN_D3);
                delay_ms(1000);
                output_high(PIN_D0);
                output_low(PIN_D1);
                output_low(PIN_D2);
                output_high(PIN_D3);
                delay_ms(1000);
             
           }     
         
           }
}
}       
}


PIC A:
Code:
#include<16F877.h>
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)


int c,d,g,h;



void main()
{
while(1)
{
   

   putc(1);

    delay_ms(10);
   
   
c=getc();
if(c==2)
{
   delay_ms(10);
   d=c+1;
   delay_ms(30);
   putc(d);
   delay_ms(10);
   }
   
   
   g=getc();
  if(g==4)
    {
    delay_ms(10);
    h=g+1;
    putc(h);
    delay_ms(10);
    }
}   
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Aug 30, 2008 4:46 pm     Reply with quote

Quote:
I tried to add #fuses HS, NOLVP, NOWDT but there are something weird. When I added #fuses HS, NOLVP, NOWDT, I can not download code to the microcontroller success. I tried lots of times but the result is the same. Could you know why?
I checked the v4.077 compiler version. Without the fuses it will set the RC clock fuse. The RC-clock is only specified up to 4MHz. that's why I assumed you use a crystal for generating the clock (you specified 10MHz clock).

1) How are you generating the processor clock? (Crystal or RC-combination?)
2) What is your compiler version?
3) Are you using the PIC16F877 or the PIC16F877A? The first is very old and not recommended for new designs. If I remember correctly the 'A' version has to be programmed with a slightly different algorithm.
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