📄 avr-m8+18b20a.asm
字号:
;显示0-125°温度,每0.5s测温一次,若温度大于32°则亮灯,不够32°则不亮灯
.include "m8def.inc"
.DEF EEDWR =R7 ;写入数据
.DEF ARL =R8 ;读出低位地址
.DEF ARH =R9 ;读出高位地址
.DEF tempa =r16 ;暂存器a
.DEF tempb =r17 ;暂存器b
.DEF tempc =r18 ;暂存器c
.DEF FLAG1 =r19 ;是否检测到DS18B20标志位
.DEF TEMPERH =r20 ;用于保存读出温度的高8位
.DEF TEMPERl =r21 ;用于保存读出温度的低8位
.def temper =r22 ;保存转换后的温度值
.DEF A_BIT =r23 ;数码管个位数存放内存位置
.DEF B_BIT =r24 ;数码管十位数存放内存位置
.DEF C_BIT =r14 ;数码管百位存放内存位置
.DEF abcd =r25 ;解码暂存器
;.DEF dd = r26 ;显示暂存器
;晶振1MHz
;PC.0--DQ DS18b20数据口
;PC.1--DATA 74hc164数据口
;PC.2--CLOCK 74hc164脉冲口
;系统主程序********************
.ORG $0000
RJMP RESET
.org $0008
rjmp Time1
.ORG $0020
RESET:
LDI tempa, HIGH(RAMEND); 主程序
OUT SPH,tempa ; 设置堆栈指针为RAM 的顶部
LDI tempa, LOW(RAMEND)
OUT SPL,tempa
LDI TEMPA,0B11111110 ;设B口方向寄存器为输出
OUT DDRB,TEMPA
LDI TEMPA,0b00111111
OUT PORTB,TEMPA
LDI TEMPA,0B11111111 ;设c口方向寄存器输出
OUT DDRC,TEMPA
LDI TEMPA,0b00100000
OUT PORTC,TEMPA
LDI TEMPA,0B11111111 ;设D口方向寄存器输出
OUT DDRD,TEMPA
LDI TEMPA,0b11111001
OUT PORTD,TEMPA
cbi portc,2
cbi portc,3
rcall delayc
rcall delayc
rcall delayc
;sbi portc,2
sbi portc,3
;***********
ldi r16,0x04 ;允许T1溢出中断
out timsk,r16
ldi r16,0x04
out tifr,r16
ldi r16,0x05 ;T1为1024分频
out tccr1b,r16
ldi r17,0x16 ;T1置初值0
ldi r16,0xfe
out tcnt1h,r16
out tcnt1l,r17 ;0.5s溢出
sei
main:
nop
nop
rjmp main
time1:
cli
in r1,sreg
rcall r18b20
ldi r17,0x16 ;设T1置初值
ldi r16,0xfe
out tcnt1h,r16
out tcnt1l,r17
out sreg,r1
sei
reti
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
r18b20:
rcall rst18b20 ;调DS18B20初始化子程序
cpi flag1,0x88
brne r18b20 ;若DS18B20不存在则从新开始
;sbi portd,5
ldi tempa,0xcc ;写CCH到DS18B20,以便跳过ROM匹配
rcall wids18b20 ;WIDS18B20是写18B20子程序
ldi tempa,0x44
rcall wids18b20 ;发温度转换命令 ;延时750us
ldi r29,0xf9
lp2:
dec r29
brne lp2
rcall rst18b20 ;温度转换完全,再次初始化
ldi tempa,0xcc
rcall wids18b20
ldi tempa,0xbe ;发读温度暂存器命令
rcall wids18b20
rcall rdds18b20 ;调用读温度子程序
mov tempa,temper
cpi tempa,0x22 ;判断,大于等于35度的数
brsh D1
rjmp d2
d1:
sbi portc,2
cbi portc,3 ;如果大于35度亮LED2
rjmp dd
d2:
cbi portc,2 ;如果小于35度亮LED1
sbi portc,3
dd:
ret
;**************DS18B20初始化子程序***********
rst18b20:
clr flag1
cbi ddrc,5 ; 释放总线
nop
nop
sbi ddrc,5 ;控制总线
cbi portc,5 ;强制拉低
rcall delay500us ;延时500us
cbi ddrc,5 ;释放总线,总线自动上拉
nop
nop
nop
ldi r29,0x0b ;在63us内检测是否出现应答信号
rst1:
sbic pinc,5 ;pc.5=0则跳下一条指令
rjmp rst2
;rjmp rst3
ldi flag1,0x88 ;置标志位,表示ds18b20存在
rcall delay500us ;延时500us
sbi portc,5 ;释放总线
ret
rst2:
dec r29
brne rst1
rst3:
clr flag1 ;清标志位,表示DS18B20不存在
sbi portc,5
ret
;*********************************
delay500us: ;ret 延时505us@1mhz
ldi r29,0xb0
delay1:
dec r29
brne delay1
ret
delay_64us:
ldi r29,0X13 ;延时子程序64us@1mhz
delay2:
dec r29 ;复位后R29=0X00
brne delay2 ;R29不为0转,为0按顺序执行
ret ;子程序返回
;***********************18B20读子程序**********
; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据
rdds18b20:
clr r28
clr tempa
rcall rd5
mov temperl,r28
rcall rd5
mov temperh,r28
rcall get_temper ; 将从DS18B20中读出的温度数据进行转换
ret
rd5: ;从DS18B20中读出一个字节的数据
cbi ddrc,5 ;释放总线
ldi tempb,8
rd4:
rcall rd1
bst tempa,5
brts rd2 ;T位=1则跳转
clc
rjmp rd3
rd2:
sec
rjmp rd3
rd3:
ror r28
dec tempb
brne rd4
ret
rd1: ;从DS18B20中读出一bit的数据
sbi ddrc,5 ;控制总线
cbi portc,5 ;强制拉低
nop
nop
nop
cbi ddrc,5 ;释放总线,DS18B20会将总线强制拉低
nop
nop
nop
nop
nop
in tempa,pinc ;读1位数,
rcall delay_46us
cbi ddrc,5 ;释放总线,自动拉高
ret
delay_46us: ; ret 延时46us @1MHZ
ldi r29,0X10 ;延时子程序
delay4:
dec r29 ;复位后R29=0X00
brne delay4 ;R29不为0转,为0按顺序执行
ret
; ***********************将从DS18B20中读出的温度数据进行转换***************
get_temper:
mov tempa,temperl
andi tempa,0xf0 ;舍去温度低位中小数点后的四位温度数值
swap tempa ;把保留的4位数放到寄存器的低4位中
mov temper,tempa ;把低4位保存到temper中
sbrc temperh,3 ;判断高8位温度值中第三位的值,(符号位S=1为负数,s=0为正数)
;为0则跳过下一条指令
inc temper
andi temperh,0x07 ;舍去符号位,只保留数值位
swap temperh
or temper,temperh ;把高位也放到temper中
ret
;***************************18B20写子程序************
wids18b20:
ldi tempb,8
cbi ddrc,5 ;释放总线rdds18b20
wid1:
bst tempa,0
rcall wid2
ror tempa
dec tempb
brne wid1
ret
wid2: ;写1bit子程序
sbi ddrc,5
cbi portc,5
nop
nop
nop
nop
nop
nop
nop
nop
nop
ldi tempc,0b11011111
bld tempc,5
sbrc tempc,5
sbi portc,5
rcall delay_56us
cbi ddrc,5
nop
ret
delay_56us:
ldi r29,0X10 ;延时子程序
delay3:
dec r29 ;复位后R29=0X00
brne delay3 ;R29不为0转,为0按顺序执行
ret
;*********************
EEWRITE:;写入EEPROM中
SBIC EECR,EEWE ;等待EEWE=0
RJMP EEWRITE
OUT EEARL,ARL
OUT EEARH,ARH
OUT EEDR,EEDWR
SBI EECR,EEMWE
SBI EECR,EEWE
RET
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2@@@@@@@@@
DELAYP: ;RET TIME0.4S @ 1MHZ延时子程序
LDI R29,3 ;延时子程序
LDI R30,7
DELAY9: DEC R31 ;复位后R30=0X00
BRNE DELAY9 ;R30不为0转,为0按顺序执行
DEC R30 ;复位后R31=0X00
BRNE DELAY9 ;R30不为0转,为0按顺序执行
DEC R29 ;复位后R29=0X00
WDR
BRNE DELAY9 ;R29不为0转,为0按顺序执行
RET ;子程序返回
DELAYFF: ;RET ;TIME0.001S @ 4MHZ延时子程序
LDI r30,6 ;r30=6 TIME0.001S
LDI r31,44
DELAY77:
DEC r31 ;复位后R30=0X00
BRNE DELAY77 ;R30不为0转,为0按顺序执行
DEC r30 ;复位后R31=0X00
BRNE DELAY77 ;R30不为0转,为0按顺序执行
WDR
BRNE DELAY77 ;R29不为0转,为0按顺序执行
RET
DELAYC: ;RET TIME0.1S @ 4MHZ延时子程序
LDI R29,3
LDI R31,7
DELAY44: DEC R30 ;复位后R30=0X00
BRNE DELAY44 ;R30不为0转,为0按顺序执行
DEC R31 ;复位后R31=0X00
BRNE DELAY44 ;R30不为0转,为0按顺序执行
DEC R29 ;复位后R29=0X00
WDR
BRNE DELAY44 ;R29不为0转,为0按顺序执行
RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -