The application code of sparkFun, has the following line which is difficult to understand.
It's requested 6, because it's requesting 6 bytes for HMC5883L module.
Wire.requestFrom(address, 6);
if(6<=Wire.available())
Where:
int TwoWire::available(void)
{
return rxBufferLength - rxBufferIndex;
}
So, the available function should return return rxBufferLength - rxBufferIndex;
where rxBufferIndex
is modified in read
function:
int TwoWire::read(void)
{
int value = -1;
// get each successive byte on each call
if(rxBufferIndex < rxBufferLength){
value = rxBuffer[rxBufferIndex];
++rxBufferIndex;
}
return value;
}
But, my current question is why decrementing return rxBufferLength - rxBufferIndex;
where rxBufferIndex
is initialized to 0 all the time, and there's no chance the returned value would be less than 6, because that would terminate the if statement?
-
What is the rxBufferLength value in your example?user31481– user314812017年12月16日 15:44:10 +00:00Commented Dec 16, 2017 at 15:44
-
6 according to HMC5883L 6 bytes data.R1S8K– R1S8K2017年12月21日 17:31:27 +00:00Commented Dec 21, 2017 at 17:31
1 Answer 1
rxBufferLength
is the number of bytes that have been received. rxBufferIndex
is the byte you would next be handed with a read()
function call.
So if you have received 6 bytes from the slave (which you will, since that is how many you requested) but not read any the available
would be 6. Ergo, 6 <= 6. I.e., you asked for 6, it collected 6, and you are checking that it got at least 6 (it can never be>6 since you only asked for 6, so why they look for at least 6 I don't know).
rxBufferIndex
is never decremented. It is incremented when you read a byte, up until rxBufferLength == rxBufferIndex
at which point there is 0 bytes available.
But, my current question is why decrementing return rxBufferLength - rxBufferIndex; where rxBufferIndex is initialized to 0 all the time, and there's no chance the returned value would be less than 6, because that would terminate the if statement?
The way that Wire.h works is that available()
will always return the number of bytes you requested if the call to requestFrom()
succeeded until you first read some of that data. If you request 6 and the call worked then you have 6. The if
could just as well be written as:
if (Wire.available()) {...
since it will always be 6 immediately after a successful call. However, that makes assumptions about how the Wire API works and could be subject to change in the future or operate differently on different platforms.
So it checks that, right after the call to requestFrom()
for 6 bytes it actually got at least 6 bytes. Without seeing what is inside the conditional if
, all I can do is make assumptions, but I would assume that it is then reading those 6 bytes, and so it wouldn't care if there happened to be more for some reason. But it doesn't want there to be 5 or fewer bytes available when it is reading 6 of them.
An if
statement doesn't "terminate" if its condition becomes false once it has been executed. It's not like a while
that keeps running until it's false - it's a single decision made at a single point in time. If anything changes in the future that would have caused a difference decision to be made (e.g., you read()
a byte, so available()
would now return 5), the decision that has been made still stands.
An analogy for you:
You want to go out for a good healthy walk - but only if it's not raining.
if (!raining) {
walk_to_shop();
walk_to_cafe();
drink_coffee();
walk_to_shop();
walk_home();
}
You go out for your walk to the shops, get a coffee, do some more shopping, and then walk home - but you only start doing that if it's not raining. If it starts raining while you're out you don't suddenly teleport back home. You could make the decision, when you come out of the cafe and see it's raining, to cut your shopping trip short, but you have to actively make that decision. Just because raining
becomes true doesn't affect the fact that you are outside and walking.
-
-
I think you're getting confused about what n
if
is.Majenko– Majenko2017年12月16日 18:43:39 +00:00Commented Dec 16, 2017 at 18:43 -
What confused me is
if(6<=Wire.available())
becauseavailable
returnsrxBufferLength - rxBufferIndex;
so ifrxBufferLength
is 6 andrxBufferIndex
is 0, thenavailable
returns 6, which istrue
in this case. But, ifrxBufferIndex
is 1 or 2, thenavailable
returns 5 or 4, which isfalse
. So, how's thatif
statement is working? Doesif(6<=Wire.available())
returns the value one time, or it returns with allrxBufferIndex
increments inside wire library?R1S8K– R1S8K2017年12月21日 17:37:40 +00:00Commented Dec 21, 2017 at 17:37 -
1@PerchEagle At the moment the
if()
executesWire.available()
will equal 6. That is the only time theif()
executes, and it can only ever give 6, since nothing has been read at that point.Majenko– Majenko2017年12月21日 18:33:07 +00:00Commented Dec 21, 2017 at 18:33 -
OK, I understand now, it runs only one time and the function every time returns 6. Thank you :) but I have another problem, the good news I succeeded accomplishing my I2C code, and that was amazing, but I have a new problem passing an array to
I2C_tx
function, I don't know why it's not working. I should ask about it in a new post.R1S8K– R1S8K2017年12月23日 06:31:37 +00:00Commented Dec 23, 2017 at 6:31