找回密码
 立即注册
查看: 70|回复: 8

不同型号的单片机的EEPROM读写是否有区别

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:578
  • 最近打卡:2026-04-30 08:45:45

4

主题

24

回帖

1421

积分

金牌会员

积分
1421
发表于 2026-4-22 23:12:45 | 显示全部楼层 |阅读模式
用同一代码测试不同型号的EEPROM读写功能,结果竟然是不同的,以下是测数据及测试代码
STC8G1K08和STC8H1K08实测数据.jpg STC8H2K08U实测数据.jpg STC8H2K12U实测数据.jpg STC8H8K64U实测数据.jpg

只需将测试代码下载到单片机中,看串口上传数据是否一致即可,请STC专业人员验证

/***********EEPROM读写测试代码***********/
/*此程序通过T0计时来产生一个近似秒信号,
主程序通过对秒信号的累计来产生时分秒3个数据,
同时当秒信号来临时,将时分秒数据保存至EEPROM中,
并将原始数据通过串口1上传,再将时分秒数据从EEPROM中读出,也通过串口1上传,
正常情况下,上传的原始数据(TEST)与从EEPROM中读出后上传的数据(EEPR)应当一致,
然而实测后发现,STC8G1K08和STC8H1K08这两个型号的单片机均读写正常,
STC8H2K08U和STC8H8K64U这两个型号的单片机从EEPROM中读出的数据与原始数据不一致,
似乎带USB的单片机都不能正常读写,烦请STC专业人员测试一下以下代码,
如果与我测试结果相同,请说明一下带USB的单片机与其他单片机在读写EEPROM时有何不同,
如果是我代码哪里有问题,请帮我改正一下,谢谢!

测试代码作于2026年4月22日,测试中有问题需要沟通可致电18729740498(王先生)

本程序仅为EEPROM读写测试使用,只要单片机硬件有串口1,T0,T1可通用测试*/

#include <reg52.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200L          //系统频率 用于串口波特率       
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;

sfr P_SW1 = 0xA2;

sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
sfr IAP_TPS = 0xF5;

sfr P5   = 0xC8;
sfr AUXR  = 0x8e;               //辅助寄存器
sfr T2H   = 0xd6;               //定时器2高8位
sfr T2L   = 0xd7;               //定时器2低8位
sbit CLK = P5^4;   //SCK(输入控制)接P32
sbit DAT = P3^3;        //DIO(数据)接 P33
sbit LCK = P5^5;        //RCK(输出控制)接P34
sbit IR_INPUT = P3^2;  //红外接收引脚
bit irflag = 0;  //红外接收标志,收到一帧正确数据后置1
uchar ircode[4];  //红外代码接收缓冲区
uchar flag=0;
uint tcount;
uchar hh,mm,ss;//时分秒时间变量
uchar eeph,eepm,eeps;//时分秒时间变量
bit B_1s;
#define  UART1_BUF_LENGTH  64

unsigned char TX1_Cnt;    //发送计数
unsigned char RX1_Cnt;    //接收计数

unsigned char idata RX1_Buffer[UART1_BUF_LENGTH]; //接收缓冲

bit busy;                                                                                        // 串口忙标志

void    PrintString1(char *puts);
void    UART_TxByte(char dat);

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 = 0x80; //使能 IAP
IAP_TPS = 12; //设置擦除等待参数 12MHz
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;
}
void IapProgram(int addr, char dat)
{
IAP_CONTR = 0x80; //使能 IAP
IAP_TPS = 12; //设置擦除等待参数 12MHz
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 = 0x80; //使能 IAP
IAP_TPS = 12; //设置擦除等待参数 12MHz
IAP_CMD = 3; //设置 IAP 擦除命令
IAP_ADDRL = addr; //设置 IAP 低地址
IAP_ADDRH = addr >> 8; //设置 IAP 高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IapIdle(); //关闭 IAP 功能
}

/***********************串口1初始化程序********************/
void ConfigUART(unsigned int baud)
{
    SCON  = 0x50;  //配置串口为模式1
    TL1 = (65536 - (FOSC/4/baud));   //设置波特率重装值
    TH1 = (65536 - (FOSC/4/baud))>>8;
    AUXR = 0x40;                //T1为1T模式,并选择定时器1为串口1的波特率发生器
        TR1=1;                                                //启动定时器1
//    AUXR |= 0x01;
    P_SW1 = 0x00;                               //RXD/P3.0, TXD/P3.1
//  P_SW1 = 0x40;                               //RXD_2/P3.6, TXD_2/P3.7
//  P_SW1 = 0x80;                               //RXD_3/P1.6, TXD_3/P1.7
//  P_SW1 = 0xc0;                               //RXD_4/P4.3, TXD_4/P4.4
    ES = 1;                     //使能串口1中断
    busy = 0;
    TX1_Cnt = 0;
    RX1_Cnt = 0;       
}       

void main()
{
        P3M1 = 0x00;
        P3M0 = 0x00;
        P5M1 = 0x00;
        P5M0 = 0x00;
  ConfigUART(9600);       

        TMOD &= 0XF0;
        TMOD |= 0x01;           //T0方式1,16位Timer0       
        TR0 = 1;                   //启动T0
        ET0 = 1;                   //允许T0中断       
       
  EA = 1;      //开总中断
    while (1)
    {                                               
                        if(B_1s)
                        {
                        B_1s = 0;                                       
                        ss++;
                         if(ss==60)
                                {
                                ss=0;
                                                        mm++;

                                        if(mm==60)
                                        {
                                                mm=0;
                                                hh++;
                                                if(hh==24)
                                                        {
                                                        hh=0;
                                                        }                               
                                        }
                                }
                        IapErase(0x0400);
                        IapProgram(0x0400, hh);
                        IapProgram(0x0401, mm);                       
                        IapProgram(0x0402, ss);       
        PrintString1("TEST_h:");
      UART_TxByte(hh/10+'0');
      UART_TxByte(hh%10+'0');       
        PrintString1("-m:");
      UART_TxByte(mm/10+'0');
      UART_TxByte(mm%10+'0');       
        PrintString1("-s:");
      UART_TxByte(ss/10+'0');
      UART_TxByte(ss%10+'0');
  PrintString1("\r\n");
                       
                        eeph=IapRead(0x0400);
                        eepm=IapRead(0x0401);
                        eeps=IapRead(0x0402);
        PrintString1("EEPR_h:");
      UART_TxByte(eeph/10+'0');
      UART_TxByte(eeph%10+'0');       
        PrintString1("-m:");
      UART_TxByte(eepm/10+'0');
      UART_TxByte(eepm%10+'0');       
        PrintString1("-s:");
      UART_TxByte(eeps/10+'0');
      UART_TxByte(eeps%10+'0');                                               
      }                       
    }
}

/*中断程序*/
void T0_ISR(void) interrupt 1
{
  TH0 = (65536 - 1000) / 256; //--- 重新给定时器T0赋初值 ---
  TL0 = (65536 - 1000) % 256;
  tcount++;
  if(tcount==1000)
        {
            tcount=0;
                B_1s = 1;                                               
        }
}       

void InterruptUART() interrupt 4  //UART中断服务函数
{
        if (RI)  //接收到字节
    {
                RI = 0;   //手动清零接收中断标志位
        }
        if (TI)  //字节发送完毕
    {
                TI = 0;   //手动清零中断标志位
                busy = 0;                                                                        // 清零忙状态
        }
}

//========================================================================
// 描述: 发送一个字节.
//========================================================================
void UART_TxByte(char dat)
{
    SBUF = dat;
    busy = 1;
    while(busy);
}

//========================================================================
// 串口2发送字符串函数
//========================================================================
void PrintString1(char *puts) //发送一个字符串
{
    for (; *puts != 0;  puts++) UART_TxByte(*puts);    //遇到停止符0结束
}
串口EEP读写测试.rar (36.13 KB, 下载次数: 1)

回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 2026-4-23 06:58:51 | 显示全部楼层
你只要看一下官方示例就知道STC不同型号的单片机的EEPROM读写区别在哪里。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:261
  • 最近打卡:2026-05-01 07:39:25

18

主题

246

回帖

568

积分

高级会员

积分
568
发表于 2026-4-23 08:15:59 | 显示全部楼层
你是否是编译好一个HEX后,直接下载到这几个型号的单片机里的,
你试下这样,在Keil中选择好相应型号的单片机,然后编译一下,逐个生成HEX,然后再下载试试咋样
因为单片机内存大小不一样,其EEPROM的地址也不一样,又因为USB固件存在的原因,内存可能会调整,
可能8K内存的EEPROM位置和12K的有差异
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:671
  • 最近打卡:2026-04-30 08:59:31
已绑定手机

52

主题

2608

回帖

9093

积分

论坛元老

积分
9093
发表于 2026-4-23 09:08:23 | 显示全部楼层
我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM空间大小。
你的程序里面EEPROM起始地址是0x0400,EEPROM空间至少需要1.5K。

截图202604230905212043.jpg

修改EEPROM大小烧录后需要重新上电才会生效

截图202604230908192776.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:578
  • 最近打卡:2026-04-30 08:45:45

4

主题

24

回帖

1421

积分

金牌会员

积分
1421
发表于 2026-4-23 10:02:52 | 显示全部楼层
好的,我按照你的操作再试一下
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:578
  • 最近打卡:2026-04-30 08:45:45

4

主题

24

回帖

1421

积分

金牌会员

积分
1421
发表于 2026-4-23 11:51:58 | 显示全部楼层
乘风*** 发表于 2026-4-23 09:08
我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM ...

按照你的操作,我测试也正常了
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:578
  • 最近打卡:2026-04-30 08:45:45

4

主题

24

回帖

1421

积分

金牌会员

积分
1421
发表于 2026-4-23 22:42:31 | 显示全部楼层
乘风*** 发表于 2026-4-23 09:08
我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM ...

你好,按照你的操作,STC8H8K64U我这边测试正常了,昨天测试STC8H2K08U和STC8H2K12U仍然不正常,但今天用公司电脑测试又正常了,所以我再试试,希望STC所有的芯片都能正常测试
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:671
  • 最近打卡:2026-04-30 08:59:31
已绑定手机

52

主题

2608

回帖

9093

积分

论坛元老

积分
9093
发表于 7 天前 | 显示全部楼层
STC8H2K系列是多级流水线,触发命令后面需要写4个NOP
  1. IAP_TRIG = 0x5a; //写触发命令(0x5a)
  2. IAP_TRIG = 0xa5; //写触发命令(0xa5)
  3. _nop_();
  4. _nop_();
  5. _nop_();
  6. _nop_();
复制代码
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:578
  • 最近打卡:2026-04-30 08:45:45

4

主题

24

回帖

1421

积分

金牌会员

积分
1421
发表于 7 天前 | 显示全部楼层
乘风*** 发表于 2026-4-24 16:37
STC8H2K系列是多级流水线,触发命令后面需要写4个NOP

好的,那我加上
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-5-1 10:29 , Processed in 0.128406 second(s), 95 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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