您的当前位置:首页正文

16进制转换算成10进制程序

2020-08-14 来源:易榕旅网
STC 单片机中的eeprom写入和读取6位的10进制数需要进行数据类型转换吗?具体是怎样现的呢?

2013-06-04 10:24

满意回答 提问者采纳 2013-06-04 10:27

6位10进制数,转换为16进制,再写入EEPROM. long x;

分4个字节写入 uchar c1;

c1= x>>24; //最高字节 c1=x>>16; //次高字节 c1=x>>8; //次低字节 c1=x&0xff; //最低字节

分别写入就可以了。追问 我用的是stc12C5A60S2单片机,我将转化轩16进制的数保存在一个数组,然后整个数组写进去,当需要的时候再读出来还原成十进制数可否呢?回答 当然可以。追问 想了一下,不知应该如何用单片机C语言去实现啊,可以指导下不?提问者评价 谢谢哈评论 | ningling_21 知道达人 | 来自团队 单片机学习 | 十级 采纳率26%擅长: 其他编程语言 汇编语言 C/C++

16进制转换算成10进制程序

来源:本站整理 作者:佚名2009年01月14日 23:33 0 分享

[导读] 16进制转换算成10进制程序 unsigned char d[10]; //用于显示的10位显示缓存 //======================

关键词:进制

16进制转换算成10进制程序

unsigned char d[10]; //用于显示的10位显示缓存

//========================================================

//16进制to10进制输出子程序:显示数据,起始位,结束位,有无小数点 //========================================================

void output(unsigned long dd,unsigned char s,unsigned char e,unsigned char dip) { unsigned long div;

unsigned char tm[8],i,j; div=10000000;

for (i=0;i<8;i++) { tm[i]=dd/div; dd%=div; div/=10; }

for (i=0;i<6;i++) { if (tm[i]!=0) break; tm[i]=nul; }

tm[5]|=dip; //小数点控制,请看“串行LED数码管显示驱动程序” j=7;

for (i=s;i} }

//把显示位5-9位的10进制数转换成为16进制数 unsigned int input(void) { unsigned int dd,dat; dd=10000;dat=0; for (i=5;i<10;i++) { dat+=dd*temp; dd/=10; }

return(dat); }

/* 89C51系列CPU编程器接收CPU程序*/ #i nclude #i nclude #i nclude #define e 8 #define p 9 #define l 10 sbit led=P3^2; sbit p27=P2^7; sbit p26=P2^6; sbit p36=P3^6; sbit p37=P3^7; sbit rst=P3^3; sbit ale=P3^5; sbit vpp=P3^4; bit b_break;

unsigned int adds;

// 13.8mS

void int_t0(void) interrupt 1 { TH0=-100; b_break=1; }

void wait(unsigned char w) { unsigned int t=w*184; b_break=0;

TL0=-t%256-1;TH0=-t/256; while (b_break==0) {} }

void nop(void) {

_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); }

unsigned char command(void) { TH0=-100;b_break=0;

while (RI==0) {if (b_break==1) return(0);} RI=0;

return(SBUF); }

void earsure(unsigned char cpu) { switch (cpu) {

case 1: //89C51

case 2:rst=p26=1;p27=p36=p37=0;nop();vpp=1;nop(); ale=0;wait(110);ale=1;nop(); break; case 3:

case 4:break; case 5:

case 6:break; } }

void program(unsigned char cpu) { unsigned int bdata adds=0; unsigned char d; switch (cpu) {

case 1: //89C51 case 2:

p36=p37=1;rst=1; while (1) {

TH0=-100;b_break=0;

while (RI==0) {if (b_break==1) return;} RI=0; d=SBUF;

//address

P0=adds%256; P2=adds/256; p27=1; //data P1=d;

nop(); //48clcl //vpp vpp=1;

nop(); //48clcl //ale ale=0;

wait(1);//100uS ale=1;

nop(); //10uS vpp=0;

nop(); //48clcl p27=0;

nop(); //48clcl P1=0xff;

TH0=-100;b_break=0;

while (d!=P1) {if (b_break==1) return;} polling

SBUF=d; adds++; }

break; case 3: case 4: case 5:

case 6:break; } }

void lock(unsigned char cpu) { unsigned char i; switch (cpu) { case 1: //89c51 case 2: //lock 1

rst=p26=p36=p27=p37=1;nop(); vpp=1; nop(); ale=0;

//data // for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop();

//lock 2

rst=p26=p27=1;p36=p37=0;nop(); vpp=1; nop(); ale=0;

// for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop();

//lock 3

rst=p26=p36=1;p27=p37=0;nop(); vpp=1; nop(); ale=0;

// for (i=0;i<6;i++) wait(100); wait(1); ale=1; nop(); vpp=0; nop(); break; case 3: case 4: case 5:

case 6:break; } }

void main(void) {

unsigned char disp,flash,temp,cpu; EA=1;

SCON=0xd8;PCON=0x80; TMOD=0x21;

TL1=TH1=0xff;TR1=1; TH0=-100;ET0=TR0=1; flash=0x80;

while (1) {

temp=command(); switch (temp) { case 0:

case 1: //89c51 case 2: //89C52 case 3: //80f51 case 4: //80F52 case 5: //87F51

case 6:cpu=temp;SBUF=temp;break;//87f52

case e:SBUF=temp;earsure(cpu);break; //erasure case p:SBUF=temp;program(cpu);break; //program case l:lock(cpu);SBUF=temp;break; //lock default:SBUF=temp;break; }

b_break=0;

if ((++disp)>flash) {disp=0;led=!led;} } }

//HT1380实时时钟驱动程序 sbit clock_dat=P0^1; sbit clock_clk=P0^2; sbit clock_rst=P0^3; sbit a0=ACC^0; sbit a1=ACC^1; sbit a2=ACC^2; sbit a3=ACC^3; sbit a4=ACC^4; sbit a5=ACC^5; sbit a6=ACC^6; sbit a7=ACC^7;

void clock_out(unsigned char dd) { ACC=dd;

clock_dat=a0;clock_clk=1;clock_clk=0; clock_dat=a1;clock_clk=1;clock_clk=0; clock_dat=a2;clock_clk=1;clock_clk=0;

clock_dat=a3;clock_clk=1;clock_clk=0; clock_dat=a4;clock_clk=1;clock_clk=0; clock_dat=a5;clock_clk=1;clock_clk=0; clock_dat=a6;clock_clk=1;clock_clk=0; clock_dat=a7;clock_clk=1;clock_clk=0; }

unsigned char clock_in(void) { clock_dat=1; a0=clock_dat;

clock_clk=1;clock_clk=0;a1=clock_dat; clock_clk=1;clock_clk=0;a2=clock_dat; clock_clk=1;clock_clk=0;a3=clock_dat; clock_clk=1;clock_clk=0;a4=clock_dat; clock_clk=1;clock_clk=0;a5=clock_dat; clock_clk=1;clock_clk=0;a6=clock_dat; clock_clk=1;clock_clk=0;a7=clock_dat; return(ACC); }

unsigned char read_clock(unsigned char ord) { unsigned char dd=0; clock_clk=0; clock_rst=0; clock_rst=1; clock_out(ord); dd=clock_in(); clock_rst=0; clock_clk=1; return(dd); }

void write_clock(unsigned char ord,unsigned char dd) { clock_clk=0; clock_rst=0; clock_rst=1; clock_out(ord); clock_out(dd); clock_rst=0; clock_clk=1; }

/*单个汉字库字摸提取程序,tc2.0编译*/ #i nclude \"stdio.h\" #i nclude \"dos.h\"

#i nclude \"process.h\" #i nclude \"string.h\"

void main(void) {

long int num_bytes,qm,wm;

unsigned char d,i,j,k,a[132],b[132]; unsigned char * data; unsigned char * hz;

static unsigned char dd[103]; FILE *fp;

if ((fp=fopen(\"hzk16f\ printf(\"can't open hzk16\\n\"); exit(1); }

clrscr(); while (1) {

data=(unsigned char *) malloc(33); printf(\"please input:\\n\");

scanf(\"%s\/*输入一个汉字*/

qm=* dd; /*通过区位码计算其在hzk16f文件中的偏移地址*/ qm=qm-161;

if (qm>87) exit(0); wm=* (dd+1); wm=wm-161;

if (wm>94) exit(0);

num_bytes=((long)qm*94+wm)*32; fseek(fp,num_bytes,SEEK_SET); fgets(data,33,fp);

for (i=0;i<32;i++) b[i]=* data++; for (i=0;i<32;i+=2) a[i/2]=b[i];

for (i=0;i<32;i+=2) a[i/2+16]=b[i+1]; for (i=8;i<16;i++) b[i]=a[i]; for (i=8;i<16;i++) a[i]=a[i+8]; for (i=8;i<16;i++) a[i+8]=b[i];

/*转换,hzf16f在电脑的储存格式是以行为字节计算的,一般的lcd都采用以列为字节计算*/

for (k=0;k<32;k+=8) { for (j=0;j<8;j++) { d=0;

for (i=0;i<8;i++) { if (a[i+k]>=0x80) { switch (i) {

case 0:d+=1;break; case 1:d+=2;break; case 2:d+=4;break; case 3:d+=8;break; case 4:d+=0x10;break; case 5:d+=0x20;break; case 6:d+=0x40;break; case 7:d+=0x80;break; } } }

for (i=0;i<8;i++) a[i+k]<<=1; b[j+k]=d; } }

clrscr();

printf(\"/*%s:*/\\n\/*输出0x00格式的16进制数*/ for (k=0;k<32;k+=8) {

for (j=0;j<8;j++) printf(\"0x%x,\ printf(\"\\n\"); }

getch(); } }

//按键扫描驱动程序

unsigned char key,key_h,kpush; unsigned int key_l;

//按键连接到p1.0、p1.1、p1.2 void int_t0(void) interrupt 1 { unsigned char dd,i;

TL0=TL0+30;TH0=0xfb; //800 /* 按键判别 */

if ((P1&0x7)==0x7) {

if ((key_l>30)&&(key_l<800)&&(key_h>30)) { //释放按键,如果之前按键时间少于1秒,读入键值 key=kpush; }

if ((++key_h)>200) key_h=200; key_l=0;

if (key>=0x80) key=0; //如果之前的按键为长按1秒,清除键值

} else {

kpush=P1&0x7; key_l++;

if ((key_l>800)&&(key_h>30)) { //如果按键超过1秒,键值加0x80标志长按键

key=kpush|0x80; key_h=0; key_l=0; } } }

void main(void) {

TMOD=0x1;TR0=1;ET0=1;EA=1; while (1) {

while (!key) {} switch (key) { case 1:break; case 2:break; } }

//串行驱动led显示,

//一个74hc595位移寄存器驱动三极管驱动led位,

//两个74hc595驱动led段,方式位5位x8段x2=10个数码管 //5分频,每次扫描时间位1.25ms

//定义特殊符号 #define nul 0xf #define qc 0xc #define qb 0xb #define q_ 0xa #define q__ 0xd #define q___ 0xe #define qp 0x10 #define qe 0x11 #define qj 0x12 #define qn 0x13 #define qf 0x14 #define qa 0x15 #define qr 0x16 #define qd 0x17 #define qu 0x18 #define ql 0x19

#define qh 0x1a #define qwen 0x1b #define qt 0x1c #define qla 0x1d #define qlb 0x1e #define qlc 0x1f #define qld 0x20 #define qle 0x21 #define qlf 0x22 #define qlg 0x23 #define qldp 0x24

//显示段信息,不同led排列组合的段信息只需更改8个数值即可。 //因此,该定义具有通用性。 // 显示

// -d 20

// |c 40 |e 10

// - g 80 // |b 2 |f 4

// _a1 .dp 8 #define pa 1 #define pb 2 #define pc 0x40 #define pd 0x20 #define pe 0x10 #define pf 4 #define pg 0x80 #define pdp 8

//--------------

#define l0 pdp+pg #define l1 255-pf-pe #define l2 pdp+pc+pf #define l3 pdp+pc+pb

#define l4 pdp+pa+pb+pd #define l5 pdp+pb+pe #define l6 pdp+pe

#define l7 pdp+pc+pg+pb+pa #define l8 pdp

#define l9 pdp+pb #define la pdp+pa

#define lb pdp+pd+pe

#define lc pdp+pg+pe+pf #define ld pdp+pc+pd #define le pdp+pe+pf #define lf pdp+pe+pf+pa #define l_ 255-pg #define lnul 255

#define ll pdp+pg+pd+pf+pe #define lp pdp+pa+pf #define lt pdp+pd+pe+pf

#define lr pdp+pe+pf+pg+pa #define ln pdp+pg+pa

#define lh pdp+pd+pe+pa #define ly pdp+pb+pd #define lu pdp+pg+pd

#define l__ pdp+pg+pb+pc+pe+pf #define l___ l__-pg #define l_1 255-pa #define l_2 255-pa-pg

#define lj 255-(pe+pf+pa)

#define lwen 255-(pd+pe+pg+pb) #define lall 0

#define lla 255-pa #define llb 255-pb #define llc 255-pc #define lld 255-pd #define lle 255-pe #define llf 255-pf #define llg 255-pg #define lldp 255-pdp

//串行送出的位信息,目前是10位led显示。

unsigned char code un_dig[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb}; //串行送出的短信息。

unsigned char code

un_disp[]={l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l_,lb,lc,l__,l___,lnul,lp,le,lj,ln,lf,la,lr,ld,lu,

ll,lh,lwen,lt,lla,llb,llc,lld,lle,llf,llg,lldp,lnul};

sbit d_clk=P0^0; //移位时钟

sbit d_dat=P0^1; //移位数据 sbit d_st=P0^2; //移位锁定

unsigned char dig; //位扫描计数器

unsigned char d[10]; //显示缓冲 //送出8位串行数据

void out_disp(unsigned char dd) { unsigned char i; for (i=0;i<8;i++) {

if (dd&1) d_dat=1; else d_dat=0; d_clk=0; dd>>=1; d_clk=1; } }

//控制小数点和闪烁,显示数据|0x040表示有小数点;显示数据|0x80表示闪烁。 void out_displ(unsigned char dd) { if (dd>=0x80) {

if (s001>flash_time) {out_disp(0xff);return;} }

dd&=0x7f;

if (dd>=0x40) {

dd=un_disp[dd&0x3f]^pdp; } else dd=un_disp[dd]; out_disp(dd); }

unsigned int s001; //闪烁时间参考 void int_t0(void) interrupt 1 { unsigned char dd;

TL0=TL0+30;TH0=0xfb; //800 time++;

if ((++s001)>=800) s001=0; // 显示

if ((++dig)>4) dig=0; d_st=0;

dd=d[dig+5]; out_displ(dd); dd=d[dig]; out_displ(dd);

out_disp(un_dig[dig]); d_st=1;

}

void main(void) { unsigned char i; TMOD=0x1; TR0=ET0=1; EA=1;

for (i=0;i<10;i++) d[i]=i; //display test while (1) {} }

STC 单片机中的eeprom写入和读取6位的10进制数需要进行数据类型转换吗?具体是怎样现的呢?

2013-06-04 10:24 dwsxfg | 分类:内存 | 浏览34次

分享到:

检举|2013-06-04 10:27 提问者采纳

6位10进制数,转换为16进制,再写入EEPROM. long x;

分4个字节写入

uchar c1;

c1= x>>24; //最高字节 c1=x>>16; //次高字节 c1=x>>8; //次低字节 c1=x&0xff; //最低字节

分别写入就可以了。

追问

我用的是stc12C5A60S2单片机,我将转化轩16进制的数保存在一个数组,然后整个数组写进去,当需要的时候再读出来还原成十进制数可否呢?

回答

当然可以。

追问

想了一下,不知应该如何用单片机C语言去实现啊,可以指导下不?

提问者评价

谢谢哈

一个牛人的关于STC的EEPROM的介绍(很不错)

***说明:相关内容来自网上,整理而成。转贴在此主要供参考学习用

单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM 中的数据是无

法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用EEPROM 或FLASHROM 等

存储器来实现。在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通

过IIC 或SPI 等接口来进行数据通信。这样不光会增加开发成本,同时在程序开发上也要花

更多的心思。在STC 单片机中内置了EEPROM(其实是采用IAP 技术读写内部FLASH 来

实现EEPROM),这样就节省了片外资源,使用起来也更加方便。下面就详细介绍STC 单

片机内置EEPROM 及其使用方法。

STC 各型号单片机内置的EEPROM 的容量各有不同,见下表: (内部EEPROM 可以擦写100000 次以上)

上面提到了IAP,它的意思是“在应用编程”,即在程序运行时程序存储器可由程序自

身进行擦写。正是是因为有了IAP,从而可以使单片机可以将数据写入到程序存储器中,使

得数据如同烧入的程序一样,掉电不丢失。当然写入数据的区域与程序存储区要分开来,以

使程序不会遭到破坏。

要使用IAP 功能,与以下几个特殊功能寄存器相关: ISP_DATA: ISP/IAP 操作时的数据寄存器。

ISP/IAP 从Flash 读出的数据放在此处,向Flash 写的数据也需放在此处 ISP_ADDRH:ISP/IAP 操作时的地址寄存器高八位。 ISP_ADDRL:ISP/IAP 操作时的地址寄存器低八位。

ISP_CMD: ISP/IAP 操作时的命令模式寄存器,须命令触发寄存器触发方可生效。

ISP_TRIG:ISP/IAP 操作时的命令触发寄存器。

当ISPEN(ISP_CONTR.7)=1 时,对ISP_TRIG 先写入0x46,再写入0xb9,ISP/IAP

命令才会生效。

单片机芯片型号起始地址内置EEPROM 容量(每扇区512 字节) STC89C51RC,STC89LE51RC 0x2000 共八个扇区 STC89C52RC,STC89LE52RC 0x2000 共八个扇区

STC89C54RD+,STC89LE54RD+ 0x8000 共五十八个扇区 STC89C55RD+,STC89LE55RD+ 0x8000 共五十八个扇区 STC89C58RD+,STC89LE58RD+ 0x8000 共五十八个扇区 寄存器标识地址名称7 6 5 4 3 2 1 0 初始值

ISP_DATA 0xE2 ISP/IAP闪存数据寄存器11111111 ISP_ADDRH 0xE3 ISP/IAP 闪存地址高位00000000 ISP_ADDRL 0xE4 ISP/IAP 闪存地址低位00000000 ISP_CMD 0xE5 ISP/IAP闪存命令寄存器MS2 MS1 MS0 xxxxx000

ISP_TRIG 0xE6 ISP/IAP 闪存命令触发xxxxxxxx

ISP_CONTR 0xE7 ISP/IAP 控制寄存器ISPEN SWBS SWRST WT2 WT1 WT0 00xx000

B7 B6 B5 B4 B3 B2 B1 B0 命令/操作模式选择 保留命令选择

- - - - - 0 0 0 待机模式,无ISP/IAP 操作

- - - - - 0 0 1 对用户的应用程序Flash 区及数据Flash 区字节读 - - - - - 0 1 0 对用户的应用程序Flash 区及数据Flash 区字节编程 - - - - - 0 1 1 对用户的应用程序Flash 区及数据Flash 区扇区擦除 ISP_CONTR:ISP/IAP 控制寄存器。

ISPEN:ISP/IAP 功能允许位。0:禁止ISP/IAP 编程改变Flash,1:允许编程改变Flash

SWBS:软件选择从用户主程序区启动(0),还是从ISP 程序区启动(1)。 SWRST:0:不操作,1:产生软件系统复位,硬件自动清零。

ISP_CONTR 中的SWBS 与SWRST 这两个功能位,可以实现单片机的软件启动,并

启动到ISP 区或用户程序区,这在“STC 单片机自动下载”一节,亦有所应用。 如:

ISP_CONTR=0x60? 则可以实现从用户应用程序区软件复位到ISP 程序区开始运行 程序。

ISP_CONTR=0x20? 则可以实现从ISP 程序区软件复位到用户应用程序区开始运行 程序。

用IAP 向Flash 中读写数据,是需要一定的读写时间的,读写数据命令发出后,要等待

一段时间才可以读写成功。这个等待时间就是由WT2、WT1、WT0 与晶体振荡器频率决定 的。

(以上的建议时钟是(WT2、WT1、WT0)取不同的值时的标称时钟,用户系统中的时钟

不要过高,否则可能使操作不稳定。)

stc单片机EEPROM读写(一)

EEPROM 操作函数:

#define RdCommand 0x01 #define PrgCommand 0x02 #define EraseCommand 0x03 #define Error 1 #define Ok 0

#define WaitTime 0x01 #define PerSector 512

unsigned char xdata Ttotal[512]? /*

打开ISP,IAP 功能 */

void ISP_IAP_enable(void) D7 D6 D5 D4 D3 D2 D1 D0

ISPEN SWBS SWRST - - WT2 WT1 WT0 设置等待时间CPU 等待时间(机器周期)

WT2 WT1 WT0 读取编程扇区擦除建议的系统时钟 0 1 1 6 30 5471 5MHz 0 1 0 11 60 10942 10MHz 0 0 1 22 120 21885 20MHz 0 0 0 43 240 43769 40MHz {

EA=0?/* 关中断*/

ISP_CONTR|=0x18?/*0001,1000*/

ISP_CONTR|=WaitTime?/*写入硬件延时*/ ISP_CONTR|=0x80?/*ISPEN=1*/ } /*

关闭ISP,IAP 功能 */

void ISP_IAP_disable(void) {

ISP_CONTR&=0x7f?/* ISPEN = 0 */ ISP_TRIG=0x00? EA=1?/* 开中断*/ } /*

公用的触发代码 */

void ISPgoon(void) {

ISP_IAP_enable()?/* 打开ISP,IAP 功能*/

ISP_TRIG=0x46?/* 触发ISP_IAP 命令字节1 */ ISP_TRIG=0xb9?/* 触发ISP_IAP 命令字节2 */ _nop_()? } /*

字节读 */

unsigned char byte_read(unsigned int byte_addr) {

ISP_ADDRH=(unsigned char)(byte_addr>>8)? /* 地址赋值*/ ISP_ADDRL=(unsigned char)(byte_addr&0x00ff)? ISP_CMD&=0xf8? /* 清除低3 位*/

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&=0xf8?/* 清空低3 位*/

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&=0xf8?/* 清低3 位*/

ISP_CMD|=PrgCommand?/* 写命令2*/ ISP_DATA=original_data?/* 写入数据准备*/ ISPgoon()?/* 触发执行*/

ISP_IAP_disable()?/* 关闭IAP 功能*/

} /*

字节写并校验 */

unsigned char byte_write_verify(unsigned int byte_addr, unsigned char original_data) {

ISP_ADDRH=(unsigned char)(byte_addr>>8)? /* 取地址*/ ISP_ADDRL=(unsigned char)(byte_addr&0xff)? ISP_CMD&=0xf8?/* 清低3 位*/

ISP_CMD|=PrgCommand?/* 写命令2*/ ISP_DATA=original_data? ISPgoon()?/* 触发执行*/

/* 开始读,没有在此重复给地址,地址不会被自动改变*/ ISP_DATA=0x00?/* 清数据传递寄存器*/ ISP_CMD&=0xf8?/* 清低3 位*/

ISP_CMD|=RdCommand?/* 读命令1*/

ISP_TRIG=0x46?/* 触发ISP_IAP 命令字节1 */ ISP_TRIG=0xb9?/* 触发ISP_IAP 命令字节2 */ _nop_()?/* 延时*/

ISP_IAP_disable()?/* 关闭IAP 功能*/

if(ISP_DATA==original_data)/* 读写数据校验*/ return Ok?/* 返回校验结果*/ else

return Error? } /*

数组写入 */

unsigned char arraywrite(unsigned int begin_addr, unsigned int len, unsigned char *array) {

unsigned int i?

unsigned int in_addr?

/* 判是否是有效范围,此函数不允许跨扇区操作*/ if(len > PerSector) return Error?

in_addr = begin_addr & 0x01ff?/* 扇区内偏移量*/ if((in_addr+len)>PerSector) return Error?

in_addr = begin_addr? /* 逐个写入并校对*/

ISP_IAP_enable()?/* 打开IAP 功能*/

for(i=0?i/* 写一个字节*/

ISP_ADDRH=(unsigned char)(in_addr >> 8)? ISP_ADDRL=(unsigned char)(in_addr & 0x00ff)? ISP_DATA=array[i]? /* 取数据*/ ISP_CMD&=0xf8?/* 清低3 位*/

ISP_CMD|=PrgCommand?/* 写命令2 */

ISP_TRIG=0x46?/* 触发ISP_IAP 命令字节1 */ ISP_TRIG=0xb9?/* 触发ISP_IAP 命令字节2 */ _nop_()? /* 读回来*/

ISP_DATA=0x00?

ISP_CMD&=0xf8?/* 清低3 位*/

ISP_CMD|=RdCommand?/* 读命令1*/

ISP_TRIG=0x46?/* 触发ISP_IAP 命令字节1 */ ISP_TRIG=0xb9?/* 触发ISP_IAP 命令字节2 */ _nop_()? /* 比较对错*/

if(ISP_DATA!=array[i]) {

ISP_IAP_disable()? return Error? }

in_addr++?/* 指向下一个字节*/ }

ISP_IAP_disable()? return Ok? } /*

扇区读出 */

/* 程序对地址没有作有效性判断,请调用前事先保证他在规定范围内*/ void arrayread(unsigned int begin_addr, unsigned char len) {

unsigned int iSectorAddr? unsigned int i?

iSectorAddr = begin_addr? // & 0xfe00? /* 取扇区地址*/ ISP_IAP_enable()? for(i=0?iISP_ADDRH=(unsigned char)(iSectorAddr>>8)?

ISP_ADDRL=(unsigned char)(iSectorAddr & 0x00ff)? ISP_CMD&=0xf8?/* 清低3 位*/

ISP_CMD|=RdCommand?/* 读命令1*/ ISP_DATA=0?

ISP_TRIG=0x46?/* 触发ISP_IAP 命令字节1 */ ISP_TRIG=0xb9?/* 触发ISP_IAP 命令字节2 */ _nop_()?

Ttotal[i]=ISP_DATA? iSectorAddr++? }

ISP_IAP_disable()?/* 关闭IAP 功能*/ }

主函数对EEPROM 操作函数进行调用: #include #include

#include #include int i?

void delay(unsigned int time) {

while(time) ? }

void main() {

_ADOS(22.1184)? //ADOS 自动下载 //for(i=0?i<100?i++) //{

//Ttotal[i]=i? //}

//arraywrite(0x8000,100,Ttotal)? /*

第一次运行时向EEPROM 中写入数据 然后再将写入函数注释掉,将先前写 入的数据读出,输出在P2 口上。 */

arrayread(0x8000,100)? for(i=0?i<100?i++) {

P2=~Ttotal[i]? delay(10000)? }

while(1)? }

stc单片机EEPROM读写(二)

sfr isp_data=0xe2; sfr isp_addrh=0xe3; sfr isp_addrl=0xe4; sfr isp_cmd=0xe5; sfr isp_trig=0xe6; sfr isp_contr=0xe7;

unsigned char eeprom_read(unsigned int addres);

void eeprom_write(unsigned int address,unsigned char wdata); void eeprom_eares(unsigned int addres);//扇区擦除。 void eeprom_eares(unsigned int addres)//扇区擦除。 {unsigned i;

isp_addrl=addres; //低位地址 isp_addrh=addres>>8; //高位地址 isp_contr=0x01;

isp_contr=isp_contr|0x80; //设时间与充ISP操作。 isp_cmd=0x03; //扇区命命令 isp_trig=0x46; //触发

isp_trig=0xb9; //触发启动。 for(i=0;i<3;i++); isp_addrl=0xff; isp_addrh=0xff; isp_contr=0x00; isp_cmd=0x00; isp_trig=0x00;

}

void eeprom_write(unsigned int addres,unsigned char write_data)//写数据。 {unsigned char i;

isp_data=write_data; //要写入的数据。 isp_addrl=addres; //低位地址 isp_addrh=addres>>8; //高位地址 isp_contr=0x01;

isp_contr=isp_contr|0x80; //设时间与充ISP操作。 isp_cmd=0x02; //写命令 isp_trig=0x46; //触发

isp_trig=0xb9; //触发启动。 for(i=0;i<3;i++); isp_addrl=0xff; isp_addrh=0xff; isp_contr=0x00; isp_cmd=0x00; isp_trig=0x00; }

unsigned char eeprom_read(unsigned int addres) {unsigned char i,z;

isp_addrl=addres; //低位地址 isp_addrh=addres>>8; //高位地址 isp_contr=0x01;

isp_contr=isp_contr|0x80; //设时间与充ISP操作。 isp_cmd=0x01; //写命令 isp_trig=0x46; //触发

isp_trig=0xb9; //触发启动。 for(i=0;i<3;i++); isp_addrl=0xff; isp_addrh=0xff; isp_contr=0x00; isp_cmd=0x00; isp_trig=0x00; z=\"isp\"_data; return(z); }

stc单片机EEPROM读写(三)

;;; 内部EEPROM读写定义

ISP_DATA EQU 0E2H ;写入读出数据寄存器. ISP_ADDRH EQU 0E3H ;地址寄存器高8位 ISP_ADDRL EQU 0E4H ;地址寄存器低8位 ISP_CMD EQU 0E5H ;命令模式寄存器 ISP_TRIG EQU 0E6H ;命令触发寄存器

ISP_CONTR EQU 0E7H ;ISP/IAP控制寄存器. ISP_IAP_BYTE_READ EQU 1 ;字节读

ISP_IAP_BYTE_PROGRAM EQU 2 ;字节编程,要空才能写 ISP_IAP_SECTOR_ERASE EQU 3 ;扇区擦除, WAIT_TIME EQU 1 ;20M以下为1 BYTE_ADDR_HIGH EQU 60H ;高位地址 BYTE_ADDR_LOW EQU 61H ;低位地址

BYTE_WRITE_DATA EQU 62H ;要写入的数据

;***********************内部EEPROM操作************************* READ_EEPROM:MOV ISP_ADDRH,ISP_ADDRH ;送高地址 MOV ISP_ADDRL,ISP_ADDRL ;送低地址 MOV ISP_CONTR,#01h ;设置等等待时间 ORL ISP_CONTR,#80h ;允许ISP/IAP操作 MOV ISP_CMD,#01h ;送读命令 MOV ISP_TRIG,#46H ;触发

MOV ISP_TRIG,#0B9H ;触发启动.

NOP NOP

MOV ISP_CONTR,#00H MOV ISP_CMD,#00H MOV ISP_TRIG,#00H MOV ISP_ADDRH,#0FFH MOV ISP_ADDRL,#0FFH

MOV 6AH,ISP_DATA ;读出的数据放到6AH单元中。 RET

WRITE_EARES: MOV WDT,#34H CLR EA ;关中断

MOV ISP_ADDRH,ISP_ADDRH ;送高地址 MOV ISP_ADDRL,ISP_ADDRL ;送低地址 MOV ISP_CONTR,#1h ;设置等等待时间

ORL ISP_CONTR,#10000000B ;允许ISP/IAP操作 MOV ISP_CMD,#3h ;送扇区命令 MOV ISP_TRIG,#46H ;触发

MOV ISP_TRIG,#0B9H ;触发启动. NOP NOP

MOV ISP_CONTR,#00H MOV ISP_CMD,#00H MOV ISP_TRIG,#00H MOV ISP_ADDRH,#0FFH MOV ISP_ADDRL,#0FFH SETB EA RET

WRITE_EEPROM:MOV WDT,#34H CLR EA

MOV ISP_DATA,BYTE_WRITE_DATA ;要写入的数据 MOV ISP_ADDRH,ISP_ADDRH ;送高地址 MOV ISP_ADDRL,ISP_ADDRL ;送低地址 MOV ISP_CONTR,#1h ;设置等等待时间

ORL ISP_CONTR,#10000000B ;允许ISP/IAP操作 MOV ISP_CMD,#02h ;送写命令 MOV ISP_TRIG,#46H ;触发

MOV ISP_TRIG,#0B9H ;触发启动. NOP NOP

MOV ISP_CONTR,#00H MOV ISP_CMD,#00H MOV ISP_TRIG,#00H MOV ISP_ADDRH,#0FFH

MOV ISP_ADDRL,#0FFH

SETB EA ;开中断 RET

STC内部EEPROM怎么存入多组数据

用“ 数组 ”或者“ 结构体 ”

【 数组 】例如:

uint8 BUF; uint8 N;

EROM_C( 1 ); //擦除扇区1(0x0200 ~ 0x02FF)

EROM_W_8( 0x0230, BUF, 100 ); //将数组BUF依次写入EEPROM从0x0230开始的连续100个单元

EROM_R_8( 0x0230, BUF, 100 ); //读出EEPROM从0x0230开始的连续100个单元写入数组BUF

EROM_R_8( 0x0290, N, 10 ); //读出EEPROM从0x0290开始的连续10个单元写入数组N

【 结构体 】例如:

struct STR_1 {

uint8 sec; uint8 min; uint8 hour; uint8 day; uint8 month; uint8 week; uint8 year; } data NOW;

EROM_C( 0 ); //擦除扇区0(0x0000 ~ 0x01FF)

EROM_W_8( 0x0000, &NOW.sec, 7 ); //将结构体中的秒、分、时、日、月、星期、年这7个数据依次写入EEPROM从0x0000开始的连续7个单元

EROM_R_8( 0x0000, &NOW.sec, 7 ); //读出EEPROM从0x0000开始的连续7个单元写入结构体

具体程序:STC通用EEPROM操作函数(通杀1T、12T系列所有型号,支持连续读/写)

因篇幅问题不能全部显示,请点此查看更多更全内容