打印
[综合信息]

【华大测评】+24C02

[复制链接]
530|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
I2c, TI, se, TE
今天搞了一下AT24C02.
原理图:

程序:
#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)
******************************************************************************/
效果图:

板子上LED2闪烁,读写正常。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:绿水本无忧因风皱面,青山原不老为雪白头。

553

主题

3530

帖子

19

粉丝