51单片机怎么使用内部EEPROM,上电次数、断电记忆,怎么实现计到最大值6千次。

51单片机怎么使用内部EEPROM,上电次数、断电记忆,怎么实现计到最大值6千次。,第1张

STC 很多都有内部EEPROM,如11或12系列的STC单兆袜片机,读写内部EEPROM有一定限制,比如写,必须先擦除再写,而且一次必须擦除一个扇区,所以还是很麻烦的,只能覆盖散闹。

要实现你的功能,一点问题没有,上电后先读取上次的计数值,再加1重新写进去就可以了。

以下是EEPROM读写子程序供参考:

------------------------------------------------

读一字节,调用前需打开 IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节

IAP_READ:

MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间

MOV IAP_CMD,#ISP_IAP_BYTE_READ 设置为IAP/ISP/EEPROM字节读模式命令

MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址

MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址

CLR EA

MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此

MOV IAP_TRIG,#0A5H 送完A5h后,ISP/IAP命令立即被触发起动

NOP

MOV A,IAP_DATA 读出的数据在IAP_DATA单元中,送入累加器A

SETBEA

LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关

RET

------------------------------------------------

字节编程,调用前需打开 IAP 功能,入口:DPTR = 字节地址, A=须编程字节的数据

IAP_WRITE:

MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间

MOV IAP_CMD,#ISP_IAP_BYTE_PROGRAM 设置为IAP/ISP/EEPROM字节编程模式命令

MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址

MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址

MOV IAP_DATA,A 要编程的数据先送进ISP_DATA寄存器

CLR EA

MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此

MOV IAP_TRIG,#0A5H 送完A5h后,ISP/IAP命令立即被触发起动

NOP

SETB EA

LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关

RET

------------------------------------------------

擦除扇区, 入口:DPTR = 扇区地址

IAP_Erase:

MOV IAP_CONTR,#ENABLE_IAP 打开 IAP 功能, 设置 Flash *** 作等待时间

MOV IAP_CMD,#03H 设置为IAP/ISP/EEPROM扇区擦除模式命令

MOV IAP_ADDRH,DPH 设置目标单元地址的高8位地址

MOV IAP_ADDRL,DPL 设置目标单元地址的低8位地址

CLR EA

MOV IAP_TRIG,#5AH 先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此族掘激

MOV IAP_TRIG,#0A5H 送完A5h后,ISP/IAP命令立即被触发起动

NOP

SETB EA

LCALL IAP_Disable 关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关

RET

------------------------------------------------

IAP_Disable:

关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

一次连续的IAP *** 作完成之后建议关闭IAP功能,不需要每次都关

MOV IAP_CONTR,#0 关闭 IAP 功能

MOV IAP_CMD,#0 清命令寄存器,使命令寄存器无命令,此句可不用

MOV IAP_TRIG,#0 清命令触发寄存器,使命令触发寄存器无触发,此句可不用

MOV IAP_ADDRH,#0FFH 送地址高字节单元为00,指向非EEPROM区

MOV IAP_ADDRL,#0FFH 送地址低字节单元为00,防止误 *** 作

RET

#include <reg51.H>

#include <intrins.H>

typedef unsigned char INT8U

typedef unsigned int INT16U

sfr IAP_DATA= 0xC2

sfr IAP_ADDRH = 0xC3

sfr IAP_ADDRL = 0xC4

sfr IAP_CMD = 0xC5

sfr IAP_TRIG= 0xC6

sfr IAP_CONTR = 0xC7

#define DEBUG_DATA 0x5A //本测试程序最终存储在 EEPROM 单元的数值

#define DATA_FLASH_START_ADDRESS 0x00 //STC5Axx 系列 EEPROM 测试起始地址

union union_temp16

{

INT16U un_temp16

INT8U un_temp8[2]

}my_unTemp16

INT8U Byte_Read(INT16U add) //读一字节,调用前需打开IAP 功能

void Byte_Program(INT16U add, INT8U ch) /液蚂/字节编程,调用前需打开IAP 功能

void Sector_Erase(INT16U add) //擦除扇区

void IAP_Disable() //关闭IAP 功能

void Delay()

void main (void)

{

INT16U eeprom_address

INT8U read_eeprom

P1 = 0xF0 //演示程序开始,让 P1[3:0] 控制的灯亮

Delay() //延时

P1 = 0x0F //演示程序开始,让 P1[7:4] 控制的灯亮

Delay() //延时

//将EEPROM 测试起始地址单元的内容读出

eeprom_address = DATA_FLASH_START_ADDRESS //将蚂李测试起始地址送eeprom_address

read_eeprom = Byte_Read(eeprom_address) //读EEPROM的值,存到read_eeprom

if (DEBUG_DATA == read_eeprom)

{ //数据是对的,亮 P1.7 控制的灯,然后在 P1 口上将 EEPROM 的数据显示出来

P1 = ~0x80

Delay() //延时

P1 = ~read_eeprom

}

else

{ //数据是错的,亮 P1.3 控制的灯,然后在 P1 口上将 EEPROM 的闷埋迟数据显示出来

//再将该EEPROM所在的扇区整个擦除,将正确的数据写入后,亮 P1.5 控制的灯

P1 = ~0x08

Delay() //延时

P1 = ~read_eeprom

Delay() //延时

Sector_Erase(eeprom_address) //擦除整个扇区

Byte_Program(eeprom_address, DEBUG_DATA)//将 DEBUG_DATA 写入 EEPROM

P1 = ~0x20//熄灭 P1.3 控制的灯,亮 P1.5 控制的灯

}

while (1) //CPU 在此无限循环执行此句

}

//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节

INT8U Byte_Read(INT16U add)

{

IAP_DATA = 0x00

IAP_CONTR = ENABLE_ISP//打开IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x01//IAP/ISP/EEPROM 字节读命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

return (IAP_DATA)

}

//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据

void Byte_Program(INT16U add, INT8U ch)

{

IAP_CONTR = ENABLE_ISP//打开 IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x02//IAP/ISP/EEPROM 字节编程命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

IAP_DATA = ch //要编程的数据先送进IAP_DATA 寄存器

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

}

//擦除扇区, 入口:DPTR = 扇区地址

void Sector_Erase(INT16U add)

{

IAP_CONTR = ENABLE_ISP//打开IAP 功能, 设置Flash *** 作等待时间

IAP_CMD = 0x03//IAP/ISP/EEPROM 扇区擦除命令

my_unTemp16.un_temp16 = add

IAP_ADDRH = my_unTemp16.un_temp8[0] //设置目标单元地址的高8 位地址

IAP_ADDRL = my_unTemp16.un_temp8[1] //设置目标单元地址的低8 位地址

//EA = 0

IAP_TRIG = 0x5A //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此

IAP_TRIG = 0xA5 //送完A5h 后,ISP/IAP 命令立即被触发起动

_nop_()

//EA = 1

IAP_Disable() //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

}

void IAP_Disable()

{

//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,

//一次连续的IAP *** 作完成之后建议关闭IAP 功能,不需要每次都关

IAP_CONTR = 0 //关闭IAP 功能

IAP_CMD = 0 //清命令寄存器,使命令寄存器无命令,此句可不用

IAP_TRIG = 0 //清命令触发寄存器,使命令触发寄存器无触发,此句可不用

IAP_ADDRH = 0

IAP_ADDRL = 0

}

void Delay()

{

INT8U i

INT16U d=5000

while (d--)

{

i=255

while (i--)

}

}

在你的C文件里引用EEPROM函数的头文件,eeprom_routines.h

然后在程序中使用

void eeprom_write(unsigned char addr, unsigned char value)

unsigned char eeprom_read(unsigned char addr)

这两个函数了。

这两个函数一个读一个写。比如你想写0x10到地址为0x55的EEPROM,

就写:eeprom_write(0x55,0x10)

同理,如果想读取0x55地址处的值,

就哗拿写:ee_value = eeprom_read(0x55)

如果编译时编译器提示悄敬找不到eeprom_routines.h,可以在

X:\Program Files\HI-TECH Software\PICC\9.81\include 启芦慎 目录下找,然后复制到自己项目文件夹下。

对了,我用的是MPLab IDE,编译器使用的是PICC。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12464252.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存