今天使用Arduino的IIC外设Wire.h库区读取的时候发现,读两百字节,每次读到32个字节就不行了;敏感的朋友,遇到32、64、1024、等数字的时候应该有点思路,可能是软件限制住了fifo的大小
以下是部分代码
Wire.beginTransmission(slaveaddr >> 1);
Wire.write(Dataaddr >> 8);
Wire.write(Dataaddr & 0xFF);
error = Wire.endTransmission();
Wire.requestFrom(slaveaddr >> 1, readnumber);
while (Wire.available())
{
buff[counter++] = Wire.read();
}
经过层层查找:
Wire.available() 是这个函数退出的
在官方提供的库中 wire.cpp中看到如下:
// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
int TwoWire::available(void)
{
return rxBufferLength - rxBufferIndex;
}
读取数据的退出收到了rxBufferLength 以及rxBufferIndex的影响
继续追踪代码:
在方法:
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
{
·······部分省略·········
// clamp to buffer length
if(quantity > BUFFER_LENGTH){
quantity = BUFFER_LENGTH;
}
// perform blocking read into buffer
uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
// set rx buffer iterator vars
rxBufferIndex = 0;
rxBufferLength = read;
········部分省略············
}
可以看到 BUFFER_LENGTH 长度跟这个宏限制有关
#define BUFFER_LENGTH 32
找到了真凶
改这个试了试,这次情况不一样了,读大于32个数时,
while (Wire.available()) 直接就退出了,所以一个数据都没读;
这里给个思路:至此我们还没看到数据从哪里来的,所以继续找到数据源头。
咱们继续深入同样的方法:
wire.h 中 看到IIC初始化方法中
void TwoWire::begin(void)
·····
twi_attachSlaveRxEvent(onReceiveService); // default callback must exist
·····
有没有点感觉? 回调函数 读取数据用的
// behind the scenes function that is called when data is received
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
继续看:
这个回调函数在在twi.c中使用
// callback to user defined callback
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
真相大白了,原来是在中断中处理的
ISR(TWI_vect){}
在这个文件中,又看到一个数据缓冲区:
twi_rxBuffer[]
定义的地方:
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
#define TWI_BUFFER_LENGTH 32
好了到此为止,问题已经解决了,
真凶就是:
wire.h
#define BUFFER_LENGTH 32
twi.h
#define TWI_BUFFER_LENGTH 32
把这两个宏定义的长度改了就可以了
我改成了:
#define BUFFER_LENGTH 220u
#define TWI_BUFFER_LENGTH 220u
最大能接收:220字节
注意:长度的定义,官方用uint8_t 类型,所以不能设置大于255。
这只是让你知道原因;
改官方库,当然不推荐,所以:
第二种方法:
当读长度大于32时,那就冲新启动总线 多次读咯。
有困惑联系:fifteenPeng@163.com