⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr-m8+18b20a.asm

📁 AVR-m8+18b20a(每0.5s测温一次
💻 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 + -