We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I would like to have my two 89C51RD2 communicate with each other via UART. They are connected such that one TX pin is connected to the other's RX pin and vice versa. I tried sending byte by byte and it is working. However, when I tried to transmit larger amount of data at one go, the receiving end isnt able to read the data. I feel that I am missing something silly. Is the microcontroller able to store the incoming data while I poll and get them byte by byte? Would somebody please advise. Thank you. Cheers
"Is the microcontroller able to store the incoming data while I poll and get them byte by byte?" You have the code for both ends, so you should be able to work it out! A: How long does your receiving code take to receive and store a byte? B: How long does your transmitting code take to prepare the next byte for transmission? Guess what happens if A>B...?! Have you looked at the interrupt-driven, ring-buffered serial IO example on this very site?
"How long does your transmitting code take to prepare the next byte for transmission?" The problem the OP has is due to the time it takes for a byte to be shifted into SBUF rather than the time it takes to prepare a byte for transmission, which is very likely to be a lot faster. Stefan
Hi Two way's to solve your problem 1.
char low_level_get(void) /* Read one char from I/O - Hardware-dep. */ { do { WATCHDOG(); } while (!RI); RI = 0; return (SBUF & 0x7F); }
char data_poll(void) { char xdata c; do { if (RI) char_poll(&c); /*Process data byte by byte*/ }while(c); /*Process data byte by byte*/ } }
char data_poll(void) { char xdata c; do { if (RI) char_poll(&c); /*Process data byte by byte*/ }while(c); /*Process data byte by byte*/ } } The above example has two problems: 1) There is no guarantee that c will be initialised before being tested as the loop condition. 2) data_poll() will not return until a binary zero is received in SBUF. Stefan
I have tried using a polling method for the receiver side. This means that the receiver will check the SBUF periodically and take in the data if any. On the other side, I have deliberately set the transmitting speed to be much lower. Hence the transmitter will not overrun the reciever. Logically, this would work since whatever that comes in from the transmitter will be taken by the reciever before the next byte comes in. However, the problem I face is that I can only recieve up to the second byte. Subsequent bytes are not read in the the reciever. I am again quite puzzled why is this so. I know it is quite vague but do anyone of you happen to have any idea why this happens?
If you are running 512k baud or 256k baud, then the transmitters send data faster than the receive can keep up with them them. I had this problem, we used a 100 or 200 microsec delay between transmits. if you are running a normal baud rate this shouldnt be a problem. But we had to set the serial interrupt highest priorty. Also if there is any other interrupt the could prevent the receive interrupt from immediately vectoring then you could have a situation where your second or third or any receive interrupt could get interrupted again before you leave the interrupt routine. So RI=1 when you leave the the rxinterrupt routine...you never will vector...hung. There is rx and tx stuff in the example below to take note of. The following code is from memory, it is not working code. char TxCount = -1; char CurrentTxBuffer[10]; char NewTxBuffer[10]; char *SendData; char RxBuffer[10]; // a circular rx buffer is best...not shown char *RxData; void MainLoop { char *RxData2; RxData = &RxBuffer; //do each new rx msg RxData2 = RxData; // do each new rx msg do { ... //Rx if(RxData2 != RxData) new rx data at *(++RxData2) ... //Is Tx Busy? example is CurrentTxBuffer // is not done yet but you want to send // another NextTxBuffer // nothing should interfere with TxCount // or SendData unless TxCount < 0 if(TxCount<0) //TxCount<0 = Tx not busy { TxCount = length of new tx message -1 SendData = &NewTxBuffer SBUF = *SendData++; //this starts tx } ...other mainloop stuff }while(1); } void SerialInterrupt(void) ... { do { if(RI) { RI=0; *RxData++=SBUF; } // Tx // dont forget there is always 1 more // TI after the last byte has been sent // So you need to transmit only if Tx // buffer count is not zero. // if(TI) { TI=0; // always clr interrupt first // dont write SBUF if Count = 0 if(TxCount--) //TxCount=TxBuffLength SBUF = *SendData++; } }while( RI || TI ); // only use the do while if you think you // are sometimes not finishing transmit, // tx hangs up. or your losing rx bytes }