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 CCS Technical Support

RS232 losing first character transmitted

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



Joined: 18 Jan 2006
Posts: 43

View user's profile Send private message

RS232 losing first character transmitted
PostPosted: Thu May 25, 2006 8:47 am     Reply with quote

Hi, I'm using a PIC 16F877, MPLAB IDE, MPLAB Debugger 2, CCS PCWH. The first character I send out does not make it to my terminal program. I've tried stepping and letting it free run, installed delays in various locations.

Basically, I enable xmit interrupts, global interrupts, use putc() to send the first character and then the rest in the xmit interrupt.

Stepping through it, all seems to work ok except for the missing first character. Any ideas ?

Thanks, Don Ware
Ttelmah
Guest







PostPosted: Thu May 25, 2006 10:04 am     Reply with quote

Multiple possibilities.
First is that the charge pump, on RS232 transceiver chips, in computer terms, takes a _long_ time to get up to full operating voltage. Can easily be several mSec on some units.
Second, is that when the PIC first wakes, the I/O line, will actually be an input for a while, before the serial port is setup. In some cases, the transceiver has sufficient pullup on it's input, for this to be treated as an 'idle' (high) state, but on some other designs, the pin floats low. On these, the receiver at the other end, can see this as a start bit, and then receive a garbage first character.
Third is that on some compiler versions, the line does not get programmed to actually be used as a serial line, till you do some I/O on the pin. This should not be a problem on the 877, since on this, the TRIS pins need to be set as inputs for the serial I/O, and this problem normally appears on chips where they need to be set as outputs. However this would appear, if at some point in your initialisation, you use an 'output_c' instruction (assuming you are using standard_io), since this would set the tris to output mode, and override the serial setting, till a byte is sent...

Best Wishes
DonWare



Joined: 18 Jan 2006
Posts: 43

View user's profile Send private message

rs232 missing first character.
PostPosted: Thu May 25, 2006 10:19 am     Reply with quote

OK thanks. Some things to think about. I'll look into options 2 and 3.

Additionally I notice that when I enable tx buffer empty interrupt, it generates an interrupt immediately before I send any characters. I can handle this though.

Thanks again.
Don
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

Re: rs232 missing first character.
PostPosted: Thu May 25, 2006 12:44 pm     Reply with quote

DonWare wrote:
OK thanks. Some things to think about. I'll look into options 2 and 3.

Additionally I notice that when I enable tx buffer empty interrupt, it generates an interrupt immediately before I send any characters. I can handle this though.

Thanks again.
Don


The interrupt is _when_ the buffer is empty so it should generate it immediately. Also, take a look at the lst file. putc() adds a few more instructions than necessary. It tests for the interrupt flag bit being set before loading the value into TXREG. You'd be better off defining the transmit register and loading the data _manually_. Also add the "noclear" flag to the interrupt. The compiler adds code to clear the flag bit but this is done in hardware so its just one more instruction.

before:
Code:

.................... #int_tbe 
.................... void tx(void)
.................... {
....................   putc('a');
009C:  MOVLW  61
009E:  BTFSS  F9E.4
00A0:  BRA    009E
00A2:  MOVWF  FAD
.................... }
00A4:  BCF    F9E.4
00A6:  GOTO   0058


after:
Code:

.................... #int_tbe noclear
.................... void tx(void)
.................... {
....................   TXREG = 'a';
009C:  MOVLW  61
009E:  MOVWF  FAD
.................... }
00A0:  GOTO   0058
DonWare



Joined: 18 Jan 2006
Posts: 43

View user's profile Send private message

Solved ?
PostPosted: Thu May 25, 2006 1:01 pm     Reply with quote

Thanks for the ideas. I was able to fix the problem by:

(1) Set up my xmit data buffer in RAM.
(2) Enable TX interrupts which causes interrupt, my tx isr starts sending characters from the beginning of the buffer (including the 1st char)

This is what my code had been doing (incorrectly)

(1) Set up my xmit data buffer in RAM.
(2) Enable TX interrupts which causes interrupt, my tx isr start to execute which advanced by tx buffer pointer.
(3) Do a fputc on my first buffer character in an attempt to start the xmit process.

So it was operator error. As usual the best solution was the simplest.

Thanks for all your help!
Don
Ttelmah
Guest







PostPosted: Thu May 25, 2006 2:39 pm     Reply with quote

I posted the following routines a little while ago, in another thread. They show how to handle an interrupt driven TX.
Code:

#byte   PIR1 =  0xF9E
#byte   TXREG =   0xFAD
#define   TXIF   4

//Must be binary multiple size for buffer code as written
#define SLBUFF (32)

//Initialise buffers
int RSTcount,RSTin,RSTout;
unsigned int LCDbuff[SLBUFF];

//Buffer tests and handling
#define isempty(buff,free,in,out,size) (free>=size)
#define isfull(buff,free,in,out,size) (free<2)
#define tobuff(buff,free,in,out,size,chr) {buff[in]=chr;\
   --free;\
  in=((in+1) & (size-1));}

unsigned int RSTfrom()
{
  /* Get character from the RS232 TX buffer */
  static unsigned int temp;
  temp=RSTbuff[RSTout];
  RSTout=(RSTout+1) & (STBUFF-1);
  RSTcount++;
  return(temp);
}

#INT_TBE /* Transmit buffer empty interrupt */
void TXINT(void) {
  /* If characters are waiting in the buffer, the next one is transferred
  to the UART otherwise the interrupt is disabled, waiting for the next
  transmission. */
  if (!isempty(RSTbuff,RSTcount,RSTin,RSTout,STBUFF)) {
    TXREG=RSTfrom();
  }
  else
    DISABLE_INTERRUPTS(INT_TBE);   /* RS232 TX */
}

void tchar(unsigned int chr) {
  /* routine to send one character on the RS232.
   This puts the specified character into the software transmit buffer
   (if data is allready being transmitted), or else sends the single
   character to the RS232 UART. */

  disable_interrupts(INT_TBE);
  /* Hold transmission if the buffer is full */
  while (isfull(RSTbuff,RSTcount,RSTin,RSTout,STBUFF)) {
    if (BIT_TEST(PIR1,TXIF)==1) {
      /* Here the transmit hardware buffer is empty */
      TXREG=RSTfrom();
      //Copy one character
    }
  }
  /* put character into the output buffer */
  tobuff(RSTbuff,RSTcount,RSTin,RSTout,STBUFF,chr);
  /* Enable interrupts */
  enable_interrupts(INT_TBE);
}


Best Wishes
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu May 25, 2006 7:16 pm     Reply with quote

Note that on an initial write, you will get back to back interrupts. This is because on the first load into TXREG, the data is immediately transferred to the transmit shift register and TXREG becomes empty again. To avoid this, I send the first char, set index to point to the next element and then enable interrupts. It saves you the overhead of the second int.
DonWare



Joined: 18 Jan 2006
Posts: 43

View user's profile Send private message

PostPosted: Fri May 26, 2006 6:52 am     Reply with quote

This is also a good idea.
I set it up and it works fine.

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