STC15F2K60S2内部EEPROM的读写操作

一、STC15F2K60S2单片机内部EEPROM的介绍

STC15系列单片机内部集成了大容量的EEPROM,其与程序空间是分开的。利用ISP/IAP技术可将内部Date Flash当EEPROM,擦写次数在10万次以上。EEPROM可分为若干个扇区,每个扇区包含512个字节。使用时,建议同一次修改的数据放在同一个扇区,不是同一次修改的数据放在不同的扇区,不一定要用满。数据存储器的擦出操作是按扇区进行的。

EEPROM可用于保存一些需要在应用过程中修改并且掉电不丢失的参数数据。在用户程序中,可以对EEPROM进行字节读/字节编程/扇区擦除操作。在工作电压Vcc偏低时,建议不要进行EEPROM/IAP操作。

                                                            图1 STC15F2K60S2系列EEPROM空间大小及地址图

注:以上内容选自STC15系列单片机官方指南书。

 

通过对STC15系列单片机官方指南书的查阅可知,IAP15系列除外,STC15F2K60S2系列单片机可通过图1的地址空间开始对其内部EEPROM进行数据的读写,而IAP15系列可在用户应用程序区修改用户应用程序区,一般从结束扇区末尾地址开始计算。

后面将会给出STC15系列单片机内部EEPROM的驱动程序,只需要调用EEPROM_Read(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)和EEPROM_Write(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)两个函数即可。

二、STC15F2K60S2内部EEPROM读写的驱动程序

1.头文件

#ifndef    _EEPROM_H_

#define    _EEPROM_H_



#include "STC15F2K60S2.h"

#include <intrins.h>



#ifndef UINT8

#define UINT8 unsigned char

#endif

#ifndef UINT16

#define UINT16 unsigned int

#endif



#ifndef EEPROM_BUFFER_LENGTH

#define EEPROM_BUFFER_LENGTH 128 //数据保护缓冲长度

#endif



#define            ISP_STANDBY()  ISP_CMD = 0               //ISP空闲命令(禁止)

#define            ISP_READ()         ISP_CMD = 1               //ISP读出命令

#define            ISP_WRITE()                ISP_CMD = 2               //ISP写入命令

#define            ISP_ERASE()               ISP_CMD = 3               //ISP擦除命令



//sfr ISP_TRIG  = 0xC6;

#define ISP_TRIG()    ISP_TRIG = 0x5A,       ISP_TRIG = 0xA5        //ISP触发命令



//                                                      7    6    5      4    3    2    1     0    Reset Value

//sfr IAP_CONTR = 0xC7;          IAPEN SWBS SWRST CFAIL  -   WT2  WT1   WT0   0000,x000        //IAP Control Register

#define ISP_EN                    (1<<7)

#define ISP_SWBS               (1<<6)

#define ISP_SWRST            (1<<5)

#define ISP_CMD_FAIL      (1<<4)

#define ISP_WAIT_1MHZ   7

#define ISP_WAIT_2MHZ   6

#define ISP_WAIT_3MHZ   5

#define ISP_WAIT_6MHZ   4

#define ISP_WAIT_12MHZ 3

#define ISP_WAIT_20MHZ 2

#define ISP_WAIT_24MHZ 1

#define ISP_WAIT_30MHZ 0



#if (MAIN_Fosc >= 24000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_30MHZ

#elif (MAIN_Fosc >= 20000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_24MHZ

#elif (MAIN_Fosc >= 12000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_20MHZ

#elif (MAIN_Fosc >= 6000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_12MHZ

#elif (MAIN_Fosc >= 3000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_6MHZ

#elif (MAIN_Fosc >= 2000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_3MHZ

#elif (MAIN_Fosc >= 1000000L)

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_2MHZ

#else

        #define            ISP_WAIT_FREQUENCY  ISP_WAIT_1MHZ

#endif



sfr ISP_DATA  = 0xC2;

sfr ISP_ADDRH = 0xC3;

sfr ISP_ADDRL = 0xC4;

sfr ISP_CMD   = 0xC5;

sfr ISP_TRIG  = 0xC6;

sfr ISP_CONTR = 0xC7;

//定义特殊功能寄存器



void EEPROM_Disable();//关闭eeprom读写

void EEPROM_SectorErase(UINT16 eeprom_address);//扇区擦除

void EEPROM_Read(UINT16 eeprom_address,UINT8 *data_address,UINT8 length);//读数据

void EEPROM_Write(UINT16 eeprom_address,UINT8 *data_address,UINT8 length);//写数据



#endif

2.主程序

#include "EEPROM.h"



//STC系列的内置EEPROM读写程序。

/************************************************************************

*STC15F2K60S2的EEPROM空间地址范围:0x0000 - 0x03FF (IAP字节读取)(1K)

*使用例程:

        EEPROM_Read(0x0000,medication_lost_warning_phone_3,12);

        EEPROM_Write(0x0000,medication_lost_warning_phone_3,12);



*************************************************************************/



//========================================================================

// 函数: void EEPROM_Disable()

// 描述: 禁止访问ISP/IAP.

// 参数: non.

// 返回: non.

//========================================================================

void EEPROM_Disable()

{

        ISP_CONTR = 0;                 //禁止ISP/IAP操作

        ISP_CMD   = 0;                 //去除ISP/IAP命令

        ISP_TRIG  = 0;                   //防止ISP/IAP命令误触发

        ISP_ADDRH = 0xff;            //清0地址高字节

        ISP_ADDRL = 0xff;             //清0地址低字节,指向非EEPROM区,防止误操作

}



//========================================================================

// 函数: void EEPROM_Read(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)

// 描述: 从指定EEPROM首地址读出n个字节放指定的缓冲.

// 参数: eeprom_address:  读出EEPROM的首地址.

//       data_address: 读出数据放缓冲的首地址.

//       length:      读出的字节长度.

// 返回: non.

//========================================================================

void EEPROM_Read(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)

{

        EA = 0;           //禁止中断

        ET0 = 0;

        ISP_CONTR = (ISP_EN + 3);     //设置等待时间,允许ISP/IAP操作,送一次就够

        ISP_READ();                                                               //送字节读命令,命令不需改变时,不需重新送命令

        do

        {

                ISP_ADDRH = eeprom_address / 256;              //送地址高字节(地址需要改变时才需重新送地址)

                ISP_ADDRL = eeprom_address % 256;             //送地址低字节

                ISP_TRIG();                                                 //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此

                                                                                     //送完A5H后,ISP/IAP命令立即被触发启动

                                                                                     //CPU等待IAP完成后,才会继续执行程序。

                _nop_();

                *data_address = ISP_DATA;                       //读出的数据送往

                eeprom_address++;

                data_address++;

        }while(--length);



        EEPROM_Disable();

        EA = 1;           //重新允许中断

        ET0 = 1;

}



//========================================================================

// 函数: void EEPROM_SectorErase(UINT16 eeprom_address)

// 描述: 把指定地址的EEPROM扇区擦除.

// 参数: eeprom_address:  要擦除的扇区EEPROM的地址.

// 返回: non.

//========================================================================

void EEPROM_SectorErase(UINT16 eeprom_address)

{

        EA = 0;           //禁止中断

        ET0 = 0;

                                                                                     //只有扇区擦除,没有字节擦除,512字节/扇区。

                                                                                     //扇区中任意一个字节地址都是扇区地址。

        ISP_ADDRH = eeprom_address / 256;                      //送扇区地址高字节(地址需要改变时才需重新送地址)

        ISP_ADDRL = eeprom_address % 256;                    //送扇区地址低字节

        ISP_CONTR = (ISP_EN + 3);     //设置等待时间,允许ISP/IAP操作,送一次就够

        ISP_ERASE();                                                     //送扇区擦除命令,命令不需改变时,不需重新送命令

        ISP_TRIG();

        _nop_();

        EEPROM_Disable();

        EA = 1;           //重新允许中断

        ET0 = 1;

}



//========================================================================

// 函数: void EEPROM_Write(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)

// 描述: 把缓冲的n个字节写入指定首地址的EEPROM.

// 参数: eeprom_address:  写入EEPROM的首地址.

//       data_address: 写入源数据的缓冲的首地址.

//       length:      写入的字节长度.

// 返回: non.

//========================================================================

void EEPROM_Write(UINT16 eeprom_address,UINT8 *data_address,UINT8 length)

{

        UINT8  sector_location;//待写入数据在扇区内的起始地址

        UINT8  xdata data_buffer[EEPROM_BUFFER_LENGTH];

        UINT16 i;

       

        sector_location = (UINT8)(eeprom_address & 0x01ff);

        eeprom_address &= 0xfe00;

       

        EEPROM_Read(eeprom_address,data_buffer,EEPROM_BUFFER_LENGTH);

       

        for(i=0; i<length; i++)

        {

                data_buffer[sector_location+i] = data_address[i];

        }

       

        EEPROM_SectorErase(eeprom_address);

        length = EEPROM_BUFFER_LENGTH;

        data_address = data_buffer;

       

        EA = 0;           //禁止中断

        ET0 = 0;



        ISP_CONTR = (ISP_EN + 3);     //设置等待时间,允许ISP/IAP操作,送一次就够

        ISP_WRITE();                                                     //送字节写命令,命令不需改变时,不需重新送命令

        do

        {

                ISP_ADDRH = eeprom_address / 256;              //送地址高字节(地址需要改变时才需重新送地址)

                ISP_ADDRL = eeprom_address % 256;             //送地址低字节

                ISP_DATA  = *data_address;                     //送数据到ISP_DATA,只有数据改变时才需重新送

                ISP_TRIG();

                _nop_();

                eeprom_address++;

                data_address++;

        }while(--length);



        EEPROM_Disable();

        EA = 1;           //重新允许中断

        ET0 = 1;

}

 

  • 10
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STC15F2K60S2是一款单片机,它内部集成了一个12位的ADC模块,可以实现模拟信号的数字化转换。以下是一个简单的STC15F2K60S2内部ADC转换程序,供参考: ``` #include <reg52.h> sbit ADC_CS = P1^4; // ADC片选 sbit ADC_CLK = P1^5; // ADC时钟 sbit ADC_DIN = P1^6; // ADC数据输入 sbit ADC_DOUT = P1^7; // ADC数据输出 unsigned int getADCResult(unsigned char ch) { unsigned char i; unsigned int result = 0; ADC_CS = 0; // 使能ADC片选 ADC_CLK = 0; // 将ADC时钟置为0 ADC_DIN = 1; // 将ADC数据输入置为1 ADC_CLK = 1; // 将ADC时钟置为1 ADC_CLK = 0; // 将ADC时钟置为0 ADC_DIN = 1; // 将ADC数据输入置为1 ADC_CLK = 1; // 将ADC时钟置为1 ADC_CLK = 0; // 将ADC时钟置为0 ADC_DIN = (ch << 4) | 0x80; // 发送通道号和启动转换命令 ADC_CLK = 1; // 将ADC时钟置为1 ADC_CLK = 0; // 将ADC时钟置为0 ADC_DIN = 0; // 将ADC数据输入置为0 for (i = 0; i < 12; i++) // 读取ADC转换结果 { ADC_CLK = 1; ADC_CLK = 0; result <<= 1; result |= ADC_DOUT; } ADC_CS = 1; // 禁用ADC片选 return result; } void main() { unsigned int result; while (1) { result = getADCResult(0); // 读取通道0的ADC转换结果 // 处理ADC转换结果 } } ``` 在上述程序中,通过getADCResult函数实现了ADC转换过程。具体步骤如下: 1. 发送启动转换命令:首先向ADC发送启动转换命令,让ADC开始对指定通道的模拟信号进行转换。 2. 读取转换结果:转换结束后,通过时钟和数据线读取ADC转换结果。由于STC15F2K60S2内部ADC是12位的,因此需要读取12个时钟周期的数据。在每个时钟周期,将ADC_CLK置为1,然后读取ADC_DOUT的值,并将其左移一位,最终得到12位的转换结果。 3. 关闭ADC片选:转换结果读取完毕后,需要禁用ADC片选。 在主函数中,可以通过调用getADCResult函数来读取指定通道的ADC转换结果,并进行相应的处理。例如,上述程序中读取了通道0的ADC转换结果,并可以在处理结果的代码块中进行相应的处理。 需要注意的是,上述程序仅为示例程序,实际应用中需要根据具体的需求进行相应的修改。同时,还需要根据具体的硬件连接情况,在程序中正确配置ADC_CS、ADC_CLK、ADC_DIN和ADC_DOUT等引脚。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值