Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 9 months ago.
Combination of Serial and SPI Communication
Hello, I'm trying to combine the serial usb communication and SPI communication in mbed LPC1768. But, everytime I try to run both communication, the data that is received is very unstable. I need to combine both of them because I need to make a hardware-in-the-loop simulation by using mbed, MATLAB and a flight controller board. This simulation is used for visual-tracking octorotor that I build for my thesis. Is there anyone know about the solution of this problem? Strangely enough, when I try not to combine them and run them separately, the communication runs well.
This is some of my code
void Receivedserial() // Used to receive serial data from MATLAB simulink { idxserial=0; overflowSerial=0; while ((overflowSerial==0) && (idxserial<10)) { temp=pc.getc(); if ((temp=='#') && (tanda==0)) { idxserial=0; tanda=1; } if ((temp=='*')&&(idxserial==9)) overflowSerial=1; ReceiveSerial[idxserial]=temp; if (overflowSerial==1) tanda=0; idxserial++; } } void communicationSPI() //Used for SPI communication between flight control board and the mbed board. { idxSPI=0; overflowSPI=0; while ((overflowSPI==0)&& (idxSPI<10)) { if(device.receive()) { temp1 = device.read(); // Read byte from master ReceiveSPI[idxSPI]=temp1; if ((temp1=='#')&&(tanda1==0)) { idxSPI=0; tanda1=1; } if ((temp1=='*') &&(idxSPI==9)) overflowSPI=1; device.reply(ReceiveSerial[idxSPI]); if (overflowSPI==1) tanda1=0; idxSPI++; } } } void sendserial() //Used for sending the data received from the flight control board to MATLAB simulink { for(unsigned char i=0;i<10;i++) { pc.putc(ReceiveSPI[i]); } }
1 Answer
9 years, 9 months ago.
I'm assuming that Receivedserial() and the SPI equivalent are called by the receive interrupts rather than being polled. If not then you need to do that before you have any real hope of getting this to work. You can run a single interface without interrupts but running two of them that way is fighting a loosing battle.
With that assumption...
If it works with one section at a time then it's probably going to be some sort of timing related problem. Normally this would indicate things are overflowing due to the timings changing or values are changing when you don't expect them to.
Are all of your packets always 10 bytes long?
It looks like your receive interrupts put data into an array that I'm guessing is 10 bytes and then your transmit functions read from the same buffers and send the whole buffer no matter how much of it contains valid data. In the interrupts you only flag an overflow if the 10th byte is a * and you still increase the index counters which means they could be pointing outside of the array. c doesn't protect against that, if you try to write to byte 11 of a 10 byte array it will let you. What ends up happening is that it trashes whatever variable happens to be in the next memory location.
Do you have any protections against the data getting changed while you are sending it?
It doesn't look as if you have any protection against the buffer getting changed by an interrupt while you are sending it. If it takes longer than expected to finish sending a packet because you've been reading a new one coming in then your buffer may change during the transmit. (Obviously not an issue if you're not using interrupts but if you're not it's not going to work well for more than one input) One thing you may want to do is copy the buffer before sending it. e.g.
main() { .. setup char tempBuffer[10]; while (true) { if (SPIReadyToSend) { // disableInterrupts _disable_irq() // copy the SPI buffer (copy to tempBuffer from RecieveSPI a total of (10 * the size of a char) bytes // (ok so sizeof() is a little redundant when it's a char array but it's a good habit to get into) memcpy(tempBuffer,ReceiveSPI, 10*sizeof(char)); // now maybe reset the counter so that the SPI buffer starts from the beginning again rather than doing that in the interrupt? _enable_irq() // re-enable interrupts sendSerial(tempBuffer); } } }
Finally a couple of notes on variable declarations:
I'm not sure what it's for but your variable tanda is used in both interrupts, that's not normally something you want to do.
The temp variables (temp for serial and temp1 for SPI) look like they are declared globally, those are very generic names, it would be safest the declare them local to the receive routines.
And if in doubt declare any variables modified in an interrupt but then used in the main code as being volatile, without that there is a risk that the compiler will optimize things and miss changes in the value.
Just wanted to reply when I saw yours. But I don't think he is running them interrupt based. Standard SPI(slave) has no interrupt based mode, and his Serial receive is doing a while loop with getc.
So easiest solution is most likely running Serial in interrupt mode, since that one already has support for interrupts. Then SPI can just stay blocking.
posted by 07 Aug 2014
Please use
posted by Erik - 07 Aug 2014<<code>> and <</code>>
(on seperate lines), now your code is unreadable.