|
|
View previous topic :: View next topic |
Author |
Message |
tranz
Joined: 10 Feb 2007 Posts: 78
|
How to Create a software UART ? |
Posted: Tue Jun 03, 2008 12:39 pm |
|
|
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
|
|
Posted: Tue Jun 03, 2008 1:06 pm |
|
|
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...?
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
|
|
Posted: Tue Jun 03, 2008 1:11 pm |
|
|
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
|
|
Posted: Tue Jun 03, 2008 1:31 pm |
|
|
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
|
|
Posted: Tue Jun 03, 2008 1:46 pm |
|
|
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
|
|
Posted: Tue Jun 03, 2008 1:57 pm |
|
|
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
|
|
Posted: Tue Jun 03, 2008 2:32 pm |
|
|
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
|
|
Posted: Wed Jun 04, 2008 7:39 am |
|
|
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
|
|
Posted: Thu Jun 05, 2008 10:20 am |
|
|
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
|
|
Posted: Thu Jun 05, 2008 10:38 am |
|
|
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
|
|
Posted: Thu Jun 05, 2008 11:04 am |
|
|
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
|
|
Posted: Thu Jun 05, 2008 12:43 pm |
|
|
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
|
|
Posted: Thu Jun 05, 2008 12:50 pm |
|
|
I see nothing on LCD, its a blank. |
|
|
tranz
Joined: 10 Feb 2007 Posts: 78
|
Latest Update |
Posted: Thu Jun 05, 2008 1:00 pm |
|
|
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
|
Re: Latest Update |
Posted: Thu Jun 05, 2008 1:39 pm |
|
|
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 |
|
|
|
|
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
|