I am trying to stream data off of an SD card using SD.h but the timing is being disrupted by a repetitive blocking of interrupts
every 34 milliseconds and lasting 1.4 milliseconds, during the 1.4 ms the MISO is low on the SPI (hardware) interface.
const int chipSelect = 53; // Mega pin 53
const byte timeStep = 130; // timer setting for 62.5us
byte dataIn,pulse;
void setup()
{
DDRC=0xff; //set port C for output
DDRG=1 //set G0 to output for test signal
pulse=0;
Serial.begin(9600);
Serial.print("Initializing SD card...");
pinMode(53, OUTPUT); // Mega pin 53
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
return;
}
Serial.println("card initialized.");
// open the file.
File dataFile = SD.open("5min.tst"); // 5 min 8bit 16khz sample
Serial.println("start");
// Initialise Timer2
TCCR2A=0;
TCCR2B=0b010; // prescale clock to 2Mhz
TCNT2=timeStep;
TIMSK2=1; // enable interrupt
// if the file is available read bytes until end
if (dataFile) {
while (dataFile.available()) {
dataIn=dataFile.read();
PORTC=dataIn;
while (TIMSK2 & 1){}; // wait for timer interrupt
TIMSK2=1; // restart timer
}
Serial.println("stop");
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening 5min.tst");
}
}
//ISR Timer2 overflow
ISR(TIMER2_OVF_vect) {
TIMSK2=0; // clear interrupt
TCNT2=timeStep; // set value for next
pulse^=1; //toggle bit to produce test clock out
PORTG=pulse;
}
// if the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
dataIn=dataFile.read();
Typically, the read() function is not used to write anything. If you are going to have comments, and I think you need even more of them, they should match reality.
sorry about the poor commenting, but as far I can see the active code is a loop reading bytes from a file on SD card:
while (dataFile.available()) {
dataIn=dataFile.read(); // get byte from file
PORTC=dataIn; // write byte to output port
while (TIMSK2 & 1){}; // wait for timer interrupt, synchronises byte output to 16 kHz timer
TIMSK2=1; // restart timer
}
and the timer interrupt:
//ISR Timer2 overflow
ISR(TIMER2_OVF_vect) {
TIMSK2=0; // clear interrupt
TCNT2=timeStep; // set value for next
pulse^=1; //toggle bit to produce test clock out. <- added to generate clock to sync scope
PORTG=pulse;
}
The signal on portG is a near perfect 16kHz interrupted every 34 ms for 1.4ms, any
ideas as to why this is happening would be greatly appreciated.
Every 512 bytes a block is read from the SD. That takes about 1.4 ms. Some reads will be longer if a new cluster in the file needs to be accessed.
Streaming data to/from an SD requires special techniques. I wrote a audio record/play library, WaveRP, that illustrates how it can be done with SdFat. SD.h is a wrapper for an old version of SdFat.
Interrupts are not disabled by the SD library. The problem is that reading a block takes a long time, at least 1.5 ms and occasionally several ms. During that time you are stuck on this statement
dataIn=dataFile.read();
and don't get to this statement
TIMSK2=1; // restart timer
on time so no timer interrupts happen.
A circular buffer won't work since the delay for the read will interfere with what ever you want to do every 62.5 us.
You could fill the buffer in loop and output the byte in the ISR.