Skip to main content
Visitor II
May 24, 2004
Question

transmit interrupt

  • May 24, 2004
  • 10 replies
  • 1502 views
Posted on May 24, 2004 at 10:47

transmit interrupt

    This topic has been closed for replies.

    10 replies

    jones2Author
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    In the serial example code, I see that the transmit method,

    forces the software to wait until all characters are transmited.

    I tried to set the t_in1 index to the last charater in the buffer,

    then set TI=1 and EA=1. and inside the interrupt, before exiting

    set again TI=1, to make it re-enter the isr and transmit the next

    chracter until t_out == t_in.

    well this way it doesn't work.

    is there a way to make it work?

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    While we have not done it yet, it should be possible to modify the ISR function to send only one character at a time while in the interrupt.

    jones2Author
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    I made this work, with just a small correction to the ISR:

    if (TI != 0)

    {

    TI = 0;

    if (t_in != t_out){

    SBUF = tbuf [t_out++];

    while(!TI); // Added line

    }else

    t_disabled = 1;

    }

    }

    I added the line:

    while(!TI); // Added line

    and it made the difference.

    now the transmit function needes only to set:

    EA=0;

    t_out = 0;

    t_in = strlen(tbuf);

    EA=1;

    TI=1;

    from this point the whole buffer will be transmitted automatically.
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    steadicopter,

    That will certainly work, but the line while(!TI) make the function blocking. That is, essentially, no other code will execute until your ISR is done sending every character. If you remove the while loop, you can certainly have the ISR transmit one character at a time and let some other code execute until the buffer's ready for another. The trick is to NOT set TI=1 on your own. The system will set this bit whenever a character has finished transmitting and will vector to the interrupt to have your ISR load up the next one.

    If you prefer doing things your way, a better thing to do would be to disable the interrupt altogether and just transmit them in some other function. This would save you returning from and immediately vectoring back to the interrupt and get your transmitting done quicker.

    Best Regards,

    Phaze426
    jones2Author
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    Thanks for the replay,

    I understand this theory, and it should work without

    the line:

    while(!TI);

    but what this does is, it prints only the first character of the buffer.

    It looks like it doesn't enter the interrupt the second time TI changes to 1.

    How could this be?

    (i posted my initializations on 06-05-2004 at 16:31 )

    [ This message was edited by: steadicopter on 19-05-2004 10:52 ]

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    steadicopter,

    Throw this into your initialization somewhere:

    IE |= 0x10;

    to make sure the serial interrupt is enabled.

    Then, once you've got your in and out pointers set, set TI=1 just like you do now. Then make your interrupt something like the following:

    if (TI) {

    TI=0;

    if (t_out != t_in) {

    SBUF = tbuf[t_out++];

    } else {

    /* disable tx */

    }

    }

    and that really should transmit every byte. If it doesn't then something somewhere ELSE in the program is probably going on with your in and out counters. Let me know if that works.

    Regards,

    Phaze426
    jones2Author
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    so everything was OK with the interupt after all.

    I removed the while(!TI) line, and it works fine now.

    the problem was that with the interrupt it was fast enough

    to get to the next time the program starts to fill the

    transmit buffer (0.2sec). so I just use different buffers

    one for the program and one for the interrupt. and just

    before starting transmit I copy the buffer to the transmit buffer.

    Thanks for the help.

    It helped me alot.
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    steadicopter,

    No problem at all, but if you'll indulge, I have a bit of preaching to do. Your method about copying one buffer over to another is good but you have to observe some caveats. What you may end up creating with your method is a ''race condition.'' That is, it may be possible that your ISR is busy sending out data from a buffer at the exact moment that you start copying a new one in and it sends half of the old one and half of the new one. One way to prevent this would be to only copy the buffer if the t_disabled bit is 1 (that is, the ISR has finished sending all the bytes in the last message).

    I guess as long as you're careful it will be fine. I just thought I'd mention this because race conditions can cause some of the most difficult to troubleshoot intermittent bugs in existence.

    Best Regards,

    Phaze426
    jones2Author
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    Thanks for the tip,

    I allready did that, because as you mentioned, without

    waiting for t1_disabled every transmit overlaps with

    the previous one, and I got ab-normal printout.

    I have to say that the uPSD design for interrupts is just

    genius at its simplisity.

    Thank you.

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:00

    steadicopter,

    The interrupt functionality and structure of the uPSD is actually from the 8 If you credit them to ST, someone from Intel will come to your door and beat you senseless.

    -Phaze426