Hi,
As WEK has shown, why don't you follow this simple logic of interrupt handling?
1. In the main routine you enable serial tx/rx interrupts and do whatever you want to do. Do not set TI bit. If data is there in buffer, either load SBUF with the first byte of data or simply set TI bit.
2. In your serial interrupt routine, follow the steps below:
a. Disable all interrupts.
b. Check if RI is set, If set, Clear RI and read data. Go to c.
c. check if TI is set , If set, Clear TI. Load next byte into SBUF if buffer not
empty .Go to d.
d. Enable Interrupt. Go to e.
e. RETI
DONOT CLEAR the interrupt flags either in Get() or Printf() functions. Do it always at the beginning of the interrupt routine as given above. Remember that a TI interrupt will only occur after 8 bits are shifted out and it takes time. So your
Printf() will not be able to clear the bit generated by its present action.
Regards,
Laktronics
Added after 4 hours 10 minutes:
Hi,
On further thinking, I feel some more constraints are to be put on step 1 given above. That is in the Main program, initiation of Tx operation should be done only under certain conditions.
Eg. Under step 1, you may initiate a TX, only when the buffer is full and will not initiate another Tx unless the buffer is empty and the interrupt due to the last character transmitted is also serviced. The catch here is due to the delay in transmission of each byte. At 9600 baud, each byte takes 1msec to be shifted out, including the start and stop bits and CPU can execute many instructions during this period. So during this period if the main routine simply checks the status of TI, it will be Zero, but it should not set TI bit now. In order to see if the last interrupt due to the last character transmitted is over, may be the interrupt routine should set a flag if a TX interrupt has occurred and there was no byte in the buffer to transmit. This flag should be checked by the main routine before initiating another TX and the flag should be cleared along with TX initiation.
Regards,
Laktronics