|
|
View previous topic :: View next topic |
Author |
Message |
scud
Joined: 19 Sep 2008 Posts: 4
|
Can't TX data correctly using 2 usart 16f877 |
Posted: Sat Mar 07, 2009 3:41 am |
|
|
Hi all,
I'm doing a project that use this setup:
Barcode scanner(Barcode) --> 16f877 (barcode) --> PC(price) -->16f877 (price) --> lcd
The device should be able to scan the barcode and transmit to pc. The pc will compare the barcode in the database and will transmit back the price to the 16f877. The price is then displayed.
Code: | #include <16f877.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=8000000)
#USE RS232 (baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, stream=pc, bits=8 ) //hardware based RS232
#USE RS232 (baud=9600, parity=N, xmit=PIN_C5,rcv=PIN_C4, stream=barcode, bits=8) // Software based
#include "lcd.c"
void main() {
CHAR code;
CHAR price;
lcd_init();
lcd_putc("hello");
delay_us(500);
lcd_putc("\f");
while (1){
code=fgetc(barcode);
fputc(code,pc);
price=fgetc(pc);
lcd_putc(price);
}
} |
At first, I've tried transmitting the data using RS232 individually - HW and SW. Works ok.
But when I want to combine both usart (using code above), I can't transmit the barcode data correctly to the pc. Instead of 9 barcode number, it transmit 1 barcode only.
How to rectify this? |
|
|
Ttelmah Guest
|
|
Posted: Sat Mar 07, 2009 5:12 am |
|
|
Remember that getc, _waits_ till a character arrives.
Now it is not in your description, how the data is 'sequenced' between the devices involved, but the code at present, _wiats_, for one character to arrive from the barcode reader. When this arrives, it sends this character to the PC, and immediately starts waiting for a character from the PC. When it does receive this, it then goes back to looking for characters from the barcode reader. Anything that has happened on the barcode 'side', while it is waiting for the PC, _will_ have been missed. You need to be looping looking for data as fast as possible, and only getting it, if it is available. So, something like:
Code: |
while (1) {
if (kbhit(barcode)) {
code=fgetc(barcode);
fputc(code,pc);
}
if (kbhit(pc)) {
price=fgetc(pc);
lcd_putc(price);
}
}
|
Best Wishes |
|
|
scud
Joined: 19 Sep 2008 Posts: 4
|
|
Posted: Sat Mar 07, 2009 8:03 am |
|
|
Great! Now I see the problem.
But it now lead to another confusion. I've used the method above, it works only if I do not add any other instruction in it. Else, there are characters will be missed. In other words, I need it to be able to RX and TX usart data while executing other instruction such as lights up LED at certain condition.
Any idea how to avoid the problem? I've tried so many ways, but still can't find the answer. |
|
|
Ttelmah Guest
|
|
Posted: Sat Mar 07, 2009 11:25 am |
|
|
So long as the other instructions are quick, they shouldn't matter.
The key problem appears, because of the nature of the software UART. There is no hardware handling this. No buffer etc.. The code _must_ reach a getc for this, within less than 1/2 the bit time of the serial, of the start bit being received, and really quite a bit less than this (perhaps about 1/3rd a bit time). So, the kbhit for the software serial, needs to be called at intervals of no more than about 1/9600 * 0.333 = 35uSec.
Now, you can do lots of other things, provided you 'think' about this time limit, and work within it.
For example, if you want to print a long string, to the hardware serial, rather than just a single character, store this into an array, and each time round the loop, check if the hardware transmit buffer is empty. If it is, and _only_ if it is, write one character to the hardware serial. Similarly for the LED's, don't every turn them on, and wait for a period of time, instead use one of the hardware timers, set this to a value so it times out, after the period you want the LED to be on for. Turn on your LED, and keep on looping, but check if this has timed out. When it does, turn off the LED.
This way, you can keep the loop time short.
Note also, that I am suggesting checking things like the timer, and transmitter buffer empty, by polling, rather than by interrupts. This is becaue of the large overhead associated with interrupts, and the fact that they will interfere with the software serial, if they occur during the transmission or receipt of a character. You can simply read the interrupt flags in the loop, and respond as if interrupts are occurring, without these problems...
Best Wishes |
|
|
scud
Joined: 19 Sep 2008 Posts: 4
|
|
Posted: Sun Mar 08, 2009 9:52 pm |
|
|
Thanks Ttelmah.
Now I've moved on and replaced rs232 with a bluetooth module. But the code below doesn't work. It should TX back whatever I type at PC. It only works if there are no delay instruction in it:
Code: | #include <16f877.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=20000000)
#USE RS232 (baud=115200, parity=N, xmit=PIN_C6, rcv=PIN_C7, stream=pc, bits=8 ) //hardware based RS232
#include "lcd.c"
void main() {
CHAR code;
//CHAR price;
lcd_init();
lcd_putc("safwan");
delay_ms(2000); //hv to remove
lcd_putc("\f");
output_high(PIN_A0);
//output_high(PIN_D1);
//output_high(PIN_D2);
//output_high(PIN_D3);
while(1){
if (kbhit(pc)) {
code=fgetc(pc);
fputc(code,pc);
}
} |
Wonder why.. |
|
|
Ttelmah Guest
|
|
Posted: Mon Mar 09, 2009 4:35 am |
|
|
Keyword - add ERRORS in the hardware declaration.
The problem is that if anything arrives from the module in the 2 second delay, the internal hardware buffer overflows. Once overflowed, the UART is disabled, till this error is cleared. The ERRORS keyword, makes the compiler add the code to clear this.
2 seconds, is a long time in computer terms, the unit presumably either sends a 'wakeup' packet, or sends a break character, till it is awake. Either will cause the lockup.
Best Wishes |
|
|
scud
Joined: 19 Sep 2008 Posts: 4
|
|
Posted: Tue Mar 10, 2009 10:12 pm |
|
|
Hmm.. I still can't make the software usart to work. This time I exchange BARCODE to hardware, PC to software. Now the PC part can't even start. my terminal freeze after sending character
Help me on how to poll this 2 device
Code: |
#include <16f877.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=20000000)
#USE RS232 (baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, stream=barcode, ERRORS, bits=8 ) //hardware based RS232
#USE RS232 (baud=9600, parity=N, xmit=PIN_C5,rcv=PIN_C4, stream=pc, ERRORS,bits=8) // Software based
#include "lcd.c"
#include "string.h"
void main() {
CHAR code;
CHAR price;
char codes[];
int x=0;
lcd_init();
lcd_putc("\f");
output_low(PIN_A0);
while(1){
if (kbhit(pc)) {
price=fgetc(pc);
if (price=='q'){
fputc(price,pc);
lcd_putc("PSA");
break;
}
}
}
delay_ms(2000);
lcd_putc("\f");
output_high(PIN_A0);
while(1){
if (kbhit(pc)) {
price=fgetc(pc);
if (price=='c')
lcd_putc("\f");
else{
fputc(price,pc);
lcd_putc(price);
}
}
if (kbhit(barcode)) {
code=fgetc(barcode);
if (code== ('0'||'1'||'2'||'3'||'4'||'5'||'6'||'7'||'8'||'9')){//(48||49||50||51||52||53||54||55||56||57)){ //0-9
codes[x]=code;
x++;
}
if (code==13){ //Enter key
x=0;
fputc(codes,pc);
lcd_putc(codes);
}
}
}
} |
|
|
|
guillermo.odone
Joined: 08 Jan 2010 Posts: 1
|
Same Problem ... |
Posted: Fri Jan 08, 2010 10:40 am |
|
|
Hi scud,
Did you fix the problem?
Cause I'm having the same problem with pic16f877a.
The CCS examples doesn't work either for me.
If I do SW USART then it worked, but HW USART doesn't.
Code: |
#include <16f877a.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=20000000)
#USE RS232 (baud=9600, parity=N, xmit=PIN_C6,rcv=PIN_C7, stream=pc, ERRORS, bits=8 ) //hardware based RS232
void main() {
CHAR code;
CHAR price;
while (1){
if ( kbhit() ){
price = fgetc( pc ) ;
putc( price ) ;
}
}
}
|
_________________ --------------------------
Lic. Guillermo L. Odone
Argentina - IliveCenter
-------------------------- |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 08, 2010 1:52 pm |
|
|
1. Are you running this program on real hardware ? Or are using
a simulator, such as MPLAB Simulator, Proteus, or Oshonsoft ?
2. Describe, or post a schematic of your connections.
If you bought a hardware board then post a link to the manual for
the board, which contains the board schematic.
3. Post your compiler version. This is a 4-digit number in this format:
x.xxx
It's given at the top of the .LST file, which will be in your project
directory after you successfully compile a file.
4. How are you testing the program ? Are you using a PC, with
HyperTerminal ? Describe your testing method. |
|
|
|
|
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
|