STC15F2K60S2内E2PROM应用

STC15F2K60S2内E2PROM应用

1.目的

单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM中的数据是无法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用内部EEPROM (EEPROM可以擦写100000次)或FLASHROM 等存储器来实现。在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通过IIC 或SPI 等接口来进行数据通信。这样不光会增加开发成本,同时在程序开发上也要花更多的心思。在STC 单片机中内置了EEPROM(其实是采用ISP/IAP技术读写内部FLASH 来实现EEPROM),正是因为有了IAP,从而可以使单片机可以将数据写入到程序存储器中,使得数据如同烧入的程序一样,掉电不丢失。当然写入数据的区域与程序存储区要分开来,以使程序不会遭到破坏。这样就节省了片外资源,使用起来也更加方便。

下面就详细介绍STC 单片机内置EEPROM 及其使用方法

2.STC15F2K60S2系列单片机的内部结构图

STC15F2K60S2系列单片机的内部结构框图如下图所示,STC15F2K60S2系列单片机中包含中央处理器(CPU)、程序存储器(Flash)、数据存储器(SRAM)、定时器、IO口、高速A/D转换、看门狗、UART高速异步串行通信口1/串行通信口2,CCP/PWM/PCA,一组高速同步串行端口SPI,片内高精度R/C时钟及高可靠复位等模块,STC15F2K60S2系列单片机几乎包含了数据采集和控制中的所有单元模块。

 

 

3.IAP及EEPROM新增特殊功能寄存器介绍:

ISP/IAP数据寄存器IAP-DATA

符号

地址

位地址及符号

复位值

IAP-DATA

C2H

MSB

 

 

 

 

 

 

LSB

1111 1111B

IAP-ADDRH

C3H

 

 

 

 

 

 

 

 

0000 0000B

IAP-ADDRL

C4H

 

 

 

 

 

 

 

 

0000 0000B

IAP-CMD

C5H

MS1

MS0

XXXX X000B

IAP-TRIG

C6H

 

 

 

 

 

 

 

 

XXXX XXXXB

IAP-CONTR

C7H

 

IAPEN

 

SWBS

 

SWRST

CMD_FALL

 

 

WT2

 

WT1

 

WT0

 

0000 X000B

PCON

87H

SMOD

SMOD0

LVDF

POF

GF1

GF0

PD

IDL

0011 0000B

IAP-DATA:ISP/IAP操作时的数据寄存器。                                                               

ISP/ IAP从Flash读出的数据放在此处,向Flash写的数据也放在此处

IAP/ISP地址寄存器IAP-ADDRH和IAP-ADDRL

IAP-ADDRH:ISP/IAP操作时的地址寄存器高八位。

IAP-ADDRL:ISP/IAP操作时的地址寄存器低八位。

IAP/ISP命令寄存器IAP-CMD

IAP/ISP命令寄存器IAP-CMD格式如下:

SFR  name

Address

Bit

B7

B6

B5

B4

B3

B2

B1

B0

IAP_CMD

C5H

name

-

-

-

-

-

-

MS1

MS0

 

MS1

MS0

命令/操作      模式选择

0

0

Standby        待机模式,无ISP操作

0

1

从用户的应用程序区对“Data  Flash/EEPROM区”进行字节读

1

0

从用户的应用程序区对“Data  Flash/EEPROM区”进行字节编程

1

1

从用户的应用程序区对“Data  Flash/EEPROM区”进行扇区擦除

程序在用户应用程序区时,仅可以对数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除

ISP/IAP命令触发寄存器IAP_TRIG

IAP_TRIG:ISP/IAP 操作时的命令模式寄存器。

在IAPEN(IAP_CONTR.7)=1时,对IAP_TRIG先写入5Ah,再写入A5h,ISP/IAP命令才会生效。

ISP/IAP操作完成后,IAP地址高八位寄存器IAP_ADDRH、IAP地址低八位寄存器IAP_ADDRL和IAP命令寄存器IAP_CMD的内容不变。如果接下来要对下一个地址的数据进行ISP/IAP操作,需手动将该地址的高八位和低八位分别写入IAP_ADDRH和IAP_ADDRL寄存器。

每次IAP操作时,都要对对IAP_TRIG先写入5Ah,再写入A5h,ISP/IAP命令才会生效。

在每次触发前,需重新送字节读/字节编程/扇区擦除命令,在命令不改变时,不需重新送命令。

ISP/IAP命令寄存器IAP_CONTR

ISP/IAP控制寄存器IAP_CONTR格式如下:

SFR   name

Address

Bit

B7

B6

B5

B4

B3

B2

B1

B0

IAP_CONTR

C7H

name

IAPEN

SWBS

SWRST

CMD_FALL

-

WT2

WT1

WT0

IAPEN:ISP/IAP功能允许为。

0:禁止IAP读/写/擦除Data Flash/EEPROM

1:允许IAP读/写/擦除Data Flash/EEPROM

SWBS:软件选择复位后从用户应用程序区启动(送0),还是从系统ISP监控程序区启动(送1).要与SWRST直接配合才可以实现

SWRST:0:不操作;1:软件控制产生复位,单片机自动复位。

CMD_FALL:如果IAP地址(由IAP地址寄存器IAP_ADDRH和IAP_ADDRL的值决定)指向了非法地址或无效地址,且送了ISP/IAP命令,并对IAP_TRIG送5Ah/A5h触发失败,则CMD_FALL为1,需软件清零。

设置等待时间

CPU等待时间(多少个CPU工作时钟)

WT2

WT1

WT0

Read/读(2个时钟)

Program/编程(=55us)

Sector Erase 扇区擦除(=21ms)

Recommended System  clock跟等待参数对应的推荐关系时钟

1

1

1

2个时钟

55个时钟

21012个时钟

<=1MHz

1

1

0

2个时钟

110个时钟

42024个时钟

<=2MHz

1

0

1

2个时钟

165个时钟

63036个时钟

<=3MHz

1

0

0

2个时钟

330个时钟

126072个时钟

<=6MHz

0

1

1

2个时钟

660个时钟

252144个时钟

<=12MHz

0

1

0

2个时钟

1100个钟

420240个时钟

<=20MHz

0

0

1

2个时钟

1320个钟

504288个时钟

<=24MHz

0

0

0

2个时钟

1760个钟

672384个时钟

<=30MHz

工作电压过低判断,此时不要进行EEPROM/IAP操作

PCON:电源控制寄存器

SFR  name

Address

Bit

B7

B6

B5

B4

B3

B2

B1

B0

PCON

87H

name

SMOD

SMOD0

LVDF

POF

DF1

GF0

PD

IDL

LVDF:低压检测标志位,当工作电压Vcc低于低压检测门槛电压时,该位置1.该位要由软件清0当低压检测电路发现工作电压Vcc偏低时,不要进行EEPROM/IAP操作。

5V单片机的低压检测门槛电压:

-40°C

25°C

85°C

4.74

4.64

4.60

4.41

4.32

4.27

4.14

4.05

4.00

3.90

3.82

3.77

3.69

3.61

3.56

3.51

3.43

3.38

3.36

3.28

3.23

3.21

3.14

3.09

 

3.3V单片机的低压检测门槛电压:

-40°C

25°C

85°C

3.11

3.08

3.09

2.85

2.82

2.83

2.63

2.61

2.61

2.44

2.42

2.43

2.29

2.26

2.26

2.14

2.12

2.12

2.01

2.00

2.00

1.90

1.89

1.89

STC15F2K60S2系列单片机EEPROM空间大小及地址

EEPROM字节数:1K;

扇区数: 2;

用IAP字节读时EEPROM起始扇区首地址: 0000h;

用IAP字节读时EEPROM结束扇区末地址: 03FFh;

用MOVC指令读时EEPROM起始扇区首地址: F000h;

用MOVC指令读时EEPROM结束扇区末地址:F3FFh;

注:512个字节为一个扇区。

4.原理图:

4.1STC15F2K60S2主芯片


4.2显示部分



4.3测试效果

当程序下载完毕,给开发板上电时数码管从000开始显示,随后(005S)断掉电源数秒,然后从新上电,此时数码管从006开始计时。

5.程序

/*********STC系列单片机EEPROM/IAP功能测试程序**************/

/************************主程序********************************/

#include <reg52.h>

#include "E2ROM.c"

code BYTE seven_seg[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82, 0xf8, 0x80, 0x90};//共阳数码管0--9(0时为有效断)

code BYTE scan_bit[] = {0xfe, 0xfd,0xfb};       //数码管位选 6 5 4 3 2 1

BYTE hour = 0, min = 0, sec = 0;

BYTE cp1, cp2, j; //控制数码管的位选

BYTE flash;      //控制小数点闪烁

/***********************中断初始化函数**********************/

void timer0_init(void)

{

       TMOD= 0x01;     //中断方式1  

       TH0= 0xf8;

       TL0= 0x2f;           //对机器脉冲计数,2000个计满溢出引发中断

       EA= 1;                 //开总中断

       ET0= 1;        //开T0中断

       TR0= 1;        //启动定时器T0

}

/*******************Timer0中断服务函数**********************/

void timer0_isr(void) interrupt 1

{

       TH0= 0xf8;      //重新附初值

       TL0= 0x2f;       //重新附初值

       cp1++;

       if(cp1>= 250)//半秒

       {

              cp1= 0;

              cp2++;

              flash= ~flash;    //每半秒取反一次

       }

       if(cp2>= 2)//一秒

       {           

              cp2= 0;

              sec++;

              IapEraseSector(0x0000);       //擦除第一扇区

              IapProgramByte(0x0000,sec);      //重新写入数据

       }

       if(sec>= 60)//当秒为60时分钟开始计数

       {

              sec= 0;

              min++;

              IapEraseSector(0x200);  //擦除第二扇区

              IapProgramByte(0x200,min);      //重新写入数据

       }

       if(min>= 60)//当分钟为60时小时开始计数

       {

              min= 0;

              hour++;

              IapEraseSector(0x600);  //擦除第三扇区

              IapProgramByte(0x600,hour);     //重新写入数据

       }

       if(hour  >= 24)hour = 0;//当小时大于24时小时赋值为0

       P0= 0xff;             //Protues仿真需要消隐

       //显示正在走时间

       switch(j)

       {

              case0 : P0 = seven_seg[sec % 10]; break;

              case1 : P0 = seven_seg[sec / 10]; break;

              case2 : P0 = seven_seg[min % 10] & (0x7f | flash); break;

       }

       P2= scan_bit[j];

       j++;

       j%= 3;

}

/*******************主函数**********************/

void main(void)

{

       timer0_init(); 

       sec= IapReadByte(0x0000);  //从扇区读数据

       min= IapReadByte(0x200);

       hour= IapReadByte(0x400);

       while(1);

}

/*******************E2ROM.C**********************/

#include <reg52.h>

#include "intrins.h"

typedef unsigned char BYTE;

typedef unsigned int WORD;

sfr IAP_DATA = 0xC2;  //IAP数据寄存器

sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字节

sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字节

sfr IAP_CMD = 0xC5;     //IAP命令寄存器

sfr IAP_TRIG = 0xC6;  //IAP命令触发寄存器

sfr IAP_CONTR = 0xC7; //IAP控制寄存器

#define CMD_IDLE 0     //空闲模式

#define CMD_READ 1  //IAP字节读命令

#define CMD_PROGRAM 2 //IAP字节编程命令

#define CMD_ERASE 3       //IAP扇区擦除命令

#define ENABLE_IAP 0x82 //ifSYSCLK<12MHZ

#define IAP_ADDRESS 0x0000

void IapIdle();

BYTE IapReadByte(WORD addr);

void IapProgramByte(WORD addr, BYTEdat);

void IapEraseSector(WORD addr);

/*******************关闭IAP**********************/

void IapIdle()

{

       IAP_CONTR= 0;                  //关闭IAP功能

       IAP_CMD= 0;                           //清除指令待机

       IAP_TRIG= 0;                           //清空触发器寄存器

       IAP_ADDRH= 0x80;                 //将地址设置到非IAP区域

       IAP_ADDRL= 0;

}

/********从ISP/IAP/EEPROM区域读取一个字节*********/

BYTE IapReadByte(WORD addr)

{

       BYTEdat;                           //数据缓冲区

       IAP_CONTR= ENABLE_IAP;           //使能IAP

       IAP_CMD= CMD_READ;          //设置读取命令

       IAP_ADDRL= addr;                   //设置IAP低八位地址

       IAP_ADDRH= addr >> 8;          //设置IAP高八位地址  

       IAP_TRIG= 0x5a;               //写触发命令(0x5a)

       IAP_TRIG= 0xa5;               //写触发命令(0xa5)

       _nop_();                       //等待ISP/IAP/EEPROM操作完成   

       dat= IAP_DATA;                //读ISP/IAP/EEPROM数据

       IapIdle();                      //关闭IAP功能

       returndat;                           //返回

}

/**********写一个字节到ISP/IAP/EEPROM区域*************/

void IapProgramByte(WORD addr, BYTEdat)

{

       IAP_CONTR= ENABLE_IAP;

       IAP_CMD= CMD_PROGRAM;

       IAP_ADDRL= addr;

       IAP_ADDRH= addr >> 8;

       IAP_DATA= dat;

       IAP_TRIG= 0x5a;

       IAP_TRIG= 0xa5;

       _nop_();

       IapIdle();

}

/**************扇区擦除***************************/

void IapEraseSector(WORD addr)

{

       IAP_CONTR= ENABLE_IAP;

       IAP_CMD= CMD_ERASE;

       IAP_ADDRL= addr;

       IAP_ADDRH= addr >> 8;

       IAP_TRIG= 0x5a;

       IAP_TRIG= 0xa5;

       _nop_();

       IapIdle();

}

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值