您的当前位置:首页正文

avr汇编百例 - 晋级篇 - 参考程序.doc

2022-09-25 来源:好走旅游网
; 以下提供几个补充参考程序,都带有详细说明和指令注释.它们是主从多机通讯程序,采 ;用中断方式写入EEPROM,直接对晶振分频产生0.1秒和秒号的精确定时程序,以及RS-232/ ;RS-485标准转换程序,AVR频率计程序,串行时锺日历芯片DS1302读写,共享时基的PWM输出、

;输入捕获测周期程序和定时信号获取,以及DS18B20测温等程序.多机通讯主要用8和9位数

;据模式区分被选分机(9位)和其它分机(8位),达到主机只与被选分机交换数据之目的.以中 ;断方式写EEPROM的优点是可与系统运行同时进行(即在线写入),占用很少机时.

;精确定时用定时/计数器1(或0)直接对MCU主频(不设分频)设定时间常数,分频精度可达到 ;1HZ.RS-232/RS-485标准转换程序中AVR不作中转,使两种器件相关脚位直接连接.以TCNT0

;定时,以T0引脚接收RS-232数据.以收到RS-232字符起始位下跳沿或结束符($03)为依据, ;控制切换RS-485的收发使能.(系统中的主AVR可兼做对通信标准之监控转换,即只是在完成

;主要工作任务的同时'附带'进行).具体过程不再细述.串行时锺日历芯片DS1302具体积小, ;可靠性高,与单片机连接方便等优点.

; 以下程序请参看有关章节或程序中的注释。

;范例91 ;多机通讯主机程序/晶振4MHZ

.ORG 0 ;以8/9位数据模式区分被选/未被选分机通讯

.EQU DTPINT=$180 ;UBRR=12 波特率19200(REL.ERR.=0.16%)

.EQU DRPINT=$1C0 ;主机对1#,2#,3#,4#分机发送数据块在$180-18F,$190-19F,$1A0-1AF)和$1B0-1BF

STRT38: RJMP RST38 ;主机从1#,2#,3#,4#分机接收数据块在$1C0-1CF,$1D0-1DF,$1E0-1EF)和$1F0-1FF .ORG $00B ; RJMP STRT38 .ORG $00C

RJMP STRT38 ;主机不设串口中断,只以查询接收 .ORG $011 RST38: LDI R16,12

OUT UBRR,R16 ;设波特率:[BAUD RATE=FCP/16(UBRR+1)] CLR R15 ;初始化分机号 LDI R27,HIGH(DTPINT)

LDI R26,LOW(DTPINT);发送数据指针(首指$180) LDI R29,HIGH(DRPINT)

LDI R28,LOW(DRPINT);接收数据指针(首指$1C0) NEXTNO: LDI R16,$18

OUT UCR,R16 ;允许UART接收和发送,8位数据模式 INC R15 ;指向1#分机

OUTLP: OUT UDR,R15 ;呼分机号,1:1#/2:2#/03:3#/04:4#... TSLOP: IN R16,USR SBRS R16,7

RJMP TSLOP ;分机返回机号?

IN R16,UDR

CP R16,R15 ;分机号正确返回? BRNE OUTLP

LDI R16,$1C ;改为9位数据模式 TXB8=0 OUT UCR,R16 ; TXLOP: LD R16,X+

OUT UDR,R16 ;向分机发送数据块 TESTL: IN R17,USR SBRS R17,5

RJMP TESTL ;等待发送完成 CPI R16,$0A

BRNE TXLOP ; RXTST: IN R17,USR

SBRS R17,7 ;RXC=1 收到数据

RJMP RXTST ;等待接收分机返回数据块 IN R16,UDR

ST Y+,R16 ;存储接收数据 CPI R16,$0A ;分机数据块发完? BRNE RXTST MOV R16,R15

CPI R16,4 ;与分机轮询通讯完毕?

BRNE NEXTNO ;未完转对下一分机通信

HH38: RJMP HH38 ;否则踏步(可改为处理分机返回的数据,之后再进行下一个轮询) .DSEG

.ORG $180 DTPINT:.BYTE $40

;$41 $45 $65 $73 $46 $42 $40 $6F $33 $44 $66 $5C $4D $4B $0D $0A ;$42 $4F $66 $78 $47 $45 $44 $63 $32 $48 $60 $7C $6D $45 $0D $0A ;$43 $56 $55 $53 $4D $4F $40 $2E $31 $42 $67 $4C $47 $4A $0D $0A ;$45 $54 $59 $63 $3D $4B $48 $2F $35 $48 $69 $3C $77 $43 $0D $0A .ORG $1C0 DRPINT:.BYTE $40

;范例92

.ORG 0 ;多机通讯1#分机程序/晶振4MHZ

.EQU DTPIT1=$180 ;(UBRR)=12 波特率为19200(REL.ERR.=0.16%) .EQU DRPNT1=$1C0 STRT39: RJMP RST39 .ORG $00B

RJMP UARXC ;8535UART接收完成中断 .ORG $00C

RJMP UATXC ;UART发送完成中断

.ORG $011

RST39: CLR R18 ;清除分机被选中(R18,6)和主机数据块接收完毕标志(R18,7) LDI R16,12

OUT UBRR,R16 ;设波特率[BAUD RATE=4000000/16*(12+1)=19200] LDI R16,HIGH(DRPNT1) MOV R8,R16

LDI R16,LOW(DRPNT1)

MOV R9,R16 ;r8,r9:接收数据指针(FIRST POINT TO $1C0) LDI R16,$98 ;允许UART中断接收,8位数据模式 OUT UCR,R16 SEI

RXDTS: SBRS R18,6 ;主机呼号已收到(若收到,在R17中)? RJMP RXDTS

OUT UDR,R17 ;返还该机号 TXDON: IN R16,USR SBRS R16,5

RJMP TXDON ;该机号发送完成?

LDI R16,$9C ; 允许UART中断接收,9位数据模式,TXB8=0 OUT UCR,R16 RCVBLK: SBRS R18,7

RJMP RCVBLK ;主机发来数据块已接收完毕? LDI R16,HIGH(DTPIT1) MOV R6,R16

LDI R16,LOW(DTPIT1)

MOV R7,R16 ;设发送数据指针r6r7,首指$180

LDI R16,$3C ;允许UART中断发送,9位数据模式,TXB8=0 OUT UCR,R16 TXDN: SBIC UCR,5

RJMP TXDN ;发送完毕? RJMP RST39 ;

:UART中断接收程序 UARXC: SBIC USR,4

RETI ;祯错误(主机正与其它分机进行9位数据模式通信),不予接收 IN R14,SREG ;保存当前状态 TST R18

BREQ NUMB ;(R18)=0时收到数据,只可能是机号,转去核实

PUSH R16 ;否则为主机向本分机发来数据块(9位模式,机号已符合) PUSH R26 PUSH R27

IN R17,UDR ;接收数据 MOV XH,R8

MOV XL,R9 ;取接收数据指针 ST X+,R17 ;转入RAM

MOV R8,XH

MOV R9,XL ;存数据指针

CPI R17,$0A ;是数据块结束符LF? BRNE RSCOM1

SBR R18,$80 ;收到完整数据块标志 RSCOM1: POP R27 POP R26 POP R16

DRETI: OUT SREG,R14 RETI

NUMB: IN R17,UDR ;取出数据

CPI R17,1 ;是1#分机?2#分机与$02比较/3#分机与$03比较... BRNE DRETI ;机号不符合,转! SBR R18,$40 ;建机号符合标志 RJMP DRETI

; UART中断发送程序

UATXC: PUSH R16 ;r6 r7:发送数据指针,首指$180 IN R16,SREG PUSH R16 PUSH R26 PUSH R27 MOV XH,R6

MOV XL,R7 ;取出发送指针 LD R16,X+ ;取数据,调指针 MOV R6,XH MOV R7,XL

OUT UDR,R16 ;送入发送寄存器 CPI R16,$0A BRNE SDCOM

CBI UCR,5 ;发送最后1个字符后,禁止发送寄存器空中断(CLR UDRIE) LDI R16,HIGH(DRPINT) MOV R8,R16

LDI R16,LOW(DRPINT)

MOV R9,R16 ;接收数据指针初始化(POINT TO $1C0) SDCOM: POP R27 POP R26 POP R16

OUT SREG,R16 POP R16 RETI .DSEG

.ORG $180 DTPIT1:.BYTE $40 .ORG $1C0

DRPNT1:.BYTE $10

;$41 $45 $65 $73 $46 $42 $40 $6F $33 $44 $66 $5C $4D $4B $0D $0A

;范例93

;以中断方式写入EEPROM(仅对8535,8515无此功能),克服查询方式占用过多机时的缺点,

;并可在线写入

;运作过程特点如下:

;(1)主程序初始化时设置EEPROM就绪(ready)中断使能位和中断总使能位

;(2)在主程序中写入第一个字节,写入完成后引起就绪中断,其他写入在中断服务中完成 ;(3)本程序为一写入特例,写入地址为$100--$1FF,可作适当修改(如设块长计数器等) ;(4)为防止高优先级中断破坏写入过程,中断服务中不允许中断嵌套

;(5)本例为简化程序只以查询写入地址循环作为背景程序,实用时可改为具体的背景序 ;(6)如能确信当前系统没有EEPROM正在写入,可删除对其进行查询部分. STWEEP: LDI R16,HIGH(ramend) OUT SPH,R16

LDI R16,LOW(ramend) OUT SPL,R16

SBI EECR,3 ;设置EEPROM就绪(ready)中断使能位 SEI ;中断总使能 RJMP SRTW .ORG $00F

RJMP EEPRDY ;8535 EEPROM就绪(ready)中断向量 SRTW: LDI YH,1

LDI YL 0 ;EEPROM 写入首地址:$100 LDI XL,$60 ;欲写入数据块首地址:$60 CLR XH

WEEP0: SBIC EECR,1 ;当前有EEPROM写入操作,有则等待写入完成 RJMP WEEP0

RCALL WREEP ;写入第一个字节,($60)->$100,写入完成后,EEWE=0时引发EEPROM就绪中断

INC YL ;调整写入地址指针 HHWEEP: TST YL

BRNE HHWEEP

CPI YH,2 ;写入地址达到$200后,写入完成 BRNE HHWEEP

CBI EECR,3 ;禁止EEPROM就绪(ready)中断 WDON: RJMP WDON ;踏步 EEPRDY: IN R6,SREG PUSH R16

RCALL WREEP ;写入一个字节 INC YL

BRNE WRETI

INC YH ;EEPROM末地址为$1FF WRETI: POP R16 OUT SREG,R6 RETI

WREEP: OUT EEARH,YH ;

OUT EEARL,YL ;写入地址送入EEAR LD R16,X+ ;取数据,调指针

OUT EEDR,R16 ;数据写入EEPROM数据寄存器

SBI EECR,2 ;设置EEPROM写入总使能位EEMWE SBI EECR,1 ;设置EEPROM写入使能位EEWE RET

;范例94 ;精确定时产生0.1秒信号

;用定时/计数器1定时,不分頻定出0.1秒信号,由PC5脚输出正脉冲。 ;晶体4.000119MHZ,计400012个数定出0.1秒信号

;对定时/计数器1重装常数进行加法补偿(扣除自然计数和补偿占用时间). ;加法补偿若产生进位,将中断次数减1

.ORG $000 ;精确定时产生0.1秒信号 STRT24: RJMP RST24

.ORG $006 ;8515 t1 overflow vector

RJMP T1_OVFL ;400012=65536*7-58740=7*$10000-$E574/故TCC=$E574 .ORG $00D

RST24: LDI R16,HIGH(ramend) OUT SPH,R16

LDI R16,LOW(ramend) OUT SPL,R16

SBI DDRC,5 ;PC5,0.1秒号输出(高有效) CBI PORTC,5 LDI R16,1 ;不分頻 OUT TCCR1B,R16 LDI R16,$E5

OUT TCNT1H,R16 LDI R16,$74

OUT TCNT1L,R16 ;写入时间常数TCC LDI R16,$80

OUT TIMSK,R16 ;允许定时/计数器1溢出中断 LDI R16,7 ;7次中断输出0.1秒号 MOV R6,R16

SEI ;中断总使能 HH1A: RJMP HH1A ; T1_OVFL:PUSH R16 PUSH R17 IN R7,SREG

DEC R6 ;中断次数减一

BRNE GOON10 ;0.1秒时间到? LDI R16,7

MOV R6,R16 ;重新装入中断次数 SBI PORTC,5 ;0.1秒号输出前沿 IN R17,TCNT1L ;*

IN R16,TCNT1H ;*读入TCNT1自然计数值 LDI R18,$7C ;*TCC=$E574 ADD R17,R18 ;*TCC+8=$E57C

LDI R18,$E5 ;*8条单周期补偿指令占用8个时钟周期 ADC R16,R18 ;*修正后TCC=$E574+(TCNT1)+8 OUT TCNT1H,R16 ;*

OUT TCNT1L,R17 ;*重新装入补偿修正后的TCC BRCC GOON09

DEC R6 ;加法补偿若产生进位,将中断次数减1 GOON09: ;. ;数据处理略 ;. ;. ;. ;.

RCALL ACLK1 ;0.1秒走时软时钟 RJMP GOON11

GOON10: CBI PORTC,5 ;输出信号后沿 GOON11: POP R17 POP R16

OUT SREG,R7

RETI

;范例95

;用定时/计数器1定时,不分頻定出1秒信号,由PC5脚输出正脉冲 ;晶体4.000133MHZ,计4000133个数定出1秒信号

;对定时/计数器1重装常数进行加法补偿(扣除自然计数和补偿占用时间). ;加法补偿若产生进位,将中断次数减1 .ORG $000 ;精确定时产生秒号 STRT25: RJMP RST25 .ORG $006

RJMP T1_OVFB ;4000133=62*65536-63099=62*$10000-$F67B/故TCC=$F67B .ORG $00D

RST25: LDI R16,HIGH(ramend) OUT SPH,R16

LDI R16,LOW(ramend) OUT SPL,R16

SBI DDRC,5 ;PC5输出秒信号(正脉冲)

CBI PORTC,5 LDI R16,1 ;不分頻 OUT TCCR1B,R16 LDI R16,$F6 ;

OUT TCNT1H,R16 ;写入TCC高8位 LDI R16,$7B ;

OUT TCNT1L,R16 ;写入TCC低8位 LDI R16,$80 ;

OUT TIMSK,R16 ;允许T/C1溢出中断 LDI R16,62 ;62次中断定出秒号 MOV R6,R16 SEI ;

HH1B: RJMP HH1B ;等待中断 T1_OVFB:PUSH R16 PUSH R17 IN R7,SREG

DEC R6 ;到62次中断? BRNE GOON12 LDI R17,62

MOV R6,R17 ;重装中断次数 SBI PORTC,5 ;输出秒信号 IN R17,TCNT1L ;*

IN R16,TCNT1H ;*读入T/C1自然计数值 LDI R18,$83 ;*TCC=$F67B ADD R17,R18 ;*TCC+8=$F683

LDI R18,$F6 ;*8条单周期补偿指令占用8个时钟周期 ADC R16,R18 ;* OUT TCNT1H,R16 ;*

OUT TCNT1L,R17 ;*重新装入补偿修正后的TCC

BRCC GOON19

DEC R6 ;加法补偿若产生进位,将中断次数减1 GOON19: ;. ;数据处理略 ;. ;. ;. ;.

RJMP GOON13

GOON12: CBI PORTC,5 ;秒号后沿 GOON13: POP R17 POP R16

OUT SREG,R7

RETI

;范例96 ;运作特点如下:

;此程序为一完整频率测量显示程序,所测频率较高(2MHZ),使用4兆晶振 ;程序兼有启动看门狗及对其管理功能

;以TCNT0精确定时输出秒号作为捕获信号,用TCNT1对被测信号频率计数

;用TCNT0直接对(8515)4兆晶振计数产生秒号,定时精度达1Hz 主常数选为256(即0) ;由PA0输出精确定时产生的秒信号(与ICP脚相连)捕获TCNT1计数值,相减计算频率 ;将频率转换为十进制数,装入显示缓存区,调DSPA子程序显示之(参考范例27和图4-5) ;重装TCC时对TCC进行修正,若修正(减法)计算不产生借位,将中断次数n减1

;被测频率可近2兆,故须设1字节扩展计数器,以tcnt1溢出中断对其计数(共3字节计数器) ;在TCNT1捕获中断服务中,以3字节减法计算频率,并置位T标志;若TCNT1溢出标志置位

;必须提前增1扩展计数器,并将TCNT1溢出标志清除(不再增1扩展计数器),再计算频率. ;TCNT1溢出中断优先级高于TCNT0,故TCNT1中断服务可能影响秒号精度,导致测量误差 ;可以排队法剔除坏值,即将几个连续采样按大小顺序排队,‘掐头去尾'只留中间再作平均. ;也可以监视LED显示,连续3秒稳定显示(高频测量允许有2Hz误差)即为所测频率正确值. ;若晶振采用12兆,被测信号频率(暂空比1:1或接近1:1)可接近6兆. .ORG $000

STRT26: RJMP RST26 ;实测8515晶振频率4.000167MHZ 计4000167个数为1秒 .ORG $003

RJMP T1_CAPT ;T/C1捕获中断 .ORG $006

RJMP T1_OVRF ;T/C1溢出中断 .ORG $007

RJMP T0_OVFB ;T/C0溢出中断

.ORG $00D ;4000167=256*15626-89=256*$3D0A-89/故TCC=89 n=15626 RST26: LDI R16,HIGH(ramend) OUT SPH,R16

LDI R16,LOW(ramend) OUT SPL,R16

SBI DDRA,0 ;PA0输出秒定时信号,捕获频率计数值 CBI PORTA,0 ;初始为低 CLR R22

CLR R21

CLR R20 ;R20,R21,R22为频率量瞬时计数采样 CLR R2 WDR

LDI R16,$0D ;启动看门狗,溢出时间为0.49\" OUT WDTCR,R16 ;写入看门狗控制寄存器 CLR XH

LDI XL,$6C ;set the display buffer pointer T26LP: ST X+,R2 CPI R26,$74

BRNE T26LP ;清除$6C--$73

LDI R16,$01 ;T/C0为定时器,不分频 OUT TCCR0,R16 LDI R16,89 ;

OUT TCNT0,R16 ;写TCC到TCNT0

LDI R16,$C6 ;上升沿捕获,允许噪音滤除,外部脉冲计数 OUT TCCR1B,R16

LDI R16,$8A ;允许T/C1捕获,溢出以及T/C0溢出中断 OUT TIMSK,R16 ;

LDI R16,$3E ;设15626(=$3D0A)次中断(高位字节已增1) MOV R1,R16 ; MOV R19,$0A ; SEI ;

HH1C: BRTS HH2C ;已采集到频率? RCALL DSPA ;仍显示原数据 RJMP HH1C

HH2C: CLT ;频率量已在R3,R4,R5 MOV R9,R3 MOV R10,R4 MOV R11,R5

RCALL CONV1 ;翻为十进制数(R12R13R14R15<--R9R10R11) LDI XL,$74 CLR XH LDI YL,15 CLR YH

HHLOP: LD R16,Y ;分解十进制数,送入LED显示区($6C--$73) ADNI R16,$0F ST -X,R16 LD R16,Y SWAP R16 ANDI R16,$0F ST -X,R16 DEC YL

CPI R26,$6C ;分解完毕? BRNE HHLOP

RJMP HH1C ;显示新数据

T0_OVFB:SEI ;TCNT0溢出,允许中断嵌套 PUSH R16 IN R8,SREG DEC R19

BRNE GOON13

CBI PORTA,0 ;秒信号后沿 DEC R1 ;到15626次中断? BRNE GOON13

SBI PORTA,0 ;秒定时捕获信号前沿

IN R16,TCNT0 ;*读TCNT0自然计数值

SUBI R16,164 ;*89之补为167,考虑补偿操作本身耗时,减去164

OUT TCNT0,R16 ;*第15626次中断后,重新装入TCC=89+(TCNT0)+3到TCNT0 LDI R16,$3E

MOV R1,R16 ;重新装入中断次数 LDI R19,$0A

BRCC GOON13 ;补偿操作如有借位,将中断次数减1

DEC R19 ;->252 253 254 255 | 0 1 2 3 4 5...加法计数方向--> GOON13: POP R16 ; | | | | | | | | | | |

OUT SREG,R8 ;<--15626次范围-->|<-15625次范围(补偿后进(借)位 ;C=l)-> RETI

T1_OVRF:IN R18,SREG ;TCNT1溢出中断服务 INC R3 ;R3为TCNT1扩展字节 OUT SREG,R18 RETI

T1_CAPT:IN R6,SREG ;T/C1捕获中断 PUSH R16

IN R5,ICR1L IN R4,ICR1H MOV R16,R22 MOV R22,R5 SUB R5,R16 MOV R16,R21

MOV R21,R4 ;与上一次采集的频率量相减,得到频率值 SBC R4,R16 IN R16,TIFR SBRS R16,7 RJMP T1CP1

INC R3 ;8515TCNT1溢出中断,预先对扩展字节计数 LDI R16,$80 ;并将溢出标志清除,(中断返回后不再计数) OUT TIFR,R16 ;清除TIFR,7 T1CP1: MOV R16,R20 MOV R20,R3

SBC R3,R16 ;采集频率量在R3,R4,R5 SET ;建采集频率量标志 POP R16

OUT SREG,R6 RETI

;范例97

; 本时基资源共享式综合测量系统,具有精确定时PWM输出、输入捕获测外部信号 ;周期、获取TCNT1溢出中断信号等多种功能。特点是TCNT1启动之后即不停运行。

; 时基资源共享式PWM的特点在于装入比较匹配寄存器之数据方式,它不是在比较 ;匹配达到时清除定时/计数器,再装入高(或低)电平时间常数:而是当比较匹配 ;达到时以定时/计数器当前值加上时间常数后将和装入比较匹配寄存器,二者效果 ;是相同的。可称前者为静态设置,后者为动态设置。后者因不停运行定时/计数器 ;,其资源可同时用于输出比较匹配A及B、输入捕获、定时信号输出等等。

; 本程序使用晶体标称值4MHZ实测为4,000,236HZ。使用定时/计数器1直接 ;对主频精确定时设定PWM高低电平的维持时间。以ICP脚输入被测周期脉冲信号。 ; 本程序PWM之暂空比与范例51相同,为5毫秒(高):10毫秒。故维持 ;高电平的时间常数为4,000,236÷200=20,001,维持低电平的时间常数为 ;4,000,236÷100=40,002。此即输出比较匹配A达到时交替写入比较匹配寄 ;存器OCR1A之对TCNT1当前内容的超前值。

; 因以TCNT1直接对主频计数,频率高周期短,输入捕获的外部信号周期不能 ;大于65536÷4,000,236=0.01638(秒)即16.38毫秒(但也不能太小,对频率 ;较高的脉冲信号应改为测频率)。以相邻两次捕获值相减之差除以主频得到被测信 ;号之周期(单位为秒)。

; 为避免小数除法运算,可将相邻两次捕获值相减之差先乘以1,000,再将乘积 ;除以主频,将得到以毫秒为单位的周期值;考虑到除法子程序DIV16只实现整数 ;除法,且除数不能大于65535,可将主频缩小100倍,即以40,002作除数,故 ;除得之商扩大了100倍。这样将整数商二翻十后,其末两位皆为小数。本程序采用 ;这种计算方法。并在主循环程序中调DSPA子程序显示所测周期值。。

; 若将以上算法中乘以1,000改为乘以10,000,并增加对商的万位转换,

;其余保留不变,则所得商数末3位皆为小数位。本算法精度高于上一种方法,如有 ;提高测量精度之必要,应采用后种算法。

; 若扩大测量信号周期,应对TCNT1溢出信号计数,做3字节减法(见范例96) ;后再计算被测信号周期(除以4,000,236)。所测信号周期可达4.194秒。 ; 本示例定时精度可与范例51做如下比较:本例中高低电平分别对主频计数 ;20,001个和40,002个。范例51中高低电平分别对主频计数19,968个和 ;40,000个。本示例定时精度明显高于范例51。

; 本示例TCNT1产生溢出中断之周期为16.38毫秒,其频率约为61HZ。在TCNT1 ;溢出中断服务子程序中由PA3以正脉冲形式输出该信号。 .ORG $000 ;USE 8535

STRT43: RJMP RST43 ;5.0000MS(高):9.9999MS(低) 晶振4,OOO,236HZ .ORG $005

RJMP T1_CP43 ;T/C1输入捕获中断 .ORG $006

RJMP T1_CA43 ;T/C1输出比较匹配A中断 .ORG $008

RJMP T1_OV43 ;TCNT1溢出中断 .ORG $011

RST43: LDI R16,HIGH(RAMEND) OUT SPH,R16

LDI R16,LOW(RAMEND) OUT SPL,R16

LDI R16,$80 ;T/C1比较匹配A达到时,清除输出脚OC1A

OUT TCCR1A,R16

LDI R16,$41 ;不分频,比较匹配达到不清TCNT1;上升沿捕获/禁止噪音滤除 OUT TCCR1B,R16 SBI DDRD,5

SBI PORTD,5 ;PD5(OC1A)初始化输出为高

SBI DDRA,3 ;PA3为TCNT1溢出中断信号输出 CBI PORTA,3 ;PA3输出为低 LDI R16,$4E

OUT OCR1AH,R16

LDI R16,$21 ;写比较匹配寄存器($4E21=20001脉宽5毫秒) OUT OCR1AL,R16

LDI R16,$34 ;允许输入捕获/输出比较匹配A/TCNT1溢出中断 OUT TIMSK,R16 CLR R21

CLR R20 ;捕获值暂存单元 CLR XH LDI XL,$6C CLR43: ST X+,R20 CPI XL,$74

BRNE CLR43 ;清除显示区$6C--$73 SEI

HH43: RCALL DSPA ;背景程序:显示捕获频率信号之周期,单位:毫秒 BRTC HH43

RCALL FIL2 ;T=1,已捕获到数据在R4,R5/先关显示 CLT

MOV R14,R4 MOV R15,R5 LDI R16,3

MOV R12,R16

LDI R16,$E8 ;取立即数1000(=$3E8) MOV R13,R16

RCALL MUL16 ;乘以1000

LDI R16,$9C ;使周期单位为毫秒 MOV R10,R16

LDI R16,$42 ;$9C42=40002 MOV R11,R16

RCALL DIV16 ;除以立即数40002,得到被测脉冲周期之单位为毫秒,且含因子100

MOV R16,R14 MOV R17,R15 LDI R18,3 LDI R19,$E8

RCALL CONVT ;二翻十,得千位 STS $70,R11 ;送入显示区

CLR R18 LDI R19,$64

RCALL CONVT ;二翻十,得百位

LDI R19,-$29 ;在百位处加小数点(百位实为个位) SUB R11,R19

STS $71,R11 ;送入显示区 LDI R19,10

RCALL CONVT ;二翻十,得十位 STS $72,R11

STS $73,R17 ;小数送入显示区

RJMP HH43 ;转去显示新采样数据 CONVT: CLR R11

COVLOP:SUB R17,R19

SBC R16,R18 ;减去十进制数某位之权 BRCS CONVCM

INC R11 ;够减,增权 RJMP COVLOP

CONVCM:ADD R17,R19 ;否则恢复余数 ADC R16,R18 RET

T1_CA43:SEI

IN R1,SREG IN R24,TCCR1A SBRS R24,6

RJMP OUTLW ;当前输出低电平,转 IN R24,OCR1AL IN R25,OCR1AH

SUBI R24,$DF ;LOW(-20001)

SBCI R25,$B1 ;HIGH(-20001)/$B1DF为20,001之补码 OUT OCR1AH,R25

OUT OCR1AL,R24 ;写入高电平维持时间超前值

LDI R24,$80 ;比较匹配A达到时,OC1A输出为低 OUT TCCR1A,R24 OUT SREG,R1 RETI

OUTLW: IN R24,OCR1AL IN R25,OCR1AH

SUBI R24,$BE ;LOW(-40002)

SBCI R25,$63 ;HIGH(-40002)/$63BE为40,002之补码 OUT OCR1AH,R25 ;

OUT OCR1AL,R24 ;写入低电平维持时间超前值 LDI R24,$C0 ;比较匹配A达到时,OC1A输出为高 OUT TCCR1A,R24 OUT SREG,R1

RETI

T1_CP43:IN R3,SREG ;T/C1捕获中断 IN R5,ICR1L IN R4,ICR1H MOV R17,R21 MOV R21,R5 SUB R5,R17 MOV R17,R20

MOV R20,R4 ;与上一次采集的频率量相减,得到频率值 SBC R4,R17 ;在R4,R5中 SET ;建采集频率量标 OUT SREG,R3 RETI T1_OV43:SEI

SBI PORTA,3 ;OUTPUT THE 61HZ PULS SBI PORTA,3 SBI PORTA,3 SBI PORTA,3

CBI PORTA,3 ;脉冲宽度2微秒

RETI

;范例98

;MAX232'R1OUT接MAX483'DI/MAX483'RO接MAX232'T1IN

;由TCNT0配合PB0以软件接收RS-232数据 对485进行监控:PB1接DE和/RE ;AVR对485发来数据不接收,该数据经MAX483'RO->MAX232'T1IN-->RS-232远端

;数据起始位下降沿引起中断接收,中断服务一开始,将对RS-485的控制改为允发禁收使RS- ;232发来数据直接通过RS-485向远端发送

;当收到RS-232数据结束符$03后,经半位延时,对RS-485的控制改为允收禁发 使能接收RS- ;485远端发来数据(故要求经RS-232发来数据要以$03为结束符,对来自RS-485数据无此要求)

;可采用avr专门管理两种标准转换方案(可采用少脚ATtiny系列),也可采取主avr兼管方案. ;主avr兼管时,它既接收处理完整串行数据块(及执行其它程序),又控制通讯标准转换. .EQU DATA4=$100

.ORG 0 ;R16:THE BIT SEQUENCE COUNTER R17:WORKING ;REG.R18:FLAG UNIT

STRT3S: RJMP RST3S ;BAUD RATE:9600 USE 8515/may REPLACE BY ATtiny serials

.ORG $007 ;$007(8515) RJMP T0_OF .ORG $00D

RST3S: LDI R17,HIGH(ramend) OUT SPH,R17

LDI R17,LOW(ramend)

OUT SPL,R17

LDI R17,$02 ;8535:$01

OUT TIMSK,R17 ;timsk,1(允许tcnt0中断) LDI R17,6 ;设外部脉冲计数 OUT TCCR0,R17

CBI DDRB,0 ;T0 为输入 LDI R17,$FF

OUT TCNT0,R17 ;计1个数即中断

SBI DDRB,1 ;PB1输出,控制DE和/RE CBI PORTB,1 ;禁止485发送 SEI CLR R18 CLR R16

HERE0: SBRC R18,0

BRNE RST3S ;无错误标志循环 SBRS R18,1

BRNE HERE0 ;未收到数据块结束符($03)循环 LDI R16,64 HERE1: DEC R16

BRNE HERE1 ;延时(48+3.5=)52微秒(超过半位,以等待半个停止位发过去) RJMP RST3S ;以使远端485正确收到停止位

T0_OF: SBI PORTB,1 ;允许485发送 IN R11,SREG PUSH R17

CPI R16,0 ;接收起始位? BRNE T0SV11

LDI R17,2 ;YES

OUT TCCR0,R17 ;改为内定时,8分频(4MHZ/8)

LDI R17,232 ;半位定时常数24,定出48微秒(<52微秒) OUT TCNT0,R17 RJMP T0SV7

T0SV11: CPI R16,1 ;半位定时后,查起始位有效性 BRNE T0SV12 SBI PORTB,0

SBIC PINB,0 ;低电平为有效 RJMP T0ER ;否则转错误处理 RJMP T0SV62 ;

T0SV12: CPI R16,10 ;停止位? BRNE T0SV3S

CLR R16 ;是

SBI PORTB,0 ;停止位为l? SBIS PINB,0

RJMP T0ER ;否,转错误处理

MOV R17,R15

CPI R17,3 ;收到结束符$03? BRNE T0SV13

ORI R18,2 ;结束符收到

OUT TCCR0,R16 ;停止TCNT0 RJMP T0SV63 T0SV13: LDI R17,6

OUT TCCR0,R17 ;改为外定时

LDI R17,$FF ;停止位下降沿即中断 OUT TCNT0,R17 RJMP T0SV63

T0SV3S: BRCC T0ER ;出错(位计数器超过10) CLC ;2--9:接收一位数据 SBI PORTB,0 ;本位为1? SBIC PINB,0 SEC

ROR R15 ;接收数据组织到R15

T0SV62: IN R17,TCNT0 ;读入TCNT0自然计数值 INC R17

SUBI R17,52 ;1位时间常数为52 OUT TCNT0,R17 ;补偿后回送定时常数 T0SV7: INC R16 ;位计数器增1 T0SV63: POP R17 OUT SREG,R11 RETI

T0ER: SBR R18,1 ;出错标志 ERR. FLAG CLR R16

OUT TCCR0,R16 ;停止TCNT0

RJMP T0SV63

;范例99

; AVR与DS1302接口为:PC0--SCLK,PC1--DATA,PC2--/RST。请参看本范例之附图。 ; 结构与运作特点如下:

;(1)采用标准频率晶体(32768HZ),便于调整(可加电容补偿),可对PC0/PC1/PC2加提拉电阻。

;(2)DS1302只有8只脚,小巧精悍,耗电省,抗干扰.便于与单片机接口,以串行方式按位读写数据.

;(3)以备用电池供电保存数据,断电后自动执行写保护,故可靠性高。上电后须用指令解除写保护。

;(4)片内除8个时钟日历单元外还有31个RAM单元,可作为系统断电保护数据存储单元 ;(5)可以并发(BURST,即连续)方式读写8个时钟日历单元(秒/分/时/日/月/周/年/年)或读写31个RAM单元,

; 命令如下:

; $BE为以并发方式写8个时钟日历单元,$BF为以并发方式读8个时钟日历单元。 ; $FE为以并发方式写31个RAM单元,$FF为以并发方式读31个RAM单元。 ;(6)除以并发方式读写外,还可按字节读写,但读写前须先写入命令。

; 读写命令格式为:1 Y A4 A3 A2 A1 A0 X,最高位为1表示命令有效,Y=0,选择读写时间/日期 ; Y=1,选择读写片内RAM,A4-A0,片内RAM/时钟单元地址,X=0,选择写操作,X=1,选择读 ;操作.

;(7)串行时钟上升沿写入一位数据,下降沿读出一位数据;且读写只有在/RST信号为高时才有效。

; 故要求/RST信号有效前时钟信号应已就绪。

;(8)本程序AVR时钟为4MHZ,若使用其他时钟,重新调整读写延时时间(程序中NOP之个数)

;(9)对RAM并发读写方法可参考并发读写时钟日历子程序进行.

;1)并发(BURST)方式写时钟日历单元(时钟日历数据 秒,分,时,日,月,周,年,年分别在R8--R15,)

WBURST: CLR YH ;

LDI YL,8 ;数据指针,首指秒单元R8 RCALL DEPRV ;解除写保护(写入$8E00) CBI PORTC,0 ;为上升沿写作准备(SCLK升高) NOP NOP NOP

SBI PORTC,2 ;复位信号变高(SETB RST) NOP NOP NOP NOP NOP NOP

LDI R18,$BE ;BURST(wr.) ADDR.&INSTRUC.(命令$BE) RCALL WBYTE ; WLOP: LD R18,Y+

RCALL WBYTE ;写入1字节数据 CPI YL,16

BRNE WLOP ;数据都写完? CBI PORTC,2 ;禁止读写 NOP NOP NOP NOP

CBI PORTC,0 RET

;2)并发(BURST)方式读时钟日历单元(时钟日历数据 秒,分,时,日,月,周,年,

;分别读到R8--R14中)

RBURST: CLR YH ;首指R8 LDI YL,8

SBI DDRC,0 ;SCLK 输出 SBI DDRC,2 ;WR/RD ENABLE 输出 SBI PORTC,0 ;时钟SCLK初始输出为低 NOP NOP NOP

SBI PORTC,2 ;复位有效,允许时钟相关沿有效 NOP NOP NOP NOP NOP NOP

LDI R18,$BF ;BURST(rd.) ADDR.&INSTRUC. RCALL WBYTE ;写入并发读命令

RLOP: RCALL RBYTE ;读出一字节时钟/日历数据 ST Y+,R18 ;存储 CPI R28,15

BRNE RLOP ;数据都读完? CBI PORTC,2 ;禁止读写 NOP NOP NOP NOP

CBI PORTC,0 ;使SCLK变低 RET

;3)解除写保护子程序(对DS1302写入$8E,$00) DEPRV: SBI DDRC,0 ;SCLK 输出 SBI DDRC,2 ;WR/RD ENABLE 输出 CBI PORTC,0 ;时钟SCLK初始输出为低 NOP NOP NOP

SBI PORTC,2 ;复位有效,允许时钟相关沿有效 NOP NOP NOP NOP NOP NOP

LDI R18,$8E

RCALL WBYTE NOP NOP

CLR R18

RCALL WBYTE ;写入$8E和$00 CBI PORTC,2 ;禁止读写 NOP NOP NOP NOP

CBI PORTC,0 RET

;4)对DS1302秒,分,时单元写入3字节数据 WTIME: CLR YH ;

LDI R17,$80 ;写秒单元命令

LDI YL,8 ;R8(秒)R9(分)R10(时) LDI R19,3

WCOM: RCALL DEPRV ;解除写保护

WLOP1: CBI PORTC,0 ;时钟SCLK初始输出为低 NOP NOP NOP

SBI PORTC,2 ;复位有效,允许时钟相关沿有效 NOP NOP NOP NOP NOP NOP

MOV R18,R17

RCALL WBYTE ;写入一字节命令 SUBI R17,$FE ;指向时间下一单元 LD R18,Y+

RCALL WBYTE ;写入时间单元1字节 CBI PORTC,2 ;禁止读写 NOP NOP NOP NOP

CBI PORTC,0 DEC R19

BRNE WLOP1 ;写完规定字节? RET

;5)写入日期子程序

WDATE: CLR YH ;

LDI YL,11 ;R11(日)R12(月)R13(周)R14(年) LDI R17,$86 ;写日单元命令 LDI R19,4 RJMP WCOM ;6)读出时间子程序

RTIME: CLR YH ;

LDI R17,$81 ;读秒单元命令

LDI YL,8 ;读出数据送到R8(秒)R9(分)R10(时) LDI R19,3

RCOM: SBI DDRC,0 ;SCLK 输出 SBI DDRC,2 ;WR/RD ENABLE 输出

RLOP1: CBI PORTC,0 ;时钟SCLK初始输出为低 NOP NOP NOP

SBI PORTC,2 ;允许读写 NOP NOP NOP NOP NOP NOP

MOV R18,R17

RCALL WBYTE ;写入读命令

SUBI R17,$FE ;指向下一单元地址 RCALL RBYTE ;读出一字节数据 ST Y+,R18

CBI PORTC,2 ;禁止读写 NOP NOP NOP NOP

CBI PORTC,0 ;时钟变低 DEC R19

BRNE RLOP1 ;已读出规定字节? RET

;7)读出日期子程序

RDATE: CLR YH

LDI YL,11 ;读出数据放入R11(日)R12(月)R13(周)R14(年) LDI R17,$87 ;读出日单元命令 LDI R19,4 RJMP RCOM

;8)将R18中数据写入DS1302

WBYTE: LDI R16,8 ;8位/字节 SBI DDRC,1 ;PC1为输出

WB1: CBI PORTC,0 ;时钟SCLK初始输出为低 ROR R18 ;一位数据传到进位C BRCC WB10 SBI PORTC,1 RJMP WB2

WB10: CBI PORTC,1 ;1位数据输出到数据线(DS1302'DATA BUS) WB2: NOP NOP NOP NOP

SBI PORTC,0 ;上升沿写入一位 DEC R16

BRNE WB1 ;8位数据都写完? RET

;9)读出DS1302一字节数据在r18中 RBYTE: LDI R16,8 ;8位/字节 CBI DDRC,1 ;PC1输入

RD1: CBI PORTC,0 ;下降沿读出一位数据 NOP NOP NOP NOP

SBI PORTC,1 ;上拉电阻激活 CLC

SBIC PINC,1

SEC ;读出一位数据并-->C ROR R18 ;组织数据

SBI PORTC,0 ;SCLK升高,为下位读准备 DEC R16

BRNE RD1 ;8位数据都写完?

RET

;范例100

; DS18B20为美国DALLAS公司(已被MAXIM公司并购)生产的单线数字温度传感器,

;可将温度信号直接转换成数字信号供单片机处理,所测温度范围-55°C~125°C,精度 ;达0.5°C,转换时间为750毫秒。该器件出厂时带有固化的8字节‘身份’编号,最低 ;位字节为家族号码$28,接下来6字节为器件流水线编号,最高位字节为CRC校验码。 ;有读ROM,匹配ROM,启动温度变换,读RAM数据等十余种命令对18B20操作。使用 ;18B20之前要用读ROM命令读出其身份编号并记录。一条单总线上可挂接任意多个 ;18B20,单片机通过单总线发出启动转换命令之后,所有18B20同时进行温度转换。

;经等待延时后,单片机通过发出匹配ROM命令,18B20编号,读RAM数据等命令等, ;读取各18B20温度数据组(每组数据共9字节)。程序中对每组数据都进行CRC校验。 ;温度数据占2字节,为补码形式。最高位为符号位,0为正1为负。高位字节和低位 ;字节的高4位为温度整数部分,最低4位为温度小数部分。程序中对温度数据进行取 ;补、左移将整数部和小数部分分离,再将它们分别转成十进制数。整数二翻十用减 ;十进一法,小数二翻十采用按权累加法(并以减负替代加正),再将它们冠以数符 ;并加小数点送入DSPA子程序的显示缓存区,调该子程序进行显示。

; 由于DSPA子程序中含0.462秒定时复位看门狗指令,故以调用DSPA为主循环程序 ;不必考虑对看门狗管理问题(初始化设置看门狗溢出周期为0.49秒)。

; DS18B20不象一般串行器件既有数据线又有时钟线,它只有一条数据线,故它 ;只能靠较严格的时序脉冲信号进行读写,程序中多种延时环节就是为调整时序所 ;设。本程序AVR使用4MHZ时钟,如改变时钟,应按定时时间重新确定延时常数。 ; 18B20的使用可采用窃电方式,此种方式要将18B20电源端接地。在线缆长测点 ;的应用场合,可控制MOS管取得数据线的强上拉,以提高总线驱动能力。 ;对18B20的ROM操作命令如下: ; 命令 代码 ; 读ROM $33 ; 匹配ROM $55 ; 跳过ROM $CC ; 搜索ROM $F0 ; 告警搜索 $EC ; 对18B20的存储器操作命令如下: ; 命令 代码 ; 写暂时存储器 $4E ; 读暂时存储器 $BE ; 复制暂时存储器 $48 ; 启动温度变换 $44

; EEPROM内容调出 $B8

; 读电源 $B4

; 有关18B20初始化,读写命令,读写时序等请参看参考文献9和10,18B20与AVR接口 ;见程序附图,CRC检测请参看4.8.4小节。 START2:LDI R16,2 OUT SPH,R16 LDI R16,$5FH

OUT SPL,R16 ;堆栈指针初始化 SBI DDRA,2

CBI PORTA,2 ;MOS管不上拉 RCALL RESET ;复位18B20 WDR

LDI R16,$0D

OUT WDTCR,R16 ;启动看门狗,溢出时间为0.49秒

CLR R2 ;执行请除看门狗指令WDR的定时器初始化请除 LDI R16,$CC ;跳越ROM(SKIP ROM) RCALL WB

LDI R16,$44 ;START DS18B20 TEMPORATURE CONVERTING RCALL WB

CLR XH

CLR YH ;指针高位字节清除 LDI YL,$6C CLR44:ST Y+,YH CPI YL,$74

BRNE CLR44 ;清除显示缓存区($6C~$74) LDI R17,163 ;4.618×163=753(ms) STR0: RCALL DSPA DEC R17

BRNE STR0 ;总共延时753ms,等待转换完成 RCALL RESET ;再次复位DS18B20 LDI XL,$60 ;温度数据指针 LDI R17,4 ;总共4只DS18B20 LDI ZH,HIGH(DATA*2)

LDI ZL,LOW(DATA*2);18B20身份数据指针

LOOP0:LDI R16,$55 ;匹配ROM命令 (match rom) RCALL WB ;写入18B20

LDI R18,8 ;18B20身份数据共8个字节固化在FLASH中 LOOP4:LPM ;取数据 MOV R16,R0 ;转入R16

RCALL WB ;写入18B20 1字节 ADIW ZL,1 ;指向下一字节 DEC R18

BRNE LOOP4 ;共写入8个字节

LDI R16,$BE ;读18B20数据存储器命令 RCALL WB ;写入该命令 LDI YL,$74

LOP40:RCALL RB ;读出18B20数据共9个字节 ST Y+,R16 ;存入$74-$7C CPI YL,$7D BRNE LOP40

RCALL RESET ;再次复位18B20 LDI YL,$74

RCALL CRC9 ;对读得数据进行CRC校验 TST R15 BREQ LLL

ERROR:LDI R16,15 ;CRC余式不为零,温度数据错误 LDI YL,$6C

EER1: ST Y+,R16 CPI YL,$74 BRNE EER1

ERR1: RCALL DSPA ;显示$FFFFFFFF,等待按键

SBRC R16,7 RJMP ERR1

RJMP START2 ;有键按下,重新启动 LLL: LDS R16,$74

LDS R15,$75 ;取温度数据 R15为HIGH BYTE ST X+,R16

ST X+,R15 ;温度转入SRAM

BST R15,7 ;数符存于T BRTC PLUS ;正数转 COM R16 COM R15 LDI R18,255 SUBI R16,R18 SBCI R15,R18 ;负数求补 PLUS: LDI R18,4

LOOP5:ADD R16,R16 ADC R15,R15 DEC R18

BRNE LOOP5 ;整数部分在R15 MOV R19,R16 ;小数部分转入R19 CLR R9 ;百位BCD予清 LDI R16,100 CP R15,R16 BRCS LOP51

INC R9 ;百位BCD存在(EXISTED)! SUB R15,R16 ;减去100

LOP51:LDI R16,10 CLR R10 LOP52:SUB R15,R16 BRCS LOP53 INC R10

RJMP LOP52 ;十位及个位BCD转换

LOP53:ADD R15,R16 ;十位在R10,个位在R15 CLR R16 SBRC R19,7

SUBI R16,-$50 ;小数最高位值为0.5 SBRC R19,6 ;其余折半递减 SUBI R16,-$25 ;0.25 SBRC R19,5

SUBI R16,-$13 ;0.125 SBRC R19,4

SUBI R16,-6 ;0.0625

CPI R16,$0A ;产生非法BCD?(只可能在低位产生) BRHC LOP54

SUBI R16,$FA ;小数部分二翻十/调整(在R16中) LOP54:MOV R11,R16 LDI YL,$6C LDI R16,$24 ST Y+,R16 ST Y+,R16 ST Y,R16 RTC LOP55

LDI R16,$14 ;负温度,加负号! ST Y,R16 LOP55:INC YL

ST Y+,R9 ;百位BCD装入 $6F 单元 ST Y+,R10 ;十位BCD直接装入$70单元 MOV R16,R15

SUBI R16,-$29 ;个位BCD加小数点后 ST Y+,R16 ;装入$71单元 MOV R16,R11 SWAP R16 ANDI R16,$0F ST Y+,R16 MOV R16,R11 ANDI R16,$0F

ST Y+,R16 ;分解小数BCD/并装入$72及$73单元 CLR R8

NORML:RCALL DSPA ;显示温度数据2.4秒 RCALL DSPA ;4.62ms×2×256=2.4s DEC R8

BRNE NORML DEC R17

BREQ HALT ;采集完4点温度? RJMP LOOP0 ;未完循环 HALT: LDI R16,$1D OUT WDTCR,R16 LDI R16,$15

OUT WDTCR,R16 ;已采集到4点温度,关看门狗 RDSPA:RCALL DSPA SBRC R16,7

RJMP RDSPA ;无键按下,显示最后采集的温度 RJMP START2 ;否则再次启动

DATA: .DB $28,$3A,$13,$08,$00,$00,$00,$E5 ;18B20身份数据 .DB $28,$4A,$4D,$08,$00,$00,$00,$14 .DB $28,$3A,$19,$08,$00,$00,$00,$5E .DB $28,$32,$33,$08,$00,$00,$00,$66

RESET: SBI DDRA,3 ;PA3为输出 CBI PORTA,3 ;负脉冲前沿 LDI R19,4 RES1: RCALL DL170

DEC R19

BRNE RES1 ;延时682.75微秒 (最短可555微秒) SBI PORTA,3 ;负脉冲结束 LDI R18,146 RES2: DEC R18

BRNE RES2 RCALL DL170 CBI DDRA3 SBI PORTA,3 CLC

SBIC PINA,3 SEC

RCALL DL170 RET

DL170: LDI R18 ,224 LP170: DEC R18 BRNE LP170 RET

WB: LDI R19,8 MOV R15,R19 SBI DDRA,3

LOOP2: CBI PORTA,3 LDI R19,23 LOP21: DEC R19 BRNE LOP21 ROR R16 BRCC LOP22 SBI PORTA,3 RJNP LOP23 LOP22: CBI PORTA,3 LOP23: LDI R19,88 LOP24: DEC R19 BRNE LOP24 SBI PORTA,3 NOP NOP NOP NOP NOP NOP

;延时110微秒

;总共280微秒 ;转为输入(CHANGE TO INPUT)

;上拉电阻激活(PULL UP MOS ACTIVED) ;18B20存在标志存于 C ;再次延时 ;延时170.75微秒(含RCALL和RET时间);写入1字节数据 ;数据线输出为低 ;延时17微秒

;1位数据由进位C转入PC3 ;延时66微秒

NOP NOP

DEC R15 BRNE LOOP2 RET

RB: LDI R19,8 ;读出1字节数据 MOV R15,R19 LOOP3: SBI DDRA,3

SBI PORTA,3 ;数据线输出为高 LDI R19,5 LOP31: DEC R19 BRNE LOP31 CBI PORTA,3 LDI R19,6 LOP3A:DEC R19 BRNE LOP3A SBI PORTA,3 LDI R19,26 LOP32: DEC R19

BRNE LOP32 CBI DDRA,3 SBI PORTA,3 CLC SBIC PINA,3

SEC LDI R19,88 LOP33:DEC R19 BRNE LOP33 ROR R16 DEC R15 BRNE LOOP3 RET

CRC9: LDI R18,9 CRC90: CLR R15 LDI R19,$8C MOV R14,R19 LP6: LDI R19,8 LD R16,Y+ LP7: LSR R16 ROR R15 BRCC NXRL EOR R15,R14 NXRL: DEC R19 BRNE LP7

;延时3.5微秒 ;数据线输出为低 ;延时4.5微秒 ;数据线输出为高 ;延时19微秒 ;转为输入 ;上拉MOS管激活 ;读出1位数据到C

;延时66微秒 ;9字节数据CRC检测程序 ;异或工作单元

DEC R18 BRNE LP6 RET

;范例101

;本子程序为生成$00--$FF共256个数据之双字节CRC校验码表子程序,生成多项式为 ;P(X)=X16+X15+X2+1=$18005。因每一字节都生成两字节的CRC校验码,故CRC校 ;验码表格长度为512字节。程序中规定将其放在片内SRAM$100--$2FF之中。也可将该

;表存放地址作为子程序的入口条件,在主程序中规定存放地址。使用的单片机为MEGA8 ;/16/128;若使用8515单片机,须使用外部扩展SRAM;本子程序产生的CRC校验码表, ;可直接烧录到FLASH,或另行作为文件保存。 ;若采用4字节的CRC校验码,表格长度达1024字节,则必须使用MEGA103/128等高档AVR

;单片机,或外扩SRAM的8515;故若处理的位序列信息不是很长,或对CRC检测的实时性

;要求不是很强,不必采用查表处理方式。

CRCTABL:LDI XH,$01 ;CRC-CODE-TABLE -GENERATING SUBPROGRAM CLR XL ;CRCTABLE FROM $100 TO $2FF CLR R16 ;USE MEGA8/16/128 LDI R17,$05

LDI R18,$80 ;P(X)=$18005 CRCT0: LDI R19,8 CLR R14

CLR R15 ;add 2bytes $00 behind a Bi CRCT1: LSL R14 ROL R15 ROL R16

BRCC CRCT2 EOR R14,R17 EOR R15,R18 CRCT2: DEC R19 BRNE CRCT1 ST X+,R14 ST X+,R15 INC R16 BRNE CRCT0 RET

;范例102 快速生成位序列校验码/或对接收位序列进行循环冗余检测子程序

;100字节位序列m0,m1,m2,m3,m4,...m98,m99在发送方以递推方式生成CRC校验码子程序

;或在接收方对该序列进行CRC检测之子程序

;在发送方,本程序为CRC校验码生成子程序。将此位序列除以生成多项式P(X) ;=X16+X15+X2+1,将生成的CRC校验码(即余式)装入位序列的最低两位字节

;(冲掉m0,m1),将最终处理的位序列发送出去。

;在接收方,本程序为CRC检测子程序。将接收到的位序列除以生成多项式P(X) ;=X16+X15+X2+1,若将原位序列最低两位字节m0,m1恢复(即除得的余式R15R14 ;与原始位序列最高两位字节相等),则为正确接收。

;本程序中循环次数为98,比位序列字节数少2。因为位序列最低两个字节m0,m1直 ;接作为(第一个)余式,不对它们查取CRC校验码。 ;X为按字节寻址位序列指针

;寻址CRC校验码表格先按字计算地址指针,将其增倍后变为按字节寻址。 CRCOUT:LDI XH,$1 ;THE BIT SEQUENCE IS IN $100---$163 CLR XL ;TOTAL 100 BYTES

LDI R16,$62 ;THE DATA BLOCK LENGTH IS 98(=100-2) LD R14,X+ ;m0 LD R15,X+ ;m1

CRCO1:LD R13,X+ ;fetch m2 at the first! LDI ZH,HIGH(DATA5) LDI ZL,LOW(DATA5) ADD R30,R13 CLR R13

ADC R31,R13 LSL R30

ROL R31 ;point to the CRC CODE! LPM EOR R14,R0 ADIW R30,1 LPM

EOR R15,R0 ;CRC CODE IN R14&R15(HIGH)! DEC R16

BRNE CRCO1 STS $101,R15

STS $100,R14 ;将生成的CRC校验码放在位序列的最低两位字节中 RET ;或将原始位序列的最低两位字节恢复 DATA5:.DB $00,$00,$80,$05 ;THE CRC CODE TABLE

.DB $80,$0F,$00,$0A ;与范例101中SRAM$100--$2FF单元内容完全相同! .DB $80,$1B,$00,$1E ;.................... ;其余略 end

因篇幅问题不能全部显示,请点此查看更多更全内容