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 support@ccsinfo.com

RS232 Receiving problem with PIC 16F877A

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
spcshen



Joined: 06 Jul 2007
Posts: 4

View user's profile Send private message

RS232 Receiving problem with PIC 16F877A
PostPosted: Fri Jul 06, 2007 3:52 pm     Reply with quote

Hello

I am trying to use PIC16F877A to receive data from a radio transceiver. My ultimate goal is to have the transceiver receive some charactors, and store in a string in the PIC for later use. So I am using the RS232 related functions to do it. My first test is to just receive 1 charactor, but I always end up receiving null.

here's my code
Code:

#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //Crystal oscillator
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES WRT_50%                  //Lower half of Program Memory is Write Protected

#use delay(clock=20000000, HS)
#use rs232(baud=9600, parity=N, xmit=PIN_A0, rcv=PIN_C7, timeout=500, bits=8, stop=1, errors)
   
#use fast_io(b)                  //set port b manually                                                     

void main()
{
   
   char value;

   set_tris_b(0x03);   //set pin B0 and B1 as input pins
   output_low(PIN_B2);
   output_low(PIN_B3);   
   output_low(PIN_B4);   
   output_low(PIN_B5);
   output_low(PIN_B6);
   output_low(PIN_B7);
   
   while(true)
   {
   
      if(kbhit())
      {
         value=getc();
                                                output_high(PIN_B3) //turn on an LED
         putc(value);
                                                delay_ms(100);
                                                output_low(PIN_B3) //turn off the LED
      }
   }
}


First, I know my baud rate is correct. Since C7 is the USART receiving pin of the PIC, I specified it to be rcv in the #use rs232().

My transceiver will hold high to pin C7 when there's no data (at 2.8V, theoretically, it should be 3.3v). Say when a charactor is received through radio, the transciver will start sending this charactor right away. For example, the charactor 'a' is received, pin c7 first goes low for 1 pulse, the high for 1 pulse, low for 4 pulses, high for 2 pulses, low for 1 pulse, and return to holding high ( each pulse is 104us since baud rate is 9600). ASCII for 'a' is 110 0001 in binary, and there is a start bit at logic low, and an end bit at logic low, so I know the transceiver is doing correctly. (I am reading all these using an oscilloscope)

I used getc() to catch this charactor and save in a char, value. When I do putc(value), I read it, it's always null, 000000000 on the xmit pin, A0.

My understanding is that since pin c7 is a hardware USART pin, so when the transciver sends the pulse to pin c7, the charactor is saved in a buffer in the PIC, and when kbhit() returns true, that means I have received something and is ready to be read. I do get my LED turned on everytime i send something through radio, which means it's ready to read. Then why is the PIC not getting the charactor 'a'?

So, what maybe the problem? Am I missing something important(like I need to configure something?) ? Is the 2.8V a problem?

Any help and suggestion is greatly appreciated. THX!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 4:17 pm     Reply with quote

Quote:
My understanding is that since pin c7 is a hardware USART pin, so when
the transceiver sends the pulse to pin c7, the character is saved in a
buffer in the PIC.

You must specify both hardware pins (C6 for xmit, C7 for recv) in the
#use rs232() statement, to make the compiler generate code for the
hardware UART. Your current statement (with A0 and C7) will generate
code for a software UART on both pins.

You didn't say what your PIC Vdd voltage is. If it's 5 volts, then 2.8v
is not high enough when driving pin C7. The PIC data sheet says that
pin C7 is a "schmitt trigger" input pin, and requires 0.8 x Vdd as the
minimum Vih level. If the PIC is running at 5v, then Vih is 4v for pin C7.
spcshen



Joined: 06 Jul 2007
Posts: 4

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 6:27 pm     Reply with quote

thx for the hints. But since I don't have any component at hand to switch the voltage to high enough, can I use some kind of software UART code and different port or pins to accomplish this? You say that I must specify xmit to C6 since it's the hardware UART transmit pin, but I can successfully send data to my transceiver using pin A0. So what you mean is that both transmit and receive pins needs to to be specified as the hardware UART pins in order for the compiler to generate code for hardware UART?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 7:16 pm     Reply with quote

I would advise you to make test programs and look at the .LST file to
see what the compiler is doing.

See this thread. It tells how to check if the compiler is generating code
for a hardware UART:
http://www.ccsinfo.com/forum/viewtopic.php?t=22149
Guest








PostPosted: Fri Jul 06, 2007 8:05 pm     Reply with quote

thx again for that reference. Now if I do want to use soft UART to do this job, it should be possible as well, isn't it? Most digital I/O pins that's not meant for hardware UART should be able to do it if the software UART is set up correctly, am I right? And how do you generate .LST file? I have never done it before...thx
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 8:35 pm     Reply with quote

Look in your project directory. A .LST file is generated after every
successful compilation.

If you can use the hardware UART, do so. It's far better than a software
UART.
spcshen



Joined: 06 Jul 2007
Posts: 4

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 9:05 pm     Reply with quote

I also know that if I could get the hardware UART to work, it's a better choice. However, as you know, the transceiver outputs at 3.3V(2.8V in reality) rather than 5V, which is common in newer electronics, and the hardware UART pins for the PIC uses schmitt triggers, which requires more than 4V to function correctly. I have no ways to get around that currently, and making my system work has the highest priority. So if I could make software UART work, then I would settle with that for now untill I find some way to convert voltage. But in general, would you tell me how the software UART work? Since data comes in asynchronously, how is data stored before getc() or gets() can be called, and how many bytes can be stored? Thank you very much!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 06, 2007 11:52 pm     Reply with quote

The CCS software UART library code works by polling the specified Rx pin
to detect a start bit. Then it does software delay loops so it can test for
the remaining bits at specific intervals. The PIC cannot be interrupted
during while the software UART is receiving a byte, or the byte will be lost.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Jul 07, 2007 6:30 am     Reply with quote

I would only use the software UART as a last resort. There is no buffering of data, all data is sent and received while the processor is running a tight loop. Interrupts will be disabled during these loops to prevent corrupted data transmissions. Just think about a 9600 baud signal to stall your program 1ms for every byte you transmit or receive.

The main problem in the software UART is the reception of data. Because there are no interrupt signals to tell you data is comming in you will have to call kbhit() at least ten times the incomming bitrate to ensure no data is lost.

It is possible to get a pseudo interrupt mechanism for data reception by also connecting the incomming signal line to the external interrupt input pin. This works most of the time except when other interrupt routines are already active and generate an unwanted delay.

Have you considered using the LF version of the 877A? Than your processor can run at the same low voltage as the I/O device. Drawback is the maximum clock frequency of 8.8MHz at 2.8V.
spcshen



Joined: 06 Jul 2007
Posts: 4

View user's profile Send private message

PostPosted: Mon Jul 09, 2007 5:02 pm     Reply with quote

Since I can't get the transceiver to output above 4V, so I tested something else. I make a regular I/O pin to imitate the waveform that would have been from the transceiver, only it's at 5V to ensure that it would be read correctly. I used pin_b7 to do the output and tied b7 to c7 and have the following code to test receiving 1 single charactor 'a'.

Code:

char value;
output_high(PIN_B7);
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

output_low(PIN_B7);
delay_us(104);
output_high(PIN_B7);
delay_us(104);
output_low(PIN_B7);
delay_us(416);
output_high(PIN_B7);
delay_us(208);
output_low(PIN_B7);
delay_us(104);
output_high(PIN_B7); //these lines are imitating 'a'

delay_ms(1);

if(kbhit())
{
    value=getc();
    printf(value); //I receive 'a' from here
}



using this piece of code, I would successfully receive an 'a' everytime on C7.

Then I tried to read 2 charactors at once using the following code, but received some weird values
Code:

char value[10];
output_high(PIN_B7);
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

output_low(PIN_B7);
delay_us(104);
output_high(PIN_B7);
delay_us(104);
output_low(PIN_B7);
delay_us(416);
output_high(PIN_B7);
delay_us(208);
output_low(PIN_B7);
delay_us(104);
output_high(PIN_B7); //these lines are imitating 'a'
delay_us(104);

output_low(PIN_B7);
delay_us(208);
output_high(PIN_B7);
delay_us(104);
output_low(PIN_B7);
delay_us(312);
output_high(PIN_B7);
delay_us(208);
output_low(PIN_B7);
delay_us(104);
output_high(PIN_B7); //these lines are imitating 'b'

delay_ms(1);

if(kbhit())
{
    gets(value);
    printf(value); //I receive weird things from here
}


My guess is that even hardware UART could only hold 1 char at once, so when I read 2 chars together, something went wrong because I didn't use gets() or getc() early enough. If I started kbhit() and getc() or gets() before the end of the first char is send, I would receive correctly?

Could someone confirm my guess? Any suggestion is helpful and appreciated..Thanks!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 09, 2007 7:12 pm     Reply with quote

Read the CCS manual on Gets(). Here's the description:
Quote:
GETS()
Reads characters (using GETC()) into the string until a RETURN
(value 13) is encountered. The string is terminated with a 0.



Also add the ERRORS parameter to your #use rs232() statement.
If you get an overrun error, it will then be cleared automatically.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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