📄 wds1620.asm
字号:
;参考程序B:WDS1620.ASM 数字式温度传感器DS1620实验DALLAS( 串行三线接口)
; WDS1620.ASM 数字温度传感器DS1620测温实验:P0.2接DQ位 P0.3接 CLK位,P0.4接RST位
;数字式温度传感器DS1620配有DALLAS( 串行三线接口)
;用DS1620测量温度,用SAA1064驱动四位数码管显示温度值:012.5℃
;设定DS1620的上限温度值(THIGH)为30度,下限温度值(TLOW)为20度.
;用DS1620测量温度,用SAA1064驱动四位数码管显示温度值:012.5℃
;显示器位置: 第一位 第二位 第三位 第四位
;显示数值 0 1` 2 . 5
;数值存储单元地址 72H 73H 74H 75H
;设定DS1620的上限温度值(THIGH)为30度,下限温度值(TLOW)为20度.
$include (c8051f020.inc)
RST EQU P0.4 ;复位线
CLK EQU P0.3 ;时钟线
DQ EQU P0.2 ;数据线
WR_CONFIG EQU 0CH ;写DS1620 CONFIGUARATION 命令
RD_TEMP EQU 0AAH ;读DS1620 温度值命令命令
RD_CONFIG EQU 0ACH ;读DS1620 CONFIGURATION命令
STOP_CONVERT EQU 22H ;停止转换命令
START_CONV EQU 0EEH ; 开始转换命令
WR_TH EQU 01H ;写温度上限命令
WR_TL EQU 02H ; 写温度下限命令
RD_TH EQU 0A1H ; 读温度上限命令
RD_TL EQU 0A2H ; 读温度下限命令
SLAW EQU 060H ;存放SAA1064 写的寻址字节在60H中
SLAR EQU 061H ;存放SAA1064 读的寻址字节在61H中
SLA EQU 68H
NUMBYT EQU 6BH ;被传送的字节数存放单元
MTD EQU 20H ;发送数据缓冲区首地址
MRD EQU 30H ;接收字节缓冲区首地址
VSCL EQU P0.1 ;IIC时钟信号
VSDA EQU P0.0 ;LLC数据输入/输出线
COM EQU 17H ;SAA1064 的设置。
SAA1064ADR EQU 070H ; SAA1064芯片的写地址
;SMBus状态:
SMB_BUS_ERROR EQU 00H ;(所有方式)总线错误
SMB_START EQU 08H ;(MT&MR)主收发器发送起始位成功.再将从机写地址送SMB0DAT
SMB_RP_START EQU 10H ;(MT&MR)主收发器重复发送起始位成功,再将从机读地址送SMB0DAT
SMB_MTADDACK EQU 18H ;(MT)主收发器发送从地址+W成功;收到 ACK(从机应答)
;再将从器件的子地址送入SMB0DAT
SMB_MTADDNACK EQU 20H ;(MT)主收发器发送从地址+W成功;收到 NACK(从机无应答)
SMB_MTDBACK EQU 28H ;(MT)主收发器发送数据字节成功;收到ACK(从机应答)
SMB_MTDBNACK EQU 30H ;(MT)主发送器发送数据成功;收到NACK(从机无应答).
SMB_MTARBLOST EQU 38H ;(MT)总线竞争失败
SMB_MRADDACK EQU 40H ;(MR)主收发器发送从地址+R成功;收到 ACK(从机应答)
SMB_MRADDNACK EQU 48H ;(MR)主收发器发送从地址+R成功;收到NACK(从机无应答)
SMB_MRDBACK EQU 50H ;(MR)主收发器接收数据成功;主机发送ACK
SMB_MRDBNACK EQU 58H ;(MR)主收发器接收数据成功;主机发送NACK
DSEG ; 数据段;
ORG 30H;
TRANSMIT_BYTE: DS 1 ;保存SMBus待发送的字节
RECEIVE_BYTE: DS 1 ; 保存SMBus刚收到的字节
SLA_ADD: DS 1 ;保存从地址
WRI_ADD: DS 1 ; 保存从地址+ WRITE
READ_ADD: DS 1 ; 保存从地址+ READ
SUBADDR: DS 1 ;要访问器件的子地址
; 用于暂存数据的单元
DATA_COUNT: DS 1 ;测试计数器变量
DATA_BYTE: DS 1 ; 测试数据
DATA_ADDR: DS 1 ; 测试存储器地址
BSEG ; 数据段;
ORG 00H
RW: DBIT 1 ;R/W命令位。l=READ,0=WRITE
SM_BUSY: DBIT 1 ;SMBus忙标志(软件保存)
BYTE_SENT : DBIT 1
CSEG ;代码段
ORG 00H ;复位
LJMP MAIN
ORG 03BH ;SMBus中断向量
LJMP SMBus_ISR
ORG 100H
MAIN: MOV WDTCN,#0deH ;关看门狗
MOV WDTCN,#0adH
LCALL PORT_Init
MOV XBR2,#40H
LCALL DS1620INT ;DS1620初始化:设定上/下限温度值
ACALL RDS1620 ;读出DS1620采集的温度值,并转化为十进制数据
LCALL DELY ;延时一秒
LCALL DISPLAY ;显示温度值(四位)
AJMP MAIN
RDS1620: SETB RST
MOV A,#START_CONV ;DS1620命令 开始转换
CALL OUT_1620
CLR RST
NOP
NOP
SETB RST
MOV A,#RD_TEMP ; DS1620命令 读出温度值
ACALL OUT_1620
ACALL IN_1620 ;输入温度值的低8位,存入20H中.
MOV 20H,A
ACALL IN_1620 ;输入温度值的高8位,存入A中.
MOV 72H,#0 ;71H存符号位"+"("0"为正,"1"为`负")
ANL A,#01
CJNE A,#1,SV ;判符号位.,(A)=0 温度为正,(A)=1,温度为负
MOV 72H,#10H ;71H存符号位"-" ("-"的字形码为"40H")查表地址为10H
MOV A,20H ;温度为负值,数据为补码,应求反加1
CPL A
INC A
MOV 75H,A
SV: MOV A,20H
ACALL EXCH ;子程序EXCH将二进制数据转化为十进制数据
RET
EXCH : CLR C ;子程序EXCH将二进制数据转化为十进制数据
MOV B,A
ANL A,#01
MOV 75H,A
MOV A,B
RRC A ;存放在72H(百为),73H(十位),74H(个位),75H(小数位)中
MOV B,#10
DIV AB
PUSH ACC
MOV 74H,B
POP ACC
MOV B,#10
DIV AB
MOV 72H,A ;存放在72H(百位),73H(十位),74H(个位),75H(小数位)中
MOV 73H,B
MOV A,B
MOV A,75H
MOV 75H,#0
CJNE A,#1,VS
MOV 75H,#5
VS: RET
OUT_1620: MOV R0,#8H ;串行输出一个字节(8 BIT),输出数据在A中。
WLP: RRC A
CLR CLK
MOV DQ,C
SETB CLK
DJNZ R0,WLP
RET
IN_1620: MOV R0,#8 ;串行输入一个字节(8 BIT),结果在R2中.
SETB DQ
MOV R2,#0
RLP: CLR CLK
MOV C,DQ
SETB CLK
MOV A,R2
RRC A
MOV R2,A
DJNZ R0,RLP
RET
DELY: MOV R5,#8 ;延时子程序(延时一秒)
TM2: MOV R6,#0H
TM1: MOV R7,#0H
DJNZ R7,$
DJNZ R6,TM1
DJNZ R5,TM2
RET
DISPLAY:CLR SM_BUSY ;为第一次传输清除SM_Busy标志
MOV R1,#50H ;从50H--5EH 看中断过程
; SAA1064W: 依次连续写入6个数到SAA1064中去:17H,3FH,06H,5BH,4FH
MOV SUBADDR,#00H ; 装入SAA1064的子地址(SUBADR=00H)
MOV DATA_COUNT,#6H ; 装入待写数据块的长度
MOV SLA_ADD,#SAA1064ADR ; 装入从器件的写地址
MOV 71H,#0AH ;(TAB+0AH)=17H=COM
MOV R0,#71H ; R0做计数器用
LCALL SEND
CLR EA ; 调用数据发送子程序
RET ; SAA1064显示结束结束,返回主程序
TAB: DB 3fH,06H,5bH,4FH,66H,6DH,7DH,07H,7FH,6FH,17H,40H
;发送子程序SEND;
;SEND子程序执行一次向SAA1064写入六位数据(0,17H,4FH,5BH,06H,3FH)的过程。
;该子程序管理SM_BUSY位,设置 RW=WRITE,装载 SLAW,启动写操作。
SEND:
PUSH ACC ;保存累加器
JB SM_BUSY,$ ;等待SMBus空闲
CLR RW ; RW= 0(写)
MOV A,SLA_ADD ; 取SLA_ADD到A
MOV WRI_ADD,A ;将SLA_ADD+ WRITE保存到SLAW
SETB SM_BUSY ; 占用SMBus
SETB STA ; 启动发送过程
JB SM_BUSY,$ ;等待发送结束(在中断中处理)
POP ACC
RET
;SMBus 中断程序 ,处理SMBUS 中断
SMBus_ISR:
PUSH PSW ; 保护现场
PUSH ACC ;
PUSH DPH ;
PUSH DPL ;
MOV A,SMB0STA ; 将当前SMBus状态(SMB0STA)装入累加器
; 每个状态对应一个地址偏移量
MOV @R1,A ;在50H---60H中存放SMB0STA和SMB0DAT,可查看中断路径
INC R1
MOV @R1,SMB0DAT;
INC R1
MOV DPTR,#SMB_STATE_TABLE ; DPTR指向状态表的起始地址
JMP @A+DPTR ;转移到当前状态
;SMBuS状态表 ;(SMB0STA =00H)
SMB_STATE_TABLE: ; SMB_BUS_ERROR总线错误(对所有方式)
ORG SMB_STATE_TABLE+SMB_BUS_ERROR
SETB STO ; 停止位置1,使硬件复位
JMP SMB_ISR_END ; 中断返回
;SMB_START ; (SMB0STA =08H)
;主发送器/接收器发送起始位成功.再将从机写地址送SMB0DAT并清除START位.
ORG SMB_STATE_TABLE+SMB_START
MOV SMB0DAT,WRI_ADD ; 装载从地址+ W````
CLR STA ; 清除START位
JMP SMB_ISR_END ; 中断返回
;SMB_RP_START ;(SMB0STA =10H)
;主发送器/接收器发送重复起始位成功.
;再将从机读地址送SMB0DAT并清除START位.
ORG SMB_STATE_TABLE+SMB_RP_START
MOV SMB0DAT,READ_ADD ;装载从地址+ R
CLR STA ; 清除START位
JMP SMB_ISR_END
;SMB_MTADDACK (SMB0STA =18H)
;主发送器(MT)发送从地址+W成功;收到 ACK(从机应答)
;再将要发的子地址送入SMB0DAT.
ORG SMB_STATE_TABLE+SMB_MTADDACK
MOV SMB0DAT,SUBADDR ;装载从器件的子地址到SMB0DAT.
SETB BYTE_SENT ;BYTE_SENT=1.在下一次中断调用时存储器地址刚被发送
JMP SMB_ISR_END
;SMB_MTADDNACK (SMB0STA =20H)
;主发送器(MT)发送从地址+W成功;收到 NACK(从机无应答)
;用确认查询重试。发送 STOP+START
ORG SMB_STATE_TABLE + SMB_MTADDNACK
SETB STO
SETB STA
JMP SMB_ISR_END
;SMB_MTDBACK (SMB0STA =28H)
;主发送器(MT)发送数据字节成功;收到ACK(从机应答)
;检查BYTE_SENT:如果为1,说明刚发出的是存储器地址;为0,刚发出的是数据字节
ORG SMB_STATE_TABLE+SMB_MTDBACK
DJNZ DATA_COUNT,ADDRESS_SENT
; JBC BYTE_SENT,ADDRESS_SENT ;如果BYTE_SENT=1,清除该位并转到
;ADDRESS_SENT去执行状态表以外的处理程序
JMP DATA_SENT ; 如果BYTE_SENT=0,数据刚被发出,
; 传输过程完成,转到传输结束
;SMB_MTDBNACK ;(SMB0STA =30H)
;主发送器(MT)发送数据成功;收到NACK,从机无应答.
;用确认查询重试。发送STOP+START重试
ORG SMB_STATE_TABLE+SMB_MTDBNACK
SETB STO
SETB STA
JMP SMB_ISR_END
; SMB_MTARBLOST ;(SMB0STA =38H);竞争失败.重新启动传输.
ORG SMB_STATE_TABLE+SMB_MTARBLOST
SETB STO
SETB STA
JMP SMB_ISR_END
; SMB_MRADDACK ;(SMB0STA =40H)
;(MR)主收发器发送从地址+R成功;收到 ACK(从机应答).主机发送ACK.
ORG SMB_STATE_TABLE+SMB_MRADDACK
SETB AA ;主机发送ACK,转入SMB_MRDBACK
JMP SMB_ISR_END
; SMB_MRADDNACK ;(SMB0STA =48H)
;(MR)主收发器发送从地址+R成功;收到NACK(从机无应答),发送重复起始位重试
ORG SMB_STATE_TABLE+SMB_MRADDNACK
SETB STA
JMP SMB_ISR_END
;SMB_MRDBACK (SMB0STA =50H)
;(MR)主收发器接收数据成功;主机发送ACK .
ORG SMB_STATE_TABLE+SMB_MRDBACK
MOV RECEIVE_BYTE, SMB0DAT
CLR AA ;主机发NACK(清除AA),下一次中断来时转入;SMB_MRDBNACK(58H)
CLR SM_BUSY;
JMP SMB_ISR_END
;SMB_MRDBNACK ;(SMB0STA =58H)
;(MR)主收发器接收数据成功;主机发送NACK
;读操作完成。读数据寄存器并发送STOP
ORG SMB_STATE_TABLE+SMB_MRDBNACK
MOV RECEIVE_BYTE, SMB0DAT
SETB STO
SETB AA ;主机发ACK,为下一次传输置位AA
CLR SM_BUSY;
JMP SMB_ISR_END
;状态表结束,处理"SMB_MTDBACK"状态码的程序段。
;对于地址字节刚发出的状态。通过检查RW位确定处理方法。
;如果为读,则转到RW_READ,如果为写,则将待发送数据装入SMBODAT。
ADDRESS_SENT:
MOV DPTR,#TAB ;查表,找到显示的数据(字型码)
MOV A,@R0
MOVC A,@A+DPTR
MOV DATA_BYTE ,A
CJNE R0,#74H,VV
ADD A,#80H ;加小数点
MOV DATA_BYTE ,A
VV: MOV SMB0DAT,DATA_BYTE ;将要显示的数据(字型码)送SAA1064
INC R0
JMP SMB_ISR_END ; 中断返回
;对于地址字节刚发出的状态。重复发送START,启动存储器读操作
RW_READ:
SETB STA ;重复发送START
JMP SMB_ISR_END ;中断返回
;这是一个写操作,数据字节已发出。传输过程结束。发送STOP,释放总线,中断返回
DATA_SENT:
SETB STO ;发送STOP后中断返回
CLR SM_BUSY ; 释放 SMBus
JMP SMB_ISR_END ; 中断返回
;SMBus ISR exit
;恢复现场,清除SI位,从中断返回
SMB_ISR_END:
CLR SI
POP DPL
POP DPH
POP ACC
POP PSW
RETI
PORT_Init :
MOV OSCICN,#14H ;内部晶振设定为2MHZ
MOV P0MDOUT,#0H ;P0口为开漏方式
MOV XBR0,#01H ;通过功能选择开关将将SDA接P0.0引脚,SCL接P0.1引脚
MOV XBR2 ,#40H; 允许功能选择开关和弱上拉
; 初始化SMBus程序段
MOV SMB0CN,#04H ; 配置 SMBus在确认周期发送 ACK
MOV SMB0CR,#0F6H ; 设置时钟速率=100 kHz (系统时钟为2MHZ)
ORL SMB0CN,#40H ; 允许SMBus
ORL EIE1,#02H ; 允许SMBus中断
SETB EA
RET
DS1620INT:
SETB RST
MOV A,#WR_TH
ACALL OUT_1620
MOV A,#3CH ;设定上限温度:30度
LCALL OUT_1620
CLR RST
NOP
NOP
SETB RST
MOV A,#WR_TL
ACALL OUT_1620
MOV A,#28H ;设定下限温度:20度
LCALL OUT_1620
CLR RST
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -