gpt4 book ai didi

Arduino - 真正的 Wire.write() 和 Wire.read() 解释的 5 个问题

转载 作者:行者123 更新时间:2023-12-04 03:17:10 29 4
gpt4 key购买 nike

我用 Google 搜索了很多次,看来我不是唯一一个在真正理解 Wire.write() 和 Wire.read() 方面遇到问题的人。作为新手,我几乎从不使用别人已经编写的库,我尝试为模块创建我的类,以便真正理解这个模块是如何工作的,并学习如何使用它进行操作。我读过很少的书和太多的教程,但我可以将这些总结为两点:a) 所有教程都只是展示了如何使用这些方法的基础知识,并且 b) 它们实际上并没有解释这些步骤,就像一切都是完全不言自明的一样。说我笨,但我感觉就像有人告诉我 1 + 1 = 2,然后给了我一些多项式方程来求解 :(
所有书籍示例和几乎所有教程看起来都像这个假想的示例:

Wire.beginTransmission(Module_Address); //Use this to start transmission    
Wire.write(0); // go to first register
Wire.endTransmission(); // end this

//阅读

Wire.requestFrom(Module_Address, 3); //Read three registers   
Wire.read(); //Read first register
Wire.read(); //Read second register
Wire.read(); //Read third register

阅读就是这样。说到写作,就更糟了:

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

到目前为止,使用我得到的任何模块都没有那么容易。通常,每个寄存器内部都有不止一个“选项”。例如,假设虚构模块具有如下所示的首次读取寄存器:

地址 |第 7 位 |第 6 位 |第 5 位 |第 4 位 |第 3 位 |位 2 |第 1 位 |位 0
数据字节 1 |静音。|选项 2.........|...................... 选项 3 .................. ……

要只读选项 3,我会使用此代码:

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

问题一
Wire.read() 之后的这个“&”到底是什么意思? (我知道它指向register中的option,但是我不是很理解这个,为什么会在那里)

问题2
为什么以前的问题没有写在任何地方?这么多的教程,这么多的书,但是我在试图弄清楚一个库是如何工作的时候偶然“发现”的。

问题3
想象一下,假设的模块在写入模式下有第三个寄存器,如下所示:

地址 |第 7 位 |第 6 位 |第 5 位 |第 4 位 |第 3 位 |位 2 |第 1 位 |位 0
数据字节 3 |写标志......|选项2…………………………选项3…………

如何在不影响选项2和选项3的情况下写flag?或者换句话说,如何写入寄存器3的写标志?如果我选择 11000000 可能会影响,因为我可能不知道选项 2 和 3 到底做什么,或者我不想干扰默认设置。

问题4
某些模块必须以二进制编码的十进制形式编写。比方说,你有一个计时器,你希望将 17 秒的倒计时设置为 0。为此,你需要写入数字 17 来注册一个,但数字应该是二进制编码的十进制。二进制编码的 17 是:0001 0111。但是当你这样做时:

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

非常感谢您的帮助:)

最佳答案

问题 1. - 4.:都包含在 Bit Manipulation tutorial 中在 AVRFreaks论坛Tutorials .简而言之:

  • 1) 在这种情况下,& 用于位掩码。
  • 2) 如果您寻找“位操作”,那么有大量教程。
  • 3) 可以通过位操作实现。如何?对于内存变量,只需使用位掩码。清除两位:var &= 0b00111111 设置两位:var |= 0b11000000。如果您没有寄存器值,则必须读取并修改并写回。如果您无法读取该值(例如,它是 eeproms 的内部地址),您无论如何都必须在内存中拥有该值。
  • 4) 在 C++ 中,以零开头的数字是八进制数。如果你想要二进制,你必须使用 0b00010111。对于 HEX 基数,您必须使用 0xFF。该教程中未明确提及,但此处均使用了这两者。
  • 5) 应该尽可能清楚。但是对于没有很好的 C++ 知识的初学者来说,无论如何都很难。对我来说,阅读没有缩进的代码是最困难的,甚至最糟糕的是缩进错误、变量名错误。这些库通常由高级用户编写,因此了解所用 MCU 的数据表等背景知识并不难理解。

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

//0x1F is hexadecimal of binary 0001111 for option 3 in register 1

0x1F 的值绝对不是 0001111 而是 00011111(或者更好:0b00011111)

关于Arduino - 真正的 Wire.write() 和 Wire.read() 解释的 5 个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40064810/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com