单片机外围设备-EEPROM

eeprom用iic通信。eeprom有几个特点需要关注:

1、可以单字节读写

2、eeprom按页划分存储,不同型号的eeprom的页大小不一致,往eeprom写数据时,如果写到了该页的末尾,会自动从该页的开头继续写,把之前的数据覆盖,读则不会。

/*
 * Copyright 2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*  Standard C Included Files */
#include <stdio.h>
#include <string.h>
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_lpi2c.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define EEPROM_I2C_MASTER       (LPI2C3)
#define EEPROM_I2C_BAUD         (400000UL)

/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define LPI2C_CLOCK_SOURCE_DIVIDER (5U)
/* Get frequency of lpi2c clock */
#define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
#define LPI2C_MASTER_CLOCK_FREQUENCY LPI2C_CLOCK_FREQUENCY

#define AT24C256
#define EEPROM_PAGE_SIZE		64
#define EEPROM_SIZE				(32*1024)
#define EEPROM_ADDR_BYTES		2
#define EEPROM_WRITE_ADDRESS_8_BIT              (0xA2)
#define EEPROM_READ_ADDRESS_8_BIT               (0xA3)

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*******************************************************************************
 * code
 ******************************************************************************/
void EepromDelayUs(uint32_t us)
{
    uint32_t tcnt;
    tcnt = us * (CLOCK_GetFreq(kCLOCK_CpuClk) / 1000000);
    while(tcnt--);
}

/*******************************************************************************
  * @brief  eeprom takes time to write data
  * @param  call after write data to eeprom
  * @retval
******************************************************************************/
uint8_t EepromWriteWait(uint8_t SlaveAddr8bit)
{
	status_t reVal = kStatus_Fail;
	uint32_t delay_count = 1000;

	do
	{
		/* �����Ӧ���־���Ա���һ�μ�� */
		LPI2C_MasterClearStatusFlags(EEPROM_I2C_MASTER, kLPI2C_MasterNackDetectFlag);

		/* ��EEPROM����д�����Ѱַ�źţ��Լ���Ƿ���Ӧ */
		reVal = LPI2C_MasterStart(EEPROM_I2C_MASTER, (SlaveAddr8bit>>1), kLPI2C_Write);

		/* ����ȴ�����30us���Ż������Ӧ���־*/
		EepromDelayUs(100);

		/* ���LPI2C MSR�Ĵ�����NDF��־������ȷ��delay_countû����0������0��Ϊ��ʱ���˳��� */
	}while(EEPROM_I2C_MASTER->MSR & kLPI2C_MasterNackDetectFlag && delay_count-- );

	/* �����Ӧ���־����ֹ��һ��ͨѶ���� */
	LPI2C_MasterClearStatusFlags(EEPROM_I2C_MASTER, kLPI2C_MasterNackDetectFlag);

	/* ����ֹͣ�źţ���ֹ�´�ͨѶ���� */
	reVal = LPI2C_MasterStop(EEPROM_I2C_MASTER);
	/* ����ȴ�����10us��ȷ��ֹͣ�źŷ������*/
	EepromDelayUs(100);

	/* ����ʧ�ܻ�ǰ��ĵȴ���ʱ */
	if(delay_count == 0 || reVal != kStatus_Success)
	{
	    return kStatus_Fail;
	}

	return kStatus_Success;
}

/*!
 * @brief I2C Msater Init
 */
void I2CMsaterInit(LPI2C_Type *base,uint32_t baud)
{
    status_t reVal                     = kStatus_Fail;

    /*Clock setting for LPI2C*/
    CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER);

    lpi2c_master_config_t masterConfig;

    /*
     * masterConfig.debugEnable = false;
     * masterConfig.ignoreAck = false;
     * masterConfig.pinConfig = kLPI2C_2PinOpenDrain;
     * masterConfig.baudRate_Hz = 100000U;
     * masterConfig.busIdleTimeout_ns = 0;
     * masterConfig.pinLowTimeout_ns = 0;
     * masterConfig.sdaGlitchFilterWidth_ns = 0;
     * masterConfig.sclGlitchFilterWidth_ns = 0;
     */
    LPI2C_MasterGetDefaultConfig(&masterConfig);

    /* Change the default baudrate configuration */
    masterConfig.baudRate_Hz = baud;

    /* Initialize the LPI2C master peripheral */
    LPI2C_MasterInit(base, &masterConfig, LPI2C_MASTER_CLOCK_FREQUENCY);
}

/*
subaddressSize is 2
*/
int32_t I2CMsaterWriteData(uint8_t SlaveAddr8bit, uint16_t WriteAddr, uint8_t* pBuffer,uint16_t DataSize)
{
    int32_t reVal;

    lpi2c_master_transfer_t masterXfer = {0};

    masterXfer.slaveAddress   = (SlaveAddr8bit>>1);
    masterXfer.direction      = kLPI2C_Write;
    masterXfer.subaddress     = (uint32_t)WriteAddr;
    masterXfer.subaddressSize = EEPROM_ADDR_BYTES;
    masterXfer.data           = pBuffer;
    masterXfer.dataSize       = DataSize;
    masterXfer.flags          = kLPI2C_TransferDefaultFlag;

    /* Send master non-blocking data to slave */
    reVal = LPI2C_MasterTransferBlocking(EEPROM_I2C_MASTER, &masterXfer);

    if (reVal != kStatus_Success)
    {
        return -1;
    }
    return 0;
}

/*
subaddressSize is 2
*/
int32_t I2CMsaterReadData(uint8_t SlaveAddr8bit, uint16_t readAddr, uint8_t* pBuffer,uint16_t DataSize)
{
    int32_t reVal;

    lpi2c_master_transfer_t masterXfer = {0};

    /* start + slaveaddress(w) + subAddress + repeated start + slaveaddress(r) + rx data buffer + stop */
    masterXfer.slaveAddress   = (SlaveAddr8bit>>1);
    masterXfer.direction      = kLPI2C_Read;
    masterXfer.subaddress     = (uint32_t)readAddr;
    masterXfer.subaddressSize = EEPROM_ADDR_BYTES;
    masterXfer.data           = pBuffer;
    masterXfer.dataSize       = DataSize;
    masterXfer.flags          = kLPI2C_TransferDefaultFlag;

    reVal = LPI2C_MasterTransferBlocking(EEPROM_I2C_MASTER, &masterXfer);
    if (reVal != kStatus_Success)
    {
        return -1;
    }
    return 0;
}


/*******************************************************************************
when NumByteToWrite > EEPROM_PAGE_SIZE ,it will go back to the start address of the page and write continuely
******************************************************************************/
int32_t EepromWriteData(uint8_t SlaveAddr8bit, uint16_t WriteAddr, uint8_t* pBuffer, uint16_t NumByteToWrite)
{
	status_t reVal = kStatus_Fail;
	uint16_t firstPageBytes,otherPageBytes,otherPageNum,lastPageBytes;

	firstPageBytes = EEPROM_PAGE_SIZE - (WriteAddr % EEPROM_PAGE_SIZE);
	otherPageBytes = (NumByteToWrite > firstPageBytes) ? (NumByteToWrite - firstPageBytes) : 0;

	if (otherPageBytes==0)
	{
		reVal = I2CMsaterWriteData(SlaveAddr8bit, WriteAddr, pBuffer, NumByteToWrite);
		if (reVal != kStatus_Success)
		{
			return kStatus_Fail;
		}
        EepromWriteWait(SlaveAddr8bit);
	}
	else
	{
	    otherPageNum =  otherPageBytes / EEPROM_PAGE_SIZE;
        lastPageBytes = otherPageBytes % EEPROM_PAGE_SIZE;

		//write first page
		reVal = I2CMsaterWriteData(SlaveAddr8bit, WriteAddr, pBuffer, firstPageBytes);
		if (reVal != kStatus_Success)
		{
			return kStatus_Fail;
		}
		EepromWriteWait(SlaveAddr8bit);
		WriteAddr += firstPageBytes;
		pBuffer += firstPageBytes;

		if(otherPageNum== 0 )
		{
			reVal = I2CMsaterWriteData(SlaveAddr8bit, WriteAddr, pBuffer, lastPageBytes);
			if (reVal != kStatus_Success)
			{
				return kStatus_Fail;
			}
			EepromWriteWait(SlaveAddr8bit);
		}
		else
		{
	        while(otherPageNum--)
	        {
				reVal = I2CMsaterWriteData(SlaveAddr8bit, WriteAddr, pBuffer, EEPROM_PAGE_SIZE);
				if (reVal != kStatus_Success)
				{
					return kStatus_Fail;
				}
				EepromWriteWait(SlaveAddr8bit);
				WriteAddr +=  EEPROM_PAGE_SIZE;
				pBuffer += EEPROM_PAGE_SIZE;
	        }

	        if(lastPageBytes != 0)
	        {
				reVal = I2CMsaterWriteData(SlaveAddr8bit, WriteAddr, pBuffer, lastPageBytes);
				if (reVal != kStatus_Success)
				{
					return kStatus_Fail;
				}
				EepromWriteWait(SlaveAddr8bit);
	        }
		}
	}
	return kStatus_Success;
}

#define BUFF_SIZE 255
uint8_t TxBuffer1[BUFF_SIZE];
uint8_t RxBuffer1[BUFF_SIZE];
void EerpromTest(void)
{
	uint16_t i,cnt;

	cnt = sizeof(TxBuffer1)/sizeof(TxBuffer1[0]);
	for(i=0;i<cnt;i++)
	{
		*(TxBuffer1+i) = i;
	}

	//test write 1 page
	I2CMsaterWriteData(EEPROM_WRITE_ADDRESS_8_BIT,2,TxBuffer1,cnt);
	EepromWriteWait(EEPROM_WRITE_ADDRESS_8_BIT);
	I2CMsaterReadData(EEPROM_READ_ADDRESS_8_BIT,0,RxBuffer1,cnt);

	//test write more than 1 page
	EepromWriteData(EEPROM_WRITE_ADDRESS_8_BIT,0,TxBuffer1,cnt);
	I2CMsaterReadData(EEPROM_READ_ADDRESS_8_BIT,0,RxBuffer1,cnt);
}






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值