不同型号的单片机的EEPROM读写是否有区别
用同一代码测试不同型号的EEPROM读写功能,结果竟然是不同的,以下是测数据及测试代码只需将测试代码下载到单片机中,看串口上传数据是否一致即可,请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;//红外代码接收缓冲区
uchar flag=0;
uint tcount;
uchar hh,mm,ss;//时分秒时间变量
uchar eeph,eepm,eeps;//时分秒时间变量
bit B_1s;
#defineUART1_BUF_LENGTH64
unsigned char TX1_Cnt; //发送计数
unsigned char RX1_Cnt; //接收计数
unsigned char idata RX1_Buffer; //接收缓冲
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结束
}
你只要看一下官方示例就知道STC不同型号的单片机的EEPROM读写区别在哪里。 你是否是编译好一个HEX后,直接下载到这几个型号的单片机里的,
你试下这样,在Keil中选择好相应型号的单片机,然后编译一下,逐个生成HEX,然后再下载试试咋样
因为单片机内存大小不一样,其EEPROM的地址也不一样,又因为USB固件存在的原因,内存可能会调整,
可能8K内存的EEPROM位置和12K的有差异 我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM空间大小。
你的程序里面EEPROM起始地址是0x0400,EEPROM空间至少需要1.5K。
修改EEPROM大小烧录后需要重新上电才会生效
好的,我按照你的操作再试一下 乘风飞扬 发表于 2026-4-23 09:08
我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM ...
按照你的操作,我测试也正常了 乘风飞扬 发表于 2026-4-23 09:08
我烧录你的程序到STC8H8K64U芯片测试是正常的。
需要注意的是IAP类型的单片机,烧录时可以自定义设置EEPROM ...
你好,按照你的操作,STC8H8K64U我这边测试正常了,昨天测试STC8H2K08U和STC8H2K12U仍然不正常,但今天用公司电脑测试又正常了,所以我再试试,希望STC所有的芯片都能正常测试 STC8H2K系列是多级流水线,触发命令后面需要写4个NOP
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
_nop_();
_nop_();
_nop_(); 乘风飞扬 发表于 2026-4-24 16:37
STC8H2K系列是多级流水线,触发命令后面需要写4个NOP
好的,那我加上
页:
[1]