基于RT1052与外设AT24C02的I2C通信demo

注:配置IO时不能配置为开漏模式

/*bsp_i2c.c*/
#include "bsp_i2c.h"
#define EEPROM_TEST_NUM 256 //写入数据个数
#define EEPROM_TEST_START_ADDR 0 //起始地址
uint8_t EEPROM_Buffer_Write[EEPROM_TEST_NUM];
uint8_t EEPROM_Buffer_Read[EEPROM_TEST_NUM];
static void LPI2C1_IOMUXC_Config(void);
static void LPI2C1_IOMUXC_PAD_Config(void);
static void EEPROM_LPI2C1_ModeInit(void);
static uint32_t I2C_Timeout_Callback(uint8_t errorcode);

static void LPI2C1_IOMUXC_Config(void)
{
    IOMUXC_SetPinMux(EEPROM_LPI2C1SCL_IOMUXC,1);
    IOMUXC_SetPinMux(EEPROM_LPI2C1SDA_IOMUXC,1);
}                               

static void LPI2C1_IOMUXC_PAD_Config(void)
{
    IOMUXC_SetPinConfig(EEPROM_LPI2C1SCL_IOMUXC,LPI2C1_PAD_CONFIG_DATA);
    IOMUXC_SetPinConfig(EEPROM_LPI2C1SDA_IOMUXC,LPI2C1_PAD_CONFIG_DATA);
}

static void EEPROM_LPI2C1_ModeInit(void)
{
    lpi2c_master_config_t masterConfig;

    CLOCK_SetMux(kCLOCK_Lpi2cMux,LPI2C1_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_Lpi2cDiv,LPI2C1_CLOCK_SOURCE_DIVIDER);

    LPI2C_MasterGetDefaultConfig(&masterConfig);

    masterConfig.baudRate_Hz = EEPROM_LPI2C1_BAUDRATE;

    LPI2C_MasterInit(EEPROM_LPI2C1_MASTER, &masterConfig, LPI2C1_CLOCK_FREQUENCY);
}

void EEPROM_LPI2C1_MasterInit(void)
{
    LPI2C1_IOMUXC_Config();
    LPI2C1_IOMUXC_PAD_Config();
    EEPROM_LPI2C1_ModeInit();
}

uint32_t EEPROM_LPI2C1_PageWrite(uint8_t ClientAddr,uint8_t WriteAddr,uint8_t *pBuffer,uint8_t NumByteToWrite)
{
    lpi2c_master_transfer_t masterXfer = {0};
    // struct _lpi2c_master_transfer
    // {
    //     uint32_t
    //         flags; /*!< Bit mask of options for the transfer. See enumeration #_lpi2c_master_transfer_flags for available
    //                   options. Set to 0 or #kLPI2C_TransferDefaultFlag for normal transfers. */
    //     uint16_t slaveAddress;       /*!< The 7-bit slave address. */
    //     lpi2c_direction_t direction; /*!< Either #kLPI2C_Read or #kLPI2C_Write. kLPI2C_Write   kLPI2C_Read  */
    //     uint32_t subaddress;         /*!< Sub address. Transferred MSB first. */
    //     size_t subaddressSize;       /*!< Length of sub address to send in bytes. Maximum size is 4 bytes. */
    //     void *data;                  /*!< Pointer to data to transfer. */
    //     size_t dataSize;             /*!< Number of bytes to transfer. */
    // };   
    status_t reVal = kStatus_Fail;//reVal = 1
    if(NumByteToWrite>EEPROM_PAGE_SIZE){
        PRINTF("NumByteToWrite>EEPROM_PageSize\r\n");
        return 1;
    }
    masterXfer.slaveAddress = (ClientAddr>>1);
    masterXfer.direction = kLPI2C_Write;
    masterXfer.subaddress = WriteAddr;
    masterXfer.subaddressSize = EEPROM_INER_ADDRESS_SIZE;
    masterXfer.data = pBuffer;
    masterXfer.dataSize = NumByteToWrite;
    masterXfer.flags = kLPI2C_TransferDefaultFlag;
    
    reVal = LPI2C_MasterTransferBlocking(EEPROM_LPI2C1_MASTER, &masterXfer);
    if(reVal!=kStatus_Success){
        PRINTF("LPI2C Write Error %s\r\n",__FUNCTION__);
        return 1;
    }
    return 0;
}
//等待内部写入数据
uint8_t EEPROM_LPI2C1_WaitStandbyState(uint8_t ClientAddr)
{
    status_t lpi2c_status;
    uint32_t delay_count = EEPROM_LPI2C1_FLAG_TIMEOUT;
    do{
        LPI2C_MasterClearStatusFlags(EEPROM_LPI2C1_MASTER,kLPI2C_MasterNackDetectFlag);
        lpi2c_status = LPI2C_MasterStart(EEPROM_LPI2C1_MASTER,(ClientAddr>>1), kLPI2C_Write);
        Delay_n10us(4);
    }while(EEPROM_LPI2C1_MASTER->MSR & kLPI2C_MasterNackDetectFlag && delay_count--);
    LPI2C_MasterClearStatusFlags(EEPROM_LPI2C1_MASTER,kLPI2C_MasterNackDetectFlag);
    lpi2c_status = LPI2C_MasterStop(EEPROM_LPI2C1_MASTER);
    Delay_n10us(1);
    if(delay_count==0 || lpi2c_status!=kStatus_Success){
        I2C_Timeout_Callback(3);
        return 1;
    }
    return 0;
}
static uint32_t I2C_Timeout_Callback(uint8_t errorcode)
{
    PRINTF("I2C Wait Timeout\r\n");
    return 0xFF;
}
//不限字节数写入数据
void I2C_EEPROM_Buffer_Write(uint8_t ClientAddr,uint8_t WriteAddr,uint8_t *pBuffer,uint16_t NumByteToWrite)
{
    uint8_t NumOfPage = 0,NumOfSingle = 0,Addr = 0,count = 0;
    uint8_t NumByteToWriteRest = NumByteToWrite;
    Addr = WriteAddr % EEPROM_PAGE_SIZE;//写入的首地址是否和一页对齐  0
    count = EEPROM_PAGE_SIZE-Addr;//该页还剩余可写入字节数 8

    NumByteToWriteRest = (NumByteToWrite>count) ? (NumByteToWrite-count):(NumByteToWrite);//248
    //要完整写入的页数不包括前count字节数
    NumOfPage = NumByteToWriteRest / EEPROM_PAGE_SIZE;//31
    //最后一页要写入的字节数
    NumOfSingle = NumByteToWriteRest % EEPROM_PAGE_SIZE;//0

    /*
    * NumByteToWrite>count时,需要先往第一页写入count个字节
    */
   if(count!=0 && NumByteToWrite>count){
       EEPROM_LPI2C1_PageWrite(ClientAddr,WriteAddr,pBuffer,count);
       EEPROM_LPI2C1_WaitStandbyState(ClientAddr);
       WriteAddr += count;
       pBuffer += count;
   }
   if(NumOfPage==0){//如果后续数据不足一页
        EEPROM_LPI2C1_PageWrite(ClientAddr,WriteAddr,pBuffer,NumOfSingle);
        EEPROM_LPI2C1_WaitStandbyState(ClientAddr);       
   }else{//如果后续数据大于一页
        while(NumOfPage--){
            EEPROM_LPI2C1_PageWrite(ClientAddr,WriteAddr,pBuffer,NumOfSingle);
            EEPROM_LPI2C1_WaitStandbyState(ClientAddr); 
            WriteAddr += EEPROM_PAGE_SIZE;
            pBuffer += EEPROM_PAGE_SIZE;
        }
        if(NumOfSingle){
            EEPROM_LPI2C1_PageWrite(ClientAddr,WriteAddr,pBuffer,NumOfSingle);
            EEPROM_LPI2C1_WaitStandbyState(ClientAddr);              
        }
   }

}
uint32_t EEPROM_LPI2C1_BufferRead(uint8_t ClientAddr,uint8_t ReadAddr,uint8_t *pBuffer,uint16_t NumByteToRead)
{
    lpi2c_master_transfer_t masterXfer = {0};
    status_t reVal = kStatus_Fail;//reVal = 1
    /* subAddress = ReadAddr, data = pBuffer 自从机处接收
    起始信号 start + 设备地址 slaveaddress(w 写方向) + 子地址 subAddress +
    重复起始信号 repeated start + 设备地址 slaveaddress(r 读方向) +
    接收缓冲数据 rx data buffer + 停止信号 stop */
    // struct _lpi2c_master_transfer
    // {
    //     uint32_t
    //         flags; /*!< Bit mask of options for the transfer. See enumeration #_lpi2c_master_transfer_flags for available
    //                   options. Set to 0 or #kLPI2C_TransferDefaultFlag for normal transfers. */
    //     uint16_t slaveAddress;       /*!< The 7-bit slave address. */
    //     lpi2c_direction_t direction; /*!< Either #kLPI2C_Read or #kLPI2C_Write. kLPI2C_Write   kLPI2C_Read  */
    //     uint32_t subaddress;         /*!< Sub address. Transferred MSB first. */
    //     size_t subaddressSize;       /*!< Length of sub address to send in bytes. Maximum size is 4 bytes. */
    //     void *data;                  /*!< Pointer to data to transfer. */
    //     size_t dataSize;             /*!< Number of bytes to transfer. */
    // };  
    masterXfer.slaveAddress = (ClientAddr>>1);
    masterXfer.direction = kLPI2C_Read;
    masterXfer.subaddress = (uint32_t)ReadAddr;
    masterXfer.subaddressSize = EEPROM_INER_ADDRESS_SIZE;
    masterXfer.data = pBuffer;
    masterXfer.dataSize = NumByteToRead;
    masterXfer.flags = kLPI2C_TransferDefaultFlag;
    reVal = LPI2C_MasterTransferBlocking(EEPROM_LPI2C1_MASTER, &masterXfer);
    if(reVal!=kStatus_Success){
        PRINTF("Read failed %s\r\n",__FUNCTION__);
        return 1;
    }
    return 0;
}

void EEPROM_LPI2C_Test(void)
{
    uint16_t i;
    PRINTF("Write Data\r\n");
    for(i=0;i<EEPROM_TEST_NUM;i++)
    {
        EEPROM_Buffer_Write[i] = i;
        PRINTF("0x%hX ", EEPROM_Buffer_Write[i]);
        if((i+1)%10==0 || i==(EEPROM_TEST_NUM-1))
            PRINTF("\r\n");
    }
    EEPROM_Buffer_Write[0] = 0xff;
    EEPROM_Buffer_Write[1] = 0x65;
    EEPROM_Buffer_Write[2] = 0x75;
    I2C_EEPROM_Buffer_Write(EEPROM_WRITE_ADDRESS_8BIT,EEPROM_TEST_START_ADDR,EEPROM_Buffer_Write,EEPROM_TEST_NUM);
    PRINTF("Write Success\r\n");

    PRINTF("Read Data\r\n");

    EEPROM_LPI2C1_BufferRead(EEPROM_READ_ADDRESS_8BIT,EEPROM_TEST_START_ADDR,EEPROM_Buffer_Read,EEPROM_TEST_NUM);
    for(i=0;i<EEPROM_TEST_NUM;i++)
    {
        PRINTF("0x%hX ", EEPROM_Buffer_Read[i]);
        if((i+1)%10==0 || i==(EEPROM_TEST_NUM-1))
            PRINTF("\r\n");
    }
}

/*bsp_i2c.h*/
#ifndef __BSP_I2C_H__
#define __BSP_I2C_H__
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#include "pad_config.h"
#include "fsl_lpi2c.h"
#include "fsl_debug_console.h"
#include "bsp_systick.h"

#define EEPROM_LPI2C1_MASTER_BASE (LPI2C1_BASE)
#define EEPROM_LPI2C1_MASTER ((LPI2C_Type *)EEPROM_LPI2C1_MASTER_BASE)

#define EEPROM_LPI2C1_BAUDRATE 400000U

#define EEPROM_LPI2C1SCL_GPIO GPIO1
#define EEPROM_LPI2C1SDA_GPIO GPIO1
#define EEPROM_LPI2C1SCL_GPIO_PIN 0U
#define EEPROM_LPI2C1SDA_GPIO_PIN 1U

#define EEPROM_LPI2C1SCL_IOMUXC IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL
#define EEPROM_LPI2C1SDA_IOMUXC IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA

#define LPI2C1_PAD_CONFIG_DATA     (SRE_0_SLOW_SLEW_RATE | \
                                 DSE_6_R0_6 | \
                                 SPEED_1_MEDIUM_100MHz | \
                                 ODE_0_OPEN_DRAIN_DISABLED | \
                                 PKE_1_PULL_KEEPER_ENABLED | \
                                 PUE_0_KEEPER_SELECTED | \
                                 PUS_3_22K_OHM_PULL_UP | \
                                 HYS_0_HYSTERESIS_DISABLED)
/*
选择 LPI2C 的时钟源
0 derive clock from pll3_60m
1 derive clock from osc_clk
*/
// 480/8=60MHz
#define LPI2C1_CLOCK_SOURCE_SELECT (0U)
// 60MHz/(5+1) = 10MHz
#define LPI2C1_CLOCK_SOURCE_DIVIDER (5U)

#define LPI2C1_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk)/8)/(LPI2C1_CLOCK_SOURCE_DIVIDER+1))


#define EEPROM_SIZE 256 //EEPROM总大小
#define EEPROM_PAGE_SIZE 8 //每页有8个字节
#define EEPROM_ADDRESS_7BIT (0xA0>>1)
#define EEPROM_WRITE_ADDRESS_8BIT (0xA0)
#define EEPROM_READ_ADDRESS_8BIT (0xA1)

#define EEPROM_INER_ADDRESS_SIZE 0x01

#define EEPROM_LPI2C1_FLAG_TIMEOUT ((uint32_t)0x100)
#define EEPROM_LPI2C1_LONG_TIMEOUT ((uint32_t)(10 * EEPROM_LPI2C1_FLAG_TIMEOUT))

void EEPROM_LPI2C1_MasterInit(void);
uint32_t EEPROM_LPI2C1_PageWrite(uint8_t ClientAddr,uint8_t WriteAddr,uint8_t *pBuffer,uint8_t NumByteToWrite);
uint8_t EEPROM_LPI2C1_WaitStandbyState(uint8_t ClientAddr);
void I2C_EEPROM_Buffer_Write(uint8_t ClientAddr,uint8_t WriteAddr,uint8_t *pBuffer,uint16_t NumByteToWrite);
uint32_t EEPROM_LPI2C1_BufferRead(uint8_t ClientAddr,uint8_t ReadAddr,uint8_t *pBuffer,uint16_t NumByteToRead);
void EEPROM_LPI2C_Test(void);
bool I2C_WriteByte(uint8_t SalveAddr,uint8_t RegAddr,uint8_t *DateByte);
#endif

/*pad_config.h*/
#ifndef __PAD_CONFIG_H__
#define __PAD_CONFIG_H__

#include "fsl_common.h"

/* SRE 压摆率选择 */
#define SRE_0_SLOW_SLEW_RATE                IOMUXC_SW_PAD_CTL_PAD_SRE(0)
#define SRE_1_FAST_SLEW_RATE                IOMUXC_SW_PAD_CTL_PAD_SRE(1)

/* 驱动能力配置,配置阻值的大小 */
#define DSE_0_OUTPUT_DRIVER_DISABLED        IOMUXC_SW_PAD_CTL_PAD_DSE(0)
/* R0 260 Ohm @ 3.3V, 150Ohm@1.8V, 240 Ohm for DDR */
#define DSE_1_R0_1                          IOMUXC_SW_PAD_CTL_PAD_DSE(1) 
/* R0/2 */
#define DSE_2_R0_2                          IOMUXC_SW_PAD_CTL_PAD_DSE(2)
/* R0/3 */
#define DSE_3_R0_3                          IOMUXC_SW_PAD_CTL_PAD_DSE(3)
/* R0/4 */
#define DSE_4_R0_4                          IOMUXC_SW_PAD_CTL_PAD_DSE(4)
/* R0/5 */
#define DSE_5_R0_5                          IOMUXC_SW_PAD_CTL_PAD_DSE(5)
/* R0/6 */
#define DSE_6_R0_6                          IOMUXC_SW_PAD_CTL_PAD_DSE(6)
/* R0/7 */
#define DSE_7_R0_7                          IOMUXC_SW_PAD_CTL_PAD_DSE(7)

/* SPEED 带宽配置 */
#define SPEED_0_LOW_50MHz                   IOMUXC_SW_PAD_CTL_PAD_SPEED(0)
#define SPEED_1_MEDIUM_100MHz               IOMUXC_SW_PAD_CTL_PAD_SPEED(1)
#define SPEED_2_MEDIUM_100MHz               IOMUXC_SW_PAD_CTL_PAD_SPEED(2)
#define SPEED_3_MAX_200MHz                  IOMUXC_SW_PAD_CTL_PAD_SPEED(3)

/* ODE 是否使用开漏模式 */
#define ODE_0_OPEN_DRAIN_DISABLED           IOMUXC_SW_PAD_CTL_PAD_ODE(0)     
#define ODE_1_OPEN_DRAIN_ENABLED            IOMUXC_SW_PAD_CTL_PAD_ODE(1)     

/* PKE 是否使能保持器或上下拉功能 */
#define PKE_0_PULL_KEEPER_DISABLED          IOMUXC_SW_PAD_CTL_PAD_PKE(0)      
#define PKE_1_PULL_KEEPER_ENABLED           IOMUXC_SW_PAD_CTL_PAD_PKE(1)      

/* PUE 选择使用保持器还是上下拉 */
#define PUE_0_KEEPER_SELECTED               IOMUXC_SW_PAD_CTL_PAD_PUE(0)   
#define PUE_1_PULL_SELECTED                 IOMUXC_SW_PAD_CTL_PAD_PUE(1)   

/* PUS 上下拉配置 */
#define PUS_0_100K_OHM_PULL_DOWN            IOMUXC_SW_PAD_CTL_PAD_PUS(0)     
#define PUS_1_47K_OHM_PULL_UP               IOMUXC_SW_PAD_CTL_PAD_PUS(1)   
#define PUS_2_100K_OHM_PULL_UP              IOMUXC_SW_PAD_CTL_PAD_PUS(2)   
#define PUS_3_22K_OHM_PULL_UP               IOMUXC_SW_PAD_CTL_PAD_PUS(3)   

/* HYS 滞后功能 */
#define HYS_0_HYSTERESIS_DISABLED           IOMUXC_SW_PAD_CTL_PAD_HYS(0)  
#define HYS_1_HYSTERESIS_ENABLED            IOMUXC_SW_PAD_CTL_PAD_HYS(1) 
#endif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值