找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10398|回复: 9
收起左侧

STC15W408AS写内部EEPROM后读出来数据不一致

  [复制链接]
ID:146949 发表于 2017-2-21 22:03 | 显示全部楼层 |阅读模式
IMG_20170221_215131.jpg 单片机:STC15W408AS
请问有人知道为什么我这个程序写入的数据与读出的不一致吗?
做了两个按健P10和P11,每次按增加或减少数值写入内部EEPROM。但读出来的总是不一样。
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sfr P4          =   0xC0;   //1111,1111 端口4
sfr P5          =   0xC8;   //xxxx,1111 端口5
sfr P6          =   0xE8;   //0000,0000 端口6
sfr P7          =   0xF8;   //0000,0000 端口7
sfr P0M0        =   0x94;   //0000,0000 端口0模式寄存器0
sfr P0M1        =   0x93;   //0000,0000 端口0模式寄存器1
sfr P1M0        =   0x92;   //0000,0000 端口1模式寄存器0
sfr P1M1        =   0x91;   //0000,0000 端口1模式寄存器1
sfr P2M0        =   0x96;   //0000,0000 端口2模式寄存器0
sfr P2M1        =   0x95;   //0000,0000 端口2模式寄存器1
sfr P3M0        =   0xB2;   //0000,0000 端口3模式寄存器0
sfr P3M1        =   0xB1;   //0000,0000 端口3模式寄存器1
sfr P4M0        =   0xB4;   //0000,0000 端口4模式寄存器0
sfr P4M1        =   0xB3;   //0000,0000 端口4模式寄存器1
sfr P5M0        =   0xCA;   //0000,0000 端口5模式寄存器0
sfr P5M1        =   0xC9;   //0000,0000 端口5模式寄存器1
sfr P6M0        =   0xCC;   //0000,0000 端口6模式寄存器0
sfr P6M1        =   0xCB;   //0000,0000 端口6模式寄存器1
sfr P7M0        =   0xE2;   //0000,0000 端口7模式寄存器0
sfr P7M1        =   0xE1;   //0000,0000 端口7模式寄存器1
sfr   IE2       = 0xaf;               //中断使能寄存器2
sfr   AUXR      = 0x8e;               //辅助寄存器
sfr   T2H       = 0xD6;               //定时器2高8位
sfr   T2L       = 0xD7;               //定时器2低8位
sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
sfr ADC_RES     =   0xBD;           //ADC高8位结果
sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器
/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER   0x80            //ADC power control bit
#define ADC_FLAG    0x10            //ADC complete flag
#define ADC_START   0x08            //ADC start control bit
#define ADC_SPEEDLL 0x00            //420 clocks
#define ADC_SPEEDL  0x20            //280 clocks
#define ADC_SPEEDH  0x40            //140 clocks
#define ADC_SPEEDHH 0x60            //70 clock
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            //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0400//测试地址
sbit    LCD5110_RES = P3^7;  //LCD5110 复位,0复位
sbit   LCD5110_SCLK = P3^6;  //LCD5110 时钟
sbit   LCD5110_SDIN = P3^5;  //LCD5110 数据
sbit     LCD5110_DC = P3^4;  //LCD5110 1写数据,0写指令
sbit     LCD5110_CE = P3^3;  //LCD5110 片选
sbit            P10 = P1^0;  //开关
sbit            P11 = P1^1;  //开关

const unsigned char code F6x8[][6] =
{
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp 0
    { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },   // ! 1
    { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },   // " 2
    { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // # 3
    { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $ 4
    { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },   // % 5
    { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },   // & 6
    { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },   // ' 7
    { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },   // ( 8
    { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },   // ) 9
    { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },   // * 10
    { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },   // + 11
    { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },   // , 12
    { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },   // - 13
    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },   // . 14
    { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },   // / 15
    { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0 16
    { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1 17
    { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2 18
    { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3 19
    { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4 20
    { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5 21
    { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6 22
    { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7 23
    { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8 24
    { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9 25

};

void Delayms(uint ms) //1mS@12.000MHz
{
   unsigned char i, j;
   while(ms--)
   {i = 12;
                j = 169;
                do
                {
                        while (--j);
                } while (--i);
   }
}

void IapIdle()//关闭IAP
{
    IAP_CONTR = 0;                  //关闭IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除触发寄存器
    IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}
uchar IapReadByte(uint addr)//从ISP/IAP/EEPROM区域读取一字节
{
    uchar dat;                       //数据缓冲区
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //设置IAP命令
    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功能
    return dat;                     //返回
}

void IapProgramByte(uint addr, uchar dat)//写一字节数据到ISP/IAP/EEPROM区域
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}
void LCD_write_byte(unsigned char dt, unsigned char command)//LCD5110写入数据
{
     unsigned char i;
     LCD5110_CE=0;                       // 关闭LCD
     LCD5110_DC=command;     // 0是写命令,1是写数据
     for(i=0;i<8;i++)
     {
          if(dt&0x80)
             LCD5110_SDIN=1;
            else
             LCD5110_SDIN=0;
          dt=dt<<1;      //dt为暂存数据   
          LCD5110_SCLK=0;_nop_();                           
          LCD5110_SCLK=1;_nop_();
     }   
     LCD5110_DC=1;   
     LCD5110_CE=1;   
     LCD5110_SDIN=1;
}
void LCD_clear(void) //5110LCD清屏
{
        unsigned int i;
        LCD_write_byte(0x0c, 0);                       
        LCD_write_byte(0x80, 0);                       
        for (i=0; i<504; i++)
        LCD_write_byte(0, 1);                       
}
void LCD_set_XY(unsigned char X, unsigned char Y)  //x 左右共0~83列可移,Y由上至下共0~5行可移
{
                LCD_write_byte(0x40 | Y, 0);        // column         Y+=64
                LCD_write_byte(0x80 | X, 0);  // row                 X+=128
}
void LCD_init(void)        //5110LCD初始化LCD_init
{            
                LCD5110_RES=0;        // 产生一个让LCD复位的低电平脉冲
                Delayms(10);
                LCD5110_RES=1;                
                LCD5110_CE = 0;         // 关闭LCD
                Delayms(10);
                LCD5110_CE = 1;// 使能LCD
                Delayms(10);
                LCD_write_byte(0x21, 0);        // 使用扩展命令设置LCD模式
                LCD_write_byte(0xC2, 0);        // 设置偏置电压//不同的屏须要微调此参数B9~C9
                LCD_write_byte(0x06, 0);        // 温度校正
                LCD_write_byte(0x13, 0);        // 1:48
                LCD_write_byte(0x20, 0);        // 使用基本命令
                LCD_clear();                // 清屏
                LCD_write_byte(0x0C, 0);        // 设定显示模式,正常显示      
                LCD5110_CE = 0;  // 关闭LCD
}
void LCD_P6x8Str(unsigned char x,unsigned char y,unsigned char ch)
{
        unsigned char i;      
        LCD_set_XY(x,y);   
        for(i=0;i<6;i++){        LCD_write_byte(F6x8[ch],1);  }
}

void LCD_P6x8Str5wita(uchar x,uchar y,uchar i)
{
        LCD_P6x8Str(x,y,i%1000/100+16);
        LCD_P6x8Str(x+6,y,i%100/10+16);
        LCD_P6x8Str(x+12,y,i%10/1+16);
}
void main()
{
          uchar dat1,dat2;
                P1M0 = 0x00;
                P1M1 = 0x00;
                P3M0 = 0x00;
                P3M1 = 0x00;
                P5M0 = 0x00;
                P5M1 = 0x00;
    LCD_init();//LCD初始化

                dat2=IapReadByte(IAP_ADDRESS+1);
                LCD_P6x8Str5wita(0,1,dat2);
        while(1)
        {
                               
                        if(!P11)
                        {
                                Delayms(40);
                                if(!P11)
                                {
                                        while(!P11);
                                        dat1++;
                                        LCD_P6x8Str5wita(0,0,dat1);
                                        IapProgramByte(IAP_ADDRESS+1, dat1);
                                        Delayms(100);
                                        dat2=IapReadByte(IAP_ADDRESS+1);
                                        LCD_P6x8Str5wita(0,1,dat2);
                                }
                        }       
                        if(!P10)
                        {
                                Delayms(40);
                                if(!P10)
                                {
                                        while(!P10);
                                        dat1--;
                                        LCD_P6x8Str5wita(0,0,dat1);
                                        IapProgramByte(IAP_ADDRESS+1, dat1);
                                        Delayms(100);
                                        dat2=IapReadByte(IAP_ADDRESS+1);
                                        LCD_P6x8Str5wita(0,1,dat2);
                                }
                        }
        }
       
}

回复

使用道具 举报

ID:162242 发表于 2017-2-22 12:49 | 显示全部楼层
PS来处理相片 图片等等
回复

使用道具 举报

ID:33544 发表于 2018-2-26 14:34 | 显示全部楼层
楼主问题解决了吗,俺也遇到了同样的问题,写入的数据和读出的数据不一至,用官方的程序测试的,不知问题出在那,板上的电源电压正常(5V)。
回复

使用道具 举报

ID:69072 发表于 2018-2-27 08:24 | 显示全部楼层
如果STC 单片机内部EEPROM某地址上已经有数据    需要先擦除再写入
如果本来已经有数据 就需要 ①读取内部EEPROM并保存数据到数组 ②擦除eeprom数据 ③再次将修改好的数据写入。  
回复

使用道具 举报

ID:213173 发表于 2018-2-27 20:55 | 显示全部楼层
STC15W的EEPROM写入数据前必须要把扇区擦除,没有看到你程序中有相关语句!
回复

使用道具 举报

ID:313791 发表于 2020-11-13 13:27 | 显示全部楼层
可以试试读取->擦除->写入的思路
回复

使用道具 举报

ID:47286 发表于 2020-11-13 23:31 | 显示全部楼层
你这样不行 这种内部EEPROM需要把所有数据读出来 在内存里修改需要修改的位 然后擦除整个扇区 再一起写进去 否则就是你见到的情况 即便你要写入的数据只有1位也要这么操作
回复

使用道具 举报

ID:315110 发表于 2020-11-14 00:37 | 显示全部楼层
dzbj 发表于 2020-11-13 23:31
你这样不行 这种内部EEPROM需要把所有数据读出来 在内存里修改需要修改的位 然后擦除整个扇区 再一起写进去 ...

涨姿势了,居然要这么操作
回复

使用道具 举报

ID:278840 发表于 2020-11-14 14:15 | 显示全部楼层
看看读取时间,和存储的时间,会不会太短了,导致读取异常
回复

使用道具 举报

ID:497980 发表于 2021-3-24 13:48 | 显示全部楼层
凤姐438 发表于 2018-2-27 08:24
如果STC 单片机内部EEPROM某地址上已经有数据    需要先擦除再写入
如果本来已经有数据 就需要 ①读取内部 ...

very good
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表