1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243 |
- /**************************************************************************//**
- * @file i2c.c
- * @version V3.00
- * @brief NUC980 series I2C driver source file
- *
- * SPDX-License-Identifier: Apache-2.0
- * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
- #include "nu_i2c.h"
- #include "nu_sys.h"
- /** @addtogroup Standard_Driver Standard Driver
- @{
- */
- /** @addtogroup I2C_Driver I2C Driver
- @{
- */
- /** @addtogroup I2C_EXPORTED_FUNCTIONS I2C Exported Functions
- @{
- */
- /**
- * @brief Enable specify I2C Controller and set Clock Divider
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u32BusClock The target I2C bus clock in Hz
- *
- * @return Actual I2C bus clock frequency
- *
- * @details The function enable the specify I2C Controller and set proper Clock Divider
- * in I2C CLOCK DIVIDED REGISTER (I2CLK) according to the target I2C Bus clock.
- * I2C Bus clock = PCLK / (4*(divider+1).
- *
- */
- uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock)
- {
- uint32_t u32Div;
- uint32_t u32Pclk;
- u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000;
- u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
- i2c->CLKDIV = u32Div;
- /* Enable I2C */
- i2c->CTL0 |= I2C_CTL0_I2CEN_Msk;
- return (u32Pclk / ((u32Div + 1U) << 2U));
- }
- /**
- * @brief Disable specify I2C Controller
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details Reset I2C Controller and disable specify I2C port.
- *
- */
- void I2C_Close(I2C_T *i2c)
- {
- /* Reset I2C Controller */
- if ((uint32_t)i2c == I2C0_BA)
- {
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 0));
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 0));
- }
- else if ((uint32_t)i2c == I2C1_BA)
- {
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 1));
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 1));
- }
- else if ((uint32_t)i2c == I2C2_BA)
- {
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 2));
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 2));
- }
- else if ((uint32_t)i2c == I2C3_BA)
- {
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) | (0x1 << 3));
- outp32(REG_SYS_APBIPRST1, inpw(REG_SYS_APBIPRST1) & ~(0x1 << 3));
- }
- /* Disable I2C */
- i2c->CTL0 &= ~I2C_CTL0_I2CEN_Msk;
- }
- /**
- * @brief Clear Time-out Counter flag
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details When Time-out flag will be set, use this function to clear I2C Bus Time-out counter flag .
- *
- */
- void I2C_ClearTimeoutFlag(I2C_T *i2c)
- {
- i2c->TOCTL |= I2C_TOCTL_TOIF_Msk;
- }
- /**
- * @brief Set Control bit of I2C Controller
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u8Start Set I2C START condition
- * @param[in] u8Stop Set I2C STOP condition
- * @param[in] u8Si Clear SI flag
- * @param[in] u8Ack Set I2C ACK bit
- *
- * @return None
- *
- * @details The function set I2C Control bit of I2C Bus protocol.
- *
- */
- void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack)
- {
- uint32_t u32Reg = 0U;
- if (u8Start)
- {
- u32Reg |= I2C_CTL_STA;
- }
- if (u8Stop)
- {
- u32Reg |= I2C_CTL_STO;
- }
- if (u8Si)
- {
- u32Reg |= I2C_CTL_SI;
- }
- if (u8Ack)
- {
- u32Reg |= I2C_CTL_AA;
- }
- i2c->CTL0 = (i2c->CTL0 & ~0x3CU) | u32Reg;
- }
- /**
- * @brief Disable Interrupt of I2C Controller
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details The function is used for disable I2C interrupt
- *
- */
- void I2C_DisableInt(I2C_T *i2c)
- {
- i2c->CTL0 &= ~I2C_CTL0_INTEN_Msk;
- }
- /**
- * @brief Enable Interrupt of I2C Controller
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details The function is used for enable I2C interrupt
- *
- */
- void I2C_EnableInt(I2C_T *i2c)
- {
- i2c->CTL0 |= I2C_CTL0_INTEN_Msk;
- }
- /**
- * @brief Get I2C Bus Clock
- *
- * @param[in] i2c Specify I2C port
- *
- * @return The actual I2C Bus clock in Hz
- *
- * @details To get the actual I2C Bus Clock frequency.
- */
- uint32_t I2C_GetBusClockFreq(I2C_T *i2c)
- {
- uint32_t u32Divider = i2c->CLKDIV;
- uint32_t u32Pclk;
- u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000;
- return (u32Pclk / ((u32Divider + 1U) << 2U));
- }
- /**
- * @brief Set I2C Bus Clock
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u32BusClock The target I2C Bus Clock in Hz
- *
- * @return The actual I2C Bus Clock in Hz
- *
- * @details To set the actual I2C Bus Clock frequency.
- */
- uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock)
- {
- uint32_t u32Div;
- uint32_t u32Pclk;
- u32Pclk = (sysGetClock(SYS_PCLK01)) * 1000000;
- u32Div = (uint32_t)(((u32Pclk * 10U) / (u32BusClock * 4U) + 5U) / 10U - 1U); /* Compute proper divider for I2C clock */
- i2c->CLKDIV = u32Div;
- return (u32Pclk / ((u32Div + 1U) << 2U));
- }
- /**
- * @brief Get Interrupt Flag
- *
- * @param[in] i2c Specify I2C port
- *
- * @return I2C interrupt flag status
- *
- * @details To get I2C Bus interrupt flag.
- */
- uint32_t I2C_GetIntFlag(I2C_T *i2c)
- {
- uint32_t u32Value;
- if ((i2c->CTL0 & I2C_CTL0_SI_Msk) == I2C_CTL0_SI_Msk)
- {
- u32Value = 1U;
- }
- else
- {
- u32Value = 0U;
- }
- return u32Value;
- }
- /**
- * @brief Get I2C Bus Status Code
- *
- * @param[in] i2c Specify I2C port
- *
- * @return I2C Status Code
- *
- * @details To get I2C Bus Status Code.
- */
- uint32_t I2C_GetStatus(I2C_T *i2c)
- {
- return (i2c->STATUS0);
- }
- /**
- * @brief Read a Byte from I2C Bus
- *
- * @param[in] i2c Specify I2C port
- *
- * @return I2C Data
- *
- * @details To read a bytes data from specify I2C port.
- */
- uint8_t I2C_GetData(I2C_T *i2c)
- {
- return (uint8_t)(i2c->DAT);
- }
- /**
- * @brief Send a byte to I2C Bus
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u8Data The data to send to I2C bus
- *
- * @return None
- *
- * @details This function is used to write a byte to specified I2C port
- */
- void I2C_SetData(I2C_T *i2c, uint8_t u8Data)
- {
- i2c->DAT = u8Data;
- }
- /**
- * @brief Set 7-bit Slave Address and GC Mode
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u8SlaveNo Set the number of I2C address register (0~3)
- * @param[in] u8SlaveAddr 7-bit slave address
- * @param[in] u8GCMode Enable/Disable GC mode (I2C_GCMODE_ENABLE / I2C_GCMODE_DISABLE)
- *
- * @return None
- *
- * @details This function is used to set 7-bit slave addresses in I2C SLAVE ADDRESS REGISTER (I2CADDR0~3)
- * and enable GC Mode.
- *
- */
- void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode)
- {
- switch (u8SlaveNo)
- {
- case 1:
- i2c->ADDR1 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
- break;
- case 2:
- i2c->ADDR2 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
- break;
- case 3:
- i2c->ADDR3 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
- break;
- case 0:
- default:
- i2c->ADDR0 = ((uint32_t)u8SlaveAddr << 1U) | u8GCMode;
- break;
- }
- }
- /**
- * @brief Configure the mask bits of 7-bit Slave Address
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u8SlaveNo Set the number of I2C address mask register (0~3)
- * @param[in] u8SlaveAddrMask A byte for slave address mask
- *
- * @return None
- *
- * @details This function is used to set 7-bit slave addresses.
- *
- */
- void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask)
- {
- switch (u8SlaveNo)
- {
- case 1:
- i2c->ADDRMSK1 = (uint32_t)u8SlaveAddrMask << 1U;
- break;
- case 2:
- i2c->ADDRMSK2 = (uint32_t)u8SlaveAddrMask << 1U;
- break;
- case 3:
- i2c->ADDRMSK3 = (uint32_t)u8SlaveAddrMask << 1U;
- break;
- case 0:
- default:
- i2c->ADDRMSK0 = (uint32_t)u8SlaveAddrMask << 1U;
- break;
- }
- }
- /**
- * @brief Enable Time-out Counter Function and support Long Time-out
- *
- * @param[in] i2c Specify I2C port
- * @param[in] u8LongTimeout Configure DIV4 to enable Long Time-out (0/1)
- *
- * @return None
- *
- * @details This function enable Time-out Counter function and configure DIV4 to support Long
- * Time-out.
- *
- */
- void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout)
- {
- if (u8LongTimeout)
- {
- i2c->TOCTL |= I2C_TOCTL_TOCDIV4_Msk;
- }
- else
- {
- i2c->TOCTL &= ~I2C_TOCTL_TOCDIV4_Msk;
- }
- i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
- }
- /**
- * @brief Disable Time-out Counter Function
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details To disable Time-out Counter function in I2CTOC register.
- *
- */
- void I2C_DisableTimeout(I2C_T *i2c)
- {
- i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
- }
- /**
- * @brief Enable I2C Wake-up Function
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details To enable Wake-up function of I2C Wake-up control register.
- *
- */
- void I2C_EnableWakeup(I2C_T *i2c)
- {
- i2c->WKCTL |= I2C_WKCTL_WKEN_Msk;
- }
- /**
- * @brief Disable I2C Wake-up Function
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details To disable Wake-up function of I2C Wake-up control register.
- *
- */
- void I2C_DisableWakeup(I2C_T *i2c)
- {
- i2c->WKCTL &= ~I2C_WKCTL_WKEN_Msk;
- }
- /**
- * @brief Write a byte to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] data Write a byte data to Slave
- *
- * @retval 0 Write data success
- * @retval 1 Write data fail, or bus occurs error events
- *
- * @details The function is used for I2C Master write a byte data to Slave.
- *
- */
- uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- I2C_START(i2c);
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, data); /* Write data to I2CDAT */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
- }
- /**
- * @brief Write multi bytes to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] *data Pointer to array to write data to Slave
- * @param[in] u32wLen How many bytes need to write to Slave
- *
- * @return A length of how many bytes have been transmitted.
- *
- * @details The function is used for I2C Master write multi bytes data to Slave.
- *
- */
- uint32_t I2C_WriteMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data[], uint32_t u32wLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- uint32_t u32txLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- case 0x28u:
- if (u32txLen < u32wLen)
- {
- I2C_SET_DATA(i2c, data[u32txLen++]); /* Write Data to I2CDAT */
- }
- else
- {
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- }
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32txLen; /* Return bytes length that have been transmitted */
- }
- /**
- * @brief Specify a byte register address and write a byte to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address (1 byte) of data write to
- * @param[in] data A byte data to write it to Slave
- *
- * @retval 0 Write data success
- * @retval 1 Write data fail, or bus occurs error events
- *
- * @details The function is used for I2C Master specify a address that data write to in Slave.
- *
- */
- uint8_t I2C_WriteByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- uint32_t u32txLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Send Slave address with write bit */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u32txLen < 1u)
- {
- I2C_SET_DATA(i2c, data);
- u32txLen++;
- }
- else
- {
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- }
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
- }
- /**
- * @brief Specify a byte register address and write multi bytes to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address (1 byte) of data write to
- * @param[in] *data Pointer to array to write data to Slave
- * @param[in] u32wLen How many bytes need to write to Slave
- *
- * @return A length of how many bytes have been transmitted.
- *
- * @details The function is used for I2C Master specify a byte address that multi data bytes write to in Slave.
- *
- */
- uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t data[], uint32_t u32wLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- uint32_t u32txLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI;
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u32txLen < u32wLen)
- {
- I2C_SET_DATA(i2c, data[u32txLen++]);
- }
- else
- {
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- }
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32txLen; /* Return bytes length that have been transmitted */
- }
- /**
- * @brief Specify two bytes register address and Write a byte to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u16DataAddr Specify a address (2 byte) of data write to
- * @param[in] data Write a byte data to Slave
- *
- * @retval 0 Write data success
- * @retval 1 Write data fail, or bus occurs error events
- *
- * @details The function is used for I2C Master specify two bytes address that data write to in Slave.
- *
- */
- uint8_t I2C_WriteByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
- uint32_t u32txLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u8Addr)
- {
- I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
- u8Addr = 0u;
- }
- else if ((u32txLen < 1u) && (u8Addr == 0u))
- {
- I2C_SET_DATA(i2c, data);
- u32txLen++;
- }
- else
- {
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- }
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
- }
- /**
- * @brief Specify two bytes register address and write multi bytes to Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u16DataAddr Specify a address (2 bytes) of data write to
- * @param[in] data[] A data array for write data to Slave
- * @param[in] u32wLen How many bytes need to write to Slave
- *
- * @return A length of how many bytes have been transmitted.
- *
- * @details The function is used for I2C Master specify a byte address that multi data write to in Slave.
- *
- */
- uint32_t I2C_WriteMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t data[], uint32_t u32wLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
- uint32_t u32txLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u8Addr)
- {
- I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
- u8Addr = 0u;
- }
- else if ((u32txLen < u32wLen) && (u8Addr == 0u))
- {
- I2C_SET_DATA(i2c, data[u32txLen++]); /* Write data to Register I2CDAT*/
- }
- else
- {
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- }
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32txLen; /* Return bytes length that have been transmitted */
- }
- /**
- * @brief Read a byte from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- *
- * @return Read a byte data from Slave
- *
- * @details The function is used for I2C Master to read a byte data from Slave.
- *
- */
- uint8_t I2C_ReadByte(I2C_T *i2c, uint8_t u8SlaveAddr)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Ctrl = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x58u:
- rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- if (u8Err)
- {
- rdata = 0u; /* If occurs error, return 0 */
- }
- return rdata; /* Return read data */
- }
- /**
- * @brief Read multi bytes from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[out] rdata[] A data array to store data from Slave
- * @param[in] u32rLen How many bytes need to read from Slave
- *
- * @return A length of how many bytes have been received
- *
- * @details The function is used for I2C Master to read multi data bytes from Slave.
- *
- *
- */
- uint32_t I2C_ReadMultiBytes(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t rdata[], uint32_t u32rLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- uint32_t u32rxLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x50u:
- rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- if (u32rxLen < (u32rLen - 1u))
- {
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- }
- else
- {
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- }
- break;
- case 0x58u:
- rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32rxLen; /* Return bytes length that have been received */
- }
- /**
- * @brief Specify a byte register address and read a byte from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address(1 byte) of data read from
- *
- * @return Read a byte data from Slave
- *
- * @details The function is used for I2C Master specify a byte address that a data byte read from Slave.
- *
- *
- */
- uint8_t I2C_ReadByteOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Ctrl = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */
- break;
- case 0x10u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x58u:
- rdata = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- if (u8Err)
- {
- rdata = 0u; /* If occurs error, return 0 */
- }
- return rdata; /* Return read data */
- }
- /**
- * @brief Specify a byte register address and read multi bytes from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u8DataAddr Specify a address (1 bytes) of data read from
- * @param[out] rdata[] A data array to store data from Slave
- * @param[in] u32rLen How many bytes need to read from Slave
- *
- * @return A length of how many bytes have been received
- *
- * @details The function is used for I2C Master specify a byte address that multi data bytes read from Slave.
- *
- *
- */
- uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t rdata[], uint32_t u32rLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
- uint32_t u32rxLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */
- break;
- case 0x10u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x50u:
- rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
- if (u32rxLen < (u32rLen - 1u))
- {
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- }
- else
- {
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- }
- break;
- case 0x58u:
- rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32rxLen; /* Return bytes length that have been received */
- }
- /**
- * @brief Specify two bytes register address and read a byte from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u16DataAddr Specify an address(2 bytes) of data read from
- *
- * @return Read a byte data from Slave
- *
- * @details The function is used for I2C Master specify two bytes address that a data byte read from Slave.
- *
- *
- */
- uint8_t I2C_ReadByteTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, rdata = 0u, u8Addr = 1u, u8Ctrl = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u8Addr)
- {
- I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
- u8Addr = 0u;
- }
- else
- {
- u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */
- }
- break;
- case 0x10u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x58u:
- rdata = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- if (u8Err)
- {
- rdata = 0u; /* If occurs error, return 0 */
- }
- return rdata; /* Return read data */
- }
- /**
- * @brief Specify two bytes register address and read multi bytes from Slave
- *
- * @param[in] *i2c Point to I2C peripheral
- * @param[in] u8SlaveAddr Access Slave address(7-bit)
- * @param[in] u16DataAddr Specify a address (2 bytes) of data read from
- * @param[out] rdata[] A data array to store data from Slave
- * @param[in] u32rLen How many bytes need to read from Slave
- *
- * @return A length of how many bytes have been received
- *
- * @details The function is used for I2C Master specify two bytes address that multi data bytes read from Slave.
- *
- *
- */
- uint32_t I2C_ReadMultiBytesTwoRegs(I2C_T *i2c, uint8_t u8SlaveAddr, uint16_t u16DataAddr, uint8_t rdata[], uint32_t u32rLen)
- {
- uint8_t u8Xfering = 1u, u8Err = 0u, u8Addr = 1u, u8Ctrl = 0u;
- uint32_t u32rxLen = 0u;
- I2C_START(i2c); /* Send START */
- while (u8Xfering && (u8Err == 0u))
- {
- I2C_WAIT_READY(i2c) {}
- switch (I2C_GET_STATUS(i2c))
- {
- case 0x08u:
- I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x18u: /* Slave Address ACK */
- I2C_SET_DATA(i2c, (uint8_t)((u16DataAddr & 0xFF00u) >> 8u)); /* Write Hi byte address of register */
- break;
- case 0x20u: /* Slave Address NACK */
- case 0x30u: /* Master transmit data NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x28u:
- if (u8Addr)
- {
- I2C_SET_DATA(i2c, (uint8_t)(u16DataAddr & 0xFFu)); /* Write Lo byte address of register */
- u8Addr = 0u;
- }
- else
- {
- u8Ctrl = I2C_CTL_STA_SI; /* Clear SI and send repeat START */
- }
- break;
- case 0x10u:
- I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- break;
- case 0x40u: /* Slave Address ACK */
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- break;
- case 0x48u: /* Slave Address NACK */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- case 0x50u:
- rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- if (u32rxLen < (u32rLen - 1u))
- {
- u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
- }
- else
- {
- u8Ctrl = I2C_CTL_SI; /* Clear SI */
- }
- break;
- case 0x58u:
- rdata[u32rxLen++] = (unsigned char) I2C_GET_DATA(i2c); /* Receive Data */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Xfering = 0u;
- break;
- case 0x38u: /* Arbitration Lost */
- default: /* Unknow status */
- u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
- u8Err = 1u;
- break;
- }
- I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
- }
- return u32rxLen; /* Return bytes length that have been received */
- }
- /**
- * @brief The macro is used to set STOP condition of I2C Bus
- *
- * @param[in] i2c Specify I2C port
- *
- * @return None
- *
- * @details Set the I2C bus STOP condition in I2C_CTL register.
- */
- void I2C_STOP(I2C_T *i2c)
- {
- (i2c)->CTL0 |= (I2C_CTL0_SI_Msk | I2C_CTL0_STO_Msk);
- while (i2c->CTL0 & I2C_CTL0_STO_Msk)
- {
- }
- }
- /*@}*/ /* end of group I2C_EXPORTED_FUNCTIONS */
- /*@}*/ /* end of group I2C_Driver */
- /*@}*/ /* end of group Standard_Driver */
- /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
|