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

async serial problem with 16F876
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
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

async serial problem with 16F876
PostPosted: Mon Apr 07, 2008 7:06 pm     Reply with quote

I can't see what is wrong here, does anybody see anything ?

I believe the following program should output a pattern of bytes, counting up. The problem is the idle time between bytes is not always high as it should be, but is following the least significant bit of the last sent byte(first data bit sent on the line).
Using a 16F876 with a 4mHz crystal, CCS 4.068 Compiler
Code:

#include "16F876.h"
#fuses XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay (clock=4000000,oscillator)
#use standard_io(C)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
void main (void)
{
   unsigned char a;
   PORTC = 0x00;
   set_tris_C(0x00);       
   for (;;) {
      a++;
      fputc(a);
      delay_ms(5);
   }  // end of forever for loop
}     // end of main()
Matro
Guest







PostPosted: Tue Apr 08, 2008 2:38 am     Reply with quote

You don't need the 5ms delay since fputc will wait for the end of the transmission.

But maybe the problem is your #use rs232 line where you don't configure the packet pattern i.e. number of sent bits, parity and stop bit length.
The "standard" is 8-N-1 that gives :
Code:

#use rs232(baud = 9600,xmit=PIN_C6,rcv=pin_C7,bits=8,parity=N,stop=1)

But you have to check that the receiver has the same configuration.

Matro.
Ttelmah
Guest







PostPosted: Tue Apr 08, 2008 4:40 am     Reply with quote

Your description of the problem, doesn't make a lot of sense.
However, key thing may be that there _will not_ be a delay for the character at all!.
The chip has a single character of hardware buffering. When you fputc the first byte, this is simply loaded into the hardware buffer, and the command _returns immediately_, leaving the hardware to get on with sending the byte. You then pause for 5mSec, during which time, the byte is sent, At the end of this time, you reload the output buffer, and start again. So as shown, there will be exactly 5mSec (plus the small amount of time needed for the loop), between the _start bits_of the characters. There won't be 5mSec _between_ the characters.
This is the whole 'key' of the hardware UART, since you can get on, and do other jobs _while_ the character is transmitting.
If you want to actually have 5mSec of 'gap' between the characters, then you need to wait for the first character to 'send', _before_ beginning your delay. You can do this by monitoring the TXSTA bit. So:
Code:

#bit TXSTA=0x98.1

void main (void)
{
   unsigned char a;
   PORTC = 0x00;
   set_tris_C(0x00);       
   for (;;) {
      a++;
      fputc(a);
      //Now wait for the character to actually send
      while(TXSTA==0) ;
      //You now get here _after_ the character has transmitted
      delay_ms(5);
   }  // end of forever for loop
}     // end of main()


Hope this is what you meant.

Best Wishes
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

PostPosted: Tue Apr 08, 2008 8:54 am     Reply with quote

Thanks folks for looking at it, but the problem is not one of timing. This is a minimum piece of code extracted from a much larger application which shows the problem. 1) I have tried all combinations of bits, parity and stop for the #use statement, all to no avail. 2) The purpose of the 5ms delay(5ms is arbitrary) is to provide a chance to see (with a scope) the TX line between characters. The real application sends data sporadically and there is a lot of idle time on the TX line. The problem is the state of the TX line between characters. It is supposed to be a logic high( just as during a stop bit) and to be ready for the leading edge of the next start bit. This instance is instead leaving TX in the state of the LS bit of the last sent byte. Hence, depending on the odd-even state of the previous byte, the start bit does not even appear as the idle state of the TX line is wrong half the time.

I have even tried this using other non-uart pins and the software uart, and the software uart works perfect. I have never seen another hardware uart behave this way, be it a standalone uart or one embedded in a micro. I just find it difficult to believe that the pic uart is this non functional, it has got to be something I am doing here. I have tried multiple 16f876 chips, I even went back to CCS 4.023 compiler (oldest I have) and the problem persists.

One effect here, if every "packet" or grouping of bytes sent (bytes with no idle time between bytes) and the packet ends with a byte whose LS bit is a 1 (which is the bit immediately after the start bit) then the idle line is correct and subsequent bytes are structured and received just fine. For example if the "packet" ends with a CR (0x0d) it works, if it ends with a LF (0x0A) the subsequent byte cannot be received as the idle line is in the start start instead of the idle state. I am just sending one byte with the counting pattern here so the problem can be seen after every other byte sent.
Matro
Guest







PostPosted: Tue Apr 08, 2008 9:10 am     Reply with quote

Please try to copy-paste the code line of my previous post and let us know.
normally after each byte the stop bit should be generated (stop bit is a logical high) so your line should always remain to high.

Anyway it looks like a bad configuration of the USART.

Matro.
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

PostPosted: Tue Apr 08, 2008 9:34 am     Reply with quote

I put in the code suggested by Matro as:

#bit TXSTA=0x98.1

void main (void)
{
unsigned char a;
PORTC = 0x00;
set_tris_C(0x00);
for (;;) {
a++;
fputc(a);
//Now wait for the character to actually send
while(TXSTA==0) ;
//You now get here _after_ the character has transmitted
delay_ms(5);
} // end of forever for loop
} // end of main()

The only effect is that the timing changes from approx 5ms from start of one byte to start of next, to 5ms between bytes. That is not the problem. As Matro stated "normally after each byte the stop bit should be generated (stop bit is a logical high) so your line should always remain to high." is what I would expect, but that is not what is happening. The idle state(following stop bit) is still following previous byte ls bit, instead of being a logic high(like the stop bit itself). Yes I agree it looks like a uart configuration error, thats what I can't find.
Matro
Guest







PostPosted: Tue Apr 08, 2008 9:42 am     Reply with quote

Maybe here come the explanation.
fputc() is used for stream (refer to CCS help) and so that's maybe why it doesn't release the line.
Your use of fputc() is not compliant with CCS help.
Try to replace fputc() by putc() or putchar() function and tell us.

Matro.
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

PostPosted: Tue Apr 08, 2008 9:50 am     Reply with quote

My original application in fact used streams to manage both the hardware uart and a software uart, but I had removed all but the fputc for this simple example that shows the failure. I tried both putc and putchar and the behavior is exactly the same.
Matro
Guest







PostPosted: Tue Apr 08, 2008 9:58 am     Reply with quote

You can also :
- remove your set_tris_c() that is not needed since you use standard_io (my advice is to remove it)
- remove "unsigned" just before "char a". A "char" is an "unsigned int8" so tha is not needed.

I don't see how the problem could be in these 2 lines but please remove the 1st and correct the 2nd and tell us.

Matro.
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

PostPosted: Tue Apr 08, 2008 10:06 am     Reply with quote

As suggested:
- remove your set_tris_c() that is not needed since you use standard_io (my advice is to remove it)
- remove "unsigned" just before "char a". A "char" is an "unsigned int8" so tha is not needed.

Changing the variable a to "char" has no effect, no change. Removing the set_tris_c statement makes it not work at all, no uart output. Changing the set_tris_c to 0xFF also makes it not work at all, no uart output.
Matro
Guest







PostPosted: Tue Apr 08, 2008 11:10 am     Reply with quote

So please post a complete "compilable" code that demonstrates the error with all preprocessor directives.

Matro.
dbroker



Joined: 27 Mar 2008
Posts: 8
Location: San Diego CA

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

PostPosted: Tue Apr 08, 2008 11:16 am     Reply with quote

As "compliable" as it gets...This is the whole program....with your suggestions..........still fails

#include "16F876.h"

#fuses XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay (clock=4000000,oscillator)
#use standard_io(C)

#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,bits=8,stop=1,parity=n)
#bit TXSTA=0x98.1

void main (void)
{
char a;

PORTC = 0x00;
set_tris_C(0x00);
for (;;) {
a++;
putc(a);
while(TXSTA==0) ;
delay_ms(5);
} // end of forever for loop
} // end of main()
Matro
Guest







PostPosted: Tue Apr 08, 2008 11:39 am     Reply with quote

Try just that :
Code:

#include "16F876.h"

#fuses XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay (clock=4000000)

#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,bits=8,stop=1,parity=n)
#bit TXSTA=0x98.1

void main (void)
{
char a;
for (;;) {
a++;
putc(a);
delay_ms(5);
} // end of forever for loop
} // end of main()


Could you confirm that your clock is generated by an external Xtal?

Matro
piripic



Joined: 15 Jan 2008
Posts: 25

View user's profile Send private message

PostPosted: Tue Apr 08, 2008 12:54 pm     Reply with quote

Hi, I just made a simulation (on proteus) and it work good. I see always on the TX line a high level between the chars (about 6 ms from start edge to next start edge).

This is the test code:

Code:
#include "16F876.h"

#fuses XT,NOWDT,NOPUT,NOPROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay (clock=4000000,oscillator)
#use standard_io(C)

#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,bits=8,stop=1,parity=n)
#bit TXSTA=0x98.1

void main (void)
{
   char a;

   output_c(0x00);
   set_tris_C(0x00);
   for (;;) {
      a++;
      putc(a);
      while(TXSTA==0) ;
      delay_ms(5);
   }
}



Maybe your pic is damaged ? Check the oscillator and the supply voltage.

Claudio
Ttelmah
Guest







PostPosted: Tue Apr 08, 2008 2:39 pm     Reply with quote

Ages ago, I had problems like this with the 16F876. It turned out that on one batch of the chips, the TRIS bits for the serial pins had to be set differently, from the settings on the data sheets. The 676, is 'odd', in requiring both TRIS bits to be set to '1' for serial I/O (most later chips require them to be set to '0'). On this batch, the TRIS for TXD, had to be set to '0', or the output behaved oddly. It was reported to Microchip, and they simply replaced the chips. It has never appeared in an erratum for the chips, and seemed to be a 'rogue' faulty batch. i wonder if the chips you have come from the same batch!...
Try manually setting the TRIS bit to 0 (define the bit using a #bit instruction, and clear this - you need to do this, rather than using the compiler instructions, since you don't want the compiler to 'know' that you are doing this, and change it back!).

Best Wishes
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