首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Arduino -5实际Wire.write()和Wire.read()解释问题

Arduino -5实际Wire.write()和Wire.read()解释问题
EN

Stack Overflow用户
提问于 2016-10-15 22:17:15
回答 1查看 4.3K关注 0票数 3

我在谷歌上搜索了很多,而且似乎我不是唯一一个在真正理解Wire.write()和Wire.read()方面有问题的人。作为新手,我几乎从不使用已经由某人编写的库,我尝试为模块创建类,以便真正了解这个模块是如何工作的,并学习如何使用它来操作。我读过很少的书和太多的教程,但我可以把它们归纳为两部分:( a)所有的教程都只是展示如何使用这些方法的基本知识;( b)它们实际上并没有解释这些步骤,就好像所有的东西都是完全不言自明的。说我笨,但我感觉好像有人告诉我1+1= 2,然后给了我一些多项式方程来解决:

所有的书籍示例和几乎所有的教程都类似于这个想象中的例子:

代码语言:javascript
复制
Wire.beginTransmission(Module_Address); //Use this to start transmission    
Wire.write(0); // go to first register    
Wire.endTransmission(); // end this    

//改为

代码语言:javascript
复制
Wire.requestFrom(Module_Address, 3); //Read three registers   
Wire.read(); //Read first register   
Wire.read(); //Read second register   
Wire.read(); //Read third register

这就是读书的问题。说到写作,更糟糕的是:

代码语言:javascript
复制
Wire.beginTransmission(Module_Address); //Use this to start transmission     
Wire.write(0); // go to first register   
Wire.write(something); //Write to first register   
Wire.write(something); //write to second register   
Wire.endTransmission(); // end this

到目前为止,与我所拥有的任何模块一起工作,从来没有那么容易。通常,每个寄存器内有多个“选项”。例如,假设虚拟模块首先读取寄存器如下:

地址_~_

数据-静音- option2.........|.....................option3.......................

要只读取选项3,我将使用以下代码:

代码语言:javascript
复制
Wire.beginTransmission(module_address);    
Wire.write(0);        
Wire.endTransmission();    

Wire.requestFrom(module_address, 1);    
byte readings = Wire.read() & 0x1F; //0x1F is hexadecimal of binary 0001111 for option 3 in register 1    

问题1

Wire.read()之后的'&‘到底是什么意思?(我知道它指向寄存器内的选项,但我并不真正理解这一点,为什么会有这样的选项)

问题2

为什么前面的问题没有写在任何地方?有这么多的教程,那么多的书,但是当我试图弄清楚一个图书馆是如何工作的时,我偶然发现了它。

问题3

假设模块在写模式下有第三个寄存器,如下所示:

地址_~_

数据option2.........|......................option3........ Byte3 \写入标志.

如何在不影响选项2和选项3的情况下编写标志?或者换句话说,如何写注册3的写标志?如果我采取11000000可能会影响,因为我可能不知道具体选项2和3做什么,或者我不希望干扰默认设置。

问题4

某些模块必须用二进制编码的十进制来写。比方说,你有一个计时器,你希望把倒计时时间设为0。要做到这一点,你需要写数字17来注册一个,但是数字应该是二进制编码的十进制。17作为二进制编码是: 0001 0111。但当你这么做的时候

代码语言:javascript
复制
Wire.beginTransmission(module_address);         
Wire.write(0);    
Wire.write(00010111);    
Wire.endTransmission();        

你得到不同的号码,13或10 (我记不起是哪个号码了,我知道是错的)。然而,在进行这个转换时: 17/10*16 + 17%10它写的是正确的数字17。是的,我也意外地发现了这一点。但是,这个等式是从哪里来的呢?我尽我所能地找了(显然是错的),但什么也没有。那么,这个方程式是怎么来的?

问题5

可能是个愚蠢的话题之外的问题,但是:

Arduino图书馆是否应该以其他人很难理解其背后的想法的方式编写?换句话说,要搞清楚开发人员到底在做什么?我记得有一个人用了很多杂乱无章的代码从传感器读取一些东西,然后用公式把它从二进制编码的十进制中转换出来,打印到串行监视器,而同样的事情也可以用简单的方法完成。

Serial.print(read_byte,HEX);

这并不是说我比他们更聪明(或更好),我只是不明白为什么有人会在没有(真的)需要的情况下编写复杂的代码。

非常感谢您的帮助:)

EN

回答 1

Stack Overflow用户

发布于 2016-10-16 06:28:46

问题1. -4:位操作教程AVRFreaks论坛教程上都有报道。因此,简而言之:

  • 1)在这种情况下,使用&进行比特掩蔽。
  • 2)如果您寻找“位操作”,那么就会有大量的教程。
  • 3)比特操作是可能的。多么?因为在内存变量中,只需使用位掩蔽。若要清除两位:var &= 0b00111111,请设置两位:var |= 0b11000000。如果没有寄存器值,则必须读取和修改并将其写回。如果您无法读取值(例如,它的内部地址类似于eeproms),那么无论如何,您都必须在内存中具有这个值。
  • 4)在C++中,从零开始的数在八进制。如果您想要二进制,就必须使用0b00010111。对于HEX基地,你必须使用0xFF。在本教程中没有明确提到这一点,但这两种方法都在这里使用。
  • 5)应尽可能明确。但是对于那些不懂C++的乞丐来说,这是很难的。对我来说,在没有缩进的情况下,阅读代码是最困难的,甚至最糟糕的是,错误的缩进,糟糕的变量名。库通常是由高级用户编写的,因此在一些背景下(比如了解使用的MCU的数据表)不难理解。

顺便说一句:错误的评论也不利于理解:

代码语言:javascript
复制
//0x1F is hexadecimal of binary 0001111 for option 3 in register 1

0x1F肯定不是二进制格式的0001111,而是00011111 (或者更好的是:0b00011111)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40064810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档