?? 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 + -