找回密码
 立即注册

QQ登录

只需一步,快速开始

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

求助单片机EEPROM储存问题,每次都是储存的跟读出的不一样

[复制链接]
ID:45129 发表于 2020-4-11 13:33 | 显示全部楼层 |阅读模式
我在单片机上储存数据时,每次都是储存的跟读出的不一样,我把程序贴上来,求大神指导下
/*当前米数储存子程序*/
void dqmscc()
{
uchar w,q,b,g,s;
  w=(unsigned char)dqms/10%10;
  q=(unsigned char)dqms/100%10;
  b=(unsigned char)dqms/10%10;
  s=(unsigned char)dqms/10%10;
  g=(unsigned char)dqms%10;  
  SectorErase(0x2000);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
  byte_write(0x2000,w);
  byte_write(0x2008,q);
  byte_write(0x200f,b);
  byte_write(0x2017,s);
  byte_write(0x201e,g);
}
/*当前米数读出子程序*/
void dqmsdc()
{  
  uchar w,q,b,g,s;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
  w=byte_read(0x2000);
  q=byte_read(0x2008);
  b=byte_read(0x200f);
  s=byte_read(0x2017);
  g=byte_read(0x201e);
  dqms=w*10000+q*1000+b*100+s*10+g;
}

回复

使用道具 举报

ID:580799 发表于 2020-4-11 14:01 | 显示全部楼层
/*当前米数储存子程序*/
void dqmscc()
{
uchar w,q,b,g,s;
  w=(unsigned char)dqms/10000%10;
  q=(unsigned char)dqms/1000%10;
  b=(unsigned char)dqms/100%10;
  s=(unsigned char)dqms/10%10;
  g=(unsigned char)dqms%10;  
  SectorErase(0x2000);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
  byte_write(0x2000,w);
  byte_write(0x2008,q);
  byte_write(0x200f,b);
  byte_write(0x2017,s);
  byte_write(0x201e,g);
}
/*当前米数读出子程序*/
void dqmsdc()
{  
  uchar w,q,b,g,s;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
  w=byte_read(0x2000);
  q=byte_read(0x2008);
  b=byte_read(0x200f);
  s=byte_read(0x2017);
  g=byte_read(0x201e);
  dqms=w*10000+q*1000+b*100+s*10+g;
}

最好写成
/*当前米数储存子程序*/
void dqmscc()
{
uchar w,q,b,g,s;
  q=(qms>>24)&0xff;
  b=(dqms>>16)&0xff;
  s=(dqms>>8)&0xff;
  g=dqms&0xff;  
  SectorErase(0x2000);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
  byte_write(0x2000,w);
  byte_write(0x2008,q);
  byte_write(0x200f,b);
  byte_write(0x2017,s);
  byte_write(0x201e,g);
}
/*当前米数读出子程序*/
void dqmsdc()
{  
  uchar w,q,b,g,s;            
  q=byte_read(0x2008);
  b=byte_read(0x200f);
  s=byte_read(0x2017);
  g=byte_read(0x201e);
  dqms=(q<<24)|(b<<16)|(s<<8)|g;
}

回复

使用道具 举报

ID:235200 发表于 2020-4-11 14:21 | 显示全部楼层
要贴出byte_read byte_write两个子函数,贴出这个看不出来
回复

使用道具 举报

ID:213173 发表于 2020-4-11 15:49 | 显示全部楼层
不知你是用单片机内置EEPROM还是外挂EEPROM。如果是内置也得知道单片机品牌型号,否则这么理解你的程序?
回复

使用道具 举报

ID:45129 发表于 2020-4-11 17:47 | 显示全部楼层
csmyldl 发表于 2020-4-11 14:21
要贴出byte_read byte_write两个子函数,贴出这个看不出来

/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
        ISP_ADDRH = (unsigned char)(byte_addr >> 8);        /* 地址赋值        */
        ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);

        ISP_CMD   = ISP_CMD        & 0xf8;                        /* 清除低3位         */
        ISP_CMD   = ISP_CMD        | RdCommand;        /* 写入读命令        */

        ISPgoon();                                                        /* 触发执行                */
        ISP_IAP_disable();                                /* 关闭ISP,IAP功能        */

        return (ISP_DATA);                                /* 返回读到的数据        */
}
/* ================== 扇区擦除 ======================== */
void sectorerase(unsigned int sector_addr)
{
        unsigned int iSectorAddr;
        iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
        ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
        ISP_ADDRL = 0x00;

        ISP_CMD        = ISP_CMD & 0xf8;                        /* 清空低3位         */
        ISP_CMD        = ISP_CMD | EraseCommand;        /* 擦除命令3         */

        ISPgoon();                                                        /* 触发执行                */
        ISP_IAP_disable();                                /* 关闭ISP,IAP功能        */

}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
        ISP_ADDRH =        (unsigned char)(byte_addr >> 8);         /* 取地址         */
        ISP_ADDRL =        (unsigned char)(byte_addr & 0x00ff);

        ISP_CMD         = ISP_CMD & 0xf8;                                /* 清低3位        */
        ISP_CMD  = ISP_CMD | PrgCommand;                /* 写命令2        */
        ISP_DATA = original_data;                        /* 写入数据准备        */
        delayms1(20);
        ISPgoon();                                                        /* 触发执行                */
        ISP_IAP_disable();                                        /* 关闭IAP功能        */
}
你好,这个是字节写跟字节读的程序,麻烦帮忙看下,单片机是STC89C52,内部EEPROM
回复

使用道具 举报

ID:45129 发表于 2020-4-11 17:48 | 显示全部楼层
xingqi 发表于 2020-4-11 14:01
/*当前米数储存子程序*/
void dqmscc()
{

谢谢,我试下看看
回复

使用道具 举报

ID:45129 发表于 2020-4-11 17:49 | 显示全部楼层
wulin 发表于 2020-4-11 15:49
不知你是用单片机内置EEPROM还是外挂EEPROM。如果是内置也得知道单片机品牌型号,否则这么理解你的程序?

谢谢提醒,单片机是STC879C52,用的是内部EEPROM
回复

使用道具 举报

ID:45129 发表于 2020-4-11 20:03 | 显示全部楼层
xingqi 发表于 2020-4-11 14:01
/*当前米数储存子程序*/
void dqmscc()
{

你好,你修改的这个含税万位数是没有处理吗?
回复

使用道具 举报

ID:213173 发表于 2020-4-11 20:49 | 显示全部楼层
hamburger3975 发表于 2020-4-11 17:49
谢谢提醒,单片机是STC879C52,用的是内部EEPROM

这是STS89C52多字节读写EEPROM的官方示例程序,汉字注释是自己添加的。
  1. /*------------------------------------------------------------------*/
  2. /* --- STC MCU Limited ---------------------------------------------*/
  3. /* --- STC89-90xx Series MCU ISP/IAP/EEPROM Demo -------------------*/
  4. /* --- Mobile: (86)13922805190 -------------------------------------*/
  5. /* If you want to use the program or the program referenced in the  */
  6. /* article, please specify in which data and procedures from STC    */
  7. /*------------------------------------------------------------------*/

  8. #include "reg51.h"
  9. #include "intrins.h"

  10. typedef unsigned char BYTE;
  11. typedef unsigned int WORD;

  12. /*Declare SFR associated with the IAP */
  13. sfr IAP_DATA    =   0xE2;           //Flash data register
  14. sfr IAP_ADDRH   =   0xE3;           //Flash address HIGH
  15. sfr IAP_ADDRL   =   0xE4;           //Flash address LOW
  16. sfr IAP_CMD     =   0xE5;           //Flash command register
  17. sfr IAP_TRIG    =   0xE6;           //Flash command trigger
  18. sfr IAP_CONTR   =   0xE7;           //Flash control register

  19. /*Define ISP/IAP/EEPROM command*/
  20. #define CMD_IDLE    0               //Stand-By
  21. #define CMD_READ    1               //Byte-Read
  22. #define CMD_PROGRAM 2               //Byte-Program
  23. #define CMD_ERASE   3               //Sector-Erase

  24. /*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
  25. //#define ENABLE_IAP 0x80           //if SYSCLK<40MHz
  26. #define ENABLE_IAP   0x81           //if SYSCLK<20MHz
  27. //#define ENABLE_IAP x82            //if SYSCLK<10MHz
  28. //#define ENABLE_IAP 0x83           //if SYSCLK<5MHz

  29. //Start address for STC89C58xx EEPROM
  30. //#define IAP_ADDRESS 0x08000
  31. #define IAP_ADDRESS 0x02000                        //宏定义EEPROM起始地址
  32. void Delay(BYTE n);
  33. void IapIdle();//关闭IAP
  34. BYTE IapReadByte(WORD addr);//IAP读字节
  35. void IapProgramByte(WORD addr, BYTE dat);//写字节
  36. void IapEraseSector(WORD addr);//扇区擦除

  37. void main()
  38. {
  39.     WORD i;

  40.     P1 = 0xfe;                      //1111,1110 System Reset OK
  41.     Delay(10);                      //Delay
  42.     IapEraseSector(IAP_ADDRESS);    //Erase current sector//IAP_ADDRESS扇区擦除
  43.     for (i=0; i<512; i++)           //Check whether all sector data is FF
  44.     {
  45.         if (IapReadByte(IAP_ADDRESS+i) != 0xff)//读IAP_ADDRESS+i是否=0xff
  46.             goto Error;             //If error, break( goto Error;无条件跳转语句)
  47.     }
  48.     P1 = 0xfc;                      //1111,1100 Erase successful
  49.     Delay(10);                      //Delay
  50.     for (i=0; i<512; i++)           //Program 512 bytes data into data flash
  51.     {
  52.         IapProgramByte(IAP_ADDRESS+i, (BYTE)i);//写IAP_ADDRESS扇区数据
  53.     }
  54.     P1 = 0xf8;                      //1111,1000 Program successful
  55.     Delay(10);                      //Delay
  56.     for (i=0; i<512; i++)           //Verify 512 bytes data
  57.     {
  58.         if (IapReadByte(IAP_ADDRESS+i) != (BYTE)i)//读IAP_ADDRESS扇区数据
  59.             goto Error;             //If error, break
  60.     }
  61.     P1 = 0xf0;                      //1111,0000 Verify successful
  62.     while (1);
  63. Error:
  64.     P1 &= 0x7f;                     //0xxx,xxxx IAP operation fail
  65.     while (1);
  66. }

  67. /*----------------------------
  68. Software delay function
  69. ----------------------------*/
  70. void Delay(BYTE n)
  71. {
  72.     WORD x;

  73.     while (n--)
  74.     {
  75.         x = 0;
  76.         while (++x);
  77.     }
  78. }

  79. /*----------------------------
  80. Disable ISP/IAP/EEPROM function
  81. Make MCU in a safe state
  82. ----------------------------*/
  83. void IapIdle()
  84. {
  85.     IAP_CONTR = 0;                  //Close IAP function
  86.     IAP_CMD = 0;                    //Clear command to standby
  87.     IAP_TRIG = 0;                   //Clear trigger register
  88.     IAP_ADDRH = 0x80;               //Data ptr point to non-EEPROM area
  89.     IAP_ADDRL = 0;                  //Clear IAP address to prevent misuse
  90. }

  91. /*----------------------------
  92. Read one byte from ISP/IAP/EEPROM area
  93. Input: addr (ISP/IAP/EEPROM address)
  94. Output:Flash data
  95. ----------------------------*/
  96. BYTE IapReadByte(WORD addr)
  97. {
  98.     BYTE dat;                       //Data buffer

  99.     IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
  100.     IAP_CMD = CMD_READ;             //Set ISP/IAP/EEPROM READ command
  101.     IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
  102.     IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
  103.     IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
  104.     IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
  105.     _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
  106.     dat = IAP_DATA;                 //Read ISP/IAP/EEPROM data
  107.     IapIdle();                      //Close ISP/IAP/EEPROM function

  108.     return dat;                     //Return Flash data
  109. }

  110. /*----------------------------
  111. Program one byte to ISP/IAP/EEPROM area
  112. Input: addr (ISP/IAP/EEPROM address)
  113.        dat (ISP/IAP/EEPROM data)
  114. Output:-
  115. ----------------------------*/
  116. void IapProgramByte(WORD addr, BYTE dat)
  117. {
  118.     IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
  119.     IAP_CMD = CMD_PROGRAM;          //Set ISP/IAP/EEPROM PROGRAM command
  120.     IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
  121.     IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
  122.     IAP_DATA = dat;                 //Write ISP/IAP/EEPROM data
  123.     IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
  124.     IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
  125.     _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
  126.     IapIdle();
  127. }

  128. /*----------------------------
  129. Erase one sector area
  130. Input: addr (ISP/IAP/EEPROM address)
  131. Output:-
  132. ----------------------------*/
  133. void IapEraseSector(WORD addr)
  134. {
  135.     IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
  136.     IAP_CMD = CMD_ERASE;            //Set ISP/IAP/EEPROM ERASE command
  137.     IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
  138.     IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
  139.     IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
  140.     IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
  141.     _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
  142.     IapIdle();
  143. }

复制代码
回复

使用道具 举报

ID:45129 发表于 2020-4-12 10:48 | 显示全部楼层
wulin 发表于 2020-4-11 20:49
这是STS89C52多字节读写EEPROM的官方示例程序,汉字注释是自己添加的。

好的,谢谢。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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