Skip to content

Commit 45be32d

Browse files
committed
add: 添加I2C的API文档
1 parent 2cd1987 commit 45be32d

1 file changed

Lines changed: 396 additions & 0 deletions

File tree

docs/library/i2c.md

Lines changed: 396 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,396 @@
1+
---
2+
title: I2C
3+
---
4+
5+
## 关于
6+
7+
I2C(Inter-Integrated Circuit)/TWI(Two-wire Interface)是一种广泛使用的串行通信,用于短距离连接设备。这是用于连接传感器、EEPROM、RTC、ADC、DAC、显示器、OLED 以及许多其他设备和微控制器的最常见外设之一。
8+
9+
这种串行通信被视为低速总线,多个设备可以连接在同一条两线总线上,每个设备都有一个唯一的 7 位地址(最多 128 个设备)。这两根线称为SDA(串行数据线)和SCL(串行时钟线)。
10+
11+
::: note
12+
SDA 和SCL 线需要上拉电阻。有关电阻值和工作电压的更多详细信息,请参阅器件数据表。
13+
:::
14+
15+
AirMCU I2C 库基于 [Arduino Wire 库](https://www.arduino.cc/en/reference/wire),并实现了更多 API,如本文档中所述。
16+
17+
## I2C 模式
18+
19+
I2C 可用于两种不同的模式:
20+
21+
- 主模式
22+
23+
- 在此模式下,AirMCU 生成时钟信号并发起与从设备的通信。
24+
25+
- 从模式
26+
27+
- 从机模式,时钟由主设备产生,如果目的地址与目的设备相同则响应主设备。
28+
29+
## I2C 通用 API
30+
31+
以下是主模式和从模式下使用的常用功能。
32+
33+
### begin
34+
35+
该函数用于使用默认配置启动外设。
36+
37+
```cpp
38+
bool begin();
39+
```
40+
41+
如果外设正确初始化,此函数将返回 `true`
42+
43+
### setSDA
44+
45+
该函数用于设置 SDA 引脚。
46+
47+
```cpp
48+
void setSDA(uint32_t pin);
49+
```
50+
51+
- `pin`:SDA 引脚。
52+
53+
或者
54+
55+
```cpp
56+
void setSDA(PinName sda)
57+
```
58+
59+
### setSCL
60+
61+
该函数用于设置 SCL 引脚。
62+
63+
```cpp
64+
void setSCL(uint32_t pin);
65+
```
66+
67+
- `pin`:SCL 引脚。
68+
69+
或者
70+
71+
```cpp
72+
void setSCL(PinName scl)
73+
```
74+
75+
::: warning
76+
`setSDA``setSCL` 函数必须在 `begin` 函数之前调用。
77+
:::
78+
79+
### setClock
80+
81+
该函数用于设置 I2C 时钟频率。
82+
83+
```cpp
84+
void setClock(uint32_t frequency);
85+
```
86+
87+
- `frequency`:I2C 时钟频率。
88+
89+
### write
90+
91+
该函数将数据写入缓冲区。
92+
93+
```cpp
94+
size_t write(uint8_t data);
95+
```
96+
97+
- `data`:要写入的数据。
98+
99+
或者
100+
101+
```cpp
102+
size_t write(const uint8_t *data, size_t len);
103+
```
104+
105+
- `data`:要写入的数据。
106+
- `len`:要写入的数据数量。
107+
108+
### end
109+
110+
该函数用于停止 I2C 通信。
111+
112+
```cpp
113+
void end();
114+
```
115+
116+
调用 `end` 后,您需要再次使用 `begin` 以再次初始化I2C驱动程序。
117+
118+
## I2C 主模式
119+
120+
该模式用于启动与从机的通信。
121+
122+
### 基本用法:
123+
124+
要开始在 Arduino 上使用 I2C 主模式,第一步是将 `Wire.h` 头文件引入到你的代码中。
125+
126+
```cpp
127+
#include <Wire.h>
128+
```
129+
130+
现在,我们可以通过调用 begin 函数来开始外设配置。
131+
132+
```cpp
133+
Wire.begin();
134+
```
135+
136+
通过使用不带任何参数的 `begin` ,所有设置都将使用默认值完成。如需自行设置值,请参阅函数说明。
137+
138+
调用 `begin` 后,我们可以通过调用 `beginTransmission` 并传递 I2C 从机地址来开始传输:
139+
140+
```cpp
141+
Wire.beginTransmission(address);
142+
```
143+
144+
要将一些字节写入从设备,请使用 `write` 函数。
145+
146+
```cpp
147+
Wire.write(data);
148+
```
149+
150+
您可以使用 `write` 函数传递不同的数据类型。
151+
152+
要结束传输,请使用 `endTransmission` 函数。
153+
154+
::: note
155+
`write` 函数不会直接写入从设备,而是添加到I2C缓冲区。为此,您需要使用 endTransmission 函数将缓冲的字节发送到从设备。
156+
:::
157+
158+
```cpp
159+
Wire.endTransmission();
160+
```
161+
162+
调用 `endTransmission` 后,I2C缓冲区中存储的数据将被传输到从设备。
163+
164+
现在您可以请求从从设备读取数据。 `requestFrom` 将要求通过提供地址和大小来读取所选设备的数据。
165+
166+
```cpp
167+
Wire.requestFrom(I2C_DEV_ADDR, SIZE);
168+
```
169+
170+
`readBytes` 将读取它。
171+
172+
```cpp
173+
Wire.readBytes(temp, error);
174+
```
175+
176+
## I2C 主机 API
177+
178+
以下是 I2C 主机 API。这些功能仅用于主模式。
179+
180+
### begin
181+
182+
您可以使用不带任何参数的 `begin` 函数来使用所有默认值。
183+
184+
```cpp
185+
bool begin();
186+
```
187+
188+
或者,您可以指定您使用的 SDA 和 SCL 引脚。
189+
190+
```cpp
191+
bool begin(uint32_t sda, uint32_t scl);
192+
```
193+
194+
### beginTransmission
195+
196+
该函数用于启动 I2C 传输。
197+
198+
```cpp
199+
void beginTransmission(uint8_t address);
200+
```
201+
202+
该函数用于启动与从设备的通信过程。在将消息写入缓冲区之前,通过传递从属 `address` 来调用此函数。
203+
204+
### endTransmission
205+
206+
使用i2c write写入缓冲区后,使用函数 `endTransmission` 将消息发送到 `beginTransmission` 函数上定义的从设备地址。
207+
208+
```cpp
209+
uint8_t endTransmission(bool stopBit = true);
210+
```
211+
212+
- `stopBit`:如果为 `true` ,则发送停止位。
213+
214+
在没有 `sendStop` 的情况下调用此函数相当于 `sendStop = true` 。
215+
216+
```cpp
217+
uint8_t endTransmission(void);
218+
```
219+
220+
该函数将返回错误代码。
221+
222+
### requestFrom
223+
224+
要从从设备读取,请使用 `requestFrom` 函数。
225+
226+
```cpp
227+
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
228+
```
229+
230+
- `address`:从设备地址。
231+
- `quantity`:要读取的字节数。
232+
- `iaddress`:内部地址。
233+
- `isize`:内部地址大小。
234+
- `sendStop`:如果为 `true` ,则发送停止位。
235+
236+
或者,您可以使用
237+
238+
```cpp
239+
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
240+
```
241+
242+
此函数将调用 `requestFrom` ,并将 `iaddress``isize` 设置为 `0`
243+
244+
或者,您可以使用
245+
246+
```cpp
247+
uint8_t requestFrom(uint8_t address, uint8_t quantity)
248+
```
249+
250+
此函数将调用 `requestFrom` ,并将 `iaddress` 和 `isize` 设置为 `0` ,并将 `sendStop` 设置为 `true` 。
251+
252+
### 示例应用程序
253+
254+
以下是如何在主模式下使用 I2C 的示例。
255+
256+
```cpp
257+
#include "Wire.h"
258+
259+
#define I2C_DEV_ADDR 0x55
260+
261+
uint32_t i = 0;
262+
263+
void setup() {
264+
Serial.begin(115200);
265+
Serial.setDebugOutput(true);
266+
Wire.begin();
267+
}
268+
269+
void loop() {
270+
delay(5000);
271+
272+
//Write message to the slave
273+
Wire.beginTransmission(I2C_DEV_ADDR);
274+
Wire.printf("Hello World! %u", i++);
275+
uint8_t error = Wire.endTransmission(true);
276+
Serial.printf("endTransmission: %u\n", error);
277+
278+
//Read 16 bytes from the slave
279+
uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);
280+
Serial.printf("requestFrom: %u\n", bytesReceived);
281+
if((bool)bytesReceived){ //If received more than zero bytes
282+
uint8_t temp[bytesReceived];
283+
Wire.readBytes(temp, bytesReceived);
284+
log_print_buf(temp, bytesReceived);
285+
}
286+
}
287+
```
288+
289+
## I2C 从机模式
290+
291+
该模式用于接受来自主机的通信。
292+
293+
### 基本用法
294+
295+
要开始在 Arduino 上使用 I2C 作为从模式,第一步是将 `Wire.h` 头文件引入到你的代码中。
296+
297+
```cpp
298+
#include <Wire.h>
299+
```
300+
301+
在调用 `begin` 之前,我们必须创建两个回调函数来处理与主设备的通信。
302+
303+
```cpp
304+
Wire.onReceive(onReceive);
305+
```
306+
307+
308+
309+
```cpp
310+
Wire.onRequest(onRequest);
311+
```
312+
313+
`onReceive` 将根据从属设备读取请求处理来自主设备的请求, `onRequest` 将处理对主设备的应答。
314+
315+
现在,我们可以通过使用设备地址调用 `begin` 函数来开始外设配置。
316+
317+
```cpp
318+
Wire.begin(I2C_DEV_ADDR);
319+
```
320+
321+
通过使用不带任何参数的 `begin` ,所有设置都将使用默认值完成。如需自行设置值,请参阅函数说明。
322+
323+
## I2C 从机 API
324+
325+
### begin
326+
327+
在从机模式下,必须通过传递从机地址来使用 `begin` 函数。
328+
329+
```cpp
330+
void TwoWire::begin(uint8_t address, bool generalCall, bool NoStretchMode)
331+
```
332+
333+
- `address`:从机地址。
334+
- `generalCall`:如果为 `true` ,则启用广播地址。
335+
- `NoStretchMode`:如果为 `true` ,则禁用时钟拉伸。
336+
337+
### onReceive
338+
339+
`onReceive` 函数用于定义从主机接收到的数据的回调。
340+
341+
```cpp
342+
void onReceive(cb_function_receive_t callback);
343+
```
344+
345+
### onRequest
346+
347+
`onRequest` 函数用于定义要发送到主机的数据的回调。
348+
349+
```cpp
350+
void onRequest(cb_function_request_t callback);
351+
```
352+
353+
### 示例应用程序
354+
355+
以下是如何在从模式下使用 I2C 的示例。
356+
357+
```cpp
358+
#include <Wire.h>
359+
360+
#define I2C_ADDR 2
361+
362+
void setup()
363+
{
364+
Wire.begin(I2C_ADDR); // join i2c bus with address #4
365+
Wire.onRequest(requestEvent); // register event
366+
Wire.onReceive(receiveEvent); // register event
367+
Serial.begin(9600); // start serial for output
368+
}
369+
370+
void loop()
371+
{
372+
//empty loop
373+
}
374+
375+
// function that executes whenever data is received from master
376+
// this function is registered as an event, see setup()
377+
void receiveEvent(int howMany)
378+
{
379+
while(1 < Wire.available()) // loop through all but the last
380+
{
381+
char c = Wire.read(); // receive byte as a character
382+
Serial.print(c); // print the character
383+
}
384+
int x = Wire.read(); // receive byte as an integer
385+
Serial.println(x); // print the integer
386+
}
387+
388+
// function that executes whenever data is requested by master
389+
// this function is registered as an event, see setup()
390+
void requestEvent()
391+
{
392+
Wire.write("hello\n"); // respond with message of 6 bytes
393+
// as expected by master
394+
}
395+
396+
```

0 commit comments

Comments
 (0)