View previous topic :: View next topic |
Author |
Message |
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
Strange behavior when NOT using ICD=TRUE |
Posted: Fri Sep 17, 2010 12:27 pm |
|
|
I am wanting to use a PIC to receive Binary data over an RS232 line. To test this, I have wired up a LED Bargraph (cathodes to Port D, anodes to +5v) so that I can display what the UART actually received.
When the UART receives a byte, I do a bit-invert, then write that out to Port D. The inverted bits are now '0' out of the port, turning on the LED segment.
I am using the PIC 16F877A Development kit, PCW v4.069, CCS's ICD-U40, and the SIOW program that comes with PCW.
The SIOW has a screen that allows you to send hex data to the serial port. Entering '0' and hitting 'send' sends a data byte of 0 across, and none of the LED segments should light. Sending 'FF' should light all of the LED segments.
With #device ICD=TRUE set, the system behaves as expected. However, when I remove the ICD=TRUE directive it does NOT work correctly. Up through maybe 7F things work as expected, but if I enter 'FF' I see the LEDs flash on, then immediately off. I also get this odd behavior on some other values, which doesn't seem to have any logic to the pattern.
What's going on here with ICD=TRUE?????
Here is the entire code:
Code: |
#include <16F877A.h>
//#device ICD=TRUE
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
BOOLEAN rd_ready;
BYTE received_data;
#int_rda //receive data is available
void serial_isr()
{
if(rd_ready == false)
{
received_data = getc();
rd_ready = true;
}
}
void main()
{
enable_interrupts(int_rda);
enable_interrupts(global);
do {
if(rd_ready == true)
{
received_data ^= 0xff; //invert received data, to drive LEDs
output_d(received_data);
rd_ready = false;
}
}
while (TRUE);
} |
Cheers,
Steve |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 17, 2010 12:48 pm |
|
|
Quote: | #int_rda //receive data is available
void serial_isr()
{
if(rd_ready == false)
{
received_data = getc();
rd_ready = true;
}
} |
This is bad design. If you get an RDA interrupt, then you have a byte
in the hardware UART's receive buffer. It must be read, or you'll
keep on getting the interrupt constantly. Don't put a condition on calling
getc() inside the isr. Just get it.
In fact, if more than 2 bytes come in to the hardware UART and you
don't get them, the UART receiver will get an overrun error and it will
lock up. You won't be able to get any bytes until you clear the error.
This is why it's a good idea to add the ERRORS parameter to your
#use rs232() statement. Then the compiler will insert code to
automatically clear any overrun errors that may occur. You'll still lose
the chars, but at least the UART's receiver won't remain locked up. |
|
|
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
|
Posted: Fri Sep 17, 2010 1:05 pm |
|
|
PCM,
I changed the ISR to the following, as per your suggestion;
Code: | #int_rda //receive data is available
void serial_isr()
{
received_data = getc();
rd_ready = true;
}
|
This had no effect on the problem of strange behavior when compiled WITHOUT the ICD=TRUE. I still get the (??chip reset??) problem.
Other thoughts?
Cheers,
Steve |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Sep 17, 2010 2:20 pm |
|
|
Hopefully some series resistors to the bargraph. Otherwise you are overloading the chip, and potentially resetting it....
Best Wishes |
|
|
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
|
Posted: Fri Sep 17, 2010 2:28 pm |
|
|
Good suggestion on the resistors - I will add them.
BUT.... that is not my problem - the system is not behaving the same when I delete the #device ICD=TRUE statement, as it does when I DO include the statement.
Cheers,
Steve |
|
|
eyewonder300
Joined: 09 Jun 2004 Posts: 52
|
|
Posted: Fri Sep 17, 2010 2:36 pm |
|
|
Well, I sure don't understand it, but putting the resistors in line with the LEDs has allowed the board to work as expected, without the ICD=TRUE directive - which is how it would be programmed eventually.
Thanks for the help.
Cheers
Steve |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Sep 17, 2010 2:47 pm |
|
|
I did a file comparison (using ExamDiff) between the .LST files with
ICD=TRUE enabled, and with it commented out.
There is a difference in the fuses:
With ICD=TRUE enabled:
Quote: | Word 1: 373A HS NOWDT NOPUT DEBUG NOPROTECT NOBROWNOUT NOLVP NOCPD NOWRT |
With ICD=TRUE commented out:
Quote: |
Word 1: 3F72 HS NOWDT PUT NODEBUG NOPROTECT BROWNOUT NOLVP NOCPD NOWRT |
Other than NODEBUG, two other differences are that ICD=TRUE disables
the PUT fuse and the BROWNOUT fuse. They are enabled when ICD=TRUE
is commented out. What if your bargraph is heavily loading down the
power supply ? What if the Vdd voltage for the PIC is drooping below
the Brownout voltage ? With ICD=TRUE enabled, there is no Brownout
fuse, so the PIC would keep on running (probably) as the Vdd drooped
down to say, 4.0 volts. But without ICD=TRUE, you will have a Brownout
reset. The Vbor voltage for the 16F877A is typically 4.0v, but can be
as high as 4.35 volts.
Solution: Add the series resistors, and/or beef up the power supply. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sat Sep 18, 2010 8:08 am |
|
|
With ICD=TRUE I believe the ICD-U40 controls MCLR. If you have not got a say 47k pull up on MCLR then when running without ( icd=true) the ICD-u40
frees MCLR to whatever you have as external circuitry. You probably have a good pull up on MCLR so this advice is just in case you forgot. |
|
|
|