This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

serial IO interrupt

I am having a problem with getting a serial port interrupt. The timer 1 & serial port interrupts are being set to the high priority level. Timer1 is being used to create the 9600 baud for my serial IO. I can transmit out by writing to the SBUF register and clearing TI outside of the Interrupt Service Routine(ISR). The ISR vector is:
interrupt [0x23] void RITI_int (void)
{
P2.0=0;
P2.0=1;
EA=0;
if (TI != 0)
TI=0; //clear transmit interrupt bit
if (RI != 0)
{
// read in the byte & put the data in the buffer.
incoming_msg_buffer[incoming_hdr_ptr++] = SBUF;

if (incoming_hdr_ptr >= RXBUFFER_SIZE)
incoming_hdr_ptr = 0;
rx_empty=FALSE;
// renable rx interrupt
RI = 0;
}
EA=1;
}.

I believe I am setting the sfrs correctly they are as follows:
TMOD= 0x20; //8bit auto-reload timer1
TH1=0xfd; //value for 9600 baud
TCON=0x40; //timer1 on
SCON=0x40; //mode1 8bit uart,reciever enabled
IE=0x98; //enable serial port interrupts, timer 1 interrupt
SPE=0; //disable SPI interface
P1=0xF0; //configure P1 lower nibble as digital inputs for key row read
REN=1; //set reciever enable
IP=0x18 // set timer1 & uart interrupts to high priority
WDE=0; //disable watchdog-for now

As I understand the TI is set by hardware on the stop bit when a byte is written to SBUF. RI is set when the stop bit is recieved into SBUF(separate from tx SBUF).
When the ISR starts EA is set low, disableing all interrupts, and set back high at the end.
In the ISR I am toggling a port pin and montoring with a scope on the target. It appears that the ISR is never initiated although I can transmit & recieving data outside of the ISR. Is there anything that doesn't look right?
Thanks,

  • Why not compare your code to the interrupt-driven serial I/O code that's already available?

    http://www.keil.com/download/docs/intsio.zip.asp

    Jon

  • See also:

    http:/http://www.embeddedfw.com

    Free production quality UART driver at bottom of page.

  • I believe I am doing something similar to the example, except my rxbuffer is setup to hold only 24 bytes and is overwritten on subsequent messages. my SFRs are setup similar: timer1 in mode2 set for 9600 baud rate, SCON in mode 1. The ISR apparently never starts even though my TI & RI bits are being set automatically.

  • I've only seen non-response to enabled interrupts when some ISR is returned from via a simple RET instead of an IRET. If you're workning in C only this is probably not the case. Are you sure both IE.EA and IE.ES are set?

  • You are using Timer1 as both a baud rate generator and a periodic interrupt source? Could we get a look at the timer ISR too? Have you tried running without the Timer1 interrupt enabled (its interrupt capability isn't needed if you are running it for BRG only)?

  • Not only is the Timer1 interrupt not needed it would waste huge amounts of CPU time if enabled when generating baud. This assumes you've got some default handler at the T1 interrupt vector to return back to your main line code too. Without that you're off in never never land.

  • I am defining the ISR for timer1, I am using it to update a count variable used and reset elsewhere in main. Here are the ISRs, As you can see I am toggling a port pin in each.
    //ISRs
    void interrupt [0x23] void RITI_int (void)
    {
    P2.0=0;
    P2.0=1;
    EA=0;
    if (TI != 0)
    {
    TI=0; //clear transmit interrupt bit
    REN=1; //reenable reciever ??auto disabled during Transmit interrupt
    }

    if (RI != 0)
    {
    // read in the byte & put the data in the buffer.
    incoming_msg_buffer[incoming_hdr_ptr++] = SBUF;

    if (incoming_hdr_ptr >= RXBUFFER_SIZE)
    incoming_hdr_ptr = 0;
    rx_empty=FALSE;
    // renable rx interrupt
    RI = 0;
    }
    EA=1;
    }

    interrupt [0x1B] void TF1_int (void)
    {
    EA=0;
    P2.2=0;
    P2.2=1;
    count++;
    EA=1;
    }

    correct me if I am wrong, the timer overflow bit is reset automaticly when entering the timer ISR. When I transmit data is is going out at the 9600 baud that I intended, but I measured the occurance of the timer interrupt to be 28.8KHz(every 35us). shouln't it be closer to 300kHz.
    Since the UART ISR insn't being initiated, I have the following routine for sending out a message:
    for (i=0;i<=tx_length;i++)
    {
    SBUF=message[i];
    while(TI!=1); //wait for end of transmission ??to be implemented in ISR
    TI=0;
    }
    I would expect that the ISR would be called after the write to SBUF, but it never gets there, so I wait until TI goes HI.
    Mark, I do have ES and EA enabled, however I do set EA low while in the ISR and set back HI when finished.

  • I am defining the ISR for timer1, I am using it to update a count variable used and reset elsewhere in main. Here are the ISRs, As you can see I am toggling a port pin in each.

    Very bad idea. I believe you are warned against doing this in the 8051 documenation. Use Timer 0 for timing when Timer 1 is used for BRG.

    Don't disable interrupts inside an interrupt. It's bad form. If you have a higher priority interrupt enabled either disable that single interrupt or make your UART ISR interrupt safe. You do not need to touch REN after it is set during some init function. This is a real mess, no offense. Good greif just look at my UART example on my web site. Start there and hack away until you get just what you need.

    When sharing read and write access to a variable between main loop and ISR code you must make it volatile, e.g. count should be a volatile var.

    Boy, those ISR's sure look like they're from IAR not Keil.

  • Dave,

    > I measured the occurance of the timer interrupt to be 28.8KHz(every 35us). shouln't it be closer to 300kHz

    Therefore the TF1 interrupt is occurring about 10 times faster than the ISR can process it and is always asserted. High level code always gets one opcode processed before the next interrupt can interfere, so the high level code still is getting 1-3% of the processor time. But look at the rules for resolution of simultaneous interrupts of equal priority. For the 8051, the RI+TI is lower priority than TF1. Thus, no RI+TI.

    This is a theory to fit the facts, but I've never tested simultaneous interrupts. Actually, I had previously thought that the "polling sequence" meant that each of the simultaneous interrupts would eventually get priority. Now, I think not.

    Thanks,
    Robert

  • In your original post...

    TH1=0xfd;

    Well, if you enable the timer 1 interrupt, you will be interrupted every time T1 overflows. If you are using a divide-by-12 devices, that interrupt is going to happen every 3 instruction cycles.

    I doubt that your ISR can actually do anything useful in only 3 instruction cycles.

    Jon