So I decided to check out the Arduino's (receive) bit timing on a scope.
The picture below shows the receive routine (incorrect) timing,
When receiving, you try and read the pin at the middle of the bit. Which is, once you see the start bit, wait 50% of the bit time, then take a reading. Notice the middle of the scope pic above how the pin is being read incorrectly. It sampled off the edge of the bit resulting in an incorrect read on the 3rd bit.
With the corrected (fixed) bit time,
Notice the reads much more closer to the center?
That was for 9600 baud. The following code should receive correctly for bauds up to and including 14400
int SoftwareSerial::read()
{
int val = 0;
int bitDelay = _bitPeriod;// - clockCyclesToMicroseconds(50);
// one byte of serial data (LSB first)
// ...--\ /--\/--\/--\/--\/--\/--\/--\/--\/--...
// \--/\--/\--/\--/\--/\--/\--/\--/\--/
// start 0 1 2 3 4 5 6 7 stop
while (digitalRead(_receivePin));
// confirm that this is a real start bit, not line noise
if (digitalRead(_receivePin) == LOW) {
// frame start indicated by a falling edge and low start bit
// jump to the middle of the low start bit
delayMicroseconds((bitDelay/2)-25);
//digitalWrite(3,LOW);
//digitalWrite(3,HIGH);
// offset of the bit in the byte: from 0 (LSB) to 7 (MSB)
for (int offset = 0; offset < 8; offset++) {
// jump to middle of next bit
delayMicroseconds(bitDelay-14);
//digitalWrite(3,LOW);
//digitalWrite(3,HIGH);
// read bit
val |= digitalRead(_receivePin) << offset;
}
delayMicroseconds(_bitPeriod-8);
return val;
}
return -1;
}
No comments:
Post a Comment