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

Reading into SBUF is SLOW


# include <stdio.h>

# include <aduc842.h>

#pragma registerbank(2)



void sendmoduleinit(void);
void InitByte_Char (volatile unsigned long);
void print2uart_hex(int);
void displaytemp1(void);

void displaycal(void);
void sendremaining(void);
volatile unsigned char moduleinit;



int ucRxChar1;

int check_sum;
int check_sum_tx;



void main()

{

EA = 1;
ES = 1;

T3CON = 0x83;

T3FD = 0x2D;

SCON = 0x50;


if(ucRxChar1 == 0xCC)

{
sendmoduleinit();
}
if (ucRxChar1 == 0xFA && ucRxChar1 == 0xFA && ucRxChar1 == 0x05 && ucRxChar1 == 0xAA && ucRxChar1 == 0x2F)


{displaytemp1();

}

if (ucRxChar1 == 0x05 && ucRxChar1 == 0xAB)


{displaycal();

}



}

void ISR_sc(void) interrupt 4 using 2

{
if (TI==1) {
TI=0; //clear interrupt
}
else {
ucRxChar1 = SBUF; //put value on pins
RI=0; //clear interrupt
}



/*REN = 1;
while(RI == 0)
                {}

                        ucRxChar1 = SBUF;
                                RI = 0;
*/
}

void sendmoduleinit(void)
{

                                        check_sum = (0xF5 ^ 0xF5 ^ 0x06 ^ 0xFF ^ 0xFF);

                                        check_sum_tx = (check_sum & 0x7F);

                                InitByte_Char(0xF5);
                                InitByte_Char(0xF5);

                                InitByte_Char(0x06);
                                InitByte_Char(0xFF);


                                InitByte_Char(0xFF);

                            print2uart_hex(check_sum_tx);


        }

void InitByte_Char (volatile unsigned long result)

{       REN = 0;
SBUF = result;

                while (TI == 0)
                         {

                         }
                 TI = 0;
 REN = 1;
}
void print2uart_hex(int chksum)
{  REN = 0;

                          SBUF = chksum;
              while (TI == 0)
                         {
                         }
                 TI = 0;
REN = 1;

}

        void displaytemp1(void)
{

                                check_sum =(0xA0 ^ 0xE2 ^ 0x07 ^ 0x00 ^ 0x62 ^ 0x00);

                                check_sum_tx = (check_sum & 0x7F);

                                InitByte_Char(0xA0);
                                InitByte_Char(0xE2);

                                InitByte_Char(0x07);
                                InitByte_Char(0x00);

                                sendremaining();
                                //InitByte_Char(0x62);
                        //      InitByte_Char(0x00);


                           // print2uart_hex(check_sum_tx);


}

void sendremaining(void)
{
InitByte_Char(0x62);
InitByte_Char(0x00);

print2uart_hex(check_sum_tx);

}


void displaycal(void)
{

                                check_sum =(0xA0 ^ 0xE2 ^ 0x07 ^ 0x00 ^ 0x25 ^ 0x00);

                                check_sum_tx = (check_sum & 0x7F);

                                InitByte_Char(0xA0);
                                InitByte_Char(0xE2);

                                InitByte_Char(0x07);
                                InitByte_Char(0x00);


                                InitByte_Char(0x25);
                        InitByte_Char(0x00);


                           print2uart_hex(check_sum_tx);

}

This is my code.
Over here I am trying to read bytes into SBUF and depending upon bytes received I am trying to send some packets.
My code is working but reading into SBUF is taking time...
Reading a single byte is not taking time but reading an entire packet takes time
can u suggest some alternative soln
regards
Mayuri

Parents Reply Children
  • As per your advice I am using array for getting the entire packet.
    My ISR is as follows:

    
    
    void ISR_sc(void) interrupt 4 using 2
    
    {
    
    if (TI==1) {
    TI=0; //clear interrupt
    }
    else {
    for (i=0;i<5;i++)
    {
    while (RI == 0)
    {}
    ucRxChar1[i] = SBUF; //put value on pins
    RI=0; //clear interrupt
    }
    }
    }
    

    Thnx for ur advice ..The code is working too..I am able to receive entire packet..

    I have 1 more issue.My protocol is such that i may get a single byte(0xCC) or entire packet of 5 bytes.

    so i tried to modified my code.

    
    void ISR_sc(void) interrupt 4 using 2
    
    {
    
    if (TI==1) {
    TI=0; //clear interrupt
    }
    
    
    else
    
    {
    for (i=0;i<5;i++)
    {
    
    while (RI == 0)
    {}
    
    ucRxChar1[i] = SBUF; //put value on pins
    RI=0; //clear interrupt
    
    
    if (ucRxChar1[0] == 0xCC)
    {
    break;
    }
    if (ucRxChar1[0] != 0xCC)
    {
    continue;
    }
    
    }
    }
    }
    
    


    This seems to be working too..reading packet is fast
    but reading a single byte 0xCC is taking time...
    wht may be the reason??

    Regards
    Mayuri

  • The reason?

    The reason is that you haven't spent time reading previous answers.

    You just should not have an interrupt routine that stays, waiting for multiple characters to arrive. If next character does not arrive, the ISR will continue to wait while your main program is locked up.

    So the ISR checks if there is a character available, and adds it to the receive buffer. Then exists.

    And the main loop check what contents there are in the receive buffer - if there is one byte, the main loop checks if that byte is a one-byte message, or if more data needs to be received before the complete message can be processed. And if more data is expected, then the main loop keeps track of a timeout counter - if more data doesn't arrive within reasonable time (maybe someone disconnected the serial cable) then the main loop have to clear the receive buffer.

    And since the ISR is "producer" and main loop is "consumer", you should look at a circular buffer - also known as a round-robin buffer. It has the advantage that the producer (ISR) is owner of the write/insertion position. And the consumer (main loop) is owner if the read/delete position. So it doesn't matter what the main loop is busy doing - the ISR may kick in at any time and can modify the insertion position without creating any timing issues.

  • My protocol is as follows:

    Initially Host sends 0xCC to my module.

    It means that my module should receive CC and send some packet X.

    When Host receives packet X, it will send packet Y of 5 bytes to the module.

    CC byte will come only once .
    I may get packet Y any time...

    I am able to read packet Y
    Y does reading CC takes time?

    since I dont have host (mother board) ready,
    I am checking this handshaking in doclight.
    I am using doclight as my host
    over there I have to continuously send CC to my module to get packet X.

    TX - CC
    TX - CC
    TX - CC
    TX - CC
    TX - CC
    TX - CC
    TX - CC
    RX - F5 F5 06 FF FF
    TX - FA FA 05 AA 2F
    RX - A0 E2 07 63 D3

  • Are you understanding what I'm writing? At all?

  • Actually I am a fresher and there is no one to help me out.

    pls help me out

  • Actually I am a fresher and there is no one to help me out.

    pls help me out

    So, have you read the answer above? They contain all the help you need!

  • My problem is solved now.

    I have used while loop instead of for loop

  • I am helping you. I am saying that the ISR gets notified if there exists one (1) received byte. So the ISR should only try to pick up one (1) character.

    It's irrelevant what the protocol looks like - let the main loop worry about what characters are received - and when.

    Next thing - haven't you realized that you can receive one random character (maybe after insert of cable) and then get your 0xCC as second character. But your code think it should look at first entry of array for 0xCC. If you get a spurious character before the 0xCC, you get into a deadlock until the other side for some reason sends enough characters to get you out of your 5-character loop.

  • thnx a lot every1 for ur help...

    My problem is solved..

    u ppl wer very supportive...:)

    regards
    Mayuri

  • It doesn't matter if you have do { ... } while (x) or while (x) { ... } or for (;;) { ... }

    The ISR should not contain any loop to receive multiple characters. It should pick up one (1) character if you got there because of a receive interrupt. It should pick up zero (0) if you got there because of a transmit interrupt.

    Only for processors that have a FIFO functionality in the UART, should an ISR pick up multiple received characters. But such a UART can wait with generating the interrupt until the receive FIFO gets past the configured watermark. For a chip without a receive FIFO - or with a receive FIFO not activated - the ISR should never ever try to receive more than one character. Never! Never! Never! And again - never!

    An ISR should be quick. Instant in. Instant out. No loop waiting an unknown time until there _maybe_ comes more characters for the ISR to pick up.

    Throw away the loop from the ISR.

    Google for code for a ring buffer.

    Let the ISR insert bytes one-by-one into the ring buffer.

    Let the main loop consume bytes one-by-one from the ring buffer.

    Let the main loop consider what bytes that may represent the start of a packet - and how many more characters you may require based on how the packet started.

    But no: NO LOOP WAITING FOR MORE CHARACTERS IN THE ISR. No "while". No "for". Instant in. Instant out.

  • My code is working
    NO, it is
    My code is 'working'

    working without quotes means working. 'working' with quotes means appears to work

    no code can be WORKING with wait loops in an ISR

    NEVER share routines between mani and ISR
    KISS Keep ISRs Short and Simple

    Erik