本帖最后由 广东梁百万 于 2017-12-31 19:03 编辑
单片机用的是STC15W480AS,传感器是18b20。
用的是汇编语言,
下面是程序的部分
以下是程序部分,是本人原创 手打出来
;下面是寄存器的分配使用
;字节20H的前4位用作18b20的存在标示位 。位00H,01H,02H,03H
;字节20H的后4位用作正负温度标志 位04H,05H,06H,07H
TPH1 EQU 24H ;存放温度值的高字节
TPL1 EQU 25H ;存放温度值的低字节
TTH1 EQU 26H ;合并成完整的温度整数\
TTL1 EQU 27H ;合并成完整的温度整数
TPH2 EQU 28H ;第二个存放温度值的高字节
TPL2 EQU 29H ;第二个存放温度值的低字节
TTH2 EQU 2AH ;第二个合并成完整的温度整数
TTL2 EQU 2BH ;第二个合并成完整的温度整数
DQ1 BIT P1.5 ;第一个DS18B20的数据口位
DQ2 BIT P1.4 ;第二个DS18B20的数据口位
TSRAM0 EQU 2CH ;定时器计数用的寄存器0
TSRAM1 EQU 2DH ;定时器计数用的寄存器1
TSRAM2 EQU 2EH ;定时器计数用的寄存器1
TSRAM3 EQU 2FH ;定时器计数用的寄存器1
TSRAM4 EQU 30H ;定时器计数用的寄存器1
YSRAM1 EQU 31H ;延时用寄存器1
YSRAM2 EQU 32H ;延时用寄存器2
YSRAM3 EQU 33H ; 延时用寄存器3
S1X EQU 34H ;第一行显示个位
S10X EQU 35H ;第一行显示十位
S100X EQU 36H ;第一行显示百位
S1000X EQU 37H ;第一行显示千位
S1XB EQU 38H ;第二行显示个位
S10XB EQU 39H ;第二行显示十位
S100XB EQU 3AH ;第二行显示百位
S1000XB EQU 3BH ;第二行显示千位
SS1 EQU 3CH ;时钟1秒计数
SS10 EQU 3DH ;时钟10秒计数
MM1 EQU 3EH ;时钟分个位
MM10 EQU 3FH ;时钟分十位
HH1 EQU 40H ;时钟小时个位
HH10 EQU 41H ;时钟小时十位
SBUF_R EQU 42H ;串口接收字节计数
RAM1602 EQU 43H ;LCD1602写入缓冲
ASWRAM1 EQU 44H ;按键A 计数
BSWRAM1 EQU 45H ;按键B 计数
RS BIT P5.5 ;LCD1602 的 RS端 ,1-数据,0-指令
EN BIT P5.4 ;LCD1602 的 E端 ,先从低变高,再变低,以确认输入数据或命令
LCD1_1 EQU 80H ;LCD1602的第一行第1个
LCD2_1 EQU 90H ;LCD1602的第二行第1个
ORG 0000H
LJMP AA1
;--------------------------
ORG 00BH;T0中断入口
LJMP T0INT
ORG 0100H
;数值初始化
AA1:MOV R0,#02H ;间接寻址,从02H开始到0FFH共256字节 全清空置零
MOV R1,#255
CL1:MOV @R0,#00H
INC R0
DJNZ R1,CL1
MOV R0,#00
MOV R1,#00
SETB DQ1
SETB DQ2
MOV SP,#0E0H;设定堆栈底在RAM的0E0H
;---------定时器T0初始化--------10毫秒@11.0592MHz
ANL AUXR,#7FH ;定时器T0时钟12T模式
ANL TMOD,#0F0H ;设置定时器模式
MOV TL0,#0FCH ;设置定时初值 #000H
MOV TH0,#0DBH ;设置定时初值 #0DCH
CLR TF0 ;清除TF0标志
SETB TR0 ;定时器0开始计时
SETB ET0 ;允许T0中断
;-------------------------
;------定时器T2初始化-------用于串口波特率
;晶振-11.0592MHZ
;波特率数对应T2重装值
;9600----0FEE0H
;4800----0FDC0H
;2400----0FB80H
;1200----0F700H
MOV T2L,#0E0H ;波特率9600
MOV T2H,#0FEH
MOV AUXR,#15H ;定时器T2工作1T模式,并开始计时 ; 选择定时器2作串口波特率
;-------------------------
MOV A,AUXR1
MOV AUXR1,A
SETB SM0
SETB SM1 ;串口工作在模式3,9位 ,波特率可变
SETB REN ;*****允许串口接收********
CLR ES ;暂停串口中断
SETB EA ;中断总开关
;---------------------------------------
;LCD1602初始化
MOV RAM1602,#000 ;清P2
LCALL DELAY15MS ;延时15毫秒
MOV RAM1602,#38H ;16行*2,5*8
LCALL ZL
LCALL DELAY5MS ;延时5毫秒
MOV RAM1602,#38H ;16行*2,5*8
LCALL ZL
LCALL DELAY5MS ;延时5毫秒
MOV RAM1602,#08H ;关显示
LCALL ZL
LCALL DELAY1MS ;延时1毫秒
MOV RAM1602,#01H ;清屏
LCALL ZL
LCALL DELAY5MS ;延时5毫秒
MOV RAM1602,#06H ;地址计数器AC自动加1,光标右移 *******
LCALL ZL ;
LCALL DELAY1MS ;延时1毫秒
MOV RAM1602,#0CH ;开显示
LCALL ZL
LCALL DELAY1MS ;延时1毫秒
;-----------------------------------
MOV R0,#80H ;给80H到09FH都置空格(20H)
MOV R1,#32 ;32个字符存储字节
CL2: MOV @R0,#20H
INC R0
DJNZ R1,CL2
MOV ASWRAM1,#00
MOV BSWRAM1,#00
;运行主程序
AA2:LCALL DS18B20_1 ;第一路温度测量
LCALL DS18B20_2
LCALL DS1820_JH
LCALL B_DS18B20_1 ;第二路温度测量
LCALL B_DS18B20_2
LCALL B_DS1820_JH
LCALL T_SC1 ;温度数送显示 第一路
LCALL TB_SC1 ;温度数送显示 第二路
LCALL SJ1 ;调用时钟计时
LCALL SW1 ;调用按键扫描
LCALL LCD_SC1 ;调用显示
LJMP AA2
;------------------------------------------
;T0定时器中断处理程序
T0INT:MOV F0,C;保护C位到标志位地址FO--T0中断处理程序开始
PUSH A
INC TSRAM0;计数,11.0592MHZ,每10ms加一次
NOP
INC TSRAM1;时钟计数 11.0592MHZ,每10ms加一次
NOP
INC TSRAM2;*******备用****11.0592MHZ,每10ms加一次
NOP
MOV A,TSRAM1
CJNE A,#010,AA3; RAM的TSRAM1加到100MS就清空
MOV TSRAM1,#00H
INC TSRAM3; 每100Ms就加1
NOP
AA3:MOV A,TSRAM0
CJNE A,#010,AA4;TSRAM0加到100MS就清空(10)
MOV TSRAM0,#000
INC TSRAM4;每100Ms就加1
AA4:MOV A,TSRAM2
CJNE A,#100,AA5 ;TSRAM2加到1秒(100)就清空
MOV TSRAM2,#00
INC SS1 ;秒计时器加1
NOP
AA5:MOV C,F0;恢复C位,****标志位地址FO用来做中断现场保护
POP A
RETI
;--------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>第一路传感器通道》》》》》》》》》》》》》
;****************** 18B20主程序1
DS18B20_1:MOV A,TSRAM4
CJNE A,#020,DS18B20_1B ;每两秒转换一次
INC TSRAM4 ;加多一个数,避免重复发送
LCALL DS18B20_RST ;设备复位和发出转换命令
DS18B20_1B:RET ;返回
;***************18B20主程序2
DS18B20_2: MOV A,TSRAM4 ;等待0.8秒
CJNE A,#29,DS18B20_2B
JNB 00H,DS18B20_2B ;设备标示位为0就返回
LCALL DS18B20_2RST ;第二次复位
MOV A,#0CCH ;跳过ROM命令
LCALL DS18B20_TXD ;送出命令
MOV A,#0BEH ;读暂存存储器
CALL DS18B20_TXD ;送出命令
CALL DS18B20_RXD ;读温度低字节
MOV TPL1,A ;存储数据
CALL DS18B20_RXD ;读温度高字节
MOV TPH1,A ;存储数据
MOV TSRAM4,#00
MOV TSRAM0,#00
DS18B20_2B:RET ;返回
;**************************************
;复位DS18B20,并检测设备是否存在
;入口参数:无
;出口参数:无
;**************************************
DS18B20_RST:CLR DQ1 ;送出低电平复位信号
LCALL DELAY600US ;延时600US
SETB DQ1 ;释放数据线
LCALL DELAY60US ;延时60US
MOV YSRAM3,#10 ;置检测次数
DS18B20_RST2:MOV C,DQ1 ;检测18B20的回应信号
JC DS18B20_RST3 ;检测到不是0就转
SETB 00H ;检测到有信号回复就置标志位
LCALL DELAY420US ;延时420US
MOV A,#0CCH ;跳过ROM命令
LCALL DS18B20_TXD ;送出命令
MOV A,#044H
LCALL DS18B20_TXD ;发送出转换命令
RET
DS18B20_RST3:LCALL DELAY4US ;延时4US
DJNZ YSRAM3,DS18B20_RST2 ; 最多10次检测
CLR 00H ;10次检测不到信号那就标示0不存在
MOV TPL1,#00FH ; 置显示255的数
MOV TPH1,#0F0H
RET
;*************第二次复位
DS18B20_2RST:CLR DQ1 ;送出低电平复位信号
LCALL DELAY600US ;延时600US
SETB DQ1 ;释放数据线
LCALL DELAY60US ;延时60US
MOV YSRAM3,#10 ;置检测次数
DS18B20_2RST2:MOV C,DQ1 ;检测18B20的回应信号
JC DS18B20_2RST3 ;检测到不是0就转
LCALL DELAY420US ;延时420US
RET
DS18B20_2RST3:LCALL DELAY4US ;延时4US
DJNZ YSRAM3,DS18B20_2RST2 ; 最多10次检测
CLR 00H ;10次检测不到信号那就标示0不存在
RET
;**************************************
;向DS18B20写1字节数据
;入口参数:ACC
;出口参数:无
;**************************************
DS18B20_TXD:PUSH 0
SETB DQ1
CLR C
MOV 0,#8 ;8位计数器
DS18B20_TXD2:CLR DQ1 ;开始时间片
LCALL DELAY4US ;延时4US
RRC A ;输出数据
MOV DQ1,C
LCALL DELAY80US ;等待18B20读取时间结束 LCALL DELAY80US ;等待18B20读取时间结束
SETB DQ1
LCALL DELAY1US ;延时1.3US
DJNZ 0,DS18B20_TXD2
POP 0
RET
;**************************************
;从DS18B20读1字节数据
;入口参数:无
;出口参数:ACC
;**************************************
DS18B20_RXD:CLR A
PUSH 0
CLR C
SETB DQ1
MOV 0,#8 ;8位计数器
DS18B20_RXD2:CLR C
SETB DQ1
LCALL DELAY1US ;延时1.3US
CLR DQ1 ;开始时间片
LCALL DELAY4US ;延时4US
SETB DQ1 ;准备接收
LCALL DELAY4US ;延时4US
NOP
MOV C,DQ1 ;读取数据
RRC A
LCALL DELAY60US ;等待时间片结束
DJNZ 0,DS18B20_RXD2
POP 0
RET
;***********************************************************
;*****************转换温度数 DS1820_JH **************
DS1820_JH:MOV A,TPH1
CLR 04H ;先把负温度标志回零
JNB 0E7H,DS1820_JH2 ;判断是否是负温度数,0E7H是A的第8位
SETB 04H; 是负温度那就置标志位为1
CPL A; A取反
PUSH 82H ;这里用到了DRTR指针计数器,需要保护原数据
PUSH 83H
MOV DPH,A ;存到数据指针DPTR高位
MOV A,TPL1 ;温度低字节取反后存到DPTR低字节
CPL A
MOV DPL,A
INC DPTR ;负温度数取反再加1
MOV TTH1,DPH ;整理后再放回
MOV TTL1,DPL
POP 83H; 恢复DPTR原数据
POP 82H
MOV A,TTH1
SWAP A
MOV TTH1,A ;得到温度整数的高4位
MOV A,TTL1
ANL A,#0F0H ;清低4位
SWAP A ;得到温度整数的低4位
ORL TTH1,A ;全部成温度整数 放在TTH
ANL TTL1,#00FH ;清高4位,得到温度小数
LJMP DS1820_JH3
DS1820_JH2:MOV A,TPH1
SWAP A ;半字节交换
MOV TTH1,A ;得到温度整数的高4位
MOV A,TPL1
ANL A,#0F0H ;清低4位
SWAP A ;得到温度整数的低4位
ORL TTH1,A ;全部成温度整数 放在TTH
MOV TTL1,TPL1
ANL TTL1,#00FH ;清高4位,得到温度小数
DS1820_JH3:MOV B,#100; 转换成BCD ****************
MOV A,TTH1
DIV AB ;分离出百位
MOV S1000X,A
MOV A,#10
XCH A,B
DIV AB
MOV S100X,A
MOV S10X,B
MOV A,TTL1 ;小数转BCD(4位小数乘10后再除16,也就是相当于乘0.625)
ANL A,#0FH ;去掉高4位整数,保留低4位小数
MOV B,#10
MUL AB ;先放大10倍
MOV B,#16
DIV AB ;再除以16
MOV S1X,A
RET
|