#include "hc32_ddl.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* Define I2C unit used for the example */
#define I2C_CH (M4_I2C1)
/* Define E2PROM device address */
#define E2_ADDRESS 0x50u
/* AT24C02 page length is 8byte*/
#define PAGE_LEN 8u
/* Define test address for read and write */
#define DATA_TEST_ADDR 0x00u
/* Define port and pin for SDA and SCL */
#define I2C1_SCL_PORT (PortC)
#define I2C1_SCL_PIN (Pin04)
#define I2C1_SDA_PORT (PortC)
#define I2C1_SDA_PIN (Pin05)
#define TIMEOUT 0x10000ul
#define I2C_RET_OK 0u
#define I2C_RET_ERROR 1u
#define GENERATE_START 0x00u
#define GENERATE_RESTART 0x01u
#define E2_ADDRESS_W 0x00u
#define E2_ADDRESS_R 0x01u
/* LED0 Port/Pin definition */
#define LED0_PORT (PortE)
#define LED0_PIN (Pin06)
/* LED1 Port/Pin definition */
#define LED1_PORT (PortA)
#define LED1_PIN (Pin07)
/* LED0~1 toggle definition */
#define LED0_TOGGLE() (PORT_Toggle(LED0_PORT, LED0_PIN))
#define LED1_TOGGLE() (PORT_Toggle(LED1_PORT, LED1_PIN))
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
******************************************************************************
** \brief Send start or restart condition
**
** \param none
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
static uint8_t E2_StartOrRestart(uint8_t u8Start)
{
uint32_t u32TimeOut = TIMEOUT;
en_flag_status_t enFlagBusy = Reset;
en_flag_status_t enFlagStartf = Reset;
/* generate start or restart signal */
if(GENERATE_START == u8Start)
{
/* Wait I2C bus idle */
while(Set == I2C_GetStatus(I2C_CH, I2C_SR_BUSY))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
I2C_GenerateStart(I2C_CH , Enable);
}
else
{
/* Clear start status flag */
I2C_ClearStatus(I2C_CH, I2C_CLR_STARTFCLR);
/* Send restart condition */
I2C_GenerateReStart(I2C_CH , Enable);
}
/* Judge if start success*/
u32TimeOut = TIMEOUT;
while(1)
{
enFlagBusy = I2C_GetStatus(I2C_CH, I2C_SR_BUSY);
enFlagStartf = I2C_GetStatus(I2C_CH, I2C_SR_STARTF);
if(enFlagBusy && enFlagStartf)
{
break;
}
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Send e2prom device address
**
** \param u16Adr The slave address
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
static uint8_t E2_SendAdr(uint8_t u8Adr)
{
uint32_t u32TimeOut = TIMEOUT;
/* Wait tx buffer empty */
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TEMPTYF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* Send I2C address */
I2C_SendData(I2C_CH, u8Adr);
if(E2_ADDRESS_W == (u8Adr & 0x01u))
{
/* If in master transfer process, Need wait transfer end*/
uint32_t u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TENDF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
}
/* Check ACK */
u32TimeOut = TIMEOUT;
while(Set == I2C_GetStatus(I2C_CH, I2C_SR_NACKDETECTF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Send data address to e2prom
**
** \param u8DataAdr Data address to be send
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
static uint8_t E2_SendDataAdr(uint8_t u8DataAdr)
{
uint32_t u32TimeOut = TIMEOUT;
/* Wait tx buffer empty */
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TEMPTYF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* Send one byte data */
I2C_SendData(I2C_CH, u8DataAdr);
/* Wait transfer end*/
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TENDF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* Check ACK */
u32TimeOut = TIMEOUT;
while(Set == I2C_GetStatus(I2C_CH, I2C_SR_NACKDETECTF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Send data to e2prom
**
** \param pTxData Pointer to the data buffer
** \param u32Size Data size
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
static uint8_t E2_WriteData(uint8_t *pTxData, uint32_t u32Size)
{
uint32_t u32TimeOut = TIMEOUT;
while(u32Size--)
{
/* Wait tx buffer empty */
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TEMPTYF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* Send one byte data */
I2C_SendData(I2C_CH, *pTxData++);
/* Wait transfer end*/
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_TENDF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* Check ACK */
u32TimeOut = TIMEOUT;
while(Set == I2C_GetStatus(I2C_CH, I2C_SR_NACKDETECTF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Receive data from e2prom
**
** \param pTxData Pointer to the data buffer
** \param u32Size Data size
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
static uint8_t E2_RevData(uint8_t *pRxData, uint32_t u32Size)
{
uint32_t u32TimeOut = TIMEOUT;
for(uint32_t i=0ul; i<u32Size; i++)
{
/* if the last byte receive, need config NACK*/
if(i == (u32Size - 1ul))
{
I2C_NackConfig(I2C_CH, Enable);
}
/* Wait receive full flag*/
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_RFULLF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
/* read data from register*/
*pRxData++ = I2C_ReadData(I2C_CH);
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief General stop condition to e2prom
**
** \param None
**
** \retval Process result
** - I2C_RET_ERROR Send failed
** - I2C_RET_OK Send success
******************************************************************************/
uint8_t E2_Stop(void)
{
uint32_t u32TimeOut;
/* Wait I2C bus busy */
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_BUSY))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
I2C_GenerateStop(I2C_CH, Enable);
/* Wait STOPF */
u32TimeOut = TIMEOUT;
while(Reset == I2C_GetStatus(I2C_CH, I2C_SR_STOPF))
{
if(0ul == (u32TimeOut--))
{
return I2C_RET_ERROR;
}
}
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Initialize the I2C peripheral for e2prom
**
** \param None
**
** \retval Process result
** - I2C_RET_ERROR failed
** - I2C_RET_OK success
******************************************************************************/
uint8_t E2_Initialize(void)
{
stc_i2c_init_t stcI2cInit;
stc_clk_freq_t stcClkFreq;
I2C_DeInit(I2C_CH);
/* Get system clock frequency */
CLK_GetClockFreq(&stcClkFreq);
MEM_ZERO_STRUCT(stcI2cInit);
stcI2cInit.u32Pclk3 = stcClkFreq.pclk3Freq;
stcI2cInit.enI2cMode = I2cMaster;
stcI2cInit.u32Baudrate = 100000ul;
stcI2cInit.u32SclTime = 0ul;
I2C_Init(I2C_CH, &stcI2cInit);
I2C_Cmd(I2C_CH, Enable);
return I2C_RET_OK;
}
/**
******************************************************************************
** \brief Initialize the system clock for the sample
**
** \param None
**
** \retval None
******************************************************************************/
static void SysClkIni(void)
{
en_clk_sys_source_t enSysClkSrc;
stc_clk_sysclk_cfg_t stcSysClkCfg;
stc_clk_xtal_cfg_t stcXtalCfg;
stc_clk_mpll_cfg_t stcMpllCfg;
MEM_ZERO_STRUCT(enSysClkSrc);
MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcXtalCfg);
MEM_ZERO_STRUCT(stcMpllCfg);
/* Set bus clk div. */
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1; // Max 168MHz
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2; // Max 84MHz
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1; // Max 168MHz
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2; // Max 84MHz
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4; // Max 60MHz
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4; // Max 42MHz
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2; // Max 84MHz
CLK_SysClkConfig(&stcSysClkCfg);
/* Switch system clock source to MPLL. */
/* Use Xtal32 as MPLL source. */
stcXtalCfg.enMode = ClkXtalModeOsc;
stcXtalCfg.enDrv = ClkXtalLowDrv;
stcXtalCfg.enFastStartup = Enable;
CLK_XtalConfig(&stcXtalCfg);
CLK_XtalCmd(Enable);
/* MPLL config. */
stcMpllCfg.pllmDiv = 1u;
stcMpllCfg.plln =42u;
stcMpllCfg.PllpDiv = 2u;
stcMpllCfg.PllqDiv = 2u;
stcMpllCfg.PllrDiv = 2u;
CLK_SetPllSource(ClkPllSrcXTAL);
CLK_MpllConfig(&stcMpllCfg);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_5);
EFM_Lock();
/* Enable MPLL. */
CLK_MpllCmd(Enable);
/* Wait MPLL ready. */
while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{
;
}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);
}
/**
******************************************************************************
** \brief Judge the result. LED0 toggle when result is error status.
**
** \param u8Result
**
** \retval None
******************************************************************************/
static void JudgeResult(uint8_t u8Result)
{
if(I2C_RET_ERROR == u8Result)
{
while(1)
{
LED0_TOGGLE();
Ddl_Delay1ms(500ul);
}
}
}
/**
*******************************************************************************
** \brief Main function of template project
**
** \param None
**
** \retval int32_t return value, if needed
**
******************************************************************************/
int32_t main(void)
{
uint8_t u8TxBuf[PAGE_LEN];
uint8_t u8RxBuf[PAGE_LEN];
uint32_t i;
uint8_t u8Ret = I2C_RET_OK;
stc_port_init_t stcPortInit;
for(i=0ul; i<PAGE_LEN; i++)
{
u8TxBuf[i] = (uint8_t)i+1u;
}
memset(u8RxBuf, 0x00, PAGE_LEN);
/* Initialize system clock*/
SysClkIni();
/*initiallize LED port*/
MEM_ZERO_STRUCT(stcPortInit);
stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enExInt = Enable;
stcPortInit.enPullUp = Enable;
/* LED0 Port/Pin initialization */
PORT_Init(LED0_PORT, LED0_PIN, &stcPortInit);
/* LED1 Port/Pin initialization */
PORT_Init(LED1_PORT, LED1_PIN, &stcPortInit);
/* Initialize I2C port*/
PORT_SetFunc(I2C1_SCL_PORT, I2C1_SCL_PIN, Func_I2c1_Scl, Disable);
PORT_SetFunc(I2C1_SDA_PORT, I2C1_SDA_PIN, Func_I2c1_Sda, Disable);
/* Enable I2C Peripheral*/
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_I2C1, Enable);
/* Initialize I2C peripheral and enable function*/
E2_Initialize();
/* E2prom byte write*/
u8Ret = E2_StartOrRestart(GENERATE_START);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_W);
JudgeResult(u8Ret);
u8Ret = E2_SendDataAdr(DATA_TEST_ADDR);
JudgeResult(u8Ret);
u8Ret = E2_WriteData(u8TxBuf, 1u);
JudgeResult(u8Ret);
u8Ret = E2_Stop();
JudgeResult(u8Ret);
/* 5mS delay for e2prom*/
Ddl_Delay1ms(5ul);
/* E2prom ramdom read*/
u8Ret = E2_StartOrRestart(GENERATE_START);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_W);
JudgeResult(u8Ret);
u8Ret = E2_SendDataAdr(DATA_TEST_ADDR);
JudgeResult(u8Ret);
u8Ret = E2_StartOrRestart(GENERATE_RESTART);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_R);
JudgeResult(u8Ret);
u8Ret = E2_RevData(u8RxBuf, 1u);
JudgeResult(u8Ret);
u8Ret = E2_Stop();
JudgeResult(u8Ret);
/* Compare the data */
if(0x01u != u8RxBuf[0])
{
/* e2prom byte write error*/
while(1)
{
LED0_TOGGLE();
Ddl_Delay1ms(500ul);
}
}
/* 5mS delay for e2prom*/
Ddl_Delay1ms(5ul);
/* E2prom page write*/
u8Ret = E2_StartOrRestart(GENERATE_START);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_W);
JudgeResult(u8Ret);
u8Ret = E2_SendDataAdr(DATA_TEST_ADDR);
JudgeResult(u8Ret);
u8Ret = E2_WriteData(u8TxBuf, PAGE_LEN);
JudgeResult(u8Ret);
u8Ret = E2_Stop();
JudgeResult(u8Ret);
/* 5mS delay for e2prom*/
Ddl_Delay1ms(5ul);
/* E2prom sequential read*/
u8Ret = E2_StartOrRestart(GENERATE_START);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_W);
JudgeResult(u8Ret);
u8Ret = E2_SendDataAdr(DATA_TEST_ADDR);
JudgeResult(u8Ret);
u8Ret = E2_StartOrRestart(GENERATE_RESTART);
JudgeResult(u8Ret);
u8Ret = E2_SendAdr((uint8_t)(E2_ADDRESS<<1u)|E2_ADDRESS_R);
JudgeResult(u8Ret);
u8Ret = E2_RevData(u8RxBuf, PAGE_LEN);
JudgeResult(u8Ret);
u8Ret = E2_Stop();
JudgeResult(u8Ret);
/* Compare the data */
for(i=0ul; i<PAGE_LEN; i++)
{
if(u8TxBuf[i] != u8RxBuf[i])
{
/* e2prom page write error*/
while(1)
{
LED0_TOGGLE();
Ddl_Delay1ms(500ul);
}
}
}
/* e2prom sample success*/
while(1)
{
LED1_TOGGLE();
Ddl_Delay1ms(500ul);
}
}
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
效果图: