1 /**************************************************************************//**
2 * @file i2c.c
3 * @version V3.00
4 * $Revision: 2 $
5 * $Date: 16/08/02 6:02p $
6 * @brief I2C Serial Interface Controller(I2C) driver source file
7 *
8 * @copyright SPDX-License-Identifier: Apache-2.0
9 * @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
10 *****************************************************************************/
11 #include "NuMicro.h"
12
13 /** @addtogroup Standard_Driver Standard Driver
14 @{
15 */
16
17 /** @addtogroup I2C_Driver I2C Driver
18 @{
19 */
20
21
22 /** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions
23 @{
24 */
25
26 /**
27 * @brief Enable specify I2C Controller and set Clock Divider
28 *
29 * @param[in] i2c Specify I2C port
30 * @param[in] u32BusClock The target I2C bus clock in Hz
31 *
32 * @return Actual I2C bus clock frequency
33 *
34 * @details The function enable the specify I2C Controller and set proper Clock Divider
35 * in I2C CLOCK DIVIDED REGISTER (I2CLK) according to the target I2C Bus clock.
36 * I2C Bus clock = PCLK / (4*(divider+1).
37 *
38 */
I2C_Open(I2C_T * i2c,uint32_t u32BusClock)39 uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock)
40 {
41 uint32_t u32Div;
42 uint32_t u32Pclk;
43
44 if((i2c == I2C1) || (i2c == I2C1_NS))
45 {
46 u32Pclk = CLK_GetPCLK1Freq();
47 }
48 else
49 {
50 u32Pclk = CLK_GetPCLK0Freq();
51 }
52
53 u32Div = (uint32_t)(((u32Pclk * 10u) / (u32BusClock * 4u) + 5u) / 10u - 1u); /* Compute proper divider for I2C clock */
54 i2c->CLKDIV = u32Div;
55
56 /* Enable I2C */
57 i2c->CTL0 |= I2C_CTL0_I2CEN_Msk;
58
59 return (u32Pclk / ((u32Div + 1u) << 2u));
60 }
61
62 /**
63 * @brief Disable specify I2C Controller
64 *
65 * @param[in] i2c Specify I2C port
66 *
67 * @return None
68 *
69 * @details Reset I2C Controller and disable specify I2C port.
70 *
71 */
72
I2C_Close(I2C_T * i2c)73 void I2C_Close(I2C_T *i2c)
74 {
75 /* Disable I2C */
76 i2c->CTL0 &= ~I2C_CTL0_I2CEN_Msk;
77 }
78
79 /**
80 * @brief Clear Time-out Counter flag
81 *
82 * @param[in] i2c Specify I2C port
83 *
84 * @return None
85 *
86 * @details When Time-out flag will be set, use this function to clear I2C Bus Time-out counter flag .
87 *
88 */
I2C_ClearTimeoutFlag(I2C_T * i2c)89 void I2C_ClearTimeoutFlag(I2C_T *i2c)
90 {
91 i2c->TOCTL |= I2C_TOCTL_TOIF_Msk;
92 }
93
94 /**
95 * @brief Set Control bit of I2C Controller
96 *
97 * @param[in] i2c Specify I2C port
98 * @param[in] u8Start Set I2C START condition
99 * @param[in] u8Stop Set I2C STOP condition
100 * @param[in] u8Si Clear SI flag
101 * @param[in] u8Ack Set I2C ACK bit
102 *
103 * @return None
104 *
105 * @details The function set I2C Control bit of I2C Bus protocol.
106 *
107 */
I2C_Trigger(I2C_T * i2c,uint8_t u8Start,uint8_t u8Stop,uint8_t u8Si,uint8_t u8Ack)108 void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack)
109 {
110 uint32_t u32Reg = 0u;
111
112 if(u8Start)
113 {
114 u32Reg |= I2C_CTL_STA;
115 }
116 if(u8Stop)
117 {
118 u32Reg |= I2C_CTL_STO;
119 }
120 if(u8Si)
121 {
122 u32Reg |= I2C_CTL_SI;
123 }
124 if(u8Ack)
125 {
126 u32Reg |= I2C_CTL_AA;
127 }
128
129 i2c->CTL0 = (i2c->CTL0 & ~0x3Cu) | u32Reg;
130 }
131
132 /**
133 * @brief Disable Interrupt of I2C Controller
134 *
135 * @param[in] i2c Specify I2C port
136 *
137 * @return None
138 *
139 * @details The function is used for disable I2C interrupt
140 *
141 */
I2C_DisableInt(I2C_T * i2c)142 void I2C_DisableInt(I2C_T *i2c)
143 {
144 i2c->CTL0 &= ~I2C_CTL0_INTEN_Msk;
145 }
146
147 /**
148 * @brief Enable Interrupt of I2C Controller
149 *
150 * @param[in] i2c Specify I2C port
151 *
152 * @return None
153 *
154 * @details The function is used for enable I2C interrupt
155 *
156 */
I2C_EnableInt(I2C_T * i2c)157 void I2C_EnableInt(I2C_T *i2c)
158 {
159 i2c->CTL0 |= I2C_CTL0_INTEN_Msk;
160 }
161
162 /**
163 * @brief Get I2C Bus Clock
164 *
165 * @param[in] i2c Specify I2C port
166 *
167 * @return The actual I2C Bus clock in Hz
168 *
169 * @details To get the actual I2C Bus Clock frequency.
170 */
I2C_GetBusClockFreq(I2C_T * i2c)171 uint32_t I2C_GetBusClockFreq(I2C_T *i2c)
172 {
173 uint32_t u32Divider = i2c->CLKDIV;
174 uint32_t u32Pclk;
175
176 if((i2c == I2C1) || (i2c == I2C1_NS))
177 {
178 u32Pclk = CLK_GetPCLK1Freq();
179 }
180 else
181 {
182 u32Pclk = CLK_GetPCLK0Freq();
183 }
184
185 return (u32Pclk / ((u32Divider + 1u) << 2u));
186 }
187
188 /**
189 * @brief Set I2C Bus Clock
190 *
191 * @param[in] i2c Specify I2C port
192 * @param[in] u32BusClock The target I2C Bus Clock in Hz
193 *
194 * @return The actual I2C Bus Clock in Hz
195 *
196 * @details To set the actual I2C Bus Clock frequency.
197 */
I2C_SetBusClockFreq(I2C_T * i2c,uint32_t u32BusClock)198 uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock)
199 {
200 uint32_t u32Div;
201 uint32_t u32Pclk;
202
203 if((i2c == I2C1) || (i2c == I2C1_NS))
204 {
205 u32Pclk = CLK_GetPCLK1Freq();
206 }
207 else
208 {
209 u32Pclk = CLK_GetPCLK0Freq();
210 }
211
212 u32Div = (uint32_t)(((u32Pclk * 10u) / (u32BusClock * 4u) + 5u) / 10u - 1u); /* Compute proper divider for I2C clock */
213 i2c->CLKDIV = u32Div;
214
215 return (u32Pclk / ((u32Div + 1u) << 2u));
216 }
217
218 /**
219 * @brief Get Interrupt Flag
220 *
221 * @param[in] i2c Specify I2C port
222 *
223 * @return I2C interrupt flag status
224 *
225 * @details To get I2C Bus interrupt flag.
226 */
I2C_GetIntFlag(I2C_T * i2c)227 uint32_t I2C_GetIntFlag(I2C_T *i2c)
228 {
229 return ((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk ? 1ul : 0ul);
230 }
231
232 /**
233 * @brief Get I2C Bus Status Code
234 *
235 * @param[in] i2c Specify I2C port
236 *
237 * @return I2C Status Code
238 *
239 * @details To get I2C Bus Status Code.
240 */
I2C_GetStatus(I2C_T * i2c)241 uint32_t I2C_GetStatus(I2C_T *i2c)
242 {
243 return (i2c->STATUS0);
244 }
245
246 /**
247 * @brief Read a Byte from I2C Bus
248 *
249 * @param[in] i2c Specify I2C port
250 *
251 * @return I2C Data
252 *
253 * @details To read a bytes data from specify I2C port.
254 */
I2C_GetData(I2C_T * i2c)255 uint8_t I2C_GetData(I2C_T *i2c)
256 {
257 return (uint8_t)(i2c->DAT);
258 }
259
260 /**
261 * @brief Send a byte to I2C Bus
262 *
263 * @param[in] i2c Specify I2C port
264 * @param[in] u8Data The data to send to I2C bus
265 *
266 * @return None
267 *
268 * @details This function is used to write a byte to specified I2C port
269 */
I2C_SetData(I2C_T * i2c,uint8_t u8Data)270 void I2C_SetData(I2C_T *i2c, uint8_t u8Data)
271 {
272 i2c->DAT = u8Data;
273 }
274
275 /**
276 * @brief Set 7-bit Slave Address and GC Mode
277 *
278 * @param[in] i2c Specify I2C port
279 * @param[in] u8SlaveNo Set the number of I2C address register (0~3)
280 * @param[in] u8SlaveAddr 7-bit slave address
281 * @param[in] u8GCMode Enable/Disable GC mode (I2C_GCMODE_ENABLE / I2C_GCMODE_DISABLE)
282 *
283 * @return None
284 *
285 * @details This function is used to set 7-bit slave addresses in I2C SLAVE ADDRESS REGISTER (I2CADDR0~3)
286 * and enable GC Mode.
287 *
288 */
I2C_SetSlaveAddr(I2C_T * i2c,uint8_t u8SlaveNo,uint8_t u8SlaveAddr,uint8_t u8GCMode)289 void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode)
290 {
291 switch(u8SlaveNo)
292 {
293 case 1:
294 i2c->ADDR1 = ((uint32_t)u8SlaveAddr << 1) | u8GCMode;
295 break;
296 case 2:
297 i2c->ADDR2 = ((uint32_t)u8SlaveAddr << 1) | u8GCMode;
298 break;
299 case 3:
300 i2c->ADDR3 = ((uint32_t)u8SlaveAddr << 1) | u8GCMode;
301 break;
302 case 0:
303 default:
304 i2c->ADDR0 = ((uint32_t)u8SlaveAddr << 1) | u8GCMode;
305 break;
306 }
307 }
308
309 /**
310 * @brief Configure the mask bits of 7-bit Slave Address
311 *
312 * @param[in] i2c Specify I2C port
313 * @param[in] u8SlaveNo Set the number of I2C address mask register (0~3)
314 * @param[in] u8SlaveAddrMask A byte for slave address mask
315 *
316 * @return None
317 *
318 * @details This function is used to set 7-bit slave addresses.
319 *
320 */
I2C_SetSlaveAddrMask(I2C_T * i2c,uint8_t u8SlaveNo,uint8_t u8SlaveAddrMask)321 void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask)
322 {
323 switch(u8SlaveNo)
324 {
325 case 1:
326 i2c->ADDRMSK1 = (uint32_t)u8SlaveAddrMask << 1;
327 break;
328 case 2:
329 i2c->ADDRMSK2 = (uint32_t)u8SlaveAddrMask << 1;
330 break;
331 case 3:
332 i2c->ADDRMSK3 = (uint32_t)u8SlaveAddrMask << 1;
333 break;
334 case 0:
335 default:
336 i2c->ADDRMSK0 = (uint32_t)u8SlaveAddrMask << 1;
337 break;
338 }
339 }
340
341 /**
342 * @brief Enable Time-out Counter Function and support Long Time-out
343 *
344 * @param[in] i2c Specify I2C port
345 * @param[in] u8LongTimeout Configure DIV4 to enable Long Time-out (0/1)
346 *
347 * @return None
348 *
349 * @details This function enable Time-out Counter function and configure DIV4 to support Long
350 * Time-out.
351 *
352 */
I2C_EnableTimeout(I2C_T * i2c,uint8_t u8LongTimeout)353 void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout)
354 {
355 if(u8LongTimeout)
356 {
357 i2c->TOCTL |= I2C_TOCTL_TOCDIV4_Msk;
358 }
359 else
360 {
361 i2c->TOCTL &= ~I2C_TOCTL_TOCDIV4_Msk;
362 }
363
364 i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
365 }
366
367 /**
368 * @brief Disable Time-out Counter Function
369 *
370 * @param[in] i2c Specify I2C port
371 *
372 * @return None
373 *
374 * @details To disable Time-out Counter function in I2CTOC register.
375 *
376 */
I2C_DisableTimeout(I2C_T * i2c)377 void I2C_DisableTimeout(I2C_T *i2c)
378 {
379 i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
380 }
381
382 /**
383 * @brief Enable I2C Wake-up Function
384 *
385 * @param[in] i2c Specify I2C port
386 *
387 * @return None
388 *
389 * @details To enable Wake-up function of I2C Wake-up control register.
390 *
391 */
I2C_EnableWakeup(I2C_T * i2c)392 void I2C_EnableWakeup(I2C_T *i2c)
393 {
394 i2c->WKCTL |= I2C_WKCTL_WKEN_Msk;
395 }
396
397 /**
398 * @brief Disable I2C Wake-up Function
399 *
400 * @param[in] i2c Specify I2C port
401 *
402 * @return None
403 *
404 * @details To disable Wake-up function of I2C Wake-up control register.
405 *
406 */
I2C_DisableWakeup(I2C_T * i2c)407 void I2C_DisableWakeup(I2C_T *i2c)
408 {
409 i2c->WKCTL &= ~I2C_WKCTL_WKEN_Msk;
410 }
411
412 /**
413 * @brief To get SMBus Status
414 *
415 * @param[in] i2c Specify I2C port
416 *
417 * @return SMBus status
418 *
419 * @details To get the Bus Management status of I2C_BUSSTS register
420 *
421 */
I2C_SMBusGetStatus(I2C_T * i2c)422 uint32_t I2C_SMBusGetStatus(I2C_T *i2c)
423 {
424 return (i2c->BUSSTS);
425 }
426
427 /**
428 * @brief Clear SMBus Interrupt Flag
429 *
430 * @param[in] i2c Specify I2C port
431 * @param[in] u8SMBusIntFlag Specify SMBus interrupt flag
432 *
433 * @return None
434 *
435 * @details To clear flags of I2C_BUSSTS status register if interrupt set.
436 *
437 */
I2C_SMBusClearInterruptFlag(I2C_T * i2c,uint8_t u8SMBusIntFlag)438 void I2C_SMBusClearInterruptFlag(I2C_T *i2c, uint8_t u8SMBusIntFlag)
439 {
440 i2c->BUSSTS = u8SMBusIntFlag;
441 }
442
443 /**
444 * @brief Set SMBus Bytes Counts of Transmission or Reception
445 *
446 * @param[in] i2c Specify I2C port
447 * @param[in] u32PktSize Transmit / Receive bytes
448 *
449 * @return None
450 *
451 * @details The transmission or receive byte number in one transaction when PECEN is set. The maximum is 255 bytes.
452 *
453 */
I2C_SMBusSetPacketByteCount(I2C_T * i2c,uint32_t u32PktSize)454 void I2C_SMBusSetPacketByteCount(I2C_T *i2c, uint32_t u32PktSize)
455 {
456 i2c->PKTSIZE = u32PktSize;
457 }
458
459 /**
460 * @brief Init SMBus Host/Device Mode
461 *
462 * @param[in] i2c Specify I2C port
463 * @param[in] u8HostDevice Init SMBus port mode(I2C_SMBH_ENABLE(1)/I2C_SMBD_ENABLE(0))
464 *
465 * @return None
466 *
467 * @details Using SMBus communication must specify the port is a Host or a Device.
468 *
469 */
I2C_SMBusOpen(I2C_T * i2c,uint8_t u8HostDevice)470 void I2C_SMBusOpen(I2C_T *i2c, uint8_t u8HostDevice)
471 {
472 /* Clear BMHEN, BMDEN of BUSCTL Register */
473 i2c->BUSCTL &= ~(I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BMDEN_Msk);
474
475 /* Set SMBus Host/Device Mode, and enable Bus Management*/
476 if(u8HostDevice == (uint8_t)I2C_SMBH_ENABLE)
477 {
478 i2c->BUSCTL |= (I2C_BUSCTL_BMHEN_Msk | I2C_BUSCTL_BUSEN_Msk);
479 }
480 else
481 {
482 i2c->BUSCTL |= (I2C_BUSCTL_BMDEN_Msk | I2C_BUSCTL_BUSEN_Msk);
483 }
484 }
485
486 /**
487 * @brief Disable SMBus function
488 *
489 * @param[in] i2c Specify I2C port
490 *
491 * @return None
492 *
493 * @details Disable all SMBus function include Bus disable, CRC check, Acknowledge by manual, Host/Device Mode.
494 *
495 */
I2C_SMBusClose(I2C_T * i2c)496 void I2C_SMBusClose(I2C_T *i2c)
497 {
498
499 i2c->BUSCTL = 0x00U;
500 }
501
502 /**
503 * @brief Enable SMBus PEC Transmit Function
504 *
505 * @param[in] i2c Specify I2C port
506 * @param[in] u8PECTxEn CRC transmit enable(PECTX_ENABLE) or disable(PECTX_DISABLE)
507 *
508 * @return None
509 *
510 * @details When enable CRC check function, the Host or Device needs to transmit CRC byte.
511 *
512 */
I2C_SMBusPECTxEnable(I2C_T * i2c,uint8_t u8PECTxEn)513 void I2C_SMBusPECTxEnable(I2C_T *i2c, uint8_t u8PECTxEn)
514 {
515 i2c->BUSCTL &= ~I2C_BUSCTL_PECTXEN_Msk;
516
517 if(u8PECTxEn)
518 {
519 i2c->BUSCTL |= (I2C_BUSCTL_PECEN_Msk | I2C_BUSCTL_PECTXEN_Msk);
520 }
521 else
522 {
523 i2c->BUSCTL |= I2C_BUSCTL_PECEN_Msk;
524 }
525 }
526
527 /**
528 * @brief Get SMBus CRC value
529 *
530 * @param[in] i2c Specify I2C port
531 *
532 * @return A byte is packet error check value
533 *
534 * @details The CRC check value after a transmission or a reception by count by using CRC8
535 *
536 */
I2C_SMBusGetPECValue(I2C_T * i2c)537 uint8_t I2C_SMBusGetPECValue(I2C_T *i2c)
538 {
539 return (uint8_t)i2c->PKTCRC;
540 }
541
542 /**
543 * @brief Calculate Time-out of SMBus idle period
544 *
545 * @param[in] i2c Specify I2C port
546 * @param[in] u32Us Time-out length(us)
547 * @param[in] u32Hclk I2C peripheral clock frequency
548 *
549 * @return None
550 *
551 * @details This function is used to set SMBus Time-out length when bus is in Idle state.
552 *
553 */
554
I2C_SMBusIdleTimeout(I2C_T * i2c,uint32_t u32Us,uint32_t u32Hclk)555 void I2C_SMBusIdleTimeout(I2C_T *i2c, uint32_t u32Us, uint32_t u32Hclk)
556 {
557 uint32_t u32Div, u32HclkKHz;
558
559 i2c->BUSCTL |= I2C_BUSCTL_TIDLE_Msk;
560 u32HclkKHz = u32Hclk / 1000U;
561 u32Div = (((u32Us * u32HclkKHz) / 1000U) >> 2U) - 1U;
562 if(u32Div > 255U)
563 {
564 i2c->BUSTOUT = 0xFFU;
565 }
566 else
567 {
568 i2c->BUSTOUT = u32Div;
569 }
570
571 }
572
573 /**
574 * @brief Calculate Time-out of SMBus active period
575 *
576 * @param[in] i2c Specify I2C port
577 * @param[in] ms Time-out length(ms)
578 * @param[in] u32Pclk peripheral clock frequency
579 *
580 * @return None
581 *
582 * @details This function is used to set SMBus Time-out length when bus is in active state.
583 * Time-out length is calculate the SCL line "one clock" pull low timing.
584 *
585 */
586
I2C_SMBusTimeout(I2C_T * i2c,uint32_t ms,uint32_t u32Pclk)587 void I2C_SMBusTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
588 {
589 uint32_t u32Div, u32Pclk_kHz;
590
591 i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
592
593 /* DIV4 disabled */
594 i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
595 u32Pclk_kHz = u32Pclk / 1000U;
596 u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
597 if(u32Div <= 0xFFU)
598 {
599 i2c->BUSTOUT = u32Div;
600 }
601 else
602 {
603 /* DIV4 enabled */
604 i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
605 i2c->BUSTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
606 }
607 }
608
609 /**
610 * @brief Calculate Cumulative Clock low Time-out of SMBus active period
611 *
612 * @param[in] i2c Specify I2C port
613 * @param[in] ms Time-out length(ms)
614 * @param[in] u32Pclk peripheral clock frequency
615 *
616 * @return None
617 *
618 * @details This function is used to set SMBus Time-out length when bus is in Active state.
619 * Time-out length is calculate the SCL line "clocks" low cumulative timing.
620 *
621 */
622
I2C_SMBusClockLoTimeout(I2C_T * i2c,uint32_t ms,uint32_t u32Pclk)623 void I2C_SMBusClockLoTimeout(I2C_T *i2c, uint32_t ms, uint32_t u32Pclk)
624 {
625 uint32_t u32Div, u32Pclk_kHz;
626
627 i2c->BUSCTL &= ~I2C_BUSCTL_TIDLE_Msk;
628
629 /* DIV4 disabled */
630 i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
631 u32Pclk_kHz = u32Pclk / 1000U;
632 u32Div = ((ms * u32Pclk_kHz) / (16U * 1024U)) - 1U;
633 if(u32Div <= 0xFFU)
634 {
635 i2c->CLKTOUT = u32Div;
636 }
637 else
638 {
639 /* DIV4 enabled */
640 i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
641 i2c->CLKTOUT = (((ms * u32Pclk_kHz) / (16U * 1024U * 4U)) - 1U) & 0xFFU; /* The max value is 255 */
642 }
643 }
644
645 /**
646 * @brief Write a byte to Slave
647 *
648 * @param[in] *i2c Point to I2C peripheral
649 * @param[in] u8SlaveAddr Access Slave address(7-bit)
650 * @param[in] u8Data Write a byte data to Slave
651 *
652 * @retval 0 Write data success
653 * @retval 1 Write data fail, or bus occurs error events
654 *
655 * @details The function is used for I2C Master write a byte data to Slave.
656 *
657 */
658
I2C_WriteByte(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8Data)659 uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8Data)
660 {
661 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
662
663 I2C_START(i2c);
664 while(u8Xfering && (u8Err == 0u))
665 {
666 I2C_WAIT_READY(i2c) {}
667 switch(I2C_GET_STATUS(i2c))
668 {
669 case 0x08u:
670 I2C_SET_DATA(i2c, (uint32_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
671 u8Ctrl = I2C_CTL_SI; /* Clear SI */
672 break;
673 case 0x18u: /* Slave Address ACK */
674 I2C_SET_DATA(i2c, u8Data); /* Write data to I2CDAT */
675 break;
676 case 0x20u: /* Slave Address NACK */
677 case 0x30u: /* Master transmit data NACK */
678 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
679 u8Err = 1u;
680 break;
681 case 0x28u:
682 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
683 u8Xfering = 0u;
684 break;
685 case 0x38u: /* Arbitration Lost */
686 default: /* Unknow status */
687 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
688 u8Err = 1u;
689 break;
690 }
691 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
692 }
693 return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
694 }
695
696 /**
697 * @brief Write multi bytes to Slave
698 *
699 * @param[in] *i2c Point to I2C peripheral
700 * @param[in] u8SlaveAddr Access Slave address(7-bit)
701 * @param[in] *au8Data Pointer to array to write data to Slave
702 * @param[in] u32wLen How many bytes need to write to Slave
703 *
704 * @return A length of how many bytes have been transmitted.
705 *
706 * @details The function is used for I2C Master write multi bytes data to Slave.
707 *
708 */
709
I2C_WriteMultiBytes(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t au8Data[],uint32_t u32wLen)710 uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t au8Data[], uint32_t u32wLen)
711 {
712 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
713 uint32_t u32txLen = 0u;
714
715 I2C_START(i2c); /* Send START */
716 while(u8Xfering && (u8Err == 0u))
717 {
718 I2C_WAIT_READY(i2c) {}
719 switch(I2C_GET_STATUS(i2c))
720 {
721 case 0x08u:
722 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
723 u8Ctrl = I2C_CTL_SI; /* Clear SI */
724 break;
725 case 0x18u: /* Slave Address ACK */
726 case 0x28u:
727 if(u32txLen < u32wLen)
728 {
729 I2C_SET_DATA(i2c, au8Data[u32txLen++]); /* Write Data to I2CDAT */
730 }
731 else
732 {
733 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
734 u8Xfering = 0u;
735 }
736 break;
737 case 0x20u: /* Slave Address NACK */
738 case 0x30u: /* Master transmit data NACK */
739 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
740 u8Err = 1u;
741 break;
742 case 0x38u: /* Arbitration Lost */
743 default: /* Unknow status */
744 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
745 u8Err = 1u;
746 break;
747 }
748 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
749 }
750 return u32txLen; /* Return bytes length that have been transmitted */
751 }
752
753 /**
754 * @brief Specify a byte register address and write a byte to Slave
755 *
756 * @param[in] *i2c Point to I2C peripheral
757 * @param[in] u8SlaveAddr Access Slave address(7-bit)
758 * @param[in] u8DataAddr Specify a address (1 byte) of data write to
759 * @param[in] u8Data A byte data to write it to Slave
760 *
761 * @retval 0 Write data success
762 * @retval 1 Write data fail, or bus occurs error events
763 *
764 * @details The function is used for I2C Master specify a address that data write to in Slave.
765 *
766 */
767
I2C_WriteByteOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t u8Data)768 uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t u8Data)
769 {
770 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
771 uint32_t u32txLen = 0u;
772
773 I2C_START(i2c); /* Send START */
774 while(u8Xfering && (u8Err == 0u))
775 {
776 I2C_WAIT_READY(i2c) {}
777 switch(I2C_GET_STATUS(i2c))
778 {
779 case 0x08u:
780 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Send Slave address with write bit */
781 u8Ctrl = I2C_CTL_SI; /* Clear SI */
782 break;
783 case 0x18u: /* Slave Address ACK */
784 I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
785 break;
786 case 0x20u: /* Slave Address NACK */
787 case 0x30u: /* Master transmit data NACK */
788 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
789 u8Err = 1u;
790 break;
791 case 0x28u:
792 if(u32txLen < 1u)
793 {
794 I2C_SET_DATA(i2c, u8Data);
795 u32txLen++;
796 }
797 else
798 {
799 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
800 u8Xfering = 0u;
801 }
802 break;
803 case 0x38u: /* Arbitration Lost */
804 default: /* Unknow status */
805 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
806 u8Err = 1u;
807 break;
808 }
809 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
810 }
811 return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
812 }
813
814
815 /**
816 * @brief Specify a byte register address and write multi bytes to Slave
817 *
818 * @param[in] *i2c Point to I2C peripheral
819 * @param[in] u8SlaveAddr Access Slave address(7-bit)
820 * @param[in] u8DataAddr Specify a address (1 byte) of data write to
821 * @param[in] *au8Data Pointer to array to write data to Slave
822 * @param[in] u32wLen How many bytes need to write to Slave
823 *
824 * @return A length of how many bytes have been transmitted.
825 *
826 * @details The function is used for I2C Master specify a byte address that multi data bytes write to in Slave.
827 *
828 */
829
I2C_WriteMultiBytesOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t au8Data[],uint32_t u32wLen)830 uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Data[], uint32_t u32wLen)
831 {
832 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
833 uint32_t u32txLen = 0u;
834
835 I2C_START(i2c); /* Send START */
836 while(u8Xfering && (u8Err == 0u))
837 {
838 I2C_WAIT_READY(i2c) {}
839 switch(I2C_GET_STATUS(i2c))
840 {
841 case 0x08u:
842 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
843 u8Ctrl = I2C_CTL_SI;
844 break;
845 case 0x18u: /* Slave Address ACK */
846 I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
847 break;
848 case 0x20u: /* Slave Address NACK */
849 case 0x30u: /* Master transmit data NACK */
850 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
851 u8Err = 1u;
852 break;
853 case 0x28u:
854 if(u32txLen < u32wLen)
855 {
856 I2C_SET_DATA(i2c, au8Data[u32txLen++]);
857 }
858 else
859 {
860 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
861 u8Xfering = 0u;
862 }
863 break;
864 case 0x38u: /* Arbitration Lost */
865 default: /* Unknow status */
866 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
867 u8Err = 1u;
868 break;
869 }
870 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
871 }
872
873 return u32txLen; /* Return bytes length that have been transmitted */
874 }
875
876 /**
877 * @brief Specify two bytes register address and Write a byte to Slave
878 *
879 * @param[in] *i2c Point to I2C peripheral
880 * @param[in] u8SlaveAddr Access Slave address(7-bit)
881 * @param[in] u16DataAddr Specify a address (2 byte) of data write to
882 * @param[in] u8Data Write a byte data to Slave
883 *
884 * @retval 0 Write data success
885 * @retval 1 Write data fail, or bus occurs error events
886 *
887 * @details The function is used for I2C Master specify two bytes address that data write to in Slave.
888 *
889 */
890
I2C_WriteByteTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t u8Data)891 uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t u8Data)
892 {
893 uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
894 uint32_t u32txLen = 0u;
895
896 I2C_START(i2c); /* Send START */
897 while(u8Xfering && (u8Err == 0u))
898 {
899 I2C_WAIT_READY(i2c) {}
900 switch(I2C_GET_STATUS(i2c))
901 {
902 case 0x08u:
903 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
904 u8Ctrl = I2C_CTL_SI; /* Clear SI */
905 break;
906 case 0x18u: /* Slave Address ACK */
907 I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
908 break;
909 case 0x20u: /* Slave Address NACK */
910 case 0x30u: /* Master transmit data NACK */
911 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
912 u8Err = 1u;
913 break;
914 case 0x28u:
915 if(u8Addr)
916 {
917 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
918 u8Addr = 0u;
919 }
920 else if((u32txLen < 1u) && (u8Addr == 0u))
921 {
922 I2C_SET_DATA(i2c, u8Data);
923 u32txLen++;
924 }
925 else
926 {
927 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
928 u8Xfering = 0u;
929 }
930 break;
931 case 0x38u: /* Arbitration Lost */
932 default: /* Unknow status */
933 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
934 u8Err = 1u;
935 break;
936 }
937 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
938 }
939 return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
940 }
941
942
943 /**
944 * @brief Specify two bytes register address and write multi bytes to Slave
945 *
946 * @param[in] *i2c Point to I2C peripheral
947 * @param[in] u8SlaveAddr Access Slave address(7-bit)
948 * @param[in] u16DataAddr Specify a address (2 bytes) of data write to
949 * @param[in] au8Data[] A data array for write data to Slave
950 * @param[in] u32wLen How many bytes need to write to Slave
951 *
952 * @return A length of how many bytes have been transmitted.
953 *
954 * @details The function is used for I2C Master specify a byte address that multi data write to in Slave.
955 *
956 */
957
I2C_WriteMultiBytesTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t au8Data[],uint32_t u32wLen)958 uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t au8Data[], uint32_t u32wLen)
959 {
960 uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
961 uint32_t u32txLen = 0u;
962
963 I2C_START(i2c); /* Send START */
964 while(u8Xfering && (u8Err == 0u))
965 {
966 I2C_WAIT_READY(i2c) {}
967 switch(I2C_GET_STATUS(i2c))
968 {
969 case 0x08u:
970 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
971 u8Ctrl = I2C_CTL_SI; /* Clear SI */
972 break;
973 case 0x18u: /* Slave Address ACK */
974 I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
975 break;
976 case 0x20u: /* Slave Address NACK */
977 case 0x30u: /* Master transmit data NACK */
978 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
979 u8Err = 1u;
980 break;
981 case 0x28u:
982 if(u8Addr)
983 {
984 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
985 u8Addr = 0u;
986 }
987 else if((u32txLen < u32wLen) && (u8Addr == 0u))
988 {
989 I2C_SET_DATA(i2c, au8Data[u32txLen++]); /* Write data to Register I2CDAT*/
990 }
991 else
992 {
993 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
994 u8Xfering = 0u;
995 }
996 break;
997 case 0x38u: /* Arbitration Lost */
998 default: /* Unknow status */
999 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1000 u8Err = 1u;
1001 break;
1002 }
1003 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1004 }
1005 return u32txLen; /* Return bytes length that have been transmitted */
1006 }
1007
1008 /**
1009 * @brief Read a byte from Slave
1010 *
1011 * @param[in] *i2c Point to I2C peripheral
1012 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1013 *
1014 * @return Read a byte data from Slave
1015 *
1016 * @details The function is used for I2C Master to read a byte data from Slave.
1017 *
1018 */
I2C_ReadByte(I2C_T * i2c,uint8_t u8SlaveAddr)1019 uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr)
1020 {
1021 uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Ctrl = 0u;
1022
1023 I2C_START(i2c); /* Send START */
1024 while(u8Xfering && (u8Err == 0u))
1025 {
1026 I2C_WAIT_READY(i2c) {}
1027 switch(I2C_GET_STATUS(i2c))
1028 {
1029 case 0x08u:
1030 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1031 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1032 break;
1033 case 0x40u: /* Slave Address ACK */
1034 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1035 break;
1036 case 0x48u: /* Slave Address NACK */
1037 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1038 u8Err = 1u;
1039 break;
1040 case 0x58u:
1041 rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1042 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1043 u8Xfering = 0u;
1044 break;
1045 case 0x38u: /* Arbitration Lost */
1046 default: /* Unknow status */
1047 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1048 u8Err = 1u;
1049 break;
1050 }
1051 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1052 }
1053 if(u8Err)
1054 {
1055 rdata = 0u; /* If occurs error, return 0 */
1056 }
1057 return rdata; /* Return read data */
1058 }
1059
1060
1061 /**
1062 * @brief Read multi bytes from Slave
1063 *
1064 * @param[in] *i2c Point to I2C peripheral
1065 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1066 * @param[out] au8Rdata[] A data array to store data from Slave
1067 * @param[in] u32rLen How many bytes need to read from Slave
1068 *
1069 * @return A length of how many bytes have been received
1070 *
1071 * @details The function is used for I2C Master to read multi data bytes from Slave.
1072 *
1073 *
1074 */
I2C_ReadMultiBytes(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t au8Rdata[],uint32_t u32rLen)1075 uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t au8Rdata[], uint32_t u32rLen)
1076 {
1077 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
1078 uint32_t u32rxLen = 0u;
1079
1080 I2C_START(i2c); /* Send START */
1081 while(u8Xfering && (u8Err == 0u))
1082 {
1083 I2C_WAIT_READY(i2c) {}
1084 switch(I2C_GET_STATUS(i2c))
1085 {
1086 case 0x08u:
1087 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1088 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1089 break;
1090 case 0x40u: /* Slave Address ACK */
1091 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1092 break;
1093 case 0x48u: /* Slave Address NACK */
1094 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1095 u8Err = 1u;
1096 break;
1097 case 0x50u:
1098 au8Rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1099 if(u32rxLen < (u32rLen - 1u))
1100 {
1101 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1102 }
1103 else
1104 {
1105 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1106 }
1107 break;
1108 case 0x58u:
1109 au8Rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1110 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1111 u8Xfering = 0u;
1112 break;
1113 case 0x38u: /* Arbitration Lost */
1114 default: /* Unknow status */
1115 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1116 u8Err = 1u;
1117 break;
1118 }
1119 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1120 }
1121 return u32rxLen; /* Return bytes length that have been received */
1122 }
1123
1124
1125 /**
1126 * @brief Specify a byte register address and read a byte from Slave
1127 *
1128 * @param[in] *i2c Point to I2C peripheral
1129 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1130 * @param[in] u8DataAddr Specify a address(1 byte) of data read from
1131 *
1132 * @return Read a byte data from Slave
1133 *
1134 * @details The function is used for I2C Master specify a byte address that a data byte read from Slave.
1135 *
1136 *
1137 */
I2C_ReadByteOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr)1138 uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr)
1139 {
1140 uint8_t u8Xfering = 1u, u8Err = 0u, u8Rdata = 0u, u8Ctrl = 0u;
1141
1142 I2C_START(i2c); /* Send START */
1143 while(u8Xfering && (u8Err == 0u))
1144 {
1145 I2C_WAIT_READY(i2c) {}
1146 switch(I2C_GET_STATUS(i2c))
1147 {
1148 case 0x08u:
1149 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
1150 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1151 break;
1152 case 0x18u: /* Slave Address ACK */
1153 I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
1154 break;
1155 case 0x20u: /* Slave Address NACK */
1156 case 0x30u: /* Master transmit data NACK */
1157 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1158 u8Err = 1u;
1159 break;
1160 case 0x28u:
1161 u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */
1162 break;
1163 case 0x10u:
1164 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1165 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1166 break;
1167 case 0x40u: /* Slave Address ACK */
1168 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1169 break;
1170 case 0x48u: /* Slave Address NACK */
1171 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1172 u8Err = 1u;
1173 break;
1174 case 0x58u:
1175 u8Rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
1176 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1177 u8Xfering = 0u;
1178 break;
1179 case 0x38u: /* Arbitration Lost */
1180 default: /* Unknow status */
1181 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1182 u8Err = 1u;
1183 break;
1184 }
1185 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1186 }
1187 if(u8Err)
1188 {
1189 u8Rdata = 0u; /* If occurs error, return 0 */
1190 }
1191 return u8Rdata; /* Return read data */
1192 }
1193
1194 /**
1195 * @brief Specify a byte register address and read multi bytes from Slave
1196 *
1197 * @param[in] *i2c Point to I2C peripheral
1198 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1199 * @param[in] u8DataAddr Specify a address (1 bytes) of data read from
1200 * @param[out] au8Rdata[] A data array to store data from Slave
1201 * @param[in] u32rLen How many bytes need to read from Slave
1202 *
1203 * @return A length of how many bytes have been received
1204 *
1205 * @details The function is used for I2C Master specify a byte address that multi data bytes read from Slave.
1206 *
1207 *
1208 */
I2C_ReadMultiBytesOneReg(I2C_T * i2c,uint8_t u8SlaveAddr,uint8_t u8DataAddr,uint8_t au8Rdata[],uint32_t u32rLen)1209 uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Rdata[], uint32_t u32rLen)
1210 {
1211 uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
1212 uint32_t u32rxLen = 0u;
1213
1214 I2C_START(i2c); /* Send START */
1215 while(u8Xfering && (u8Err == 0u))
1216 {
1217 I2C_WAIT_READY(i2c) {}
1218 switch(I2C_GET_STATUS(i2c))
1219 {
1220 case 0x08u:
1221 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
1222 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1223 break;
1224 case 0x18u: /* Slave Address ACK */
1225 I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
1226 break;
1227 case 0x20u: /* Slave Address NACK */
1228 case 0x30u: /* Master transmit data NACK */
1229 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1230 u8Err = 1u;
1231 break;
1232 case 0x28u:
1233 u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */
1234 break;
1235 case 0x10u:
1236 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1237 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1238 break;
1239 case 0x40u: /* Slave Address ACK */
1240 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1241 break;
1242 case 0x48u: /* Slave Address NACK */
1243 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1244 u8Err = 1u;
1245 break;
1246 case 0x50u:
1247 au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
1248 if(u32rxLen < (u32rLen - 1u))
1249 {
1250 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1251 }
1252 else
1253 {
1254 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1255 }
1256 break;
1257 case 0x58u:
1258 au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
1259 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1260 u8Xfering = 0u;
1261 break;
1262 case 0x38u: /* Arbitration Lost */
1263 default: /* Unknow status */
1264 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1265 u8Err = 1u;
1266 break;
1267 }
1268 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1269 }
1270 return u32rxLen; /* Return bytes length that have been received */
1271 }
1272
1273 /**
1274 * @brief Specify two bytes register address and read a byte from Slave
1275 *
1276 * @param[in] *i2c Point to I2C peripheral
1277 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1278 * @param[in] u16DataAddr Specify an address(2 bytes) of data read from
1279 *
1280 * @return Read a byte data from Slave
1281 *
1282 * @details The function is used for I2C Master specify two bytes address that a data byte read from Slave.
1283 *
1284 *
1285 */
I2C_ReadByteTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr)1286 uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr)
1287 {
1288 uint8_t u8Xfering = 1u, u8Err = 0u, u8Rdata = 0u, u8Addr = 1u, u8Ctrl = 0u;
1289
1290 I2C_START(i2c); /* Send START */
1291 while(u8Xfering && (u8Err == 0u))
1292 {
1293 I2C_WAIT_READY(i2c) {}
1294 switch(I2C_GET_STATUS(i2c))
1295 {
1296 case 0x08u:
1297 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
1298 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1299 break;
1300 case 0x18u: /* Slave Address ACK */
1301 I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
1302 break;
1303 case 0x20u: /* Slave Address NACK */
1304 case 0x30u: /* Master transmit data NACK */
1305 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1306 u8Err = 1u;
1307 break;
1308 case 0x28u:
1309 if(u8Addr)
1310 {
1311 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
1312 u8Addr = 0u;
1313 }
1314 else
1315 {
1316 u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */
1317 }
1318 break;
1319 case 0x10u:
1320 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1321 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1322 break;
1323 case 0x40u: /* Slave Address ACK */
1324 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1325 break;
1326 case 0x48u: /* Slave Address NACK */
1327 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1328 u8Err = 1u;
1329 break;
1330 case 0x58u:
1331 u8Rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1332 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1333 u8Xfering = 0u;
1334 break;
1335 case 0x38u: /* Arbitration Lost */
1336 default: /* Unknow status */
1337 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1338 u8Err = 1u;
1339 break;
1340 }
1341 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1342 }
1343 if(u8Err)
1344 {
1345 u8Rdata = 0u; /* If occurs error, return 0 */
1346 }
1347 return u8Rdata; /* Return read data */
1348 }
1349
1350 /**
1351 * @brief Specify two bytes register address and read multi bytes from Slave
1352 *
1353 * @param[in] *i2c Point to I2C peripheral
1354 * @param[in] u8SlaveAddr Access Slave address(7-bit)
1355 * @param[in] u16DataAddr Specify a address (2 bytes) of data read from
1356 * @param[out] au8Rdata[] A data array to store data from Slave
1357 * @param[in] u32rLen How many bytes need to read from Slave
1358 *
1359 * @return A length of how many bytes have been received
1360 *
1361 * @details The function is used for I2C Master specify two bytes address that multi data bytes read from Slave.
1362 *
1363 *
1364 */
I2C_ReadMultiBytesTwoRegs(I2C_T * i2c,uint8_t u8SlaveAddr,uint16_t u16DataAddr,uint8_t au8Rdata[],uint32_t u32rLen)1365 uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t au8Rdata[], uint32_t u32rLen)
1366 {
1367 uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
1368 uint32_t u32rxLen = 0u;
1369
1370 I2C_START(i2c); /* Send START */
1371 while(u8Xfering && (u8Err == 0u))
1372 {
1373 I2C_WAIT_READY(i2c) {}
1374 switch(I2C_GET_STATUS(i2c))
1375 {
1376 case 0x08u:
1377 I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | (uint8_t)0x00u)); /* Write SLA+W to Register I2CDAT */
1378 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1379 break;
1380 case 0x18u: /* Slave Address ACK */
1381 I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
1382 break;
1383 case 0x20u: /* Slave Address NACK */
1384 case 0x30u: /* Master transmit data NACK */
1385 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1386 u8Err = 1u;
1387 break;
1388 case 0x28u:
1389 if(u8Addr)
1390 {
1391 I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
1392 u8Addr = 0u;
1393 }
1394 else
1395 {
1396 u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */
1397 }
1398 break;
1399 case 0x10u:
1400 I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | (uint8_t)0x01u)); /* Write SLA+R to Register I2CDAT */
1401 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1402 break;
1403 case 0x40u: /* Slave Address ACK */
1404 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1405 break;
1406 case 0x48u: /* Slave Address NACK */
1407 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1408 u8Err = 1u;
1409 break;
1410 case 0x50u:
1411 au8Rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1412 if(u32rxLen < (u32rLen - 1u))
1413 {
1414 u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
1415 }
1416 else
1417 {
1418 u8Ctrl = I2C_CTL_SI; /* Clear SI */
1419 }
1420 break;
1421 case 0x58u:
1422 au8Rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
1423 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1424 u8Xfering = 0u;
1425 break;
1426 case 0x38u: /* Arbitration Lost */
1427 default: /* Unknow status */
1428 u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
1429 u8Err = 1u;
1430 break;
1431 }
1432 I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
1433 }
1434 return u32rxLen; /* Return bytes length that have been received */
1435 }
1436
1437 /**@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */
1438
1439 /**@}*/ /* end of group I2C_Driver */
1440
1441 /**@}*/ /* end of group Standard_Driver */
1442