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

How to Create a software UART ?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

How to Create a software UART ?
PostPosted: Tue Jun 03, 2008 12:39 pm     Reply with quote

Hi,

I am using 18F4680 and 16F877A to communicate between them selves. I am using the following codes to initiate the UART communication.

Code:


//FOR 18F4680

#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7, STREAM=USER) //hardware UART

#use rs232(baud=4800, xmit=PIN_C1,rcv=PIN_C0, STREAM=HOSTPC) // This is the software UART.

//FOR 16F877A

#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, STREAM=HOSTPC)   //hardware uart


Kindly let me know, if I am doing something wrong.

Thanks in advance.

Cheers
Tranz
Indy



Joined: 16 May 2008
Posts: 24

View user's profile Send private message

PostPosted: Tue Jun 03, 2008 1:06 pm     Reply with quote

Quote:
Kindly let me know, if I am doing something wrong.
The code fragments look al right to me. But you posting the code here suggests it is not working...? Confused

Is one of the two PIC processors running on the internal clock or on an RC-clock? If yes, than know that for RS232 these clocks are not accurate enough. RS232 allows a frequency deviation of maximal 3%.
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Tue Jun 03, 2008 1:11 pm     Reply with quote

I am using external oscillators on both the micro controllers, but unfortunately the data does not seem to go to the other end.
Indy



Joined: 16 May 2008
Posts: 24

View user's profile Send private message

PostPosted: Tue Jun 03, 2008 1:31 pm     Reply with quote

The initialisation of your RS232 looks fine, you will have to post more code for us to point the error.

You do know that a soft UART does not generate interrupts?
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Tue Jun 03, 2008 1:46 pm     Reply with quote

Oh, then how would I be able to know when the data arrives at the other end.. Here is what I am trying to do..

Code:


//on the 16f677A side

#INT_RDA
      void isr_routine()
      {
      lcd_putc("abc");
      }


void main()
      {
      lcd_init();
     
      setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
   
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
 
      enable_interrupts(GLOBAL);
   
      enable_interrupts(INT_RDA);// i am expecting this to work, since this is a hardware uart
       
      lcd_putc("abc");       
      }

//ON THE 18F4680 side

#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7, STREAM=USER,parity=N,stop=1)
#use rs232(baud=4800, xmit=PIN_C1,rcv=PIN_C0, STREAM=HOSTPC)

void main()
{
fprintf(HOSTPC,"a");
.....

}




the hardware UART is working fine, but I have no way of finding out whether the software UART is working or not, any suggestions?
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Tue Jun 03, 2008 1:57 pm     Reply with quote

tranz wrote:
Oh, then how would I be able to know when the data arrives at the other end.. Here is what I am trying to do..

Code:


//on the 16f677A side

#INT_RDA
      void isr_routine()
      {
      lcd_putc("abc");
      }
...


Only the hardware UART will cause an INT_RDA. A software UART works by your calling fputc or fprintf on the sending end and calling fgetc or fgets on the receiving end. The software UART is just code that gets executed when you make these calls. So to see if anything is being received, call fgetc and see what gets returned.

Since a software UART does not have any buffering hardware associated with it, you must make sure you call fgetc before the character starts arriving. If your code is not sitting in a fgetc or something like it, there is nothing there to receive the data. It will just be missed.

Robert Scott
Real-Time Specialties
Ttelmah
Guest







PostPosted: Tue Jun 03, 2008 2:32 pm     Reply with quote

Also, it is perhaps worth pointing out that the example code given has a major problem:
INT_RDA, being called, means there _is_ a character waiting to be received. The handler _must_ retrieve this character, or it'll be continuously called. The example code, does not do this.

Best Wishes
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Jun 04, 2008 7:39 am     Reply with quote

Most of the applications where I receive data with a software UART run in a tight loop, polling kbhit() at least 5 or 10 times each serial bit length. Then when kbhit() returns true you can call getc() before too much of the start bit has passed.
_________________
The search for better is endless. Instead simply find very good and get the job done.
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Thu Jun 05, 2008 10:20 am     Reply with quote

Well I tried all the suggestions given above, and none of them seem to work for me :(

Here is the code I am trying on the recieving end,

Code:

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

#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, STREAM=HOSTPC)




////////test.c/////////////////
#include <interface.h>

#include <stdio.h>
#include "lcd2.c"

#define TRUE 1

   void main()
      {
      char c;
     
      lcd_init();
      c=fgetc(HOSTPC);
      while(TRUE)
      {
      while(kbhit())
      {
      c=fgetc(HOSTPC);
      printf(lcd_putc,"%s", c);
      }
     
      //printf(lcd_putc, "hello World");
      //delay_ms(1000);
      }
      }



anysuggestions
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Thu Jun 05, 2008 10:38 am     Reply with quote

Your first c=fgetc(HOSTPC) does not do anything to report what "c" was. It goes right into waiting for kbhit(), which won't be true until the second character is received. Then those characters should be displayed on your LCD. Are you sure your LCD is working? It would help to put something like fprintf(lcd_putc, "Starting..."); at the very beginning of your program so that you could check the LCD function first. The next big problem is your..

printf(lcd_putc,"%s", c);

When "%s" is used, the corresponding parameter is expected to be a zero-terminated string referenced by its address. Instead you have a character refereced by its value. This is almost sure to crash. Change your format specifier to "%c", or simply use fputc instead of printf. Oh, another problem is the use of printf. It does not take a stream specifier (lcd_putc) as the first parameter. For that you want to use fprintf().

Robert Scott
Real-Time Specialties
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Thu Jun 05, 2008 11:04 am     Reply with quote

I have checked the LCD, its working, when I used fprintf, I get the error

" STREAM MUST BE CONSTANT IN THE VALID RANGE"

The LCD is working fine with printf.

Tried the "%c" too, that also does not seem to help. Is there anything I am missing out?
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

PostPosted: Thu Jun 05, 2008 12:43 pm     Reply with quote

tranz wrote:
I have checked the LCD, its working, when I used fprintf, I get the error

" STREAM MUST BE CONSTANT IN THE VALID RANGE"

The LCD is working fine with printf.

Tried the "%c" too, that also does not seem to help. Is there anything I am missing out?

You are right about the lcd_putc. I should have realized the lcd_putc is a put character function and not a stream. And apparently the %s does accept a character as well as a string in the CCS implementation. Then tell us what you mean by "does not seem to help". What do you see on the LCD?

Robert Scott
Real-Time Specialties
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Thu Jun 05, 2008 12:50 pm     Reply with quote

I see nothing on LCD, its a blank.
tranz



Joined: 10 Feb 2007
Posts: 78

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

Latest Update
PostPosted: Thu Jun 05, 2008 1:00 pm     Reply with quote

Here are some results worth pondering about,

I have got rid of the complex subroutines I was initially using, and wrote a simple code just to test the UART, here is the code..

Code:

//18f4680 side//////


#use rs232(baud=4800, xmit=PIN_C1,rcv=PIN_C0, STREAM=HOSTPC)

void main()
   {
   while(1)
   {
    BYTE c=10001000;
    fputc(c, HOSTPC);
   }}

/// on 16F877A side////////


   void main()
      {
      byte c;
     
      lcd_init();
      c=fgetc(HOSTPC);
      while(TRUE)
      {
      while(kbhit())
      {
      //printf(lcd_putc, "Starting...");
      c=fgetc(HOSTPC);
      printf(lcd_putc,"%x",c);
      //delay_ms(100);
      }
     
      //printf(lcd_putc, "hello World");
      //delay_ms(1000);
      }
      }





Now with this I get "c6" on my LCD. So I am deducing it is working, now for what it says, in binary it means 11000110. So I am missing some data, any ideas about how to rectify the problem?
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

Re: Latest Update
PostPosted: Thu Jun 05, 2008 1:39 pm     Reply with quote

Do you get just one "c6", or over and over again? Don't you mean BYTE c=0b10001000;? If you want to send a recognizeable character, specify it as '?' rather than in binary or hex.

Another thing you should test is to put a 1 second delay between each character you send out.

And why are you discarding the first character that you read?

And why are you using while(kbhit()) instead of if(kbhit())?

Robert Scott
Real-Time Specialties
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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