1 /*
2 * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2024-12-30 CDT first version
9 */
10
11 /*
12 * 程序清单:这是 I2C 设备使用例程。
13 * 例程导出了 i2c_sample 到控制终端。
14 * 命令调用格式:i2c_sample
15 * 命令解释:
16 * 程序功能:查找I2C模块,读写I2C设备。
17 * 注意:测试要用逻辑分析仪或示波器抓取信号
18 */
19
20 #include <rtthread.h>
21 #include <rtdevice.h>
22 #include <board.h>
23
24 /*
25 * to readout/write from/into i2c device, user could use this macro to choice
26 * either rt_i2c_master_send & rt_i2c_master_recv or rt_i2c_transfer
27 */
28 #if defined(RT_USING_I2C)
29
30 #define USING_RT_I2C_TRANSFER
31
32 /* defined EEPROM */
33 #if defined(HC32F472) || defined(HC32F460) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8) || \
34 defined(HC32F334)
35 #define EE_DEV_ADDR 0x50
36 #define EE_TEST_PAGE_CNT 8 // Test 8 pages
37 #endif
38
39 /* define EEPROM hardware */
40 #if defined(HC32F472) || defined(HC32F460) || defined(HC32F448) || defined(HC32F4A8) || defined(HC32F334)
41 #define EE24C256
42 #elif defined(HC32F4A0)
43 #define EE24C02
44 #endif
45
46 #if defined (EE24C1024)
47 #define EE_PAGE_SIZE 256 // 24C1024
48 #define EE_WORD_ADR_SIZE 2 // 2 word addr
49 #elif defined (EE24C256)
50 #define EE_PAGE_SIZE 64 // 24C256
51 #define EE_WORD_ADR_SIZE 2 // 2 word addr
52 #elif defined (EE24C02)
53 #define EE_PAGE_SIZE 8 // 24C02
54 #define EE_WORD_ADR_SIZE 1 // 1 word addr
55 #endif
56
57 /* device information */
58 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8) || defined(HC32F334)
59 #define HW_I2C_DEV "i2c1"
60 #define SW_I2C_DEV "i2c1_sw"
61 #elif defined(HC32F460)
62 #define HW_I2C_DEV "i2c3"
63 #define SW_I2C_DEV "i2c1_sw"
64 #endif
65
66 /* this API is for eeprom size is smaller than 256Bytes */
eeprom_page_write(uint32_t page,uint8_t * pBuf)67 static void eeprom_page_write(uint32_t page, uint8_t *pBuf)
68 {
69 struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
70 uint8_t TxBuf[EE_PAGE_SIZE + EE_WORD_ADR_SIZE] = {0};
71 struct rt_i2c_msg msg[1];
72
73 #if defined (BSP_USING_I2C_HW)
74 hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV); //hw i2c
75 #else
76 hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV); //sw i2c
77 #endif
78
79 /* START --- ADR_W --- WORD_ADR(1 byte) --- DATAn --- STOP */
80 if (EE_WORD_ADR_SIZE == 2)
81 {
82 TxBuf[0] = (page * EE_PAGE_SIZE) / 256; // addrH
83 TxBuf[1] = page * EE_PAGE_SIZE; // addrL
84 }
85 else
86 {
87 TxBuf[0] = page * EE_PAGE_SIZE;
88 }
89 for (int i = 0; i < EE_PAGE_SIZE; i++) // data fill
90 {
91 TxBuf[i + EE_WORD_ADR_SIZE] = *pBuf++;
92 }
93 msg[0].addr = EE_DEV_ADDR;
94 msg[0].flags = RT_I2C_WR;
95 msg[0].len = EE_PAGE_SIZE + EE_WORD_ADR_SIZE;
96 msg[0].buf = TxBuf;
97
98 #if defined(USING_RT_I2C_TRANSFER)
99 rt_i2c_transfer(hc32_i2c, &msg[0], 1);
100 #else
101 rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_STOP, TxBuf, msg[0].len / 2);
102 rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_START, TxBuf + msg[0].len / 2, msg[0].len - msg[0].len / 2);
103 #endif
104 /* write cycle 5ms */
105 rt_thread_mdelay(5);
106 }
107
eeprom_page_read(uint32_t page,uint8_t * pBuf)108 static void eeprom_page_read(uint32_t page, uint8_t *pBuf)
109 {
110 struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
111 uint8_t readAddr[EE_WORD_ADR_SIZE];
112 #if defined(USING_RT_I2C_TRANSFER)
113 struct rt_i2c_msg msg[2];
114 #endif
115
116 #if defined (BSP_USING_I2C_HW)
117 hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV); //hw i2c
118 #else
119 hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV); //sw i2c
120 #endif
121
122 if (EE_WORD_ADR_SIZE == 2)
123 {
124 readAddr[0] = (page * EE_PAGE_SIZE) / 256; // addrH
125 readAddr[1] = page * EE_PAGE_SIZE; // addrL
126 }
127 else
128 {
129 readAddr[0] = page * EE_PAGE_SIZE;
130 }
131
132 #if defined(USING_RT_I2C_TRANSFER)
133 msg[0].addr = EE_DEV_ADDR;
134 msg[0].flags = RT_I2C_WR;
135 msg[0].len = EE_WORD_ADR_SIZE;
136 msg[0].buf = readAddr;
137
138 msg[1].addr = EE_DEV_ADDR;
139 msg[1].flags = RT_I2C_RD;
140 msg[1].len = EE_PAGE_SIZE;
141 msg[1].buf = pBuf;
142 rt_i2c_transfer(hc32_i2c, &msg[0], 2);
143 #else
144 rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_STOP, readAddr, EE_WORD_ADR_SIZE);
145 rt_i2c_master_recv(hc32_i2c, EE_DEV_ADDR, 0, pBuf, EE_PAGE_SIZE);
146 #endif
147 }
148
eeprom_test(void)149 void eeprom_test(void)
150 {
151 uint32_t page, i;
152 uint32_t compareValueDiff = 0;
153 static rt_uint8_t trans_buf[EE_PAGE_SIZE * EE_TEST_PAGE_CNT];
154 static rt_uint8_t recv_buf[EE_PAGE_SIZE * EE_TEST_PAGE_CNT];
155
156 /* write e2 */
157 for (i = 0; i < sizeof(trans_buf); i++)
158 {
159 trans_buf[i] = i;
160 }
161 for (page = 0; page < EE_TEST_PAGE_CNT; page++)
162 {
163 eeprom_page_write(page, trans_buf + EE_PAGE_SIZE * page);
164 }
165 /* read e2 */
166 for (i = 0; i < sizeof(trans_buf); i++)
167 {
168 recv_buf[i] = 0;
169 }
170 for (page = 0; page < EE_TEST_PAGE_CNT; page++)
171 {
172 eeprom_page_read(page, recv_buf + EE_PAGE_SIZE * page);
173 }
174 /* compare e2 */
175 for (i = 0; i < sizeof(recv_buf); i++)
176 {
177 if (trans_buf[i] != recv_buf[i])
178 {
179 compareValueDiff = 1;
180 break;
181 }
182 }
183 if (compareValueDiff == 0)
184 {
185 rt_kprintf("eeprom test ok!\r\n");
186 }
187 else
188 {
189 rt_kprintf("eeprom test failed!\r\n");
190 }
191 }
192
193 /* TCA9539 device */
194 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8)
195
196 /* TCA9539 define */
197 #define TCA9539_DEV_ADDR (0x74) // TCA9539 chip address on I2C bus
198
199 #define TCA9539_REG_INPUT_PORT0 (0x00U)
200 #define TCA9539_REG_INPUT_PORT1 (0x01U)
201 #define TCA9539_REG_OUTPUT_PORT0 (0x02U)
202 #define TCA9539_REG_OUTPUT_PORT1 (0x03U)
203 #define TCA9539_REG_INVERT_PORT0 (0x04U)
204 #define TCA9539_REG_INVERT_PORT1 (0x05U)
205 #define TCA9539_REG_CONFIG_PORT0 (0x06U)
206 #define TCA9539_REG_CONFIG_PORT1 (0x07U)
207
tca9539_test(void)208 void tca9539_test(void)
209 {
210 struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
211 static rt_uint8_t send_buf0[0x10];
212 static rt_uint8_t send_buf1[0x10], recv_buf1[0x10];
213 struct rt_i2c_msg msg[2];
214
215 #if defined (BSP_USING_I2C_HW)
216 hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV); //hw i2c
217 #else
218 hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV); //sw i2c
219 #endif
220 RT_ASSERT(hc32_i2c != RT_NULL);
221
222 send_buf0[0] = TCA9539_REG_CONFIG_PORT1;
223 send_buf0[1] = 0xFF;
224 msg[0].addr = TCA9539_DEV_ADDR;
225 msg[0].flags = RT_I2C_WR;
226 msg[0].len = 2;
227 msg[0].buf = send_buf0;
228 rt_i2c_transfer(hc32_i2c, &msg[0], 1);
229
230 send_buf0[0] = TCA9539_REG_OUTPUT_PORT1;
231 send_buf0[1] = 0xAC;
232 msg[1].addr = TCA9539_DEV_ADDR;
233 msg[1].flags = RT_I2C_WR;
234 msg[1].len = 2;
235 msg[1].buf = send_buf0;
236 rt_i2c_transfer(hc32_i2c, &msg[1], 1);
237
238 /* read */
239 send_buf1[0] = TCA9539_REG_OUTPUT_PORT1;
240 msg[0].addr = TCA9539_DEV_ADDR;
241 msg[0].flags = RT_I2C_WR;
242 msg[0].len = 1;
243 msg[0].buf = send_buf1;
244
245 msg[1].addr = TCA9539_DEV_ADDR;
246 msg[1].flags = RT_I2C_RD;
247 msg[1].len = 1;
248 msg[1].buf = recv_buf1;
249 rt_i2c_transfer(hc32_i2c, &msg[0], 2);
250
251 if (recv_buf1[0] == 0xAC)
252 {
253 rt_kprintf("tca9539 test ok!\r\n");
254 }
255 else
256 {
257 rt_kprintf("tca9539 test failed!\r\n");
258 }
259 }
260 #endif
261
i2c_sample(int argc,char * argv[])262 static void i2c_sample(int argc, char *argv[])
263 {
264 eeprom_test();
265 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8)
266 tca9539_test();
267 #endif
268 }
269
270 MSH_CMD_EXPORT(i2c_sample, i2c sample);
271
272 #endif/* RT_USING_I2C */
273
274 /*
275 EOF
276 */
277