Receiving data from serial and writing to a microcontroller.

Hi there again!

I am developing an interface and i have some problems.
This interface is used to read and write some microcontrollers.

The protocol is similar to SPI and there is an interface for the LPT port.
I have managed to transfer most of the old LPT code to the arduino!
I can read and erase the microcontroller data but i have problems writing data!
The read, erase and flash routines are executed in the arduino and the data are transfered to and from the PC.
Read and erase work perfect. The flash routine seems to have some problems.

int Flash(long start, long region, long control, long ctl, long mcr) {
  int Npp;
  unsigned char MSB = 0;
  unsigned char LSB = 0;
  unsigned int data = 0;
  boolean flag;
  
  PutWord(mcr, 0x8000);        // Disable
  PutWord(mcr, 0x5AC0);        // Enable write to control block

  for (long counter = start; counter <= region; counter++) {
    MSB = Serial.read();
    LSB = Serial.read();
    data = word(MSB, LSB);
    flag = false;                // Margin Flag
    Npp = 0;
    PutWord(ctl, 0x0002);
    PutWord(control + counter, data);
    while (Npp <49) {
      PutWord(ctl, 0x0003);
      delayMicroseconds(20);
      PutWord(ctl, 0x0002);
      delayMicroseconds(10);
      if (flag == true) {
        Npp--;
        if (Npp == 0) {
          PutWord(ctl, 0x000A);
          if (GetWord(control + counter) == 0x00) {
            PutWord(ctl, 0x0000);
            if (counter > (region -1)) {
              goto exit;
            } else break;
          } else {
            break;
          }
        }
      } else {
        Npp++;
        PutWord(ctl, 0x000A);
        if (GetWord(control + counter) == 0x00) {
          flag = true;
        }
        if (Npp == 49) {
          goto exit;
        }
      }
    }
    counter++;
  }
exit:
  return 0;
}

The problem seems to be that the incomming data, come too fast before the flash routine writes them to the microcontroller. I tried to reduce the baud rate but i had no luck!

The exact same routine works on the pc using the LPT port!

Any suggestions?

  for (long counter = start; counter <= region; counter++) {
    MSB = Serial.read();
    LSB = Serial.read();

What happens when there are zero bytes or only one byte available from Serial?

When you say zero bytes you mean 0x00? If yes then it should write 0x00. The write should be in alligned words, so all the bytes that come in are words! At least this is what it is supposed to be! Keep in mind that this should work with a terminal program! I choose to send a file and this is how it uploads the file to the microprocessor! The files are 16k or 4k plus one byte which is the command!

psyche: When you say zero bytes you mean 0x00?

No. I mean no data has arrived on the serial port when you call Serial.read().

You caught me! You think that i should put something like

if( Serial.available() > 0) {
MSB = Serial.Read();
LSB = Serial.Read();
}

I tried to write 0x00 to all the addresses and it succeeded, so the problem is in the serial read. I have to sychronize it somehow!

:/

Or is this better?

while(!Serial.available()) ;

Or is this better?

Better than what? Spinning your wheels waiting for data is rarely better than processing data only when it is ready to be processed.

If you need to read two bytes at a time, make the if test true only when there are at least two bytes to read:

if( Serial.available() > 1)
{
MSB = Serial.Read();
LSB = Serial.Read();
}

I tried your code but it doesn’t work

  for (long counter = start; counter <= region; counter++) {
    if(Serial.available() > 0) {
      MSB = Serial.read();
      LSB = Serial.read();
      data = word(MSB, LSB);
      flag = false;                // Clear Margin Flag 
      Npp = 0;                     // Clear Npp Counter
      PutWord(ctl, 0x0002);        // Set Lat, Clear Eras
      PutWord(control + counter, data);    // Write data to address
      while (Npp < 49) {
        PutWord(ctl, 0x0003);      // Set ENPE
        delayMicroseconds(20);     // PWpp Delay
        PutWord(ctl, 0x0002);      // Clear ENPE
        delayMicroseconds(10);     // Tpr Delay
        if (flag == true) {        // Margin Flag Set
          Npp--;                   // Increase Npp
          if (Npp == 0) {          // Npp = 0?
            PutWord(ctl, 0x000A);  
            if (GetWord(control + counter) == 0x00) {    // Data Correct
              PutWord(ctl, 0x0000);    // Clear LAT
              if (counter > (region -1)) { // Done Programming???
                goto exit;
              } 
              else break;    // Increment Address;
            } 
            else {    // Data Not Correct
              goto exit;
              break;
            }
          }
        } 
        else {      // Margin Flag Not Set
          Npp++;      // Increment Npp
          PutWord(ctl, 0x000A);
          if (GetWord(control + counter) == 0x00) {  // Data Correct
            flag = true;      // Set Flag
          }
          if (Npp == 49) {
            goto exit;
          }
        }
      }
      counter++;
    }  
exit:
    return 0;
  }

It just exits!
The bytes come continously one behind the other, i am sending a file from the terminal!
After i read the 2 bytes i need to block the other coming bytes until these 2 are written to the microprocessor!
If these 2 are written then read the other 2 and block again!

if( Serial.available() >= 2 ) {
MSB = Serial.Read();
LSB = Serial.Read();
}

psyche: Or is this better?

while(!Serial.available()) ;

It really depends on the application but I agree with PaulS. Rarely is a busy-loop better than the alternative.

A little snippage happened:

  for (long counter = start; counter <= region; counter++) {
    if(Serial.available() > 0) {
      MSB = Serial.read();
      LSB = Serial.read();
      counter++;
    }  
  }

If there is no serial data, how fast do you think this loop will be executed?

While is is executing, one byte arrives. You read both of them.

Can’t you see that that is a problem?

Loose the gotos. You can put return statements in place of most of them. Restructure your code to get rid of that crutch.

Oh, any why are you incrementing counter twice each pass through the loop?

It looks to me like it has to block for each counter value as currently structured. Perhaps this would work:

for (long counter = start; counter <= region; counter++) {
    while (Serial.available <= 2) {;}    // spin here until 2 chars are ready
    MSB = Serial.Read();   // read 'em
    LSB = Serial.Read();
   …

I agree that the code looks a bit strange, it was written a few years back when i started coding! I have to clean it up and review it!

I am incrementing the counter twice because it works with words, not single bytes! I know that i could do just by counter+2 but i couldn't think that back then! :P

I tried your suggestions and the for loop exits! I will rework the code and see what i will come up with!

I know that i could do just by counter+2 but i couldn't think that back then!

And you still shouldn't. It's counter += 2.