标题:
51单片机关于EEPROM的读写
[打印本页]
作者:
内卷1234
时间:
2024-3-2 14:08
标题:
51单片机关于EEPROM的读写
首先我们要知道什么是EEPROM
这里要看自己的单片机EEPROM地址大小和起始地址
主要要用到的寄存器并不多,一个是IAP_CMD(C5H),还有的就是IAP_CONTR(C7H)
然后以下就是通过代码写命令到寄存器最后进行数据操作即可
单片机源程序如下:
#include "STC15F2kxx.h"
#include "stceeprom.h"
#include <intrins.h>
#include <string.h>
#include "delay.h"
//关闭IAP功能
void IapIdle()
{
IAP_CONTR = 0;
IAP_CMD = 0;
IAP_TRIG = 0;
IAP_ADDRH = 0x80;
IAP_ADDRL = 0;
}
//擦除指定地址的扇区
void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP;//使能IAP
IAP_CMD = CMD_ERASE; //擦除命令
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_(); //等待
IAP_TRIG = 0xa5;
_nop_();
IapIdle();//关闭IAP功能
}
//往指定地址中写入一个字节字符数据
void IapWritecChar(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //写命令
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_DATA = dat;
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
IapIdle();
}
//往指定地址写入两个字节数据
void IapWriteInt(WORD addr,unsigned int dat)
{
unsigned char i;
typedef union //设置共用体,用char分摊2字节
{
unsigned int dat1;
char mchar[2];
}NEW_DATA;
NEW_DATA data1;
data1.dat1 = dat;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //写命令
for(i = 0; i < 2; i++)
{
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_DATA = data1.mchar[i];
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
addr++;
}
IapIdle(); //关闭IAP功能
}
//往指定地址写入四个字节数据
void IapWriteI32(WORD addr, unsigned long dat)
{
unsigned char i;
typedef union//设置共用体,用char分摊4字节
{
unsigned long dat1;
char mchar[4];
}NEW_DATA;
NEW_DATA data1;
data1.dat1 = dat;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //写命令
for(i = 0; i < 4; i++)
{
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_DATA = data1.mchar[i];
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
addr++;
}
IapIdle(); //关闭IAP功能
}
/*******************************************************************************
* 函数名 : Powerlost_data
* 描述 : 断电中断数据写入函数
* 输入 : addr 地址 dat 写入数据
* 输出 : 无
* 返回值 : 无
* 说明 : 为了应对中断函数与主函数循环使用IapWriteI32函数冲突
*******************************************************************************/
void Powerlost_data(WORD addr ,unsigned long dat)
{
unsigned char i;
typedef union//设置共用体,用char分摊4字节
{
unsigned long dat1;
char mchar[4];
}NEW_DATA;
NEW_DATA data1;
data1.dat1 = dat;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //写命令
for(i = 0; i < 4; i++)
{
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_DATA = data1.mchar[i];
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
addr++;
}
IapIdle(); //关闭IAP功能
}
//往指定起始地址写入不固定长度的字符串数据
void IapWriteString(WORD addr,BYTE *mString,BYTE n)
{
unsigned char i;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //写命令
for(i=0; i<n ;i++)
{
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_DATA = mString[i];
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
addr++;
}
IapIdle(); //关闭IAP功能
}
//向指定地址读取一个字节的字符数据
char IapReadChar(WORD addr)
{
BYTE dat;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //读命令
IAP_ADDRL = addr; //指定地址
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
dat = IAP_DATA;
IapIdle(); //关闭IAP功能
return dat;
}
//向指定地址读取两个字节的数字数据
unsigned int IapReadInt(WORD addr)
{
unsigned int dat;
unsigned char i;
typedef union //设置共用体,用char分摊2字节
{
unsigned int dat1;
char mchar[2];
}NEW_DATA;
NEW_DATA data1;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //读命令
for(i = 0; i < 2; i++)
{
IAP_ADDRL = (addr + i); //指定地址
IAP_ADDRH = ((addr + i) >> 8);
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
data1.mchar[i]= IAP_DATA;
}
IapIdle(); //关闭IAP功能
dat = data1.dat1;
return dat;
}
//向指定地址读取四个字节的数字数据
unsigned long IapReadI32(WORD addr)
{
unsigned long dat;
unsigned char i;
typedef union//设置共用体,用char分摊4字节
{
unsigned long dat1;
char mchar[4];
}NEW_DATA;
NEW_DATA data1;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //读命令
for(i = 0; i < 4; i++)
{
IAP_ADDRL = (addr + i); //指定地址
IAP_ADDRH = ((addr + i) >> 8);
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
data1.mchar[i] = IAP_DATA;
}
IapIdle();//关闭IAP功能
dat = data1.dat1;
return dat;
}
//向指定地址读取不定长度的字符串数据
void IapReadString(WORD addr,BYTE *mString, BYTE n)
{
unsigned char i;
memset(mString,0,strlen(mString));
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //读命令
for(i = 0; i < n; i++)
{
IAP_ADDRL = (addr + i); //指定地址
IAP_ADDRH = ((addr + i) >> 8);
IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效
_nop_();
IAP_TRIG = 0xa5;
_nop_();
mString[i] = IAP_DATA;
}
IapIdle();//关闭IAP功能
}
复制代码
作者:
aidianzi
时间:
2024-3-9 11:49
小数据可以这样写分开几个字节几个字节的写,不过建议写数据可以使用一个结构体把数据和校验数据都写进去,使用指针,存储根据结构体数据sizeof结果直接写入,读取时通过结构体数据大小一次性读取并做校验,我现在数据量小CRC8做校验,要是数据量大可以考虑CRC16或32
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1