|
|
View previous topic :: View next topic |
Author |
Message |
dbroker
Joined: 27 Mar 2008 Posts: 8 Location: San Diego CA
|
async serial problem with 16F876 |
Posted: Mon Apr 07, 2008 7:06 pm |
|
|
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
|
|
Posted: Tue Apr 08, 2008 2:38 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 4:40 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 8:54 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 9:10 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 9:34 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 9:42 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 9:50 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 9:58 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 10:06 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 11:10 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 11:16 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 11:39 am |
|
|
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
|
|
Posted: Tue Apr 08, 2008 12:54 pm |
|
|
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
|
|
Posted: Tue Apr 08, 2008 2:39 pm |
|
|
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 |
|
|
|
|
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
|