|
|
View previous topic :: View next topic |
Author |
Message |
ramans
Joined: 10 Oct 2005 Posts: 9
|
Software vs Hardware UART on PIC16f877a |
Posted: Mon Oct 10, 2005 11:04 am |
|
|
Hi all I have some code below which I'm using to interface my PIC16f877a with a GPS module, I have stripped this down to illustrate my question.
Code: | #use delay (clock=20000000)
#use RS232(STREAM=gps,BAUD=2400, PARITY=N, BITS=8, XMIT=PIN_C6, FORCE_SW, RCV=PIN_C7, DISABLE_INTS)
#use RS232(STREAM=dbg,BAUD=9600, XMIT=PIN_D0, FORCE_SW, INVERT)
void main()
{
char str[80];
char ch;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);
setup_wdt(WDT_2304MS);
set_tris_b(0b11111011);
while(1)
{
output_high(PIN_B0);
delay_ms(500);
output_low(Pin_B0);
delay_ms(500);
fprintf(dbg,"blink yah\n\r");
fprintf(dbg, "fgetc ");
while(1)
{
ch = fgetc(gps);
fputc( ch, dbg );
restart_wdt();
}
}
}
|
This works just great the way it is but if I add a FORCE_SW to the RS232 statement for the GPS Stream that it fails. The issue of course being that for some reason the GPS works just fine with the Hardware UART but not with software.
I can use this same circuit with the same GPS And PIC with Pic Basic Pro and the software Serial port works just fine. Now I was using the UART for something else so I'd like to figure out why it's not working with a software UART, does anyone have any ideas?
thanks!
-Raman |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 10, 2005 12:38 pm |
|
|
If you can post a small program in PicBasicPro that works, then do so.
Especially post the setup code for the serial ports, because I wonder
if PBP is really using a software USART. |
|
|
ramans
Joined: 10 Oct 2005 Posts: 9
|
|
Posted: Mon Oct 10, 2005 2:05 pm |
|
|
PCM programmer wrote: | If you can post a small program in PicBasicPro that works, then do so.
Especially post the setup code for the serial ports, because I wonder
if PBP is really using a software USART. |
Certainly here's a sample. I know it's using the software UART because I'm using different PINs!!! I moved it to these pin's because I was having an issue and wanted to try the hardware UART out to see if that worked, which it did. here's a line of code it PBP that works:
Code: | GPSIn VAR PORTB.2
SerIn2 GPSIn,396,[wait("GPGGA,"),firstchar, DEC timeInt, DEC timeDec, DEC latInt, DEC latDec, DEC longInt, DEC longDec,DEC quality, DEC cSats]
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 10, 2005 3:30 pm |
|
|
1. What is your version of the compiler ? This will be a number such
as 3.191, or 3.236, etc. It's given at the top of the .LST file, which
is in your project directory.
2. Does the program you posted do anything, or does it lock up ?
Describe what it does. Does it display the text from these two lines ?
Code: |
fprintf(dbg,"blink yah\n\r");
fprintf(dbg, "fgetc ");
|
3. Post your #fuses statement. It looks like you're using PCW or
PCWH. I believe CCS puts the #fuses statement in some small
little .h file in your project directory.
4. In the program you posted, you're echoing incoming bytes from
the GPS out to the Debug port. In your PBP program, did you
do a test very similar to this ?
5. What is the byte data rate of the incoming GPS data ? Are there
any gaps between bytes ? If so, what are the size of the gaps in ms ? |
|
|
Guest
|
|
Posted: Mon Oct 10, 2005 3:39 pm |
|
|
Okay I'm using the 30day demo to see if I can do somethings with it that I can't get our existing copy of the Hi-Tech compiler to do (So far I can!) so we're planning on purchasing.
1) the compiler version is shown as: CCS PCM C Compiler, Version 3.236d, 11660 07-Oct-05 16:27
2) Yes it outputs the blink yah line, and the fgetc line then it output complete garbage, although it's consistent garbage, i.e. it looks just like it's at slightly the wrong baud rate or something. Removing the Force_SW line to make it use the Hardware UART on those two pins causes it to work as expected, producing the expected output. So it's almost as if the hardware UART as the correct BAUD rate but the software one does not.
3) Fuses statement ( in fact complete header file)
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES BROWNOUT //Reset when brownout detected
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000) |
4) Yes I did something similar in PBP and it works as expected
5) I'm not sure, I don't currently have a scope available to me to do this with, but I do know that if I use PBP or the Hardware UART I get the expected data. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 10, 2005 4:24 pm |
|
|
The first thing to do is change that fuse to NOLVP. |
|
|
ramans
Joined: 10 Oct 2005 Posts: 9
|
|
Posted: Mon Oct 10, 2005 4:48 pm |
|
|
PCM programmer wrote: |
The first thing to do is change that fuse to NOLVP. |
No good, same result. I should mention that I'm using EPICWin to program, so I went and checked the fuse settings there (Configuration) and I have the following set
Watch Dog
Brown Out
Flash Program Write
thank you!
-R |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 10, 2005 5:07 pm |
|
|
To test your problem further, I need to make a split RS232 cable adapter.
I might have one somewhere, but I can't work on it until tomorrow
morning. |
|
|
Guest
|
Re: Software vs Hardware UART on PIC16f877a |
Posted: Mon Oct 10, 2005 10:23 pm |
|
|
I noticed that the only "tris" statement in your code is for port_b.
Once you revert from the hardware USART to a software UART, you'll likely need also to provide a "tris_a" statement to assure your receive pin is an input and your transmit pin is set as an output. |
|
|
Guest
|
Re: Software vs Hardware UART on PIC16f877a |
Posted: Mon Oct 10, 2005 10:25 pm |
|
|
oops, meant to say a "tris_c" statement... |
|
|
ramans
Joined: 10 Oct 2005 Posts: 9
|
|
Posted: Tue Oct 11, 2005 9:40 am |
|
|
Definitely a good thought. As that's left over from when I moved the device from the pins I had been using to the hardware UART to test that. Changing the statement to "set_Tris_c" has no effect, I get the same output.
Here's the output in case it's helpful:
Code: |
blink yah
fgetc $#��R��c�,��kF#�c�,��#QLHt�YT#�K��c�,'�F���$#��R��c�,��KF#�c�,��#QLHt�Y
T#�k��c�,'�F���$#��R��c�,��KF#�c�,��#QLHt�YT#�K��c�,'�F���$#��R��c�,��KF#�c�
,��#QLHt�YT#�K��c�,'�F���$#��R��c�,��kF#�c�,��#QLHt�YT#�K��c�,'�F���$#��R��c�
,��KF#�c�,��#QLHt�YT#�K��c�,'�F���
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Oct 11, 2005 10:16 am |
|
|
Code: | while(1)
{
ch = fgetc(gps);
fputc( ch, dbg );
restart_wdt();
} | A problem with this code using software UARTs is that while you are transmitting data to the dbg port you are missing the first few bits of data comming in on the gprs port. With hardware UARTs this is no problem as these will buffer data while handling the other port.
If the data you are receiving is terminated with a newline character you can try an easy workaround using fgets() instead of fgetc().
I also added fast_io as it results in shorter code and to make sure the compiler doesn't mess with your TRIS settings.
Code: | #include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOLVP //<-- Changed //Disable Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay (clock=20000000)
#use RS232(STREAM=gps,BAUD=2400, PARITY=N, BITS=8, XMIT=PIN_C6, FORCE_SW, RCV=PIN_C7, DISABLE_INTS)
#use RS232(STREAM=dbg,BAUD=9600, XMIT=PIN_D0, FORCE_SW, INVERT)
#use fast_io(B); // <-- ADDED
#use fast_io(C); // <-- ADDED
void main()
{
char str[80];
char ch;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(VREF_LOW|-2);
setup_wdt(WDT_2304MS);
set_tris_b(0b11111011);
set_tris_c(0b10111111); // <-- Added
while(1)
{
output_high(PIN_B0);
delay_ms(500);
output_low(Pin_B0);
delay_ms(500);
fprintf(dbg,"blink yah\n\r");
fprintf(dbg, "fgetc ");
while(1)
{
fgets(str, gps); // <-- Changed fgetc() to fgets()
fputs(str, dbg); // <-- Changed fputc() to fputs()
restart_wdt();
}
}
} |
|
|
|
ramans
Joined: 10 Oct 2005 Posts: 9
|
|
Posted: Tue Oct 11, 2005 11:02 am |
|
|
First let me say Wow, this is great, I've gotten almost no feedback from my questions for That other compiler having this level of response is definitely making this the one to be using.
Now on to my experiments with the latest suggestions:
I added the fast_io code in (had to remove the ; at the end to get it compile, I think that's correct)
and no dice. What ends up happening is the watch dog timer ends up resetting before anything comes in off of the port. and I end up just getting repeated fgetc blink yah lines out. Disabling the watchdog timer causes a hang after the fgetc output.
Again switching off the software port, and using the hardware one causes it to behave as expected.
-R |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 11, 2005 11:29 am |
|
|
I don't have your exact hardware, but I made a test setup that
should be similar. I made a Rx/Tx splitter cable and connected
one cable to COM1 and the other to COM2 on my PC. I opened
two terminal windows, one for each COM port, and set one to 2400
and the other to 9600.
If I just type in text from the keyboard, there's little or no problem.
If I mash several keys at once ("asdf"), then I get bad characters
displayed. But that's what I'd expect. Here's a sample. The first part
is typed normally, and then I start mashing four keys at a time:
Quote: | asdfasdfasdfasdfasdfasdfasdfasdfafsdf�sdfX�df�d�f��dsf�df�d� |
But I think you have implied that somehow this all works flawlessly
with PicBasicPro. So I'm curious. I have PBP on my system.
Can you post a short but complete PBP test program, and do the same
test that I did above ? I would like to test it, and look at their .LST
file.
Here's my test program. The code generates two software UARTs.
Code: |
#include <16F877A.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#use RS232(STREAM=gps,BAUD=2400, RCV=PIN_C7)
#use RS232(STREAM=dbg,BAUD=9600, XMIT=PIN_C6)
//======================================
main(void)
{
char ch;
while(1)
{
ch = fgetc(gps);
fputc( ch, dbg);
}
} |
|
|
|
ramans
Joined: 10 Oct 2005 Posts: 9
|
|
Posted: Tue Oct 11, 2005 12:20 pm |
|
|
Here's some PBP code that works:
Code: |
DEFINE OSC 20
INCLUDE "modedefs.bas"
DEFINE DEBUG_REG PORTD
DEFINE DEBUG_BIT 0
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 1
baud VAR WORD
onoff VAR BYTE
LET baud = 396
again: Debug $0d,$0a
Debug "[Not Inverted] [",DEC baud,"] Hello."
LET onoff = 0
GoSub GetCurrentPosition
GoTo again
'
' Get Current GPS Position
'
GetCurrentPosition:
loop:
instr VAR BYTE[80]
IF onoff = 0 Then
High PORTB.0
onoff = 1
Else
Low PORTB.0
onoff = 0
EndIF
bvar1 VAR BYTE
bvar2 VAR BYTE
SerIn2 PORTC.7,baud,[STR instr\80\$0d]
Debug STR instr,$0d,$0a
GoTo loop |
|
|
|
|
|
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
|