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

Correct Way of Temporarily Disabling an Interrupt

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



Joined: 31 Oct 2008
Posts: 17

View user's profile Send private message

Correct Way of Temporarily Disabling an Interrupt
PostPosted: Wed Dec 24, 2008 2:20 pm     Reply with quote

I have a PIC18F4685 that communicates over a half-duplex RS232-type bus. The bus itself is a single wire that switches from GND to 24V using an open collector and a pull-up. The IC that handles the electrical interface (i.e. voltage translation) internally echoes PIC's C6(TX) to its C7(RX).

That means that every time PIC sends a byte, it also gets an INT_RDA interrupt and gets the byte it just sent out. This behavior is not desirable. I'd like to ignore anything that's sent out. In fact, I'd rather not be interrupted at all due to bytes I put on the bus.

I disabled the RDA interrupt inside of the sending function (below) and it does work, but I got there by trial and error and don't really know why it works. For example if I comment out the getch(PC_COMM); line the "self-interrupts" start up. I put it back in, and they stop.

Ideally, I'd like to disable just INT_RDA, not all GLOBAL (I plan to have an INT_EXT for example I'd like to be able to service at all times), but this was the only combination that works. Anyone have any ideas?

Code:
void send_one_byte(int data)
{
   disable_interrupts(INT_RDA);
   disable_interrupts(GLOBAL);
   
   //fprintf(PC_COMM, "%C", data);
   putc(data);
   clear_interrupt(INT_RDA);
   getch(PC_COMM);
   delay_ms(15); // Ensure 15ms spacing between calls
   
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
}
Ttelmah
Guest







PostPosted: Wed Dec 24, 2008 4:01 pm     Reply with quote

You only need to disable the interrupt you are worried about. Turning off 'global' as well, turns off _all_ interrupts. See below for why you may need this.
Now, the problem in your case, is that since it takes time to send a byte, you need to wait for the transmission to complete, and read the byte retrieved, before re-enabling the interrupt.
So, more efficient code would be:
Code:

void send_one_byte(int data) {
   disable_interrupts(INT_RDA);
   putc(data);
   getc(); //Reading the byte, clears the interrupt
   enable_interrupts(INT_RDA);
   delay_ms(15); //If you need a delay, put it outside the disabled section.
}

Now, the 'getc', is essential. It is this that actually waits for the character to arrive, and clears the interrupt. The RDA interrupt, actually cannot be cleared, while a byte is waiting. This is why removing the getc, stopped the code working.

Second comment, you are using a stream name in the getc, but not anywhere else. Is there only one stream?.

Third comment, if you need to use the global disable instead (you don't need both), it implies that one of your other interrupt routines, is itself accessing the UART. If so, then you just need to substitute 'GLOBAL' for 'INT_RDA' in both the disables. However this is 'messy', and suggests you should re-think your approach.

As a comment, why not leave interrupts enabled, and just throw away the transmitted byte? You can do this by just setting a flag 'next_throw', as soon as you call putc, and in the receive interrupt, if this flag is set, just throw away the character, and clear this flag. This way the interrupt can be left enabled (except for the couple of instructions while you call putc, and set the flag). Improves the chances of not missing anything.

Best Wishes
RickMarsen



Joined: 31 Oct 2008
Posts: 17

View user's profile Send private message

PostPosted: Wed Dec 24, 2008 4:44 pm     Reply with quote

Ttelmah,

Thanks for taking a look at my code. The code you replied with works great. I will try to re-write my send function, as suggested, with a flag that removes the need to disable any interrupts.

You are correct, there _is_ only one serial stream in this project - I was just reusing some code I wrote before. getch(PC_COMM) has been replaced by getc() throughout.

Rick
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