|
|
View previous topic :: View next topic |
Author |
Message |
jahan
Joined: 04 Apr 2005 Posts: 63
|
Interrupt ... Interrupt ... can interrupts be interrupted? |
Posted: Thu Jun 30, 2005 9:51 am |
|
|
I'm trying to write a few lines of code to use interrupts for buffering data in and out of serial port using 16F877A.
I'm using the example codes with CCS.
My question is: Can each interrupt be interrupted by the other one?
here is my code:
any comment?
Code: |
/***********************************************************
* Program: NetMedia.c
* Authro: Jahan K Jamshidi
* Date: 5.25.2005
* MCU: 16F877A
* Devices: NetMedia - SitePlayer
* Description:
This program will monitor serial data coming in
from siteplayer and will display data on LCD.
initial setup will send a request to get IP
and will display it on LCD. Then will request
Status of siteplayer, if stat is 0x80, that means
a data was posted to site player.
a few things could happen:
1. check for known values on memory of site
player, read them and act accordingly.
2. update EEPROM with number of hits on page
***********************************************************/
#include <16F877A.H>
#device *=16 // use 16-bit RAM address
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
// #include "LCDD.c" //LCD on D Port
#include <LCD.c>
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
#define T_BUFFER_SIZE 64
byte t_buffer[T_BUFFER_SIZE];
byte t_next_in = 0;
byte t_next_out = 0;
#define R_BUFFER_SIZE 64
byte buffer[R_BUFFER_SIZE];
byte r_next_in = 0;
byte r_next_out = 0;
// interrupt to buffer outgoing serial data
#int_tbe
void serial_out_isr(void {
putc(t_buffer[t_next_out]);
t_next_out = (t_next_out+1) % T_BUFFER_SIZE;
if(t_next_in == t_next_out)
disable_interrupts(int_tbe);
}
void bputc(char c) {
short restart;
int ni;
restart = t_next_in == t_next_out;
t_buffer[t_next_in] = c;
ni = (t_next_in + 1) % T_BUFFER_SIZE;
while (ni == t_next_out);
t_next_in = ni;
if (restart)
enable_interrupts(int_tbe);
}
// interrupt to buffer incoming serial data
#int_rda
void serial_in_isr(void) {
int t;
buffer[r_next_in] = getc();
t = r_next_in;
r_next_in = (r_next_in + 1) % R_BUFFER_SIZE;
if (r_next_in == r_next_out)
r_next_in = t;
}
#define kbhit (r_next_in != r_next_out)
byte bgetc() {
byte c;
while (!kbhit);
c=buffer[r_next_out];
r_next_out = (r_next_out + 1) % R_BUFFER_SIZE;
return (c);
}
void main (void) {
int Click;
int Stat;
int IP1,IP2,IP3,IP4;
enable_interrupts(GLOBAL);
enable_interrupts(int_rda);
lcd_init();
lcd_putc("Jahan Web Server");
delay_ms(100);
// get IP and show on LCD
bputc(0xD3); // next 3 = get IP address
bputc(0xE6);
bputc(0xFF);
IP1 = bgetc();
IP2 = bgetc();
IP3 = bgetc();
IP4 = bgetc();
lcd_gotoxy(0,2);
printf(lcd_putc,"%u.%u.%u.%u ",IP1,IP2,IP3,IP4);
while (1) {
bputc(0x10); // get status
Stat = bgetc();
if (Stat != 0x00) { // if 0x00 nothing has changed since last time
lcd_gotoxy(0,3);
printf(lcd_putc,"Stat: %U ",Stat);
}
// if form submitted, check other stuff and get values.
if (Stat == 0x80) { // D7=1 of status byte = form submit
output_high(PIN_A0); // blink
Click = read_eeprom(0x00); // read clicks from EEPROM
delay_ms(50);
Click++;
write_eeprom(0x00,Click); // update clicks on EEPROM
delay_ms(100);
bputc(0x80); // next 3 = put click back on
bputc(0x00); // memory location 0 to be display
bputc(Click); // on the site by siteplayer
lcd_gotoxy(0,4);
printf(lcd_putc,"Clicks: %u",Click); //show it on LCD
output_low(PIN_A0); // end blink
}
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 30, 2005 10:09 am |
|
|
No.
The interrupst will always be treated sequentially. The interrupt flags for the individual interrupts can still be set inside an interrupt, so as soon as the first interrupt exits, if the flag is set, the other code will get called.
There are exceptions on the latter (18) chips, but not on the 16 chips.
However it is important to realise that provided the response time of each handler is kept short, so that all the handlers can be executed in less time that the shortest interval between events, everything will be OK.
At the 'cost' of an extra storage location, you can speed up the handlers significantly, by storing the count seperately. This then allows much faster testing for the buffer being empty/full etc.. Also, if the buffers are binary multiples (as yours are, 16, 32, 64 bytes etc.), it is faster to just use '&' to calculate the remainder, than to use the modulus function.
So the line:
ni = (t_next_in + 1) % T_BUFFER_SIZE;
will be faster as:
ni=((t_next_in + 1) & (T_BUFFER_SIZE-1));
Best Wishes |
|
|
jahan
Joined: 04 Apr 2005 Posts: 63
|
|
Posted: Thu Jun 30, 2005 11:16 am |
|
|
Thankx for help.
I have a quick question about:
Code: |
void bputc(char c)
...
restart = t_next_in == t_next_out;
...
|
is this correct?
does it to do == first then =
restart = (tnext_in == t_text_out)
or the other way around? |
|
|
bfemmel
Joined: 18 Jul 2004 Posts: 40 Location: San Carlos, CA.
|
|
Posted: Thu Jun 30, 2005 11:31 am |
|
|
Quote: | is this correct?
does it to do == first then =
restart = (tnext_in == t_text_out)
or the other way around? |
This is basic C, Chapter 2 in K&R. The comparison operator, "==", has higher precedence than the assignment operator, "=", so the parenthesis are not required although if in doubt you should use them. They sometimes do make the code more readable.
Code: |
restart = (tnext_in == t_text_out);
// is the same as
restart = tnext_in == t_text_out;
|
- Bruce |
|
|
jahan
Joined: 04 Apr 2005 Posts: 63
|
|
Posted: Thu Jun 30, 2005 12:15 pm |
|
|
second part:
Code: |
void bputc(char c) {
short restart;
int ni;
restart = t_next_in == t_next_out;
t_buffer[t_next_in] = c;
ni = (t_next_in + 1) % T_BUFFER_SIZE;
while (ni == t_next_out); // ******** HERE ****
t_next_in = ni;
if (restart)
enable_interrupts(int_tbe);
}
|
see ********** HERE ********* above ...
doesn't the code get "stuck" in a loop if ni is always equal to t_next_out? |
|
|
Guest
|
|
Posted: Thu Jun 30, 2005 12:26 pm |
|
|
Quote: | doesn't the code get "stuck" in a loop if ni is always equal to t_next_out? |
It's a circular buffer so you are waiting for a byte to be sent out until you can put another byte into the buffer. This is only going to happen when the buffer is full. The variable t_next_out is changed in the serial_out_isr() interrupt routine.
I thought this was your code?
- Bruce |
|
|
jahan
Joined: 04 Apr 2005 Posts: 63
|
|
Posted: Thu Jun 30, 2005 12:30 pm |
|
|
the part of NetMedia is mine.
as I mentioned earlier,
Quote: | I'm using the example codes with CCS.
|
Thank you for your help ... |
|
|
|
|
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
|