View previous topic :: View next topic |
Author |
Message |
Izzy
Joined: 27 May 2007 Posts: 106
|
Problem receiving data from PC to PIC , Help! |
Posted: Thu Jul 12, 2007 5:41 am |
|
|
Hello ,
I am having problem receivng the data sent from the PC (com1) to the PIC (Software Uart).
Since hardware uart has already been used for another communication, I had to use software Uart for receing data from the PC, But I cant receive data.
I was using external interrupt PIN B0 for the receive PIN and C5 as the transmit pin. So that when ever any data arrive it would interrupt and go into Interrrupt sub routine where I have While (Kbhit()) to receive data.
When I used kbhit() it doesnot receive any data, but when I remove it , it will receive first character .
I dont know what is the problem, first I thought it was problem of delay. But I have tried with various delays and it still wont work.
Is there any thing that I am missing about the software UART? |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Thu Jul 12, 2007 8:51 am |
|
|
Sorry I happen to post this code somewhere else.
anyway here you go again ,
Here is my Test code:
I couldnt even receive all the data when I try to receive data from hardware uart. (Sent from PC)
I dont know why is this happening?
Quote: |
#include <18f4520.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#use rs232 (stream=PC, baud=9600, xmit=PIN_C5, rcv=PIN_B0, ERRORS)
#use rs232 (stream=huart, baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
int loop=0;
char Get_robot_data[80];
#INT_EXT
Void PC_Command_Received()
{
while(kbhit(radio))
{
Get_PC_data[loop] = fgetc(PC);
fputc(Get_PC_data[loop], debug);
loop++;
}
loop=0;
}
//#INT_RDA
void Data_Receive_BaseStation()
{
while(kbhit(huart))
{
Get_robot_data[loop] = fgetc(huart);
fputc(Get_PC_data[loop], debug);
loop++;
}
loop=0;
}
void main()
{
enable_interrupts(INT_RDA);
//clear_interrupt(INT_EXT);
//enable_interrupts(INT_EXT);
//ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
while(true)
{
}
} |
|
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Thu Jul 12, 2007 9:46 am |
|
|
What is the purpose of "while(kbhit(huart)) "? It seems to me that you must have gotten a start bit to get to the int routine. Once you get the first character there are one or more stop bits before the next character. These stop bits will drop you out of the while(kbhit(huart)) loop, so loop gets set back to 0 and the next character causes another interrupt which overwrites the first character. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Thu Jul 12, 2007 10:34 am |
|
|
I was not even able to capture all the data with hardware TX and RX pins.
It only gets 3-4 character and ignores the rest.
And with software UART I cna only get the first character.
I am totaly confused how is this happening.
@Sherpa
The purpose of while(kbhit(huart)) "? was to check if there was any data in the receive PIN.
I had no problem communicating with PIC to PIC or from PIC to RF module and Vice versa.
Can someone explain? |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Fri Jul 13, 2007 4:43 am |
|
|
Anyone? |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sat Jul 14, 2007 6:32 am |
|
|
Can anyone help me here please?
Shouldnt transmitting data from computer's COM1 to the PIC be simple ? What am I doing wrong here? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Sat Jul 14, 2007 8:20 am |
|
|
Quote: |
The purpose of while(kbhit(huart)) "? was to check if there was any data in the receive PIN.
|
1) The purpose of kbhit() is ONLY to check if a START bit has arraived.
2) If you want to check it, you should use the IF preposition, not WHILE, hence
take out both WHILE.
3) If the INT_RDA interrupt had been triggered, it is because the hardware module
had been detected the incoming character, hence it is not necesary any kbhit() inside
this subroutine handler, the received char is already in the receiver buffer,
all you need is to GET IT using fgetc(huart)
4) The interrupt handler should be as short as possible, take out all the putc() functions.
5) Do not reinvent the wheel. Search in this forum and you will see tons of examples
regarding this.
Humberto |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sat Jul 14, 2007 12:02 pm |
|
|
If I remove the while(kbhit()), then it will only get the first character of the 28 byte long array. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Jul 14, 2007 4:22 pm |
|
|
Izzy wrote: | If I remove the while(kbhit()), then it will only get the first character of the 28 byte long array. | You have already been told twice: Also remove the putc and 'loop=0' from both interrupts. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 15, 2007 6:24 am |
|
|
I did as you said and it doesnot work.
Here is the simple test code:
Quote: |
#include <18f4520.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#use rs232 (stream=pc, baud=9600, xmit=PIN_B1, rcv=PIN_B0)
int loop=0; ;
char Get_robot_data[5];
//*******************************************************************************
#INT_EXT
Void PC_Command_Received()
{
Get_robot_data[loop] = fgetc(pc);
loop++;
}
//*******************************************************************************
void main()
{
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
while(true)
{
if(loop==4)
{
fputs(Get_robot_data,debug);
loop=0;
}
}
} |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Jul 15, 2007 7:04 am |
|
|
What clock oscillator do you use? Your current setup doesn't look correct.
To get a 40MHz you have two options:
1) Connect a 10MHz crystal or ceramic resonator to the OSC1 and OSC2 pins and select the H4 fuse (HS + 4 x PLL).
2) Connect a 40MHz external clock and select either fuse EC or EC_IO.
You are resetting the loop variable to 0 in the main loop too often, it will never count up to 4.
Change to: Code: | while(true)
{
if (loop == 4)
{
fputs(Get_robot_data,debug);
loop=0; // <-- moved this line
}
} |
fputs will write everything up to the end of the string, how do you assure the string is terminated in the expected way?
There is no mechanism to prevent buffer overflow on reception.
And then there is the potential conflict of new data comming in while you are writing to the debug port...
These problems have already been solved by other people. Seach this forum for example code.
Another tip: When posting code do not use the 'quote' button but the 'code' button, this will preserve the formatting of your code. |
|
|
Izzy
Joined: 27 May 2007 Posts: 106
|
|
Posted: Sun Jul 15, 2007 7:26 am |
|
|
Sorry about that, that loop=0 was supposed to be inside.
Well using for loop in the main body solved the problem.
thanks a lot.
Code: | #include <18f4520.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT
#use delay(clock=40,000,000)
#use rs232(stream=debug, DEBUGGER)
#use rs232 (stream=pc, baud=9600, xmit=PIN_B1, rcv=PIN_B0)
int loop=0, loop1=0;
char Get_robot_data[3];
//*******************************************************************************
#INT_EXT
Void PC_Command_Received()
{
// while(kbhit(pc))
// {
Get_robot_data[loop] = fgetc(pc);
loop++;
// }
// command_received=1;
}
//*******************************************************************************
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
while(true)
{
if(loop==2)
{
for(loop1=0;loop1<2;loop1++)
{
fputc(Get_robot_data[loop1],debug);
}
loop=0;
}
}
} |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Jul 15, 2007 9:31 am |
|
|
Glad to hear you are having progress.
Still, you only fixed one problem. For example your oscillator setup is still an invalid combination for 40MHz. If it works you are lucky, but don't start complaining in the future when weird things are happening in your program.
Don't be stubborn trying to re-invent the wheel. Have a look at the code designed by others. For example look into the CCS supplied demo application ex_sisr.c which uses a circular buffer for storing the data (solves the problem for conflict when reading in main() while receiving new data in the isr). |
|
|
|