Dear all, I am completely stumped. I have a piece of code in which (normally) the process will not enter in to. It concerns a uart routine where it enters into the routine if a packet size has been detected. For some reason it enters into the routine even if there is no comm data. The variable(PacketSize) is previously initialized to "0". When the target device is powered up, I should have no output on the comm port. I do not recieve normal string data but garbage. Due to it sending anything at all I conclude that the variable PacketSize must be over written at some point. I have read on previous postings that it could have something to do with the pointers. I just can't figure out what. By the way, the simulator runs perfectly, the target device (AT89C51ED2) in a live enviroment gives the problem. Any advise will be welcome. Sorry if I'm not very clear in explaining the problem, it just that it's not that clear to me either.
void main(void) { InitVars(); com_baudrate (); while(1) { if (PacketSize > 0) { if (DecodeStringData()) { MainConveyorMotor = 1; SendComm("Hello", 0); } PacketSize = 0; } } } unsigned char DecodeStringData(void) { unsigned char i; unsigned short shReadCheckSum; unsigned char chMode; unsigned char chPos; unsigned short shChecksum; chMode = 0; chPos = 0; SBUF = PacketSize + '0'; shChecksum = calculateChecksum(&ReceivedPacket[1], PacketSize - 6); shReadCheckSum = 0; for (i = 1; i < (PacketSize - 1);i++) { if (chMode == 0) { // get command if ((ReceivedPacket[i] == ',') || (ReceivedPacket[i] == ';')) { Command[chPos] = 0; chPos = 0; if (ReceivedPacket[i] == ',') etc....etc....
void SendComm(unsigned char * pStringbuffer,unsigned char Stringlength) reentrant { idata unsigned char Ctr; if (Stringlength != 0) { for(Ctr=0; Ctr<Stringlength; Ctr++) { tbuf[t_in++] = pStringbuffer[Ctr]; } } else { for(Ctr=0; Ctr < 256; Ctr++) { if (pStringbuffer[Ctr] == 0) { break; } tbuf[t_in++] = pStringbuffer[Ctr]; } } if( t_in != t_out) { TI = 1; } }
Your code is quite strange. The Decode() function writes to SBUF, which seems odd, and it doesn't wait for TI, which may cause garbled serial output. I forgot to mention. The SBUF thingy was only in there for testing purposes. I wasn't meant to be there. I the above posting it's corrected (Sorry). But anyway... Still the same problem. Meaning PacketSize is being overwritten somewhere. Regards John Garrelts
John, There is something problematic in your code. Does this function get called spuriously ALL the time, or just sometimes? The reason I ask is this: You say that you receive "garbage" on startup. From this, you conclude that your ISR would never intentionally set the PacketSize variable to something. But look -- all that it takes for PacketSize to be set to non-zero is for that string of "garbage" to include an ASCII ETX at some point. Even assuming the data is truly random, you've got a 1/255 chance on every single character you spuriously receive. Further, I don't see any buffer length checks in your ISR. That is, every time you get a character, you're storing the character in the "rbuf" buffer at position "r_in," but you never check to make sure that r_in is not greater than the size of your array. So... if you have a 25-position array and you receive 100 characters of garbage at startup, your routine is going to happily stomp over whatever happens to be above the buffer in memory. Perhaps try something like this:
#define MAX_PACKET_SIZE 25 unsigned char rbuf[MAX_PACKET_SIZE];
if (RI) { RI = 0; if (r_in < MAX_PACKET_SIZE) { rbuf[r_in] = SBUF; r_in++; } else { //Do something here to reset the state //because you've overflowed } }
Hi John, A minor thing is XDATLEN should be 0700H to cover 0x0..0x6FF, but more importantly have you initialised within AUXR the XRAM size bits XRS2, XRS1 and XRS0 to '100' to enable 1792 byte of internal XRAM within STARTUP.A51 in the 'IF XDATALEN <> 0' conditional assembly code before the MOV DPTR,#XDATASTART line? Hope this helps, Mark.