|
|
View previous topic :: View next topic |
Author |
Message |
eatnumber1
Joined: 28 Oct 2006 Posts: 5
|
PIC16f88 sending garbage over rs232 |
Posted: Sat Oct 28, 2006 2:53 pm |
|
|
I have a PIC16f88 and have been trying to get it to send some kind of understandable data to the serial port on my computer. I am NOT using a
MAX232 chip or MOFETs, it is directly wired. I am also using the hardware UART.
My code is as follows:
Code: | #include <16f88.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //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=4000000)
#use rs232(baud=9600,xmit=PIN_B5,rcv=PIN_B2,parity=N,bits=8,ERRORS)
void main() {
// enable_interrupts(INT_RDA);
// enable_interrupts(GLOBAL);
while(true){
putc('A');
//printf( "Online\r\n" );
}
} |
No matter what I do, I just can't seem to get it to print anything but garbage... Anyone have any ideas? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 28, 2006 3:24 pm |
|
|
Quote: | I am NOT using a MAX232 chip or MOFETs, it is directly wired.
I am also using the hardware UART. |
The MAX232 has inverters in it. Your PC has the equivalent of a MAX232
in it, also. So if you don't have a MAX232 on your PIC board then the
PIC must invert the signal before it's sent out. Also, the received signal
must be inverted by the PIC.
This inversion can't be done with the hardware UART. It has no capability
to do this. This means you must use a software UART.
The CCS #use rs232() library will automatically create code to use the
hardware UART if you specify the hardware UART pins in the #use rs232()
statement. However, this is a way to overcome this. You can add the
FORCE_SW parameter to the #use rs232() statement. In addition to this,
you should also add the INVERT parameter. This will create the kind of
UART that you need, so it will work with your hardware connections.
Also, keep in mind that the PC will send out a +/- 10 volt levels to the
Rx pin of your PIC. These voltages exceed the specs for input pin.
The most common way to fix this problem is to put in a series resistor
on the Rx pin. A common value used for this is 22K ohms. This limits
the current, and the voltages are then clamped by the input protection
diodes on the PIC's Rx pin. If you already ran it without the resistor,
then it's possible that the Rx pin is burned up. You might have to
switch to using a different pin.
One more thing: You have the LVP fuse enabled. Are you using a Low
Voltage programmer, such as the "TLVP" ? That's not very common.
If you're using a normal programmer, such as ICD2, CCS ICD-U40,
PicStart-Plus, Warp13a, etc., then you should change the fuse to NOLVP.
With a software UART, you can't use INT_RDA interrupts. Delete the
lines that enable INT_RDA and GLOBAL interrupts. Also, the ERRORS
parameter doesn't work with a soft UART. The compiler will ignore it. |
|
|
eatnumber1
Joined: 28 Oct 2006 Posts: 5
|
|
Posted: Sat Oct 28, 2006 3:29 pm |
|
|
Thanks for the quick reply.
If I use a software UART, what are the limitations of this? Will I have to do anything special in order to use the serial?
Sorry about my complete lack of understanding about UARTs. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 28, 2006 3:39 pm |
|
|
The CCS software UART library uses instructions to "bit bang" an i/o pin
to create the waveforms. It uses software delay loops to create the
proper pulse lengths. It can't be interrupted during this time, or the
pulses will be the incorrect length. This applies to receiving data as well.
It puts a much higher load on the PIC's processing power. You can't do
multi-tasking as easily. For these reasons, most people try to use the
hardware UART. |
|
|
eatnumber1
Joined: 28 Oct 2006 Posts: 5
|
|
Posted: Sat Oct 28, 2006 3:49 pm |
|
|
I changed the code as per your recommendations:
Code: | #include <16f88.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //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
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_B5,rcv=PIN_B2,parity=N,bits=8,FORCE_SW,INVERT)
void main() {
while(true){
putc('A');
//printf( "Online\r\n" );
}
}
|
However when I plug it into my serial port, I get no output from hyperterm.
Edit: Scratch that, I just plugged it in again, and now I am getting a constant stream of Ps with a Q when it starts up. (it's supposed to give me a stream of As) |
|
|
BlownTransistor Guest
|
|
Posted: Sat Oct 28, 2006 4:36 pm |
|
|
I hope you are using a resistor on the rx line. Don't expect reliable communication on every PC with only 0 - +5v drive. You should use a max232.
daehtib! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 28, 2006 4:38 pm |
|
|
I think it should work. Verify that Hyperterminal is set for 9600, N, 8, 1,
so it matches the #use rs232() statement.
If it still doesn't work, I can check it on my hardware later tomorrow.
So if it doesn't work, post your compiler version. This will be a number
such as 3.191, or 3.236, or 3.249, etc., and you can find it at the top of
the .LST file, which will be in your project directory. Then I'll test it with
your version. |
|
|
eatnumber1
Joined: 28 Oct 2006 Posts: 5
|
|
Posted: Sat Oct 28, 2006 5:06 pm |
|
|
It still doesn't work, I'm using compiler version 3.249 and verified hyperterminal's settings.
Thanks for all your help. |
|
|
Guest
|
|
Posted: Sat Oct 28, 2006 5:22 pm |
|
|
Set your tris registers
Code: |
Code:
#include <16f88.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //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
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_B5,rcv=PIN_B2,parity=N,bits=8,FORCE_SW,INVERT)
void main() {
SET_TRIS_B(4);//00000100
while(true){
putc('A');
delay_ms(100); //delay so you don't flood your terminal out
//printf( "Online\r\n" );
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 28, 2006 9:37 pm |
|
|
Quote: | Set your tris registers
SET_TRIS_B(4);//00000100
|
He doesn't have to set the TRIS. He's using "standard i/o" mode,
which is the default mode of the compiler (you don't have to specify it).
In that mode, the compiler handles the TRIS.
Here's the start-up code, which executes when the program first begins.
It sets the TRIS for Pin B5 to be an output. It also sets Pin B5 to be an
an output, because it's the Tx pin for software UART. Also, because the
the INVERT parameter is used, the idle state for the Tx pin is a logic low
level. So Pin B5 is set to output a low level.
Code: | ....... void main() {
002A: CLRF FSR
002B: MOVLW 1F
002C: ANDWF STATUS,F
002D: MOVLW 60
002E: BSF STATUS.5 // Bank 1
002F: MOVWF OSCCON
0030: BCF TRISB.5 // Set Pin B5 to be an output.
0031: BCF STATUS.5 // Bank 0
0032: BCF PORTB.5 // Set pin B5 to a low level.
|
The CCS library code for the software also handles the TRIS. Here's the
first part of the code. Notice how it's setting the TRIS for pin B5 to 0,
which means it becomes an output pin. There's no need to set the TRIS
for pin B2, because the power-on reset state for TRIS registers is "all
inputs". So pin B2, as the Rx pin, is already setup correctly as an input.
Code: |
... #use rs232(baud=9600,xmit=PIN_B5,rcv=PIN_B2,
parity=N,bits=8,FORCE_SW,INVERT)
0004: BSF STATUS.5
0005: BCF TRISB.5 // Set Pin B5 to be an output
0006: BCF STATUS.5
0007: BSF PORTB.5
0008: MOVLW 08
0009: MOVWF @78
000A: NOP
000B: NOP
000C: NOP |
|
|
|
Popped Capacitor Guest
|
|
Posted: Sun Oct 29, 2006 12:25 am |
|
|
Ah, I see.
Well, maybe he smoked his hardware like you said PCM.
His baud rate could be off by using the internal rc oscillator.
I wonder if the compiler is setting the OSCCON(6:4) reg (0x8F)correct.
It isn't shown in the ASM list.
Bits 6-4 should be 110 for 4Mhz.
I guess he doesn't have an oscilloscope to check the baud rate. |
|
|
eatnumber1
Joined: 28 Oct 2006 Posts: 5
|
|
Posted: Sun Oct 29, 2006 2:57 am |
|
|
Unfortunatley, I don't have an oscilloscope. I will also be getting a new PIC within the next few weeks, so we'll see about that one... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 29, 2006 5:51 pm |
|
|
Quote: |
Now I am getting a constant stream of Ps. (it's supposed to give me a
stream of As) |
I did some testing on a PicDem2-Plus board, and I'm getting the same
result: Continuous P's are sent out.
I then switched to using the hardware UART, but still with the INTRC_IO.
It also failed. It gave a string of P's.
I put in a delay between sending out the 'A' characters. A delay of two
milliseconds between chars fixed it.
I then got rid of the internal oscillator and put in a 4 MHz crystal with
the XT setting. That worked, and without any delay between chars.
Earlier, I had changed the character to 'U' and noticed on my scope that
the frequency was 4.7 KHz or so. This is a little low, but should have
been close enough. So for my next test, I set the OSCTUNE register
to a value of 2, which shows 4.80 KHz on my scope. That should have
fixed it, I believed, but it didn't.
At this point, I drew a diagram of the outgoing bitstream which comes
out of the Tx pin, for both the 'A' and the 'P' characters. The following
diagram shows the start bit (0), followed by the data byte (LSB first)
and then a stop bit (1).
A -- 0x41: 0 1000 0010 1
P -- 0x50: 0 0000 1010 1
If you look at this, you can see that the 'A' character has the same
bit pattern as the 'P', if you start at the 3rd bit in. In other words
if you skip the first 0 1 in the 'A', and then repeat the 'A' character,
you have the exact same pattern as continuous 'P's.
Apparently, if you send continuous characters with no inter-character
spacing, the bit timing must be exactly correct or the PC's UART will
start at an incorrect bit and interpret the character incorrectly.
It works OK with a crystal, which is going to be within 50 ppm accuracy,
and it fails with the INTRC oscillator, even though the scope shows it
to be fairly close to the proper frequency.
Also, I checked the settings on my PC's UART and the both hardware
fifos are enabled. (It also fails with the fifos disabled).
My advice is to use a crystal. |
|
|
Fried Resistor Guest
|
|
Posted: Sun Oct 29, 2006 7:50 pm |
|
|
PCM, with > 6000 posts and the extent you go to help
people with their conundrums you must enjoy it. |
|
|
gaireilong Guest
|
project |
Posted: Sat Jan 26, 2008 11:12 pm |
|
|
I got problem in my project,actually I'm doing a project of Odour tracking mobile robot using PIC16F88,for that I need c-program of frequency pulse reading,give some hints or example so that I can modify.I hope you'll do my needfull things.Thank you. |
|
|
|
|
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
|