• Home
Name Date Size #Lines LOC

..--

include/12-May-2024-9611

src/12-May-2024-376229

BUILD.gnD12-May-2024838 2723

README_zh.mdD12-May-20249.4 KiB423312

eeprom_example.cD12-May-20242.9 KiB10269

README_zh.md

1# 小凌派-RK2206开发板基础外设开发——I2C控制EEPROM读写
2
3本示例将演示如何在小凌派-RK2206开发板上使用I2C控制EEPROM读写
4
5![小凌派-RK2206](../../docs/figures/lockzhiner-rk2206.jpg)
6
7## 程序设计
8
9### API分析
10
11#### eeprom_init()
12
13```c
14unsigned int eeprom_init();
15```
16
17**描述:**
18
19EEPROM初始化,包括i2c初始化。
20
21**参数:**
22
2324
25**返回值:**
26
270为成功,反之失败
28
29#### eeprom_deinit()
30
31```c
32unsigned int eeprom_deinit();
33```
34
35**描述:**
36
37EEPROM注销。
38
39**参数:**
40
4142
43**返回值:**
44
450为成功,反之失败
46
47#### eeprom_get_blocksize()
48
49```c
50unsigned int eeprom_get_blocksize();
51```
52
53**描述:**
54
55EEPROM获取页大小。
56
57**参数:**
58
5960
61**返回值:**
62
63返回页大小。
64
65#### eeprom_readbyte()
66
67```c
68unsigned int eeprom_readbyte(unsigned int addr, unsigned char *data);
69```
70
71**描述:**
72
73EEPROM读一个字节。
74
75**参数:**
76
77* addr:EEPROM存储地址
78* data: 存放EERPOM的数据指针
79
80**返回值:**
81
82返回读取字节的长度,反之为错误。
83
84#### eeprom_writebyte()
85
86```c
87unsigned int eeprom_writebyte(unsigned int addr, unsigned char data);
88```
89
90**描述:**
91
92EEPROM写一个字节。
93
94**参数:**
95
96* addr:EEPROM存储地址
97* data: 写ERPOM的数据
98
99**返回值:**
100
101返回写入字节的长度,反之为错误。
102
103#### eeprom_writepage()
104
105```c
106unsigned int eeprom_writepage(unsigned int addr,
107                unsigned char *data,
108                unsigned int data_len);
109```
110
111**描述:**
112
113EEPROM写1个页字节。
114
115**参数:**
116
117* addr: EEPROM存储地址,必须是页地址
118* data: 写ERPOM的数据指针
119* data_len: 写EEPROM数据的长度,必须是小于或等于1个页大小
120
121**返回值:**
122
123返回写入字节的长度,反之为错误。
124
125#### eeprom_read()
126
127```c
128unsigned int eeprom_read(unsigned int addr,
129                unsigned char *data,
130                unsigned int data_len);
131```
132
133**描述:**
134
135EEPROM读多个字节。
136
137**参数:**
138
139* addr: EEPROM存储地址,必须是页地址
140* data: 存放EERPOM的数据指针
141* data_len: 读取EERPOM数据的长度
142
143**返回值:**
144
145返回读取字节的长度,反之为错误。
146
147#### eeprom_write()
148
149```c
150unsigned int eeprom_write(unsigned int addr,
151                unsigned char *data,
152                unsigned int data_len);
153```
154
155**描述:**
156
157EEPROM写多个字节。
158
159**参数:**
160
161* addr: EEPROM存储地址,必须是页地址
162* data: 写ERPOM的数据指针
163* data_len: 写EEPROM数据的长度
164
165**返回值:**
166
167返回写入数据的长度,反之为错误。
168
169### 主要代码分析
170
171#### i2c初始化源代码分析
172
173这部分代码为i2c初始化的代码。首先用 `I2cIoInit()` 函数将GPIO0_PA0复用为I2C0_SDA_M2,GPIO0_PA1复用为I2C1_SCL_M2。最后调用 `LzI2cInit()`函数初始化I2C1端口。
174
175```c
176if (I2cIoInit(m_i2cBus) != LZ_HARDWARE_SUCCESS) {
177    printf("%s, %d: I2cIoInit failed!\n", __FILE__, __LINE__);
178    return __LINE__;
179}
180if (LzI2cInit(EEPROM_I2C_BUS, m_i2c_freq) != LZ_HARDWARE_SUCCESS) {
181    printf("%s, %d: I2cIoInit failed!\n", __FILE__, __LINE__);
182    return __LINE__;
183}
184```
185
186#### K24C02读操作
187
188本模块只采用K24C02读模式的连续读数据(Sequential Read)。具体如何控制i2c读K24C02数据的操作如下:
189
190```c
191/***************************************************************
192* 函数名称: eeprom_readbyte
193* 说    明: EEPROM读一个字节
194* 参    数:
195*           @addr: EEPROM存储地址
196*           @data: 存放EERPOM的数据指针
197* 返 回 值: 返回读取字节的长度,反之为错误
198***************************************************************/
199unsigned int eeprom_readbyte(unsigned int addr, unsigned char *data)
200{
201    unsigned int ret = 0;
202    unsigned char buffer[1];
203    LzI2cMsg msgs[2];
204
205    /* K24C02的存储地址是0~255 */
206    if (addr >= EEPROM_ADDRESS_MAX) {
207        printf("%s, %s, %d: addr(0x%x) >= EEPROM_ADDRESS_MAX(0x%x)\n", __FILE__, __func__, __LINE__, addr, EEPROM_ADDRESS_MAX);
208        return 0;
209    }
210
211    buffer[0] = (unsigned char)addr;
212
213    msgs[0].addr = EEPROM_I2C_ADDRESS;
214    msgs[0].flags = 0;
215    msgs[0].buf = &buffer[0];
216    msgs[0].len = 1;
217
218    msgs[1].addr = EEPROM_I2C_ADDRESS;
219    msgs[1].flags = I2C_M_RD;
220    msgs[1].buf = data;
221    msgs[1].len = 1;
222
223   ret = LzI2cTransfer(EEPROM_I2C_BUS, msgs, 2);
224   if (ret != LZ_HARDWARE_SUCCESS) {
225       printf("%s, %s, %d: LzI2cTransfer failed(%d)!\n", __FILE__, __func__, __LINE__, ret);
226       return 0;
227   }
228
229    return 1;
230}
231```
232
233#### K24C02写操作
234
235本模块采用K24C02写模式的字节写操作(Byte Write)。具体如何控制i2c往K24C02写字节的操作如下:
236
237```c
238/***************************************************************
239* 函数名称: eeprom_writebyte
240* 说    明: EEPROM写一个字节
241* 参    数:
242*           @addr: EEPROM存储地址
243*           @data: 写EERPOM的数据
244* 返 回 值: 返回写入数据的长度,反之为错误
245***************************************************************/
246unsigned int eeprom_writebyte(unsigned int addr, unsigned char data)
247{
248    unsigned int ret = 0;
249    LzI2cMsg msgs[1];
250    unsigned char buffer[2];
251
252    /* K24C02的存储地址是0~255 */
253    if (addr >= EEPROM_ADDRESS_MAX) {
254        printf("%s, %s, %d: addr(0x%x) >= EEPROM_ADDRESS_MAX(0x%x)\n", __FILE__, __func__, __LINE__, addr, EEPROM_ADDRESS_MAX);
255        return 0;
256    }
257
258    buffer[0] = (unsigned char)(addr & 0xFF);
259    buffer[1] = data;
260
261    msgs[0].addr = EEPROM_I2C_ADDRESS;
262    msgs[0].flags = 0;
263    msgs[0].buf = &buffer[0];
264    msgs[0].len = 2;
265
266    ret = LzI2cTransfer(EEPROM_I2C_BUS, msgs, 1);
267    if (ret != LZ_HARDWARE_SUCCESS) {
268       printf("%s, %s, %d: LzI2cTransfer failed(%d)!\n", __FILE__, __func__, __LINE__, ret);
269       return 0;
270    }
271
272    /* K24C02芯片需要时间完成写操作,在此之前不响应其他操作*/
273    eeprog_delay_usec(1000);
274
275    return 1;
276}
277```
278
279本模块采用K24C02写模式的页写操作(Page Write)。具体如何控制i2c往K24C02写页的操作如下:
280
281```c
282/***************************************************************
283* 函数名称: eeprom_writepage
284* 说    明: EEPROM写1个页字节
285* 参    数:
286*           @addr: EEPROM存储地址,必须是页地址
287*           @data: 写EERPOM的数据指针
288*           @data_len: 写EEPROM数据的长度,必须是小于1个页大小
289* 返 回 值: 返回写入数据的长度,反之为错误
290***************************************************************/
291unsigned int eeprom_writepage(unsigned int addr, unsigned char *data, unsigned int data_len)
292{
293    unsigned int ret = 0;
294    LzI2cMsg msgs[1];
295    unsigned char buffer[EEPROM_PAGE + 1];
296
297    /* K24C02的存储地址是0~255 */
298    if (addr >= EEPROM_ADDRESS_MAX) {
299        printf("%s, %s, %d: addr(0x%x) >= EEPROM_ADDRESS_MAX(0x%x)\n", __FILE__, __func__, __LINE__, addr, EEPROM_ADDRESS_MAX);
300        return 0;
301    }
302
303    if ((addr % EEPROM_PAGE) != 0) {
304        printf("%s, %s, %d: addr(0x%x) is not page addr(0x%x)\n", __FILE__, __func__, __LINE__, addr, EEPROM_PAGE);
305        return 0;
306    }
307
308    if ((addr + data_len) > EEPROM_ADDRESS_MAX) {
309        printf("%s, %s, %d: addr + data_len(0x%x) > EEPROM_ADDRESS_MAX(0x%x)\n", __FILE__, __func__, __LINE__, addr + data_len, EEPROM_ADDRESS_MAX);
310        return 0;
311    }
312
313    if (data_len > EEPROM_PAGE) {
314        printf("%s, %s, %d: data_len(%d) > EEPROM_PAGE(%d)\n", __FILE__, __func__, __LINE__, data_len, EEPROM_PAGE);
315        return 0;
316    }
317
318    buffer[0] = addr;
319    memcpy(&buffer[1], data, data_len);
320
321    msgs[0].addr = EEPROM_I2C_ADDRESS;
322    msgs[0].flags = 0;
323    msgs[0].buf = &buffer[0];
324    msgs[0].len = 1 + data_len;
325
326    ret = LzI2cTransfer(EEPROM_I2C_BUS, msgs, 1);
327    if (ret != LZ_HARDWARE_SUCCESS) {
328       printf("%s, %s, %d: LzI2cTransfer failed(%d)!\n", __FILE__, __func__, __LINE__, ret);
329       return 0;
330    }
331
332    /* K24C02芯片需要时间完成写操作,在此之前不响应其他操作*/
333    eeprog_delay_usec(1000);
334
335    return data_len;
336}
337```
338
339## 编译调试
340
341### 修改 BUILD.gn 文件
342
343修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `b3_eeprom` 参与编译。
344
345```r
346"b3_eeprom",
347```
348
349在主目录下输入编译命令。
350
351```shell
352hb build -f
353```
354
355### 运行结果
356
357示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,显示如下:
358
359```c
360************ Eeprom Process ************
361BlockSize = 0x8
362Write Byte: 3 = !
363Write Byte: 4 = "
364Write Byte: 5 = #
365Write Byte: 6 = $
366Write Byte: 7 = %
367Write Byte: 8 = &
368Write Byte: 9 = '
369Write Byte: 10 = (
370Write Byte: 11 = )
371Write Byte: 12 = *
372Write Byte: 13 = +
373Write Byte: 14 = ,
374Write Byte: 15 = -
375Write Byte: 16 = .
376Write Byte: 17 = /
377Write Byte: 18 = 0
378Write Byte: 19 = 1
379Write Byte: 20 = 2
380Write Byte: 21 = 3
381Write Byte: 22 = 4
382Write Byte: 23 = 5
383Write Byte: 24 = 6
384Write Byte: 25 = 7
385Write Byte: 26 = 8
386Write Byte: 27 = 9
387Write Byte: 28 = :
388Write Byte: 29 = ;
389Write Byte: 30 = <
390Write Byte: 31 = =
391Write Byte: 32 = >
392Read Byte: 3 = !
393Read Byte: 4 = "
394Read Byte: 5 = #
395Read Byte: 6 = $
396Read Byte: 7 = %
397Read Byte: 8 = &
398Read Byte: 9 = '
399Read Byte: 10 = (
400Read Byte: 11 = )
401Read Byte: 12 = *
402Read Byte: 13 = +
403Read Byte: 14 = ,
404Read Byte: 15 = -
405Read Byte: 16 = .
406Read Byte: 17 = /
407Read Byte: 18 = 0
408Read Byte: 19 = 1
409Read Byte: 20 = 2
410Read Byte: 21 = 3
411Read Byte: 22 = 4
412Read Byte: 23 = 5
413Read Byte: 24 = 6
414Read Byte: 25 = 7
415Read Byte: 26 = 8
416Read Byte: 27 = 9
417Read Byte: 28 = :
418Read Byte: 29 = ;
419Read Byte: 30 = <
420Read Byte: 31 = =
421Read Byte: 32 = >
422```
423