STC8A4K系列单片机EEPROM编程

这段时间在弄STC8A系列单片机做一个设计,遇到一些问题,第一次写博客,把遇到的问题写下来分享一下。
遇到的问题就是EEPROM不能正确的读取到存储的数据。数据存入eeprom后,读取出来的数据不正确。我看了单片机文档但是并没有提到这个点。下面就详细的讲一下这个点,希望有问题的小伙伴遇到问题可以参考一下。
先看一下STC8A系列的eeprom基本信息:
老手或者着急的老哥直接跳去末尾。
EEPROM的访问方式主要由两种:MOV和IAP,具体的历程官方文档给的有,我主要使用的是IAP的方式,先看一下EEPROM内存大小,不同单片机型号不一样,注意不要超出范围了。

STC8A4K系列单片机EEPROM编程_第1张图片
STC8A4K系列单片机EEPROM编程_第2张图片
我是用的是图中这一款,有32K 64个扇区,这里需要注意一下:读、写和擦除,其中擦除操作是以扇区为单位进行操作,每扇区为 512 字节,即每执行一次擦除命令就会擦除一个扇区,而读数据和写数据都是以字节为单位进行操作的,即每执行一次读或者写命令时只能读出或者写入一个字节。所以存数据尽量放在一个扇区内。
下面进入干货区(撸代码)
首先下面是寄存器的基础配置,这里主要查看相关文档来配置,具体的查看参考手册。

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

上面的可有可无:主要是下面几个函数。

//读取数据函数,入口参数是地址
char IapRead(int addr)
{
    char dat;

    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}
//写入函数,数据和地址,注意要是用16进制数据
void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

上面的几个函数主要是就是基本操作,老手可以忽略,可以直接到最末尾。主要得问题是下面的一个函数:

//擦除扇区内容  这个函数很重要
void IapErase(int addr)
{
    IAP_CONTR = WT_12M;                         //使能IAP
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}

该函数是擦除扇区内容,为什么要重点说明呢,因为问题就出在这里。
先看一下我的问题程序:


void eeprom_write()
{
		IapProgram(0x400, (adc_max)%256);
		IapProgram(0x420, (adc_min)%256);	
}

void eeprom_read()
{
	adc_max = IapRead(0x400);
	adc_min = IapRead(0x420);
}

这两个就是读取和写入的函数了,分别将ADC两个参数写入0X400和0X420的内存空间,按照这个程序数据可以存进去,但是无法正确读出来,测试的时候,数据时准时不准,查阅很多地方都找不到答案。最终在一片帖子上发现了问题:
就是刚刚那个函数,擦除函数。

IapErase(0x0400);

好!先看代码,跟着代码去学习。更正过后的程序如下:

void eeprom_write()
{
		*IapErase(0x0400);*
		IapProgram(0x400, (adc_max)%256);
		IapProgram(0x420, (adc_min)%256);	
}

void eeprom_read()
{
	adc_max = IapRead(0x400);
	adc_min = IapRead(0x420);
}

问题就出在哪里,程序整个思路是OK的,问题就是:
STC单片机的EEPROM在写入的时候必须擦除整个扇区,否则就会出现我这个错误,读出数据不正确。

这里注意一下为什么只清除0X400开始的内存呢? 认真读过的老哥应该知道,前面说过清除是清除整个扇区,每个扇区512字节,所以 只需要写最开始的那一段就可以了。

好的就是这么个问题,这可能就是常识,才疏学浅,老司机不要嫌弃。

你可能感兴趣的:(嵌入式,单片机,eeprom,c语言,keil,mdk)