单片机外围设备-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_SIZE64
#define EEPROM_SIZE(32*1024)
#define EEPROM_ADDR_BYTES2
#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);
}
原文地址:https://blog.csdn.net/sscb0521/article/details/140472990
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!