单片机外围设备-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 pagereVal = 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 pageI2CMsaterWriteData(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 pageEepromWriteData(EEPROM_WRITE_ADDRESS_8_BIT,0,TxBuffer1,cnt);I2CMsaterReadData(EEPROM_READ_ADDRESS_8_BIT,0,RxBuffer1,cnt);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/872369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何PR到别人仓库(指定分支,无废话)

如何PR到别人仓库&#xff08;指定分支&#xff09; 记录一下&#xff0c;之前都是直接master分支&#xff0c;现在记录如何pr到别人仓库的其他分支 首先进入别人仓库然后点击fork到自己仓库 步骤&#xff08;以博主自己一个例子为例&#xff09; &#xff08;1&#xff09;…

c++ primer plus 第16章string 类和标准模板库,16.1.3 使用字符串

c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 文章目录 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串16.1.3 使用字符串程序清单16.3 hangman.cpp 16.1.3 使用字符串 现在&a…

【题目/训练】二叉树的创建遍历(递归非递归)

一、根据二叉树创建字符串 思路&#xff1a;在正常前序递归遍历的基础上&#xff0c;单独加上一个考虑到右子树为空的情况&#xff0c;如下&#xff1a;其结果为 1&#xff08;2&#xff08;4&#xff08;5&#xff09;&#xff08;6&#xff09;&#xff09;&#xff09;&…

android11为开机动画添加铃声(语音)

一、碰到的问题 1、第一次开机无铃声 2、开机时铃声和动画不同步&#xff0c;开头的铃声会丢失 3、开机时铃声/动画不能完全播放完 二、解决 以下为添加的patch /开机铃声不同步&#xff0c;语音第一段无声 diff --git a/media/libmediaplayerservice/MediaPlayerService…

馥郁珍藏:品味红酒的层次与细腻

在生活的点滴中&#xff0c;总有一些事物以其不同的魅力&#xff0c;让我们为之驻足&#xff0c;为之沉醉。红酒&#xff0c;便是其中之一。它不仅仅是一种饮品&#xff0c;更是一种情感的寄托&#xff0c;一种生活的艺术。今天&#xff0c;就让我们一起走进红酒的世界&#xf…

原码补码反码移码

符号位为左边的第一位&#xff0c;正数的为0 &#xff0c;负数为1&#xff1b; 正数 原码、反码、补码一致&#xff1b;移码是补码符号位取反。 负数的反码为 符号位不变以原码其他位 取反&#xff0c;补码是反码加1位&#xff0c;移码是补码的符号位取反&#xff1b;

工控主板:搭载海光3300处理器的全国产化工控主板

最近为客户定做了一款全国产化的工控机主板。搭载海光3300核心板的含有丰富接口的工控主板。

一张图生成绘画全过程,这下人人都成“原画师”了

玩过SD的应该都知道ControlNet吧&#xff0c;最近ControlNet的作者Lvmin Zhang 又搞了一个开源项目PaintsUndo&#xff0c;在Github刚上线就收获了2.7k Star。 只需要上传一张静态图像&#xff0c;PaintsUndo就可以根据提供的图像自动生成对应的绘画全过程视频。 展示从一张白…

linux中关于环境变量的常用的设置方法

一. linux中设置环境变量的方式 1.使用/etc/environment, 是一个全局的环境变量设置文件&#xff0c;它会影响到所有用户和所有进程。当你需要设置一个全局的环境变量时&#xff0c;应该使用这个文件。这个文件的格式是 KEYvalue&#xff0c;每行一个环境变量。 2. 使用/etc/…

C# Winform的三态CheckBox,以及批量修改Panel中的控件

在C# WinForms中&#xff0c;如果你想批量修改一个Panel容器内的所有CheckBox控件的状态&#xff0c;你可以使用foreach循环来遍历Panel的Controls集合。下面是一个示例&#xff0c;展示了如何将一个Panel内所有的CheckBox控件设为选中状态&#xff08;Checked true&#xff0…

昇思25天学习打卡营第13天|munger85

文本解码原理–以MindNLP为例 重要的就是怎么样把数字最后转化成真正的文字。而且自回归模型它会一个字给一个字的预测&#xff0c;下一个字应该是什么&#xff1f; 如果这个模型下载很慢&#xff0c;你就可以通过这种方式从摩大社区进行下载。 这种方式&#xff0c; 每一次候…

C语言经典程序100案例

C语言经典程序100题(完整版) 【程序1】题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数都是多少 程序分析&#xff1a;可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足条件的排列。 #include "stdio…

如何让LabVIEW程序框图的图标简化,从而节省空间?

再点击选项 取消掉箭头所示的√即可。 这样就可以将生成的图标从下面所示&#xff1a; 变成简化的图标&#xff0c;如下所示&#xff1a;

【Pytorch】数据集的加载和处理(一)

Pytorch torchvision 包提供了很多常用数据集 数据按照用途一般分为三组&#xff1a;训练&#xff08;train&#xff09;、验证&#xff08;validation&#xff09;和测试&#xff08;test&#xff09;。使用训练数据集来训练模型&#xff0c;使用验证数据集跟踪模型在训练期间…

LeetCode:经典题之102、103题解及延伸|双端队列Deque|树的简介|二叉树中BFS与层序遍历的关系

系列目录 88.合并两个有序数组 52.螺旋数组 567.字符串的排列 643.子数组最大平均数 150.逆波兰表达式 61.旋转链表 160.相交链表 83.删除排序链表中的重复元素 389.找不同 1491.去掉最低工资和最高工资后的工资平均值 896.单调序列 206.反转链表 92.反转链表II 141.环形链表 …

安全防御拓扑1

目录 实验的拓扑&#xff1a; 要求&#xff1a; 我搭建的实验拓扑 步骤&#xff1a; 创建vlan&#xff1a; 接口配置&#xff1a; 防火墙&#xff1a; 防火墙配置&#xff1a; 建立安全策略&#xff1a; 防火墙的用户&#xff1a; 办公区的市场部和研发部用户 市场部…

杰发科技AC7801 —— __attribute__指定地址存储常量

const uint8_t usFlashInitVal[] __attribute__((at(0x08002800))) {0x55,0x55,0x55,0x55,0x55};//定位在flash中&#xff0c;0x00030000开始的6个字节信息固定 注意7801的地址在8000000之后 如地址选0x00000800烧录时候报错 不知道是不是atclinktool的bug&#xff0c;使用_…

PCIe总线的序

PCIe序的要求是为了满足满足生产者/消费者模型&#xff0c;和避免死锁。可以通过配置RO和IDO使得报文通过中间路径变为宽松排序&#xff0c;但可能会带来一些违反生产者/消费者模型的问题&#xff0c;需要开发者自行保证. 生产/消费者工作流程 生产者&#xff08;FPGA板卡&am…

勒索防御第一关 亚信安全AE防毒墙全面升级 勒索检出率提升150%

亚信安全信舷AE高性能防毒墙完成能力升级&#xff0c;全面完善勒索边界“全生命周期”防御体系&#xff0c;筑造边界勒索防御第一关&#xff01; 勒索之殇&#xff0c;银狐当先 当前勒索病毒卷携着AI技术&#xff0c;融合“数字化”的运营模式&#xff0c;形成了肆虐全球的网…

【C/C++】内存相关

内存相关 1 ptmalloc ptmalloc是GNU C Library&#xff08;glibc&#xff09;中的默认内存分配器&#xff0c;广泛用于Linux系统。以下是对ptmalloc的详细解析&#xff1a; 一、概述 起源&#xff1a;ptmalloc起源于Doug Lea的malloc实现&#xff0c;并由Wolfram Gloger进行…