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

18F4520 and INT_TBE / INT_RDA

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



Joined: 04 Apr 2005
Posts: 63

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

18F4520 and INT_TBE / INT_RDA
PostPosted: Sun Aug 03, 2008 12:09 am     Reply with quote

Question about Serial Interrupts Buffers.

Does 18F4520 have internal buffer for serial communication?

Do I still need to use the 2 INT's for serial data buffers?

Thanks
Ttelmah
Guest







PostPosted: Sun Aug 03, 2008 2:21 am     Reply with quote

All PICs have a _small_ buffer. The size is a minimum of just under two characters (one in the input shift register, and the separate read latch), and the same in the output direction. PICs like the 4520, have an extra byte in the read buffer. Enough to help handle faster data rates without character loss, but not anything more.
Yes. There are effectively two separate devices. This is required, because this is an asynchronous bus, so data can arrive and depart at different times (unlike a synchronous bus, where on device provides the master clock, and bytes arrive and depart together).

Best Wishes
jahan



Joined: 04 Apr 2005
Posts: 63

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

PostPosted: Sun Aug 03, 2008 9:14 am     Reply with quote

Thank you for your reply. It does confirm my original thoughts that having a larger buffer helps with ASYNC data transfer.

The reason I asked the question is because, each time I "enable_interrupts(INT_TBE);" the data coming back to me from device is corrupted. As soon as I disable it, then I'm OK.

another follow-up thought:
In my project, I know when I'm send data out and also exactly know what I'm getting back (time and size), so should I still use the INT's?

Thanks Ttelman.
Ttelmah
Guest







PostPosted: Sun Aug 03, 2008 2:58 pm     Reply with quote

INT_TBE, should _only_ be enabled, when you have got data to send. It will occur _continuously_, while the transmit buffer is empty.
Example code:
Code:

#byte PIR1=0xF9E
#bit TXIF=PIR1.4
#byte TXREG=0xFAD
#byte TXSTA=0xFAC
#bit TRMT=TXSTA.1 //For 18 chips. Change all these for 16 chips

#define BUFFSIZE (32)
struct buffer {
   char buff[BUFFSIZE];
   int8 in;
   int8 out;
};
   
struct buffer rs232_txbuff;

#define bkbhit(b) (b##.in!=b##.out)
#define isempty(b) (b##.in==b##.out)
#define incin(b) if(++b##.in>=BUFFSIZE) b##.in=0
#define incout(b) if(++b##.out>=BUFFSIZE) b##.out=0
#define clrbuff(b) b##.out=b##.in=0

#INT_TBE /* Transmit buffer empty interrupt */
void TXINT(void) {
   if (isempty(rs232_txbuff)) {
      DISABLE_INTERRUPTS(INT_TBE);
   }
   else {
      TXREG=rs232_txbuff.buff[rs232_txbuff.out];
      incout(rs232_txbuff);
   }
}

void rs232_bputc(char val) {
   int8 next;
   /* routine to send one character on the RS232.
   This puts the specified character into the software transmit buffer
   (if data is already being transmitted), or else sends the single
   character to the RS232 UART. */
   /* Waits if the buffer is full */
   //Buffer is full if _next_ addition address matches current retrieval
   //address
   next=rs232_txbuff.in+1;
   if (next>=BUFFSIZE) next=0;
   disable_interrupts(INT_TBE);
   while (next==rs232_txbuff.out) {
      if (TXIF==1) {
         /* Here the transmit hardware buffer is empty */
         TXREG=rs232_txbuff.buff[rs232_txbuff.out];
         //So send one char
         TXIF=0;
         incout(rs232_txbuff);
      }
   }
   /* put character into the output buffer */
   rs232_txbuff.buff[rs232_txbuff.in]=val;
   rs232_txbuff.in=next;

   /* Enable interrupts */
   enable_interrupts(INT_TBE);
}


Leave the interrupt disabled, then when you want to send characters, call rs232_bputc with the data. It'll automatically enable the interrupt as needed.
The same buffer handling code, can be used for a receive buffer, by adding:
Code:

struct buffer rs232_rxbuff;

//Routine to get a character from the RS232. Waits if no data available
char rs232_bgetc() {
   int8 temp;
   while (!bkbhit(rs232_rxbuff)) ;
   temp=rs232_rxbuff.buff[rs232_rxbuff.out];
   incout(rs232_rxbuff);
   return temp;
}

//Serial RX interrupt
#int_rda
void receive_rs232(void) {
   rs232_rxbuff.buff[rs232_rxbuff.in]=getc();
   incin(rs232_rxbuff);
   if (rs232_rxbuff.in==rs232_rxbuff.out) {
      //Buffer overflow
      incout(rs232_rxbuff);
   }
}

You can see the syntax for using the bkbhit call, and reading data, in the above bgetc routine. The receive interrupt needs to be enabled in the main for this.

Best Wishes
jahan



Joined: 04 Apr 2005
Posts: 63

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

PostPosted: Mon Aug 04, 2008 10:11 am     Reply with quote

Thank you for your help and sample codes;

reading your code I came across following:

Code:
#byte PIR1=0xF9E
#bit TXIF=PIR1.4
#byte TXREG=0xFAD
#byte TXSTA=0xFAC
#bit TRMT=TXSTA.1 //For 18 chips. Change all these for 16 chips


can you explain what these are? I don't see them anywhere in examples provided by CCS.

Thanks
Ttelmah
Guest







PostPosted: Mon Aug 04, 2008 10:23 am     Reply with quote

Register definitions.....
Lot's of examples here, and in the CCS example code.
Names are those used in the data sheet.
So, 'PIR1', is the 'Peripheral Interrupt flag Register 1'. Then the Transmit interrupt flag, is bit 4 in this.
There are internal instructions to clear this, but not directly to test it. Hence the definitions.
Similarly, the corresponding putc, and getc instructions will write/read the data registers, but add significant testing overhead. Since the interrupt occurring, implies the output buffer _is_ empty, it is faster to just load the byte directly into the register. etc. etc..

Best Wishes
jahan



Joined: 04 Apr 2005
Posts: 63

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

PostPosted: Mon Aug 04, 2008 11:32 am     Reply with quote

thank you for your detailed explanation.

you are a great resource in this community.
jhortwo



Joined: 03 Oct 2011
Posts: 1

View user's profile Send private message MSN Messenger

PostPosted: Mon Oct 03, 2011 12:09 pm     Reply with quote

Thanks for the tips, works fine with pic16f690, now i want to use transmit enable pin but i don't know how to do it. I set enable pin in the # USE RS232 but doesn't work. I try setting this after and before the lines:
Code:

#byte PIR1=0x0C
#bit TXIF=PIR1.4
#byte TXREG=0x19
#byte TXSTA=0x98
#bit TRMT=TXSTA.1
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