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

Can't TX data correctly using 2 usart 16f877

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



Joined: 19 Sep 2008
Posts: 4

View user's profile Send private message

Can't TX data correctly using 2 usart 16f877
PostPosted: Sat Mar 07, 2009 3:41 am     Reply with quote

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







PostPosted: Sat Mar 07, 2009 5:12 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Mar 07, 2009 8:03 am     Reply with quote

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







PostPosted: Sat Mar 07, 2009 11:25 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Mar 08, 2009 9:52 pm     Reply with quote

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







PostPosted: Mon Mar 09, 2009 4:35 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Mar 10, 2009 10:12 pm     Reply with quote

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

View user's profile Send private message

Same Problem ...
PostPosted: Fri Jan 08, 2010 10:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jan 08, 2010 1:52 pm     Reply with quote

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.
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