51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机源码 > 详细内容
x5045的读写程序(汇编)
发布时间:2009/6/4  阅读次数:693  字体大小: 【】 【】【

发布者:  未知     来源:网络

X25045是带有串行E2PROM的CPU监控器。现在型号改为X5045,性能相同

图2是它的引脚图:

CS/WDI:片选输入/看门狗复位输入;

SO:串行输出;

WP:写保护输入;

Vss:地;

Vcc:电源;

RESET:复位输出;

SCK:同步时钟输入;

SI:串行输入。

X25045的状态寄存器描述器件的当前状态,各位意义如表1所列。

表1

7 6 5 4 3 2 1 0
0 0 WD1 WD0 BL1 BL0 WEL WIP

其中,WD1、WD0是看门狗定时时间设置位;BL1、BL0是存储单元写保护区设置位;WEL是只读标志,1表明写使能开关打开;WIP也是只读标志,1代表芯片内部正处于写周期。电复位时,各位都被清零。

X25045芯片功能包括以下4种:

(1)上电复位控制。在对X25045通电时,ERSET引脚输出有效的复位信号,并保持至少200ms,使CPU有效复位。

(2)电源电压监控。当检测到电源电压低于内部门槛电压VTRIP时,RESET输出复位信号,直至电源电压高于VTRIP并保持至少200ms,复位信号才被撤消。VTRIP的出厂值根据芯片型号不同共有5个级别的电压范围。对于需要电源电压精确监控的应用,用户可以搭建编程电路,对芯片内VTRIP电压进行微调。

(3)看门狗定时器。芯片内部状态寄存器的WD1、WD0是看门狗定时设置位,通过状态寄存器写指令WRSR修改这2个标志位,就能在3种定时间隔中进行选择或关闭定时器。对看门狗的复位由CS输入电平的下降沿完成。表2是WD1、WD0组合的含义。

表2

WD1 WD0 看门狗定时值
0 0 1.4s
0 1 600ms
1 0 200ms
1 1 禁止看门狗工作

(4)串行E2PROM。芯片内含512字节存储单元,10万次可靠写,数据保持时间100年。XICOR设计了3种保护方式防止误写。包括:WP写保护引脚,当引脚被拉低时,内部存储单元状态寄存器都禁止写入;存储区域写保护模式,通过对状态寄存器的BL1、BL0位的设置,可以选择对不同的存储区域进行写保护;在进行任何写操作前都必须打开写使能开关,而且在上电初始化写操作完成时,写使能开关自动关闭。显然,在几方面的保护之下,产生误写的可能性极小,表 3是BL1、BL0组合的含义。

表3

BL1 BL0 写保护的单元地址
0 0 没有保护
0 1 180H~1FFH
1 0 100H~1FFH
1 1 000H~1FFH

对X25045的操作是通过4根口线CS、SCK、SI和SO进行同步串行通信来完成的。SCK是外部输入的同步时钟信号。在对芯片定改指令或数据时,时钟前沿将SI引脚信号输入;在读邮数据时,时钟后沿将数据位输出到SO引脚上。数据的输入/输出都是高位在先。

芯片内部共有6条指令,如表4所列。

表4

命令名称 命令格式 内 容
WREN 0000 0110 打开写使能开关
WRDI 0000 0100 关闭写使能开关
RDSR 0000 0101 读状态寄存器
WRSR 0000 0001 写状态寄存器
READ 0000 A8011 读存储单元
WRITE 0000 A8010 写存储单元

(1)WREN和WRDI是写使能开关的开/关指令。它们都是单字节指令。

(2)RDSR和WRSR是状态寄存器的读/写指令。在从SI输入指令后,RDSR的执行结果,即状态寄存器内容须从SO读出;而WRSR需要紧接着输入修改数据。

(3) READ和WEITE是存储单元的读/写指令。输入指令后(指令码第三代表存储单元地址的最高位),接着输入低八位地址,最后就可以连续读出或写入数据。其中,读指针和写指针的工作方式完全不同,读指针的全部8位用来计数,0FFH溢出后变成00H;写指针只用最低两位计数,XXXXXX11B溢出后变成 XXXX XX00B,所以连续写的实际结果是在4个单元中反复写入。另外,由于E2PROM的写入时间长,所以在连续两条写指令之间应读取WIP状态,只有内部写周期结束时才可输入下一条写指令。

AT89C2051内部没有SPI接口硬件,因此本系统利用了单片机的4根口线和软件模拟读写时序的方式与X25045通信。软件包在文末给出。

;1)读指定地址的内容
;开机后,LED数码管以十六进制形式显示一个数字
;按下S1键或S2键,LED数码管上显示的数字加1或减1
;该数字表示的是待读的X5045中存储器单元的地址,
;按下S4键,读出该单元的内容,并且以十六进制的形式显示在LED数码管上。
2)将值写入指定单元
;开机后,P1.0所接LED点亮,此时,可以按S1或S2,使LED数码管显示至待写入单元的地址值,
;然后按下S3键,该地址值被记录,P1.1所接LED亮,按S1或S2,
;LED数码管以十六进制形式显示待写入的数据,按下S4键,该数据被写入刚才指定的EEPROM单元中。

CS BIT P2.4 ;
SI BIT P2.2 ;
SCK BIT P2.3 ;
SO BIT P2.0 ;
WP BIT P2.1 ;

WREN_INST EQU 06H ;写允许命令字(WREN)
WRDI_INST EQU 04H ;写禁止命令字(WRDI)
WRSR_INST EQU 01H ;写状态寄存器命令字(WRSR)
RDSR_INST EQU 05H ;读状态寄存器命令字(RDSR)
WRITE_INST EQU 02H ;写存储器命令字 (WRITE)
READ_INST EQU 03H ;读存储器命令字 (READ)
MAX_POLL EQU 99H ;测试的最大次数

WDT200 EQU 90H ;WD1 WD0=01
WDT600 EQU 0A0H;WD1 WD0=10
WDT1400 EQU 80H ;如果最高位是1代表设置看门狗WD1 WD0 =00
NOWDT EQU 0B0H;WD1 WD0=11
PROQTR EQU 04H ;BL1 BL0=01保护区域为高128字节
PROHALF EQU 08H ;BL1 BL0=10写保护区域为高256字节
PROALL EQU 0CH ;BL1 BL0=11写保护区域为整个存储器
NOPRO EQU 00H ;如果最高位是0,代表设置保护区域 BL1 BL0=00,不写保护

KMARK BIT 00H ;有键被按着
KFIRST BIT 01H ;第一次
KFUNC BIT 02H ;代表两种功能
KENTER BIT 03H ;代表执行S4键的操作
KS12 BIT 04H ;S1 S2两个键被按下
KFUNC1 BIT 05H
KCOUNT EQU 21H ;统计次数
COUNT EQU 22H
COUNTER EQU 23H ;用于显示的计数器
MTD EQU 30H ;发送数据缓冲区
MRD EQU 30H ;接收数据缓冲区
NUMBYT EQU 2FH ;传送字节数存放单元
STATBYT EQU 2FH ;状态字节存放单元
DATAADDR EQU 2DH ;该单元及DATAADDR+1是待操作的EEPROM的地址单元,该位存入高1位地址,ADDRDATA+1单元存入低8位地址
FIRST EQU P2.7;第一位数码管的位控制
SECOND EQU P2.6;第二位数码管的位控制
DISPBUF EQU 5EH ;5E,5FH是显示缓冲区
TMRVAR EQU 60110;65536-5000*12/11.0592 定时器初值5毫秒


ORG 0
JMP START
ORG 0BH
JMP INT_T0
ORG 30H
START:
MOV SP,#5FH
CALL INIT_T0
SETB P2.0
SETB CS
SETB SO
CLR SCK
CLR SI ;初始化
MOV 20H,#0 ;复位所有标志
CLR A
MOV COUNT,A
MOV KCOUNT,A
MOV COUNTER,A
MOV P1,#11111110B ;点亮"读"控制灯
MOV A,COUNT
CALL CALC
SETB CS
SETB SO
CLR SCK
CLR SI ;初始化
SETB EA
LOOP:
JB KS12,MAIN_0
JMP MAIN_1
MAIN_0:
MOV A,COUNT
CALL CALC
MAIN_1:
JB KFUNC,MAIN_2 ;如果是第二功能(写)转
MOV P1,#11111110B ;否则点亮LED1
MOV DATAADDR,#0 ;在本应用中,高位地址始终为0
MOV DATAADDR+1,COUNT;将计数值送到地址寄存器中
JMP MAIN_3
MAIN_2:
MOV P1,#11111101B ;点亮LED2
MOV R0,#MTD
MOV A,COUNT
MOV @R0,A ;将计数值送入数值寄存器中
MAIN_3:
JB KENTER,MAIN_4 ;如果有回车键,转
JMP LOOP ;否则回去继续循环
MAIN_4:
JB KFUNC,MAIN_5 ;如果是第二功能,转
CLR P1.7 ;点亮D8,显示命令被正确执行
MOV NUMBYT,#1 ;读出1个字节
CALL READ_DATA ;读数据存于MRD开始的缓冲区
MOV R0,#MRD
MOV A,@R0
MOV COUNT,A ;送到计数器中
CALL CALC ;调用计算显示程序
CLR KENTER ;清回车标记
CALL DELAY
SETB P1.7
JMP LOOP ;继续循环
MAIN_5:
SETB WP ;
CLR P1.7 ;点亮D8,显示命令被正确执行
MOV NUMBYT,#1 ;写入1个字节
CALL WRITE_DATA ;将数据写入EEPROM
CLR KENTER
CLR WP
CALL DELAY
SETB P1.7
JMP LOOP
;主程序到此结束

DELAY:
MOV R7,#0FFH
D1: MOV R6,#0FFH
DJNZ R6,$
DJNZ R7,D1
RET

CALC:
MOV B,#16
DIV AB
MOV DISPBUF,A
MOV DISPBUF+1,B
RET
INIT_T0: ;初始化T0为5毫秒的定时器
MOV TMOD,#01H
MOV TH0,#HIGH(TMRVAR)
MOV TL0,#LOW(TMRVAR)
SETB ET0 ;开T0中断
SETB TR0 ;定时器0开始运行
RET ;返回

;以下是中断程序,实现显示及键盘处理
INT_T0: ;定时器T0的中断响应程序
PUSH ACC ;ACC入栈
PUSH PSW ;PSW入栈
SETB RS0 ;用第二组工作寄存器
MOV TH0,#HIGH(TMRVAR) ;
MOV TL0,#LOW(TMRVAR)
SETB FIRST
SETB SECOND ;关显示
MOV A,#DISPBUF ;显示缓冲区首地址
ADD A,COUNTER
MOV R0,A
MOV A,@R0 ;根据计数器的值取相应的显示缓冲区的值
MOV DPTR,#DISPTAB ;字形表首地址
MOVC A,@A+DPTR ;取字形码
MOV P0,A ;将字形码送P0位(段口)
MOV A,COUNTER ;取计数器的值
JZ DISPFIRST ;如果是0则显示第一位
CLR SECOND ;否则显示第二位
AJMP DISPNEXT
DISPFIRST:
CLR FIRST ;显示第一位
DISPNEXT:
INC COUNTER ;计数器加1
MOV A,COUNTER
DEC A ;如果计数器计到2,则让它回0
DEC A
JZ RSTCOUNT
AJMP KEY
RSTCOUNT:
MOV COUNTER,#0 ;计数器的值只能是0或1
KEY:
ORL P3,#00111100B
MOV A,P3
ORL A,#11000011B
CPL A
JZ NO_KEY ;无键按下,返回
JNB KMARK,KEY_1 ;键按下标志有效吗(无效转)?
DEC KCOUNT ;键值计数器减1
MOV A,KCOUNT
JNZ INT_EXIT ;如果是0,退出中断
JNB P3.2,KEY_S1 ;S1键按下
JNB P3.3,KEY_S2 ;S2键按下
JNB P3.4,KEY_S3 ;S3键按下
JNB P3.5,KEY_S4 ;S4键搂下
JMP NO_KEY ;无键按下
KEY_1:
MOV KCOUNT,#4
SETB KMARK
JMP INT_EXIT
KEY_S1:
INC COUNT
SETB KS12
JMP KEY_2
KEY_S2:
DEC COUNT
SETB KS12
JMP KEY_2
KEY_S3:
JB KFUNC1,KEY_S31
CPL KFUNC ;如果KFUNC=0,代表第一种功能,KFUNC=1,第二种功能
SETB KFUNC1
KEY_S31:
CLR KS12
JMP KEY_2
KEY_S4:
SETB KENTER ;如果该位是1,则根据KFUNC分别执行读或写的操作
CLR KS12
KEY_2:
JNB KFIRST,KEY_3 ;如果无效,转
MOV KCOUNT,#20
JMP INT_EXIT
KEY_3:
MOV KCOUNT,#200
SETB KFIRST
JMP INT_EXIT
NO_KEY:
CLR KMARK
CLR KFIRST
CLR KFUNC1
MOV KCOUNT,#0
INT_EXIT:
POP PSW
POP ACC
RETI

DISPTAB: DB 28H,7EH,0A4H,64H,72H,61H,21H,7CH,20H,60H,30H,23H,0A9H,26H,0A1H,0B1H,0FFH

;名称:写数据,将数据缓冲区的数据写入指定的地址
;描述:MTD指定数据缓冲区首地址,NUMBYT指定字节数,DATAADDR及DATAADDR+1指定被写器件地址
;不允许跨页
;使用资源:R0,R1,A,B
;数据写完,全部存储单元处于保护状V态
WRITE_DATA:
MOV R0,#DATAADDR ;地址单元的高8位
MOV A,@R0
MOV DPH,A
INC R0
MOV A,@R0
MOV DPL,A
MOV R1,NUMBYT ;从传送字节数存元中获取待写字节数
MOV R0,#MTD ;待写数据缓冲区
W_L:
SETB WP;
CALL WREN_CMD ;写允许
CLR SCK ;将SCK拉低
CLR CS ;将/CS拉低
MOV A, #WRITE_INST
MOV B, DPH
MOV C, B.0
MOV ACC.3, C
LCALL OUTBYT ;送出含有地址最高位的写指令
MOV A, DPL
LCALL OUTBYT ;送出地址的低8位
MOV A, @R0
LCALL OUTBYT ;送出数据
CLR SCK ;将SCK拉低
SETB CS ;升高/CS
LCALL WIP_POLL ;测试是否已器件内部是否写完
INC DPL
INC R0
DJNZ R1,W_L
MOV STATBYT,#PROALL ;状态存放单元
CALL SET_STATUS ;整个存储器均被保护
RET
;名称:读数据,把指定地址单元中的数据读入数据缓冲区
;描述:MRD指定数据缓冲区首地址,NUMBYT指定字节数,DATAADDR及DATAADDR+1指定被写器件地址
;使用资源:B,R0,DPTR
;不允许跨页
READ_DATA:
MOV R0,#DATAADDR ;地址单元的高8位
MOV A,@R0
MOV DPH,A
INC R0
MOV A,@R0
MOV DPL,A
MOV R1,NUMBYT ;从传送字节数存元中获取待写字节数
MOV R0,#MRD ;待读数据缓冲区
R_L:
CLR SCK ; 将SCK拉低
CLR CS ; 将/CS拉低
MOV A, #READ_INST
MOV B, DPH
MOV C, B.0
MOV ACC.3, C
LCALL OUTBYT ; 送出含有地址最高位的读指令
MOV A, DPL
LCALL OUTBYT ;送出低8位地址
LCALL INBYT ; 读数据
CLR SCK ; 将SCK拉低
SETB CS ;升高/CS
MOV @R0,A
INC R0
INC DPL
DJNZ R1,R_L
RET
;名称;SET_STATUS  
;7 6 5 4 3 2 1 0
;0 0 WD1 WD0 BL1 BL0 WEL WIP
;如果需要设置保护和看门狗,需分两次进行
;STATBYT传递参数,共8个预定义常量
;资源使用:R0,R1,A,B
SET_STATUS:
CALL RDSR_CMD ;读当前寄存器的状态,在A中
MOV B,A ;存入B
MOV A,STATBYT ;读入参数
JB ACC.7,SET_WDT ;如果最高位是1则转设置看门狗
MOV C,ACC.2 ;否则是设置保护区域
MOV B.2,C
MOV C,ACC.3
MOV B.3,C
JMP WRITE_STATUS
SET_WDT:
MOV C,ACC.4
MOV B.4,C
MOV C,ACC.5
MOV B.5,C
WRITE_STATUS:
CLR SCK ;将SCK拉低
CLR CS ;将/CS拉低
MOV A, #WRSR_INST
LCALL OUTBYT ;送出 WRSR 指令
MOV A, B
LCALL OUTBYT ;送出状态寄存器的状态
CLR SCK ;将SCK拉低
SETB CS ;升高/CS
LCALL WIP_POLL ;测试是否已器件内部是否写完
RET
;名称:WREN_CMD
;描述:写允许
;功能:这段程序发送命令允许写存储器单元和状态寄存器
;调用子程序: OUTBYT
;输入:没有
;输出:没有
;寄存器使用:A
WREN_CMD:
CLR SCK ;将SCK拉低
CLR CS ;将 /CS 拉低
MOV A, #WREN_INST
LCALL OUTBYT ;送出WREN_INST指令
CLR SCK ;将SCK拉低
SETB CS ;将 /CS 升高
RET
;名称:WRDI_CMD
;描述:写禁止
;功能:这段程序发送命令禁止对存储单元和状态寄存器写
;调用子程序:OUTBYT
;输入:无
;输出:无
;寄存器使用:A
WRDI_CMD:
CLR SCK ;将SCK拉低
CLR CS ;将/CS拉低
MOV A, #WRDI_INST
LCALL OUTBYT ;送出WRDI指令
CLR SCK ;将SCK拉低
SETB CS ;升高/CS
RET
;名称:RDSR_CMD
;描述:读状态寄存器
;功能:本程序发送命令用以读状态寄存器
;调用子程序:OUTBYT, INBYT
;输入:无
;输出:A= 状态寄存器
;寄存器使用:A
RDSR_CMD:
CLR SCK ;将SCK拉低
CLR CS ;将/CS拉低
MOV A, #RDSR_INST
LCALL OUTBYT ;发送 RDSR 指令
LCALL INBYT ;读状态寄存器
CLR SCK ;将SCK拉低
SETB CS ;升高/CS
RET
;名称:RST_WDOG
;描述:复位看门狗定时器
;功能:这段程序用来复位看门狗定时器,不发送命令
;调用子程序:无
;输入:无
;输出:无
;寄存器使用:无
RST_WDOG:
CLR CS ;将 /CS 拉低
SETB CS ;将 /CS 升高
RET

;名称: WIP_POLL
;描述: 器件内部编程检查
;功能:本程序通过检查WIP位来确定X5045内部编程是否结束
;子程序调用: RDSR_CMD
;输入:无
;输出:无
;寄存器使用: R3, A

WIP_POLL:
MOV R3, #MAX_POLL ;设置用于偿试的最大次数
WIP_POLL1:
LCALL RDSR_CMD ;读状态寄存器
JNB ACC.0, WIP_POLL2;如果WIP 位是 '0' 说明内部的写周期完成了
DJNZ R3, WIP_POLL1 ;如果WIP 位是 '1'说明内部写周期还没有完成
WIP_POLL2:
RET

;名称: OUTBYT
;描述:将一个字节送到EEPROM
;功能:本段程序移位送出一个字节,从最高位开始送PROM
;调用子程序:无
;输入:A = 待送的字节
;输出:无
;寄存器使用: R2, A

OUTBYT:
MOV R2, #08 ;设置位计数(共8位)
OUTBYT1:
CLR SCK ;将SCK拉低
RLC A ;带进位位的左移位
MOV SI, C ;送出进位位
SETB SCK ;将 SCK 升高
DJNZ R2, OUTBYT1 ;循环8次
CLR SI ;将SI置于已知的状态
RET

;名称: INBYT
;描述:从EEPROM中接收数据
;功能:这段程序从EEPROM中接收数据,高位在先
;调用子程序:无
;输入:无
;输出:A = 接收到的数据
;寄存器使用:R2, A

INBYT:
MOV R2, #08 ;设置计数(共8位)
INBYT1:
SETB SCK ;将 SCK 升高
CLR SCK ;将SCK拉低
MOV C, SO ;将输出线的状态读到进位位
RLC A ;带进位位的循环左移
DJNZ R2, INBYT1 ;循环8次
RET
END

  

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号