AVR单片机 汇编自学笔记 100例
学习笔记-avr单片机C编程1
学习笔记-avr单片机C编程1这几天在看AVR 单片机的书。
ASURO 的项目的编程是建立在已有的成熟函数上,所以导致我对AVR 单片机的运行机理(中断、定时器的使用)不甚了解。
突然一个个超声波模块的程序放在眼前,才发现我连AVR 单片机的了解基本上等于零。
另外一个项目需要用mega128 控制直流电机,还有和无线、有线遥控器的通信,电路(模块)需要自己搭起来,那么就必须知道AVR 单片机的原理和编程。
和已经学过的51 单片机相比,MEGA 系列单片机是十分高级的单片机,功能强大,因而在构造和使用上也复杂了一些。
存储器区别,AVR 分为5 个部分,访问指令上有区别。
输入输出,51 是准双向口,每个端口只有一个寄存器。
而AVR 的I/O 口是标准双向口,每个端口有三个寄存器,DDRX(输出使能),PORTX(输出数据,上拉使能?),PINX(输入管脚)。
定时器,51 的定时器两种用法,即以晶振频率的十二分频信号作为输入的定时器工作方式,或以外部引脚INT0,INT1 上输入信号的计数器工作方式。
而AVR 的定时器除了普通的定时/计数功能外,还有一些增强的功能,如:比较匹配(?),PWM 调制器,由ICP 引脚或模拟比较器触发的捕捉功能(?)。
在选择输入信号上,分频比有1、8、64、256、1024 几种,作为计数器使用,既可上升沿触发,也可以下降沿触发。
如下,一部分和定时器相关的寄存器T0: TCCR0: CS02 CS01 CS00 分频比T1: TCCR1A: COM1X1/0 PWM11/0 TCCR1B: ICNC1,CTC1,ICES1 TCNT1 OCIX 等等 C 中的一些位操作已经模块化了,如PORTB|=(1PWM 脉宽调制波PWM 是脉冲宽度调制的简称。
实际上,PWM 波也是一个连续的方波,但在一个周期中,其高电平和低电平的占空比是不同的。
一个典型PWM 的波形如图8-15 所示。
AVR学习笔记
AVR学习笔记前言:学习一块单片机,我们要几项准备工作:1.开发软件(熟悉开发软件操作流程,基本上开发软件都差不多的,学会了一款,再学其它的就会很顺手了(新建工程、新建设计文件、把源文件加到工程里面、最后设置一些参数)2.编程语言(这个就不用说了,先学语法规则,能够熟练掌握到自己写的代码没有语法错误,然后再逐步把自己的想法驾驭到编程语言上)3.硬件(硬件包括的范围很广,不仅包括你所要学的单片机还有单片机的外围电路所用到的器件),最好要学一款仿真软件。
我们始终要记住学单片机绝对不可以纸上谈兵,一定要实践,就是把自己所写的代码下载到板上,看看实际效果。
开发板可以买,也可以自己做!我喜欢自己做。
实验一:点亮发光二极管1.avr单片机的i/o端口1)学习单片机的主要任务就是了解、掌握单片机i/o端口的功能,以及如何正确设计这些端口与外围电路的连接,从而能够组成一个嵌入式系统,并编程、管理和运用他们完成各种各样的任务。
2)atmega16有4个8位的双向i/o端口pa、pb、pc、pd,他们对外对应32个i/o引脚,每一位都可以独立地用于逻辑信号的输入和输出。
在5v工作电压下,输出高点平时,每个引脚可输出达20ma的驱动电流;而输出低电平时,每个引脚可吸收最大为40ma的电流,可以直接驱动发光二极管(一般的发光二极管的驱动电流为10ma)和小型继电器等小功率器件。
avr大部分的i/o端口都具备双重功能(有的还有第三功能)。
其中第一功能是作为数字通用i/o接口使用,而复用的功能可分别与片内的各种不同功能的外围接口电路组合成一些可以完成特殊功能的i/o口,如定时器、计数器、串行接口、模拟比较器、捕捉器、usart、spi等。
3)avr单片机的每组i/o口都搭载存有三个8为寄存器,分别就是:方向掌控寄存器ddrx、数据寄存器portx、输出插槽寄存器pinx(x=a/b/c/d).i/o口的工作方式和整体表现特征由这三个i/o寄存器掌控。
AVR汇编百例 - 浮点程序库
;范例62.ORG $A00EXCH: MOV R5,R8 ;两浮点数交换子程序MOV R8,R12MOV R12,R5EXCH1: MOV R5,R9 ;尾数交换MOV R9,R13MOV R13,R5MOV R5,R10 ;双字节交换MOV R10,R14MOV R14,R5MOV R5,R11MOV R11,R15MOV R15,R5RETDP: ANDI R16,$7F ;处理积/商数符,计算积/商阶码子程序SBRC R9,7SUBI R16,$80SBRC R13,7SUBI R16,$80 ;积/商符号放在r16,7ADD R12,R8 ;移码相加(除数阶码已求补)LDI R17,$80BRCC DP1ADD R12,R17 ;移码求和有进位,将和再加上$80,再有进位为溢出RETDP1: SUB R12,R17 ;移码求和无进位,将和减去$80,有借位RET ;或差为0也为溢出NEG3: COM R15 ;3字节数据求补COM R14 ;先求反后加1COM R13INC3: LDI R17,255SUB R15,R17 ;以减去-1代替加1SBC R14,R17SBC R13,R17RET;范例63 ;浮点数比较大小子程序X1为被减数X2为减数FPCP: SBRC R9,7 ;X1为正,跳行RJMP CP1SBRC R13,7 ;X2为正,跳行RJMP CP2 ;X1,X2异号FPCP1: CP R11,R15 ;X1,X2皆为正,以尾数低位字节,中位字节,高位字节和CPC R10,R14 ;阶码的顺序(按无符号数)进行比较CPC R9,R13 ;不等,阶码大者浮点数值也大;只有阶码和尾数对应相等,CPC R8,R12 ;两浮点数才相等RET ;比较结果:Z=1时X1=X2,否则C=0时X1>X2,C=1时X1<X2 CP1: SBRC R13,7RJMP CP3 ;两负数比较,转CP2: CP R13,R9 ;正数与负数比较,只比较尾数高位字节即可RETCP3: CP R15,R11 ;X1,X2皆为负,以尾数低位字节,中位字节,高位字节和CPC R14,R10 ;阶码的顺序(按无符号数)进行比较CPC R13,R9 ;但要将X1、X2交换位置后按正数比较过程进行CPC R12,R8CP4: RET ;比较结果:Z=1时X1=X2,否则C=0时X1>X2,C=1时X1<X2;范例64FPSU: LDI R17,$80 ;浮点减法子程序SUB R13,R17 ;减数数符求反后作为加数FPAD: TST R8 ;浮点加法子程序BREQ DON1 ;被加数为0,加数为和TST R12BRNE FPLAD ;加数为0,取被加数为和SA V0: MOV R12,R8 ;传送被加数取代加数MOV R13,R9MOV R14,R10MOV R15,R11DON1: RETFPLAD: ANDI R16,$3f ;清除被加数,加数数符SBRC R9,7ORI R16,$80 ;被加数数符取到(R16,7)SBRC R13,7ORI R16,$40 ;加数数符取到(R16,6)LDI R17,$80OR R9,R17OR R13,R17 ;恢复尾数最高位MOV R17,R12SUB R17,R8 ;计算阶差BREQ GOON ;两阶相等,转BRCC NX3NEG R17 ;不够减求补CPI R17,24BRCC EXAD ;|阶差|>24,取被加数为和NX2A: LSR R13ROR R14ROR R15BRNE NX2A ;加数阶小,右移加数对阶MOV R12,R8 ;取被加数阶为和之阶BRCC GOONRCALL INC3 ;舍入移出位RJMP GOONNX3: CPI R17,24BRCC COM1 ;阶差>24,取加数为和LOOP: LSR R9ROR R10ROR R11DEC R17BRNE LOOP ;加数阶大,右移被加数对阶BRCC GOONRCALL INC3A ;舍入移出位GOON: SBRC R16,6SUBI R16,$80SBRS R16,7 ;判别两数是否同号RJMP SAMS ;同号转SUB R15,R11 ;异号,执行减法,加数为被减数SBC R14,R10SBC R13,R9BRCC NOM ;够减转SUBI R16,$40 ;否则被减数数符求反为和之数符RCALL NEG3 ;并将差求补NOM: MOV R17,R13OR R17,R14OR R17,R15BREQ DON0 ;差为0转NMLOP: SBRC R13,7RJMP COM1LSL R15ROL R14ROL R13DEC R12BRNE NMLOP ;规格化OV1: SEV ;阶码变为0,下溢(可取为0,不算溢出)RETSAMS: ADD R15,R11ADC R14,R10ADC R13,R9 ;两数同号,执行加法BRCC COM1ROR R13ROR R14INC R12 ;有进位时右规1次($7F+1=$80溢出)BREQ OV1 ;阶码增1后变为0为上溢BRNC COM1RCALL INC3COM1: CLVSBRC R16,6RETCOMA: LDI R17,$7FAND R13,R17 ;正数数符为0DON: RETEXAD: RCALL SA V0 ;取被加数为和SBRS R16,7RJMP COMA ;配置数符RETDON0: CLR R12 ;浮点数为0RET;范例65 ;浮点乘法子程序FPMU: TST R8BREQ M0 ;被乘数为0,积为0TST R12BRNE M1 ;乘数为0,积也为0M0: RJMP G0M1: RCALL DP ;处理积符号,计算积之阶码BRCS OV2BREQ OV2 ;判断溢出LDI R17,$80OR R9,R17OR R13,R17 ;恢复尾数最高位MOV R5,R13MOV R6,R14MOV R7,R15 ;乘数转入R5,R6,R7LDI R17,25 ;设右移部分积次数CLR R13CLR R14CLR R15 ;r13r14r15清除,存放积CLCLOOP1: BRCC M2ADD R15,R11ADC R14,R10ADC R13,R9 ;乘数右移移出位为1,被乘数加入部分积1次M2: ROR R13ROR R15ROR R5ROR R6ROR R7 ;部分积连同乘数右移1位DEC R17BRNE LOOP1 ;尾数相乘计算完成?SBRC R13,7RJMP M3 ;乘积最高位为1 转ROL R5ROL R15ROL R14ROL R13 ;乘积最高位为0,高4位字节左移1位SBRS R5,7RJMP M5RCALL INC3 ;末位字节舍入BRNE M5SEC ;舍入后R13变为0ROR R13 ;将其改为$80(即0.5)RJMP COM2M5: DEC R12 ;舍入后R13不为0BRNE COM2 ;阶码减1OV2: SEV ;变为0为溢出RETM3: SBRC R5,7RCALL INC3 ;乘积低3位字节舍入COM2: LDI R17,$7FSBRS R16,7AND R13,R17 ;正数将符号位请除DON2: CLVRET;范例66FPDI: TST R12 ;浮点除法子程序BREQ OV3 ;除数为0,溢出TST R8BRNE D1RJMP G0 ;被除数为0,商为0D1: NEG R12 ;除数阶码求补,以加补码代替减原码RCALL DP ;处理商符号,计算商之阶码BRCS OV3BREQ OV3 ;判断溢出LDI R17,$80OR R9,R17OR R13,R17 ;恢复尾数最高位FPD3: LDI R17,25 ;左移相减试商25次,最后1次舍入SUB R11,R15SBC R10,R14SBC R9,R13BRCS D2 ;第一次尾数相减试商INC R12 ;够减,商阶增1SECBRNE D3 ;商阶增1后不为0,转计商;否则为溢出OV3: SEVRETD2: ADD R11,R15ADC R10,R14ADC R9,R13 ;不够减则恢复被除数LOOP2: LSL R11ROL R10ROL R9 ;被除数算术左移BRCS D4 ;进位位为1,够减,本位商1SUB R11,R15SBC R10,R14SBC R9,R13 ;否则相减试商BRCS D2ASECRJMP D3 ;够减,本位商1D2A: ADD R11,R15 ;不够减,恢复被除数ADC R10,R14ADC R9,R13CLC ;本位商0RJMP D3D4: SUB R11,R15SBC R10,R14SBC R9,R13 ;被除数减去除数D3: DEC R17BRNE D5 ;除法未完成,循环(1-1=0,不溢出)MOV R13,R5MOV R14,R6MOV R15,R7 ;取回商BRCC COM3RCALL INC3 ;第25位商舍入($800000-$FFFFFF不溢出,故INC3不会溢出!)COM3: LDI R17,$7FSBRS R16,7AND R13,R17 ;配置商数符DON3: RETD5: ROL R7 ;在R5,R6,R7中记商(不必预先清除)ROL R6ROL R5 ;商数左移1位并记商RJMP LOOP2;范例67FPSQ: ANDI R16,$7F ;模拟手算开平方子程序SBRC R13,7ORI R16,$80 ;负数建虚根标志FPS0: TST R12BREQ DON4 ;0的平方根为0LDI R17,$80OR R13,R17 ;恢复尾数最高位LSR R12 ;阶码算术右移1位BRCC FSQ2INC R12 ;移出位舍入RCALL INC3 ;先将位数增1(提前舍入)BRCS FSQ1 ;C=1,不够减SECROR R13 ;若尾数变为0将其改为0.5($80-->r13)RJMP FSQ2FSQ1: LSR R13ROR R14ROR R15 ;否则将为数算术右移FSQ2: LDI R17,25 ;开出25位根,末位舍入MOV R8,R17LDI R17,$40ADD R12,R17 ;根恢复为移码CLR R5CLR R6CLR R7 ;根扩展区清除CLR R9CLR R10CLR R11 ;根存储区清除FSQ3: SUB R13,R17SBC R7,R11SBC R6,R10SBC R5,R9 ;试根BRCS FSQ3ASECRJMP FSQ4 ;够减,本位根1FSQ3A: ADD R13,R17ADC R7,R11ADC R5,R9 ;否则恢复开平方数之尾数CLC ;本位商0FSQ4: DEC R8BRNE FSQ5 ;开出第25位根?FQDON: MOV R13,R9MOV R14,R10MOV R15,R11 ;回送根尾数BRCC COM4RCALL INC3 ;第25位根舍入COM4: LDI R17,$7FAND R13,R17 ;根尾数为正数DON4: RETFSQ5: ROL R11ROL R10ROL R9 ;根尾数带进位左移,记根LSL R15ROL R14ROL R13ROL R7ROL R6ROL R5LSL R15ROL R14ROL R13ROL R7ROL R6ROL R5 ;开平方数之尾数连同扩展区左移2位BRCC FSQ3 ;未产生进位,循环RJMP FQDON ;否则进位为第25位根(不须试,并结束子程序)!;范例68 ;牛顿迭代开平方子程序FSQR: TST R12BREQ SQRT ;0的平方根为0ANDI R16,$7ESBRC R13,7ORI R16,$80 ;虚根标志SBRC R12,0INC R16 ;阶码为奇数LDI R17,$7FAND R13,R17 ;尾数变为正数LSR R12ADC R12,R17 ;得到根之移码PUSH R12 ;暂存LDI R17,$80MOV R12,R17SBRC R16,0INC R12 ;得到X1的阶码(0.5≤X1<2)RCALL LD1 ;存X1LSR R13ROR R14ROR R15LDI R17,$40SBRS R16,0 ;阶码为奇数时算术右移尾数即得到X1之尾数;否则将其最;高位字节加上$40OR R13,R17 ;得到首次根r0=(1+x1)/2LDI R17,3MOV R0,R17 ;迭代3次FSQLP: RCALL LD2RCALL GET1RCALL FPDIRCALL GET2RCALL FPADDEC R12 ;计算r(i+1)=(x1/ri+ri)/2DEC R0BRNE FSQLP ;r3的尾数为根之尾数POP R12 ;取回根之阶码SQRT: RET ;r16,7=1 为虚数根;范例69 ;基本运算程序的演示程序DMST1: .EQU SPL=$3D.EQU SPH=$3ELDI R16,2 ;high(ramend)OUT SPH,R16LDI R16,$5F ;low(ramend)OUT SPL,R16LDS R11,$60 ;r11,7:数符r11,6 :阶符r11,5--0:阶(最大为38)LDS R12,$61 ;r12-r15:尾数LDS R13,$62LDS R14,$63LDS R15,$64 ;尾数共8位BCD码RCALL DTOB ;转为二进制浮点数RCALL LD2 ;暂存LDS R11,$65 ;r11,7:数符r11,阶符r11,5--0:阶(最大为38)LDS R12,$66 ;r12-r15:尾数LDS R13,$67LDS R14,$68LDS R15,$69RCALL DTOB ;转为二进制浮点数RCALL GET2 ;取第一操作数RCALL FPAD ;调基本运算子程序之一(FPSU/FPMU/FPDI) RCALL BTOD ;转回十进制浮点数DMRET: RJMP DMRET;范例70 ;辅助子程序KP2: MOV R8,R12 ;复制第二操作数MOV R9,R13MOV R10,R14MOV R11,R15RETLD1: STS $70,R12 ;存浮点数STS $71,R13STS $72,R14SYS $73,R15RETLD2: STS $74,R12 ;存浮点数STS $75,R13STS $76,R14STS $77,R15RETLD3: STS $78,R12 ;存浮点数STS $79,R13STS $7A,R14STS $7B,R15RETGET1: LDS R8,$70 ;取浮点数LDS R9,$71LDS R10,$72LDS R11,$73RETGET2: LDS R8,$74 ;取浮点数LDS R9,$75LDS R10,$76LDS R11,$77RETGET3: LDS R8,$78 ;取浮点数LDS R9,$79LDS R10,$7ALDS R11,$7BRETINVPI: LDI R17,$86 ;取浮点数180/лMOV R8,R17LDI R17,$65MOV R9,R17LDI R17,$2EMOV R10,R17LDI R17,$E1MOV R11,R17RETG90: LDI R17,$87 ;取浮点数90 MOV R8,R17LDI R17,$34MOV R9,R17CLR R10CLR R11RETDTOR: RCALL PI18 ;角度化为弧度RJMP FPMURTOD: RCALL INVPI ;弧度化为角度RJMP FPMUGHPI: LDI R17,$81 ;取浮点数л/2 MOV R8,R17LDI R17,$49MOV R9,R17LDI R17,$0fMOV R10,R17LDI R17,$DBMOV R11,R17RETG01: LDI R17,$7D ;取浮点数0.1 MOV R8,R17LDI R17,$4CMOV R9,R17LDI R17,$CCMOV R10,R17LDI R17,$CDMOV R11,R17RETG1: LDI R17,$81 ;取浮点数1MOV R8,R17CLR R9CLR R10CLR R11RETPI18: LDI R17,$7B ;取浮点数л/180MOV R8,R17LDI R17,$0EMOV R9,R17LDI R17,$FAMOV R10,R17LDI R17,$35MOV R11,R17RETGINT: LDI R17,R12 ;浮点数取整CPI R17,$81BRCC GINT1RCALL G0 ;阶码<$81,结果为0RJMP KP2GINT1: ANDI R16,$DDSBRC R13,7ORI R16,2 ;记数符CPI R17,$98BRCC GOVER ;阶码>$97,溢出RCALL BRK ;分解出整数部分(在R9 R10 R11)SBRS R16,1RET ;正数返回NEG3A: COM R11 ;负数求(r9 r10 r11)之补COM R10COM R9INC3A: LDI R17,255SUBI R11,R17SBCI R10,R17SBCI R9,R17 ;求反后加1RETGOVER: ORI R16,$20 ;设整数部分超过23位标志RETBRK: ANDI R16,$DF ;将正浮点数分解为整数/小数两部分LDI R17,$80OR R13,R17 ;恢复尾数最高位CLR R9CLR R10CLR R11MOV R17,R12SUBI R17,$80BREQ BRKRTBRCS LOOPTCPI R17,$19 ;整数部分超过24位BRCC GOVER ;为溢出LOOP4: LSL R15ROL R14ROL R13ROL R11ROL R10ROL R9DEC R17BRNE LOOPT ;左移位数为阶码-$80,整数部分进入r9-r11中BRKRT: RETLOOPT: LSR R13 ;只有小数部分右移尾数($80-阶码)位ROR R14ROR R15INC R17BRNE LOOPTRETNRML: ANDI R16,$BF ;1字节正整数(在R13中)规格化为浮点数CLR R14CLR R15LDI R12,$88 ;设阶码RJMP NMLOPG10: LDI R17,$84 ;取浮点数10MOV R8,R17LDI R17,$20MOV R9,R17CLR R10CLR R11RETGLN2: LDI R17,$80 ;取浮点数ln2(=0.6931471806)MOV R8,R17LDI R17,$31MOV R9,R17LDI R17,$72MOV R10,R17LDI R17,$18MOV R11,R17RETGLN10: LDI R17,$82 ;取浮点数ln10(=2.302585093)MOV R8,R17LDI R17,$13MOV R9,R17LDI R17,$5DLDI R17,$8EMOV R11,R17RETINVX: TST R12 ;计算1/X, X=0时溢出BRNE INVOV4: SEVRETINV: RCALL G1 ;取1RJMP FPDI;范例71 ;用荷纳法计算多项式值子程序FPLN1: ORI R16,$10 ;设计算奇函数(lnx,sinx,arcsinx 等)标志RCALL LD3 ;存XRCALL KP2RCALL FPMU ;计算X2RJMP FLN0 ;FPLN2: ANDI R16,$EF ;设计算偶函数(EXP,COSX等)标志FLN0: RCALL LD1 ;存T,T=X 或T=X2POP R30POP R31 ;系数表数据地址进入ZLSL R30ROL R31 ;由按字取数变为按字节取数LPM ;r0<--(z)取阶码MOV R8,R0ADIW R30,1 ;指针增1LPM ;取尾数高位字节MOV R9,R0ADIW R30,1 ;z+1LPM ;取尾数中位字节MOV R10,R0ADIW R30,1 ;z+1LPM ;取尾数低位字节MOV R11,R0 ;取浮点数到r8 r9 r10&r11ADIW R30,1 ;z+1PLN: RCALL M1 ;计算(....((An*T+A(n-1))*T+A(n-2))*T+....+Ai)*T LPMMOV R8,R0ADIW R30,1LPMMOV R9,R0ADIW R30,1LPMADIW R30,1LPMMOV R11,R0 ;取A(i-1)ADIW R30,1RCALL FPLAD ;计算(....((An*T+A(n-1))*T+A(n-2))*T+....+Ai)*T+A(i-1)LPMRCALL GET1DEC R0BRNE PLN ;1为停止符号;否则继续计算PEND: SBRS R16,4RJMP RENDRCALL GET3 ;奇函数取出自变量RCALL M1 ;自变量乘以计算结果才是函数值REND: LSR R31ROR R30 ;Z指针折半后ADIW R30,1 ;增1为后继指令地址IJMP ;转到该地址去执行;范例72LNX: TST R12 ;对数函数子程序BREQ OV5SBRS R13,7RJMP LN1OV5: SEV ;求负数或0的对数为错误RETLN1: ANDI R16,$7E ;R16,7:(T-1)/(T+1)或(2T-1)/(2T+1)之符号R16,0:p之符号; mMOV R0,R12 ;设X=2 *T, 则LnX=m*Ln2+LnT,存入p=mLDI R17,$F3CP R15,R17LDI R17,$04CPC R14,R17LDI R17,$35CPC R13,R17 ; _BRCC LN5 ;T>√2/2时跳转DEC R0 ;取p=m-1 LnX=(m-1)*Ln2+LN(2T)MOV R17,R15OR R17,R14OR R17,R13MOV R12,R17BREQ LN5A ;2T-1=0 只须计算(m-1)Ln2RCALL KP2 ;R12 NOUSED!LSL R9ROL R10ROL R11 ;(2T-1)LSR R13ROR R14ROR R15LDI R17,$80OR R13,R17 ;2T+1LDI R17,$7EMOV R12,R17 ;取1/(2T+1)的阶码RJMP LNTLPLN5: ORI R16,$80 ;(T-1)为负,数符位改为1RCALL KP2RCALL NEG3ALDI R17,$80ADD R9,R17 ;计算(T-1)LSR R13ROR R14ROR R15LDI R17,$C0OR R13,R17LDI R17,$7FMOV R12,R17 ;取1/(T+1)的阶码LNTLP: LSL R11ROL R10ROL R9 ;(2T-1)或(T-1)规格化DEC R12 ;调整(2T-1)/(2T+1))或(T-1)/(T+1)的阶码SBRS R9,7RJMP LNTLPRCALL FPD3 ;计算(2T-1)/(2T+1)或(T-1)/(T+1) 位r16,7为商之数符PUSH R0RCALL FPLN1 ;计算LnT或Ln(2T).DB $7E,$12,$49,$25 ;0.14285714 ;er.total<0.000000029!.DB $7E,$4C,$CC,$CD ;0.2.DB $7F,$2A,$AA,$AB ;0.33333333.DB $81,$00,$00,$00 ;1.DB $01,$00 ;结束符INC R12POP R0LN5A: LDI R17,$80ADD R0,R17BREQ LN53 ;p=$80结束BRCS LN51NEG R0INC R16 ;p为负数LN51: RCALL LD1 ;存LnT或Ln(2T)MOV R13,R0RCALL NRML ;|P|规格化RCALL GLN2 ;取ln2RCALL FPMU ;计算|p|*ln2RCALL GET1 ;取LnT或Ln(2T)SBRS R16,0RJMP LN52RCALL FPSU ;p<0 计算lnT-|p|*ln2或Ln(2T)-|p|*ln2RETLN52: RCALL FPAD ;p>0 计算lnT+|p|*ln2或Ln(2T)+|p|*ln2 LN53: RET;范例73 ;对数衍生函数子程序LGX: RCALL LNX ;计算lnxRCALL GLN10 ;取ln10RCALL EXCHRJMP FPDI ;转计算lgx=lnx/ln10LGAX: RCALL LD2 ;存aRCALL EXCHRCALL LNX ;计算lnxRCALL GET2 ;取aRCALL LD2 ;存lnxRCALL EXCHRCALL LNX ;计算lnaRCALL GET2 ;转计算logax=lnx/lnaRJMP FPDI;范例74EXP: MOV R17,R12 ;指数函数子程序CPI R17,$68 ;X之阶<$68E1: BRCC E2RCALL G0ROR R12 ;(R12)=$80INC R12 ;取exp=1RETE2: ANDI R16,$3F ;r16,6:数符SBRC R13,7ORI R16,$40 ;负数LDI R17,$7FAND R13,R17 ;取正(取|X|)LDI R17,$33CP R15,R17LDI R17,$0FCPC R14,R17LDI R17,$30CPC R13,R17LDI R17,$87CPC R12,R17 ;|X|与88.02969 比较BRCS E3 ;|X|<88.02969 转SBRS R16,6RJMP OV6G0: CLR R12 ;若x<-88.02969CLR R13CLR R14 ;Exp=0CLR R15RETOV6: SEV ;x>88.02969,Exp溢出RETE3: CLR R0 ;X整数部分予清除LDI R17,$81MOV R8,R17LDI R17,$38MOV R9,R17LDI R17,$AAMOV R10,R17LDI R17,$3BMOV R11,R17 ;取log2e(=1/ln2)RCALL FPMU ;计算X/ln2LDI R17,$80SBRC R16,6OR R13,R17MOV R17,R12CPI R17,$81BRCS E6 ;X/ln2整数部分为0 转RCALL BRK ;否则分解该数为整数I(在R11),小数F两部分LDI R17,$80MOV R12,R17RCALL NOM ;小数部分规格化为浮点数SBRC R16,6NEG R11 ;整数部分求补MOV R0,R11 ;E6: PUSH R0RCALL FPLN2 ;计算EXP(F*ln2).DB $69,$5A,$92,$9F ;0.10178086 E-6 ;er.total<0.000000024.DB $6D,$31,$60,$11 ;0.13215487 E-5.DB $70,$7F,$E5,$FE ;0.15252734 E-4.DB $74,$21,$84,$89 ;0.15403530 E-3.DB $77,$2E,$C3,$FF ;0.13333558 E-2.DB $7A,$1D,$95,$5B ;0.96181291 E-2.DB $7C,$63,$58,$47 ;0.55504109 E-1.DB $7E,$75,$FD,$F0 ;0.24022651.DB $80,$31,$72,$18 ;0.69314718.DB $81,$00,$00,$00 ;1.DB $01,$00 ;结束符POP R0ADD R12,R0 ;整数部分I 加入阶码中RET;范例75 ;指数衍生函数子程序DXP: RCALL GLN10 ;取ln10RJMP EXP0 ;转计算EXP(X*ln10) AXP: RCALL LD2 ;存XRCALL EXCHRCALL LNX ;计算lnaRCALL GET2 ;取出xEXP0: RCALL FPMURJMP EXP ;转计算EXP(X*lna);范例76 ;双曲函数和反双曲函数子程序SHX: RCALL SUB11 ;计算双曲正弦RCALL FPSUBRNE NX48RETCHX: RCALL SUB11 ;计算双曲余弦RCALL FPADNX48: DEC R12RETSUB11: RCALL EXPRCALL LD2RCALL INVXRJMP GET2ASHX: RCALL SUB2 ;计算反双曲正弦RCALL FPADASH: RCALL FPSQRCALL GET2RCALL FPADRJMP LNXACHX: RCALL SUB2 ;计算反双曲余弦RCALL EXCHRCALL FPSURJMP ASHSUB2: RCALL LD2 ;存XRCALL KP2RCALL FPMU ;得到X2RJMP G1 ;取浮点数1; 范例77 ;正弦函数子程序SINX: RCALL RTOD ;弧度化为角度SINX1: CLR R16 ;X1为角度SBRC R13,7INC R16 ;存数符LDI R17,$7F ;X1-->|X1|AND R13,R17NX30: RCALL G90INC R8INC R8 ;取360°RCALL FPCP1 ;|X1|与360°比较BREQ GE0 ;相等,转出BRCC NX31 ;|X1|<360°转出RCALL EXCHRCALL FPSU ;否则|X1|-360°-->|X1|RJMP NX30 ;循环NX31: DEC R8RCALL FPCP1 ;|X1|与180°比较BREQ GE0 ;相等,转出BRCC NX32 ;|X1|<180°,转RCALL EXCHRCALL FPSU ;否则|X1|-180°-->|X1|INC R16 ;将数符求反NX32: RCALL G90RCALL FPCP1 ;|X1|与90°比较BRCC NX36INC R8RCALL FPSU ;|X1|>90°,取180°-|x1|-->|x1| RJMP NX36GE0: RJMP G0 ;|X1|=0 则sinX=0NX36: RCALL DTOR ;变回弧度XMOV R17,R12CPI R17,$79 ;阶码<$79,sinX=XBRCS PP2RCALL FPLN1 ;计算sin|X|.DB $60,$30,$92,$32 ; 0.16059044 E-9 er.total<0.0000000071.DB $67,$D7,$32,$2A ;-0.25052108 E-7.DB $6E,$38,$EF,$1C ; 0.27557319 E-5.DB $74,$D0,$0D,$01 ;-0.19841270 E-3.DB $7A,$08,$88,$88 ; 0.83333333 E-2.DB $7E,$AA,$AA,$AA ;-0.16666667.DB $81,$00,$00,$00 ;1.DB $01,$00 ;结束符PP2: LDI R17,$80SBRC R16,0PP3: OR R13,R17 ;配置数符DON6: RET;范例78 ;衍生三角函数子程序CTNX: RCALL RTOD ;弧度化为角度CTNX1: RCALL TANX1 ;计算tgXRJMP INVX ;取倒数为ctgXTANX: RCALL RTOD ;弧度化为角度TANX1: RCALL LD2 ;存XRCALL SINX1 ;计算sinXRCALL GET2 ;取XRCALL LD2 ;存sinXRCALL EXCHRCALL COSX1 ;计算cosXBRNE NX39OV7: SEVRET ;cosX=0,溢出NX39: RCALL GET2 ;取sinXRJMP FPDI ;tgX=sinX/cosXCOSX: RCALL RTOD ;弧度化为角度COSX1: RCALL G90 ;取浮点数90°RCALL FPSURJMP SINX1 ;cosX=sin(90-X);范例79 ;反正弦函数子程序ASINX: MOV R17,R12CPI R17,$78BRCS DON6 ;X阶码<$78,acrsinX=XANDI R16,8 ;清除数符和|X|>0.5标志,保留计算acosx标志(R16,3)SBRC R13,7INC R16 ;记数符LDI R17,$7FAND R13,R17 ;取绝对值X-->|X|RCALL G1RCALL FPCP1BREQ AABRCC AA1OV8: SEV ;|X>1,溢出RETAA: RCALL GHPIRCALL EXCHRJMP PP2 ;|X|=1,arcsinX=±л/2AA1: MOV R17,R12CPI R17,$80BRNE AS1 ;|X|<0.5,y=|x|MOV R17,R13OR R17,R14OR R17,R15BREQ AS1 ;X=0.5,y=|x|ORI R16,$20 ;X>0.5,建标RCALL NEG3LDI R17,$80ADD R13,R17LDI R17,$7FMOV R12,R17 ;((1-|x|)/2)方根之阶最大为$7FNRMLP: LSL R15ROL R14ROL R13DEC R12SBRS R13,7RJMP NRMLP ; __________RCALL FPS0 ;√(1-|X|)/2-->yAS1: RCALL FPLN1 ;计算arcsiny.DB $7A,$3D,$43,$C4 ;0.11551801 E-1 er. total<0.0000000245 .DB $7A,$64,$CC,$CD ;0.13964844 E-1.DB $7B,$0E,$27,$62 ;0.17352764 E-1.DB $7B,$37,$45,$D1 ;0.22372159 E-1.DB $7B,$78,$E3,$8E ;0.30381944 E-1.DB $7C,$36,$DB,$6E ;0.44642857 E-1.DB $7D,$19,$99,$9A ;0.075.DB $7E,$2A,$AA,$AA ;0.16666667.DB $81,$00,$00,$00 ;1.DB $01,$00 ;结束符SBRS R16,5RJMP PP2 ;|x|≤0.5 转配置数符,有acsin|x|=acsinyINC R12 ;否则取2arcsiny(=arccosx)SBRC R16,3 ;测试计算ARCCOSX的标志RJMP ACSRT ;有计算ARCCOSX标志,转清除该标志(其余计算在ACOSX子程序中完成)RCALL GHPI ;否则取л/2AS2: RCALL FPSU ;|X|>0.5时,arcsin|X|=л/2 -2arcsinyPP20: RJMP PP2 ;转去配置数符;范例80 ;函数值为弧度的反三角函数子程序ACOSX: ORI R16,8 ;设计算arccosx标志RCALL ASINX ;调反正弦函数子程序RCALL GHPI ;取л/2SBRC R16,3 ;计算ARCCOS|X|标志未被清除?RJMP AS3 ;是,转计算arccosx=л/2-arcsinxSBRS R16,0 ;x>0且x>0.5RJMP ACSRT ;有arccosx=2arcsiny!INC R8 ;否则取л;即当x<0且|X|>0.5时,有arccosX=л-2arcsinyAS3: RCALL FPSUACSRT: ANDI R16,$F7 ;清除计算arccosx标志RETATANX: MOV R17,R12 ;反正切函数子程序CPI R17,$98BRCS AT1RCALL GHPI ;X阶码大于$98,取л/2RCALL EXCHROL R9BRCC AT2LDI R17,$80OR R13,R17 ;arctgx=л/2AT2: RETAT1: MOV R17,R12CPI R17,$74 ;X阶码小于$74,arctgX=XBRCS AT2RCALL KP2RCALL LD1 ;存XRCALL FPMURCALL G1RCALL FPAD ; _______RCALL FPSQ ;计算√(1+X2)RCALL GET1RCALL FPDIRJMP ASINX ;转计算arctgx=arcsin(X/√<(1+X2)ACTNX: RCALL ATANX ;反余切函数子程序RCALL GHPIRJMP FPSU ;arcctgX=л/2-arctgx;范例81 ;函数值为角度的反三角函数子程序ASNX: RCALL ASINX ;反正弦函数子程序,结果以角度表示RJMP RTODACSX: RCALL ACOSX ;反余弦函数子程序,结果以角度表示RJMP RTODATNX: RCALL ATANX ;反正切函数子程序,结果以角度表示RJMP RTODACNX: RCALL ACTNX ;反余切函数子程序,结果以角度表示RJMP RTOD;范例82 ;函数计算子程序演示程序DMST2: LDI R16,2OUT SPH,R16LDI R16,$5F ;堆栈指针初始化OUT SPL,R16LDS R11,$65 ;取操作数(自变量X)LDS R12,$66 ;r11,7:数符r11,6:阶符LDS R13,$67 ;r11,5--0:阶(最大为38)LDS R14,$68LDS R15,$69 ;r12-r15:十进制尾数(8位BCD码)RCALL DTOB ;翻为二进制浮点数RCALL LNX ;调函数子程序之一RCALL BTOD ;将函数值转为十进制浮点数DMHER: RJMP DMHER;范例83 ;阶乘子程序NP: RCALL G1 ;取浮点数1MOV R17,R12 ;二进制整数N在R12中CPI R17,2 ;N<2,N!=1BRCS GGCPI R17,34BRCS NX59OV9: SEV ;N>33,溢出RETGG: RJMP SA V0 ;取N!=1NX59: MOV R0,R12 ;存NDEC R0 ;N-1PUSH R17 ;取T=1 并存入LDI R17,$81STS $70,R17CLR R17STS $71,R17STS $72,R17STS $73,R17 ;存储浮点数1L43: POP R13 ;取TINC R13 ;T+1-->TPUSH R13 ;存TRCALL NRML ;T规格化RCALL GET1 ;取阶段阶乘结果RCALL FPMU ;得到当前T!RCALL LD1DEC R0BRNE L43 ;T=N时得到N!POP R0RET;范例84 ;长整数(r9,r10,r11,r12)规格化为浮点数LINOM: BST R9,7 ;数符存于TBRTC LI10CLR R16 ;负数求补SUB R16,R12MOV R12,R16CLR R16SBC R16,R11MOV R11,R16CLR R16SBC R16,R10MOV R10,R16CLR R16SUB R16,R9MOV R9,R16LI10: LDI R16,$A0 ;取阶32(长整数共32位)LP10: SBRC R9,7RJMP NX63 ;最高位为1,已规格化LSL R12ROL R11ROL R10ROL R9 ;否则左规1位DEC R16 ;阶码减1BRNE LP10RJMP G0 ;左规达32次,浮点数为0;范例85 ;定点十进制数翻为二进制浮点数DTOB1: RCALL LD1 ;存入十进制小数RCALL CONV2 ;定点整数十翻二RCALL GET1 ;取出十进制小数RCALL LD1RCALL SA V0RCALL CONV4 ;定点小数十翻二RCALL GET1 ;取出二进制定点整数LDI R16,$98 ;予设阶码LP11: SBRC R9,7RJMP NX63 ;最高位为1,已规格化LSL R15ROL R14ROL R13ROL R12ROL R11ROL R10ROL R9 ;整数和小数部分左移一位DEC R16 ;阶码减1CPI R16,$60BRNE LP11RET ;得到浮点数0NX63: MOV R13,R9MOV R14,R10MOV R15,R11 ;尾数取到r13-r15SBRS R12,7RJMP PP6RCALL INC3 ;尾数截去部分舍入BRNE PP6INC R16 ;尾数变为0将阶码增1SECROR R13 ;$80-->r13,即将尾数变为0.5PP6: MOV R12,R16 ;取回阶码BLD R13,7 ;装入数符(T-->R13,7)RET;范例86 ;浮点数十翻二DTOB: ANDI R16,$FC ;r11,7:数符r11,6:阶符r11,5--0:阶(最大为38)SBRC R11,6 ;R12---R15;8BCD码尾数INC R16 ;阶符存于R16,0SBRC R11,7ORI R16,2 ;数符存于R16,1MOV R17,R11ANDI R17,$3F ;取阶MOV R0,R17 ;存于R0MOV R8,R12OR R8,R13OR R8,R14OR R8,R15BREQ PP8 ;十进制浮点数尾数为0,取二进制浮点数0 PUSH R16RCALL CONV4 ;十进制浮点数尾数翻为二进制定点小数MOV R16,R15MOV R15,R14MOV R14,R13MOV R13,R12 ;二进制定点小数转入r13r14r15r16LDI R17,$80 ;予设阶码MOV R12,R17LP14: SBRC R13,7RJMP NX67LSL R16ROL R15ROL R14ROL R13DEC R12RJMP LP14 ;二进制定点小数规格化为浮点数NX67: SBRS R16,7RJMP NX66RCALL INC3 ;调整BRNE NX66INC R12SEC ;调整后结果为0将其改为0.5ROR R13 ;即$80-->r13NX66: LDI R17,$7FPOP R16SBRS R16,1AND R13,R17 ;配置数符SBRS R16,0RJMP DBL4 ;正阶转DBL1: LDI R17,$10SUB R0,R17BRCS DBL2RCALL INVDP ;RCALL FPMU ;阶码减10, X*10ˉ1o -->X RJMP DBL1DBL2: ADD R0,R17 ;不够减则恢复阶BREQ PP8DBL3: RCALL G01 ;取0.1RCALL FPMUDEC R0 ;X*0.1-->X,阶减1BRNE DBl3RETDBL4: LDI R17,$10SUB R0,R17 ;阶减10BRCS DBL5RCALL DDP ;X*101o -->XRCALL FPMURJMP DBL4DBL5: ADD R0,R17 ;不够减则恢复阶BREQ PP8DBL6: RCALL G10RCALL FPMUDEC R0 ;X*10-->X,阶减1BRNE BDL6PP8: RETINVDP: LDI R17,$5F ;取浮点数10ˉ1oMOV R8,R17LDI R17,$5BMOV R9,R17LDI R17,$E6MOV R10,R17LDI R17,$FFMOV R11,R17RET ;DDP: LDI R17,$A2 ;取浮点数101oMOV R8,R17LDI R17,$15MOV R9,R17LDI R17,$02MOV R10,R17LDI R17,$F9MOV R11,R17RET;范例87 ;浮点数二翻十BTOD: TST R12BREQ PP4 ;转取十进制浮点数0ANDI R16,$FC ;予清十进制浮点数数符及阶符(r16,1&0) CLR R0 ;予清十进制浮点数之阶SBRC R13,7ORI R16,2 ;取数符LDI R17,$7FAND R13,R17 ;取绝对值BTA: RCALL DDPRCALL FPCP1 ;|X|与101o 比较BREQ BTBBRCC BTC ;|X|<101o 转BTB: RCALL INVDPRCALL FPMU ;|X|*10ˉ1o-->|X|LDI R17,$10ADD R0,R17 ;十进制浮点数阶加10RJMP BTABTC: RCALL INVDP ;RCALL FPCP1 ;|X|与10ˉ1o 比较BREQ BTC1 ;BRCS BT0 ;|X|>10ˉ1o 转BTE: RCALL DDP ;RCALL FPMU ;|X|*101o -->|X|LDI R17,$10ADD R0,R17 ;十进制浮点数阶加10ORI R16,1 ;置负阶RJMP BTCBTC1: LDI R17,9 ;|X|=10ˉ1o 特别处理ADD R0,R17 ; -9ORI R16,1 ;取0.1*10SJMP BT4BT0: RCALL G1RCALL FPCP1 ;|X|与1比较BREQ BT1BRCC BT2 ;|X|<1转BT1: RCALL G01RCALL FPMU ;|X|*0.1-->|X|INC R0 ;十进制浮点数阶加1RJMP BT0BT2: RCALL G01RCALL FPCP1 ;|X|与0.1比较BREQ BT4BRCS BDS ;|X|≤0.1转出BT3: RCALL G10RCALL FPMU ;|X|*10--->|X|INC R0 ;十进制浮点数阶加1ORI R16,1 ;置负阶RJMP BT2PP4: RJMP KP2 ;十进制浮点数取为0BT4: LDI R17,$10MOV R9,R17CLR R10CLR R11CLR R12 ;十进制浮点数尾数取为0.10000000BT6: MOV R8,R0 ;取十进制浮点数阶SBRS R8,3RJMP BT7SBRC R8,1SUBI R8,$FA ;对产生非法BCD调整(加6)BT7: LDI R17,$40SBRC R16,0OR R8,R17 ;配置阶符(r8,6)LSL R17SBRC R16,1OR R8,R17 ;配置阶浮(r8,7)RETBDS: RCALL BT6 ;BT6将十进制浮点数阶,阶符和数符配置到R8 LDI R17,$80OR R13,R17 ;恢复尾数最高位LDI R17,$98SUB R17,R12 ;右移次数为($98-阶码)RJMP CONV31 ;调CONV31子程序完成尾数二翻十,结果在(r9r10r11r12);范例88 ;二进制浮点数快速翻为定点十进制数,整数在r9,r10,r11中,小数在r13,r14,r15中FBTOD: RCALL BRK ;二进制浮点数分解为整数和小数两部分SBRC R16,5RET ;整数部分多于24位,溢出MOV R0,R13MOV R5,R14MOV R8,R15 ;小数部分转入R0R5R8RCALL CONV1 ;定点整数二翻十,结果在R12,R13,R14,R15RCALL LD1 ;十进制整数-->RAMMOV R15,R8MOV R14,R5MOV R13,R0 ;取回二进制小数RCALL CONV3 ;定点小数二翻十,结果在r9,r10,r11,r12RCALL EXCH1 ;十进制定点小数转入r13,r14,r15,r12RCALL GET1 ;取出十进制定点整数r8,r9,r10,r11)/小数在r13,r14,r15,r12CLR R16 ;清除无用的标志!RET;范例89.ORG $E80 ;最小二乘法拟和直线子程序.EQU NUMB=10 ;取10点,即十对浮点数,按增地址存放Y1,X1,Y2,X2,..Yn,Xn .EQU TABLA=$9000 ;数据表,第一个浮点数为Y1STRT: LDI R28,$70CLR R29 ;POINT TO $0070LP51: ST Y+,R29 ;累加和或暂存区清除(LD1,LD2,LD3,LD4和LD5子程序工作区)CPI R28,$84BRNE LP51LDI R16,NUMB ;取拟合点数MOV R0,R16LDI R29,$90CLR R28 ;参加拟合数据首地址$9000IN R16,MCUCR,7SBR R16,$C0 ;片外RAM,选一个读写等待周期OUT MCUCR,R16LOOP3: RCALL GETA ;取浮点数Yi 占4字节即Yi0,Yi1,Yi2,Yi3 RCALL INVX ;计算1/YiRCALL LD6 ;暂存RCALL GET1 ;取累加和nRCALL FPAD ;1/Yi加入累加和(∑1/Yi是∑1/Yi 简写形式,下同)RCALL LD1 ; i=1RCALL GET6 ;取1/YiPUSH R28PUSH R29 ;保护堆栈指针RCALL GETA ;取浮点数Xi(Xi0,Xi1,Xi2,Xi3)占4字节POP R29POP R28 ;恢复堆栈指针,仍指向XiRCALL FPMU ;计算Xi/YiRCALL LD7 ;暂存RCALL GET2RCALL FPAD ;Xi/Yi加入累加和∑(Xi/Yi)RCALL LD2RCALL GET7 ;取出Xi/YiRCALL SA V0 ;RCALL FPMU ;计算(Xi/Yi)2RCALL GET3RCALL FPAD ;(Xi/Yi)2加入累加和∑(Xi/Yi)2RCALL LD3RCALL GET6 ;取1/YiRCALL SA V0 ;RCALL FPMU ;计算1/Yi2RCALL LD6 ;暂存RCALL GET4RCALL FPAD ;1/Yi2 加入累加和∑1/Yi2RCALL LD4RCALL GET6 ;取出1/Yi2RCALL GETA ;再取XiRCALL FPMU ;计算Xi/Yi2RCALL GET5RCALL FPAD ;Xi/Yi2加入累加和∑Xi/Yi2RCALL LD5DEC R0 ;点数减1BRNE LOOP3 ;未到总点数n,循环RCALL GET4RCALL SA V0RCALL GET3RCALL FPMU ;计算(∑1/Yi2)*(∑(Xi/Yi)2) 并存入RCALL LD6RCALL GET5 ;取出∑Xi/Yi2RCALL SA V0RCALL FPMU ;计算(∑Xi/Yi2)2RCALL GET6RCALL FPSU ;计算c=(∑1/Yi2)*(∑(Xi/Yi)2-(∑Xi/Yi2)2 RCALL LD6 ;存入RCALL GET2RCALL SA V0RCALL GET4RCALL FPMU ;计算(∑(Xi/Yi)*(∑1/Yi2)并存入RCALL LD7RCALL GET1RCALL SA V0RCALL GET5RCALL FPMU ;计算(∑1/Yi)*(∑(Xi/Yi2) 并存入RCALL GET7RCALL FPSU ;计算d=(∑Xi/Yi)*(∑1/Yi2)-(∑1/Yi)*(∑Xi/Yi2)) RCALL GET6 ;取cRCALL EXCHRCALL FPDI ;计算b=d/c并存入RCALL LD7RCALL GET5 ;取∑Xi/Yi2RCALL FPMU ;计算(∑Xi/Yi2)*bRCALL GET1RCALL FPSU ;计算(∑1/Yi)-(∑Xi/Yi2)*bRCALL GET4 ;取∑1/Yi2RCALL EXCHRCALL FPDI ;计算a=(∑1/Yi-(∑Xi/Yi2)*b)/∑1/Yi2 RCALL LD6 ;结果a在$84-$87中,b在$88-$8b中RERGETA: LD R12,Y+LD R13,Y+LD R14,Y+LD R15,Y+ ;从外部SRAM中取浮点数到R12-R15 RETLD4: STS $7C,R12 ;存浮点数STS $7D,R13STS $7E,R14STS $7F,R15RETLD5: STS $80,R12 ;计算∑Xi/Yi2的存储单元STS $81,R13STS $82,R14STS $83,R15RETLD6: STS $84,R12 ;暂存1/Yi,1/Yi2等浮点数STS $85,R13STS $86,R14STS $87,R15RETLD7: STS $88,R12 ;暂存Xi/Yi等浮点数STS $89,R13STS $8A,R14STS $8B,R15RETGET4: LDS R8,$7C ;取浮点数LDS R9,$7DLDS R10,$7ELDS R11,$7FRET ;GET5: LDS R8,$80 ;取∑Xi/Yi2或中间结果LDS R9,$81LDS R10,$82LDS R11,$83RETGET6: LDS R8,$84 ;取浮点数1/Yi,1/Yi2等LDS R9,$85LDS R10,$86LDS R11,$87RETGET7: LDS R8,$88 ;取浮点数Xi/Yi等LDS R9,$89LDS R10,$8ALDS R11,$8BRET;范例90GETAD: LDI R17,0Bxxx01110;PC0&PC4输入/PC1-PC3输出&PC3(CAL) OUT DDRC,R17 ;CBI PORTC,1GAD1: SBI PORTC,4SBIB PINC,4 ;查DRDYRJMP GAD1 ;低为数据准备好GAD2: SBI PORTC,4SBIC PINC,4 ;PINC:$13/PORTB:$15RJMP GAD2 ;DRDY低有效CBI PORTC,2 ;置片选有效LDI R16,16 ;16位数据GETL0: CLC ;予清除CSBI PORTC,0SBIC PINC,0 ;接收一位数据SECROL R14 ;数据高位在前ROL R13 ;在R13R14里带进位左移SBI PORTC,1CBI PORTC,1 ;发出时钟,下降沿读出数据DEC R16BRNE GETL0SBI PORTC,2 ;置片选无效MOV R4,R14 ;MOV R3,R13 ;保存GADCOM: CLR R15 ;3字节小数r13r14r15(0)规格化为浮点数LDI R16,$80MOV R12,R16 ;阶码为$80GAD: SBRC R13,7RJMP GETL2LSL R14。
AVR汇编百例 - 实用程序
;范例19 ;等步距线性内插计算子程序.EQU TBLGTH=10CHETA: LDI R16,TBLGTH-1 ;r16<--表长(即字数)-1LDI R31,HIGH(chtbl*2);y0(函数初值)在r14r15,STEP(步长)在r10r11,自变量X 在r12r13LDI R30,LOW(chtbl*2+1);查表指针,首指数据表第1字之高位字节!RCALL CPMR1 ;X与表中第一个字型数据(X0)比较BRCC CHRET ;X<X0 查表结束,Y=Y0CHET1: RCALL CMPR1 ;X与表中下一个数据比较BRCC NX33 ;X<X(i+1) 找到插值区间ADD R15,R11 ;否则Y0中加入一个STEP:Yk=Y0+k*step(步距为负时则;减去|STEP|)ADC R14,R10DEC R16BRNE CHET1 ;未查到表格终值,循环;否则结束,Y取得最大值Yn CHRET: RETNX33: SBIW R30,5 ;指针退回(-5),指向XiMOV R8,R14MOV R9,R15 ;保存Y0+i*STEPRCALL SUBS ;(X-Xi)-->r16r17MOV R15,R17MOV R14,R16 ;转入r14r15RCALL MUL16 ;(X-Xi)*STEP-->r12r13r14r15MOV R10,R12MOV R11,R13 ;保存乘积高位字LPM ;X(i+1)低位字节MOV R13,R0ADIW R30,1LPM ;X(i+1)高位字节MOV R12,R0SBIW R30,3 ;指针指向XiRCALL SUBS ;X(i+1)-Xi-->r16r17MOV R12,R10MOV R13,R11 ;取回乘积高位字MOV R10,R16MOV R11,R17 ;X(i+1)-Xi-->r10r11RCALL DIV165 ;(X-Xi)*STEP/[X(i+1)-Xi]-->r14r15ADD R15,R9ADC R14,R8 ;Y0+i*STEP+(X-Xi)*STEP/[X(i+1)-Xi]-->r14r15RET ;若STEP为负值则改为计算(r8r9)减去(r14r15)之值CMPR1: LPM ;取数据高位字节ADIW R30,2 ;指向下一数据的高位字节CP R0,R12 ;与X高位字节相比较BRNE CPRT1 ;不相等即转出SBIW R30,3 ;否则调整指针LPM ;取数据低位字节ADIW R30,3 ;指向下一数据的高位字节CP R0,R13 ;与X低位字节相比较CPRT1: RET ;以进位C带回比较结果SUBS: LPM ;计算(X-Xi)或[X(i+1)-Xi]并送入r16r17MOV R5,R0 ;取Xi低位字节ADIW R30,1LPM ;取Xi高位字节SBIW R30,1 ;仍指向Xi低位字节SUB R13,R5MOV R17,R13SBC R12,R0MOV R16,R12 ;计算差并将其转入R16R17RET;自变量x表长为12字CHTBL:DW 19214,23404,27600,32799,37009,40211,45414,48618,51821,55029,57787,60070 ;步距表长为11字STEPT: DW 356,366,379,395,415,440,471,509,555,603,657;不等步距线性内插计算子程序,步距表首址在R6R7中;自变量X在R12R13之中,函数初值Y0在R14R15中;范例20 ;表长(字个数)-1在R16中CHTSTP: LDI R31,HIGH(chtbl*2)LDI R30,LOW(chtbl*2+1);查表指针LDI R16,LOW(stept*2)MOV R7,R16LDI R16,HIGH(stept*2)MOV R6,R16 ;步距表指针LDI R16,TBLGTH-1 ;r16<--表长(字个数)-1RCALL CMPR1 ;X与表首数据比较BRCC CHSTPT ;X<X0 查表结束,有Y=Y0CHSTP1: RCALL CMPR1 ;否则与表中下一数据比较BRCC CHSTP3 ;X<X(i+1),找到插值区间!RCALL GTSTP ;查表取STEP字型变量ADD R15,R11 ;Y0<--Y0+STEPkADC R14,R10DEC R16BRNE CHSTP1 ;未查到表格终值循环;否则结束,Y取得最大值Yn CHSTPT: RETCHSTP3: SBIW R30,5 ;指针退回,指向Xi低位字节MOV R8,R14MOV R9,R15 ;Y0+∑STEPk送入r14 r15RCALL SUBS ;(X-Xi)->r16r17MOV R14,R16 ;(X-Xi)转入R14R15RCALL GTSTP ;查表取STEPi-->R10R11RCALL MUL16 ;(X-Xi)*STEPi-->R12R13R14R15MOV R10,R12MOV R11,R13 ;保存积高位字LPMMOV R13,R0ADIW R30,1LPMMOV R12,R0SBIW R30,3RCALL SUBS ;(X(i+1)-Xi)-->r16 r17MOV R12,R10MOV R13,R11MOV R10,R16MOV R11,R17 ;取回积高位字&(X(i+1)-Xi)-->r10r11RCALL DIV165 ;(X-Xi)*STEPi/[X(i+1)-Xi]-->r14r15ADD R15,R9 ;ADC R14,R8 ;Y0+∑STEPk+(X-Xi)*STEPi/[X(i+1)-Xi]-->r14r15 RETGTSTP: MOV R5,R6 ;查取STEP字型变量/POINTER in r6r7!MOV R6,R30MOV R30,R5MOV R5,R7MOV R7,R31MOV R31,R5 ;(r6r7)<-->ZLPMMOV R11,R0ADIW R30,1LPMMOV R10,R0 ;STEPk取到r10r11ADIW R30,1MOV R5,R6MOV R6,R30MOV R30,R5MOV R5,R7MOV R7,R31MOV R31,R5 ;指针增2后送回r6r7RET;范例21 ;功能表程序FUNC2: LDS R16,$A3 ;use r0,r8,r9,r10,r11,r16&r17/& subprogram dspa SBR R16,$80 ;功能表程序标志LDI YH,2LDI YL,0 ;功能内容表SRAM地址RCALL FLFUNC ;CLR r27!LDI R16,2ST X,R16 ;显示'FUNC.2'RCALL DL2SCLR R9 ;功能内容寻址偏移量R9!CLR R8 ;功能名称寻址偏移量(R8)=(r9)*3FFUNC0: RCALL DSF_ ;显示'F- 'FF0: RCALL DSPA ;in subprogram dspy clr. r27!CPI R16,11 ;回车键按下?BRNE FF2PFF0C: RCALL COMBNO ;合成功能名称送入r16 CPI R16,20 ;是最后一个功能名称?BRNE FF1CLR R9 ;是,两偏移量初始化!CLR R8FF1: LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2);功能名称表指针ADD ZL,R8ADC ZH,R27 ;(r27)=0 ALWAYSLPMMOV R16,R0RCALL BRA3A ;分解新功能名称到$6E/$6FFF0G: LDI R28,0ADD R28,R9 ;功能内容指针加偏移量LD R16,YLDI R26,$72RCALL BRAX ;将新功能内容分解到$72/$73FF0A: RCALL DSPA ;显示新功能名称/内容CPI R16,11BRNE FF0B ;回车键按下?INC R8INC R8INC R8 ;是,功能名称寻址偏移量加3INC R9 ;功能内容寻址偏移量加1RJMP FF0C ;转回FF2P: RJMP FF2FF0B: CPI R16,10BRNE FF0DRCALL DSF_ ;清除键按下,清除显示区后,显示‘F-’FF1B: RCALL DSPACPI R16,11BREQ FF1 ;转恢复当前显示CPI R16,10BRCC FF1BRJMP FF2D ;只有数字键按下才转出去处理FF0D: CPI R16,10BRCC FF0AFF1D: LDI R17,$24 ;STS $73,R17 ;数字键处理,先在缓存区内放一空白FF0E: LDS R17,$73STS $72,R17 ;键入数字左移STS $73,R16 ;存入新数字FF0F: RCALL DSPACPI R16,10BREQ FF0G ;清除键按下,恢复显示旧功能内容BRCS FF0E ;键入数字左移更新CPI R16,11BRNE FF0FLDS R26,$72 ;回车键按下RCALL COMBA ;合成新功能内容(combin $72&$73 into binary(r16)) MOV R17,R8INC R17LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R17 ;取当前功能内容下限ADC ZH,R27FF1F: LPMCP R16,R0BRCS DSER2 ;新功能内容小于下限,错误INC R17LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R17 ;取当前功能内容上限ADC ZH,R27LPMCP R0,R16BRCS DSER3 ;新功能内容大于上限,错误FF7: LDI R28,0ADD R28,R9 ;功能内容表首地址为$200!ST Y,R16 ;合法的新功能内容进入功能内容表INC R9INC R8INC R8INC R8 ;调整偏移量,进入下一个功能显示RJMP FF0CFF1P: RJMP FF1DSER2: RCALL FERR2 ;显示'F Err.2'2秒RCALL EXCH0RJMP FF0G ;恢复原数据显示DSER3: RCALL FERR3 ;显示'F Err.3'2秒RCALL EXCH0RJMP FF0G ;恢复原数据显示FF2: CPI R16,10BRCS FF2D ;功能键按下,转初始RJMP FF0FF2D: LDI R17,$24 ;数字键按下,在显示缓存区内左移STS $6F,R17 ;FF3: LDS R17,$6FSTS $6E,R17STS $6F,R16FF4: RCALL DSPACPI R16,10BRNE FF41RCALL DSF_ ;清除数字,显示‘F-’FF40: RCALL DSPACPI R16,11BREQ FF1P ;转回显示当前功能名称及内容CPI R16,10BRCC FF40 ;无效键按下,转回RJMP FF2D ;否则转数字处理FF41: BRCS FF3CPI R16,11BRNE FF4RCALL COMBNO ;合成新功能名称CLR R10 ;功能名称偏移量计数器清除CLR R11 ;功能内容偏移量计数器清除SFFLP: LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R10ADC ZH,R27LPMCP R0,R16 ;BREQ SFFND ;在功能名称表中找到新名称INC R11 ;INC R10INC R10INC R10 ;调整偏移量LDI R17,60CP R10,R17 ;功能名称指针偏移量超过59?BRCS SFFLP ;否,继续查功能名称表RCALL FERR1 ;查完功能名称表未查到键入功能名称!RJMP FFUNC0 ;转回恢复原显示SFFND: MOV R9,R11 ;得到功能内容指针偏移量MOV R8,R10 ;得到功能名称指针偏移量RJMP FF0G ;转显示新功能名称及内容FTABL: .DB 1,0,1,2,1,8,3,0,2,4,0,1 5,1,2,6,0,4,7,1,4,8,1,2,9,2,7,10,1,5,11,1 .DB 5,12,0,5,13,1,2,14,1,7,15,1,10,16,1,4,17,2,4,18,2,5,19,1,2,20,1,3 COMBNO: LDI XL,$6E ;取$6E$6F中的BCD码,合成新功能名称子程序COMBA: LD R16,X+CPI R16,$24BRNE CMBACLR R16CMBA: MOV R0,R16LSL R16LSL R16ADD R16,R0LSL R16 ;高位BCD乘10LD R0,XADD R16,R0 ;加低位BCDRETDSF_: RCALL FIL8 ;准备显示'F- 'LDI R16,$0FSTS $6C,R16LDI R16,$14STS $6D,R16RETBRA3A: LDI XL,$6E ;二进制数转换为两位BCD码并显示BRAX: LDI R17,$24 ;十位为0时显示空白ST X,R17BRHOUR: CLR R0 ;BRX0: SUBI R16,10 ;减10BRCS BRX2INC R0RJMP BRX0BRX2: SUBI R16,-10 ;不够减恢复出十位BCDTST R0BREQ BRX1ST X,R0 ;放入显示区BRX1: INC R26ST X,R16BRART: RETFERR1: LDI XL,$71 ;显示'F Err.1'LDI R16,1ST X,R16RJMP FER123FERR2: RCALL MOVE1 ;显示'F Err.2' LDI R16,2STS $71,R16RJMP FER123FERR3: RCALL MOVE1 ;显示'F Err.3' LDI R16,3STS $71,R16FER123: LDI XL,$6CLDI R16,$0FST X+,R16LDI R16,$24ST X+,R16LDI R16,$0EST X+,R16LDI R16,$1BST X+,R16LDI R16,$3BST X+,R16 ;显示'F Err.1/2/3'LDI R16,$24 ;2秒STS $72,R16STS $73,R16RCALL DL2SRETFIL8: LDI R26,8 ;将显示缓存区充空白MOV R10,R26LDI R26,$6CCLR R27LDI R16,$24FILP: ST X+,R16DEC R10BRNE FILPRETFLFUNC: RCALL FIL8 ;准备显示'Func.' LDS R26,$6CLDI R16,$0F ;'F'ST X+,R16LDI R16,$1E ;'u'ST X+,R16LDI R16,$17 ;'n'ST X+,R16LDI R16,$40 ;'c.'ST X+,R16RETEXCH0: LDI ZL,$14 ;将显示缓存区内容转移$6C-$73<-->$214-$21B LDI ZH,2LDI XL,$6CEXL: LD R16,XLD R17,ZST X+,R17ST Z+,R16CPI R26,$74BRNE EXLRETMOVE1: LDI ZL,$14 ;将显示缓存区内容传送到$214-$21BLDI ZH,2LDI XL,$6CMV1: LD R16,X+ST Z+,R16CPI R26,$74BRNE MV1RET;范例22 ;读出EEPROM子程序REEP: LDI YH,1LDI YL 0 ;EEPROM 读出首地址:$100LDI XL,$60 ;读出数据存放首地址:$60CLR XHREEP1: SBIC $1C,1 ;查EEWE位,EEWE=1为当前尚有写入操作未结束RJMP REEP1 ;等待EEWE=0OUT $1F,YHOUT $1E,YL ;读出地址写入EEPRO地址寄存器SBI $1C,0 ;设置读出使能位(EERE)IN R16,$1D ;从EEPROM数据寄存器中读出数据ST X+R16 ;存入缓存区INC YLBRNE REEP1 ;INC YHCPI YH,2 ;EEPROM最末数据(地址为$1FF)读完?BRNE REEP1RET;范例23 ;写入EEPROM子程序WEEP: LDI YH,1LDI YL 0 ;EEPROM 写入之首地址:$100LDI XL,$60 ;写入数据存储区首地址:$60CLR XHWEEP1: SBIC $1C,1 ;查EEWE位,EEWE=1为当前尚有写入操作未结束RJMP WEEP1 ;等待EEWE=0OUT $1F,YHOUT $1E,YL ;送写入地址到EEPRO地址寄存器LD R16,X+ ;取写入数据并调整数据指针OUT $1D,R16 ;送到EEPROM数据寄存器SBI $1C,2 ;设置EEPROM写入总使能位EEMWESBI $1C,1 ;设置EEPROM写入使能位EEWEINC YLBRNE WEEP1INC YHCPI YH,2 ;EEPROM最末写入单元地址为$1FFBRNE WEEP1RET。
AVR汇编百例 - 晋级篇 - 参考程序
; 以下提供几个补充参考程序,都带有详细说明和指令注释.它们是主从多机通讯程序,采;用中断方式写入EEPROM,直接对晶振分频产生0.1秒和秒号的精确定时程序,以及RS-232/ ;RS-485标准转换程序,A VR频率计程序,串行时锺日历芯片DS13021302具体积小,;可靠性高,与单片机连接方便等优点.; 以下程序请参看有关章节或程序中的注释。
;范例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-1BFSTRT38: RJMP RST38 ;主机从1#,2#,3#,4#分机接收数据块在$1C0-1CF,$1D0-1DF,$1E0-1EF)和$1F0-1FF.ORG $00B ;RJMP STRT38.ORG $00CRJMP STRT38 ;主机不设串口中断,只以查询接收.ORG $011RST38: LDI R16,12OUT 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,$18OUT UCR,R16 ;允许UART接收和发送,8位数据模式INC R15 ;指向1#分机OUTLP: OUT UDR,R15 ;呼分机号,1:1#/2:2#/03:3#/04:4#...TSLOP: IN R16,USRSBRS R16,7RJMP TSLOP ;分机返回机号?IN R16,UDRCP R16,R15 ;分机号正确返回?BRNE OUTLPLDI R16,$1C ;改为9位数据模式TXB8=0OUT UCR,R16 ;TXLOP: LD R16,X+OUT UDR,R16 ;向分机发送数据块TESTL: IN R17,USRSBRS R17,5RJMP TESTL ;等待发送完成CPI R16,$0ABRNE TXLOP ;RXTST: IN R17,USRSBRS R17,7 ;RXC=1 收到数据RJMP RXTST ;等待接收分机返回数据块IN R16,UDRST Y+,R16 ;存储接收数据CPI R16,$0A ;分机数据块发完?BRNE RXTSTMOV R16,R15CPI R16,4 ;与分机轮询通讯完毕?BRNE NEXTNO ;未完转对下一分机通信HH38: RJMP HH38 ;否那么踏步〔可改为处理分机返回的数据,之后再进行下一个轮询〕.DSEG.ORG $180DTPINT:.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 $1C0DRPINT:.BYTE $40;范例92.ORG 0 ;多机通讯1#分机程序/晶振4MHZ.EQU DTPIT1=$180 ;〔UBRR〕=12 波特率为19200(REL.ERR.=0.16%).EQU DRPNT1=$1C0STRT39: RJMP RST39.ORG $00BRJMP UARXC ;8535UART接收完成中断.ORG $00CRJMP UATXC ;UART发送完成中断.ORG $011RST39: CLR R18 ;去除分机被选中〔R18,6〕和主机数据块接收完毕标志(R18,7) LDI R16,12OUT UBRR,R16 ;设波特率[BAUD RATE=4000000/16*〔12+1)=19200]LDI R16,HIGH(DRPNT1)MOV R8,R16LDI R16,LOW(DRPNT1)MOV R9,R16 ;r8,r9:接收数据指针(FIRST POINT TO $1C0)LDI R16,$98 ;允许UART中断接收,8位数据模式OUT UCR,R16SEIRXDTS: SBRS R18,6 ;主机呼号已收到〔假设收到,在R17中〕?RJMP RXDTSOUT UDR,R17 ;返还该机号TXDON: IN R16,USRSBRS R16,5RJMP TXDON ;该机号发送完成?LDI R16,$9C ; 允许UART中断接收,9位数据模式,TXB8=0OUT UCR,R16RCVBLK: SBRS R18,7RJMP RCVBLK ;主机发来数据块已接收完毕?LDI R16,HIGH(DTPIT1)MOV R6,R16LDI R16,LOW(DTPIT1)MOV R7,R16 ;设发送数据指针r6r7,首指$180LDI R16,$3C ;允许UART中断发送,9位数据模式,TXB8=0OUT UCR,R16TXDN: SBIC UCR,5RJMP TXDN ;发送完毕?RJMP RST39 ;:UART中断接收程序UARXC: SBIC USR,4RETI ;祯错误〔主机正与其它分机进行9位数据模式通信〕,不予接收IN R14,SREG ;保存当前状态TST R18BREQ NUMB ;〔R18〕=0时收到数据,只可能是机号,转去核实PUSH R16 ;否那么为主机向本分机发来数据块〔9位模式,机号已符合〕PUSH R26PUSH R27IN R17,UDR ;接收数据MOV XH,R8MOV XL,R9 ;取接收数据指针ST X+,R17 ;转入RAMMOV R8,XHMOV R9,XL ;存数据指针CPI R17,$0A ;是数据块结束符LF?BRNE RSCOM1SBR R18,$80 ;收到完整数据块标志RSCOM1: POP R27POP R26POP R16DRETI: OUT SREG,R14RETINUMB: IN R17,UDR ;取出数据CPI R17,1 ;是1#分机?2#分机与$02比拟/3#分机与$03比拟...BRNE DRETI ;机号不符合,转!SBR R18,$40 ;建机号符合标志RJMP DRETI; UART中断发送程序UA TXC: PUSH R16 ;r6 r7:发送数据指针,首指$180IN R16,SREGPUSH R16PUSH R26PUSH R27MOV XH,R6MOV XL,R7 ;取出发送指针LD R16,X+ ;取数据,调指针MOV R6,XHMOV R7,XLOUT UDR,R16 ;送入发送存放器CPI R16,$0ABRNE SDCOMCBI UCR,5 ;发送最后1个字符后,禁止发送存放器空中断(CLR UDRIE)LDI R16,HIGH(DRPINT)MOV R8,R16LDI R16,LOW(DRPINT)MOV R9,R16 ;接收数据指针初始化〔POINT TO $1C0)SDCOM: POP R27POP R26POP R16OUT SREG,R16POP R16RETI.DSEG.ORG $180DTPIT1:.BYTE $40.ORG $1C0DRPNT1:.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,R16LDI R16,LOW(ramend)OUT SPL,R16SBI EECR,3 ;设置EEPROM就绪(ready)中断使能位SEI ;中断总使能RJMP SRTW.ORG $00FRJMP EEPRDY ;8535 EEPROM就绪(ready)中断向量SRTW: LDI YH,1LDI YL 0 ;EEPROM 写入首地址:$100LDI XL,$60 ;欲写入数据块首地址:$60CLR XHWEEP0: SBIC EECR,1 ;当前有EEPROM写入操作,有那么等待写入完成RJMP WEEP0RCALL WREEP ;写入第一个字节,($60)->$100,写入完成后,EEWE=0时引发EEPROM就绪中断INC YL ;调整写入地址指针HHWEEP: TST YLBRNE HHWEEPCPI YH,2 ;写入地址到达$200后,写入完成BRNE HHWEEPCBI EECR,3 ;禁止EEPROM就绪(ready)中断WDON: RJMP WDON ;踏步EEPRDY: IN R6,SREGPUSH R16RCALL WREEP ;写入一个字节INC YLBRNE WRETIINC YH ;EEPROM末地址为$1FFWRETI: POP R16OUT SREG,R6RETIWREEP: OUT EEARH,YH ;OUT EEARL,YL ;写入地址送入EEARLD R16,X+ ;取数据,调指针OUT EEDR,R16 ;数据写入EEPROM数据存放器SBI EECR,2 ;设置EEPROM写入总使能位EEMWESBI EECR,1 ;设置EEPROM写入使能位EEWERET;用定时/计数器1定时,不分頻定出0.1秒信号,由PC5脚输出正脉冲。
AVR 100个汇编范例
SBC R16,R9
RCALL SUDAA
MOV R13,R16
MOV R16,R12
SBC R16,R8
RCALL SUDAA
ADLOP: LD R16,-X ;X-1指向被加数;
LD R6,-Y ;Y-1指向加数
ADC R16,R6
RCALL ADDAA ;相加后调整
ST X,R16 ;返还调整后结果
RET ;否则返回
LDI R17,255
SUB R13,R17
SBC R12,R17 ;以减去-1($FFFF)替代加1
RET
RET
;范例2
SUDAA: BRCC SBD1 ;bcd码减法调整子程序,差在R16中
BRHC SBD3
SUBI R16,$66 ;进位半进位都置位,将差减去立即数$66
DEC R7
BRNE ADLOP
RET
;范例6
SUBCD4: MOV R16,R15 ;4字节压缩bcd码减法子程序
SUB R16,R11 ;R12,R13,R14,R15内为被减数,R8,R9,R10,R11内为减数
SUBLP: LD R16,-X ;X-1指向被减数
LD R6,-Y ;Y-1指向减数
SBC R16,R6
RCALL SUDAA ;相减后调整
ST X,R16 ;返还调整后结果
;范例10 ;32位被除数/16位除数-->16位商,精确到1
DIV16: LDI R16,16 ;(r12r13r14r15)/(r10r11)-->r14r15
DLOOP: LSL R15
AVR自学笔记
RXB8(bit1):接收数据位 8 TXB8(bit0):发送数据位 8 *UCSRC: URSEL(bit7):读 UCSRC 时为 1,写 UCSRC 时为 1(?)(编译器自动处理) UMSEL(bit6):0,异步。1,同步 UPM1~UPM0(bit5、4):奇偶校验模式
USBS(bit3):停止位数选择;0 时,1bit 停止位,1 时,2bit 停止位 UCSZ1~UCSZ0(bit2、1):字符长度设置
一、基础知识 1.开发工具: 编辑与编译软件:WinAVR 仿真软件:AVR Studio 下载软件:AVR_fighter、MuCodeISP 等 在需要在中断函数中被修改的全局变量需要用 volatile 关键字声明 2.第一个简单的 AVR 程序 AVR 引脚排列:
ATMega8 引脚排列
ATMega16 引脚排列
*PWM 输出频率计算公式(快速 PWM 模式)
*PWM 输出频率计算公式(相位修正 PWM 模式)
4. 异步串行口 USART(同步或异步): ①相关寄存器:UDR(数据寄存器)、UCSRA(控制与状态寄存器 A)、UCSRB(控制与状态寄存器 B)、UCSRC (控制与状态寄存器 C)、UBRRL(波特率寄存器 L)、UBRRH(波特率寄存器 H) ②三个中断源:发送结束中断、发送数据寄存器空中断、接收完成中断(常用) ③寄存器介绍 *UDR: 8 位数据寄存器,接收和发送为同一地址的不同寄存器 *UCSRA:
②注意 OCR0(输出比较寄存器)用于输出比较,产生事件匹配中断,这里没有列出 *TCCR0:
FOC0(bit7):强制输出比较,仅在 WGM00 指明非 PWM 模式时才有效 WGM00、WGM01(bit6、3):波形产生模式
AVR汇编百例 - 电机控制
;范例32 ;步进电机控制程序.ORG 0STRT10: RJMP RST10 ;8535/8515/晶振4MHZ.ORG $011RST10: LDI R16,HIGH(ramend)OUT SPH,R16LDI R16,LOW(ramend)OUT SPL,R16SER R16OUT DDRB,R16 ;B口为输出LDI R17,8OUT PORTB,R16 ;接通总开关LDI R16,50 ;50次基本运作RCALL DELAY5 ;延时5毫秒LOOPX: LDI R17,$68 ;step1时序脉冲控制OUT PORTB,R17RCALL DELAY2 ;延时2毫秒LDI R17,$38 ;step2时序脉冲控制OUT PORTB,R17RCALL DELAY2 ;延时2毫秒LDI R17,$98 ;step3时序脉冲控制OUT PORTB,R17RCALL DELAY2 ;延时2毫秒LDI R17,$C8 ;step4时序脉冲控制OUT PORTB,R17RCALL DELAY2 ;延时2毫秒DEC R16BRNE LOOPX ;到50次?LDI R17,8OUT PORTB,r17 ;关闭各相位开关RCALL DELAY5RCALL DELAY5 ;延时10毫秒CLR R17OUT PORTB,R17 ;关闭所有相位开关和总开关HH0: RJMP HH0 ;踏步DELAY1: LDI R17,$06 ;延时1毫秒MOV R15,R17 ;1000/0.75=1333=$535,外層计数器装入$06 LDI R17,$35 ;DEC+BRNE=0.75微秒RJMP DLCOMDELAY2: LDI R17,$0B ;延时2毫秒MOV R15,R17 ;2000/0.75=2666=$0A6A,外層计数器装入$0B LDI R17,$6ADLCOM: DEC R17BRNE DLCOMDEC R15BRNE DLCOMRETDELAY5: LDI R17,$1B ;延时5毫秒MOV R15,R17 ;5000/0.75=6666=$1A0A,外層计数器装入$1BLDI R17,$0ARJMP DLCOM;范例33.ORG 0 ;8515采用定时器中断输出时序脉冲方式控制电机转动STRT11: RJMP RST11 ;晶振4MHZ.ORG $007RJMP T0_OVF ;中断服务程序与STRT12共用.ORG $00DRST11: LDI R17,HIGH(ramend)OUT SPH,R17LDI R17,LOW(ramend)OUT SPL,R17LDI R17,$68MOV R7,R17 ;初始脉冲为0B01101000SER R17OUT DDRB R17 ;B口为输出LDI R17,N ;运作次数N(N>0)RCALL STPDRV ;初始化子程序HH20: RJMP HH20 ;实用时改为具体的背景程序!STPDRV: TST R17BRNE STPDR1INC R17 ;N=0时,将其改为1STPDR1: MOV R6,R17INC R6 ;N+1-->r6(max.is 256;“植树问题”,N必需增1!LDI R17,$A4CBR R17,$20STS $A4,R17 ;清除连续转动电机标志LDI R17,$08OUT PORTB,R17 ;接通总开关LDI R17,4 ;0B00000100/ 256分频(4兆/256=1兆/64)OUT TCCR0,R17LDI R17,178 ;78*64=4.992msOUT TCNT0,R17 ;时间常数,首定时为5毫秒LDI R17,$02OUT TIMSK,R17 ;允许T/C0溢出中断SEIHH21: SJMP HH21;范例34.ORG $000 ;步进电机手动控制程序(8515)晶振4MHZ STRT12: RJMP RST12.ORG $007RJMP T0SEV.ORG $00DRST12: LDI R17,HIGH(ramend)OUT SPH,R17LDI R17,LOW(ramend)OUT SPL,r17LDI R17,$68MOV R7,R17 ;第一个时序脉冲LDI R17,$F8OUT DDRB,R17 ;PB7-PB3输出,PB2-PB0输入CLR R17OUT PORTB,R17 ;输出为低电平LDS R17,$A4SBR R17,$20 ;设置连续转动标志CBR R17,$40 ;设置电机正转标志TSTLP1: SBI PORTB,1 ;PB1接地,正转SBIS PINB,1RJMP TSTL11 ;TSTL10: SBI PORTB,2SBIC PINB,2 ;PB2接地,反转RJMP TSTLP1 ;PB1,PB2都未接地,反复查询SBR R17,$40 ;设置电机反转TSTL11: STS $A4,R17 ;保存标志CLR R6INC R6 ;R6中装入1,减一次即为0!LDI R17,$08OUT PORTB,R17 ;接通总开关LDI R17,4 ;0B00000100/256分频(256/4=64微秒)!OUT TCCR0,R17LDI R17,178 ;178之补为78,78*64=4.992msOUT TCNT0,R17 ;LDI R17,$02OUT TIMSK,R17 ;允许T/C0中断(toie1=$39,7 toie0=$39,1);8535,toie1:$39,2 toie0:$39,0SEITSTLP2: SBI PORTB,1SBI PORTB,2IN R17,PINBANDI R17,6CPI R17,6BRNE TSTLP2 ;两开关未全部打开,查询等待LDS R17,$A4CBR R17,$20 ;清除连续转动标志STS $A4,R17 ;TSTLP3: IN R17,TIMSKSBRC R17,1 ;已禁止8515中断?(8535:timsk,0)RJMP TSTLP3 ;未,查询等待RJMP RST12T0_OVF: PUSH R17 ;电机控制中断服务子程序IN R17,SREGPUSH R17LDS R17,$A4SBRC R17,7RJMP T0SV2 ;$A4,7:关电机前10毫秒延时标志MOV R17,R7CPI R17,$68BRNE T0SV0LDS R17,$A4SBRC R17,5RJMP T0SV0 ;电机连续转动,不减R6DEC R6 ;R6减为0,将停止电机BREQ T0SV1 ;T0SV0: LDI R17,225 ;每步进延时(256-225)*64=1.984MS err.<0.8% OUT TCNT0,R17 ;OUT PORTB,R7 ;步进控制脉冲输出LDS R17,$A4SBRC R17,6RJMP T0SV A ;$A4,6=1 为连续反转CLCSBRC R7,4 ;组织下一步控制脉冲SECROR R7LDI R17,$08 ;正转OR R7,R17 ;01101***->00111***->10011***->11001***->01101***.......RJMP T0RETT0SV A: MOV R17,R7 ;SBR R17,$04ROL R17 ;组织下一步控制脉冲(反转)BRCS T0SVBCBR R17,$10 ;01101***->11001***->10011***->00111***->01101***.......! T0SVB: MOV R7,R17RJMP T0RETT0SV1: LDS R17,$A4SBR R17,$80STS $A4,R17 ;总开关关断前10毫秒延时标志LDI R17,$08OUT PORTB,R17 ;关断4个相位开关LDI R17,100 ;156(256-100)*64=9.984msOUT TCNT0,R17 ;RJMP T0RETT0SV2: LDI R17,$07OUT PORTB,R17 ;关闭所有开关CLR R17OUT TCCR0,R17 ;关T/C0中断OUT TIMSK,R17LDS R17,$A4CBR R17,$C0STS $A4,R17 ;清除10毫秒延时和反向转动标志T0RET: POP R17OUT SREG,R17POP R17RETI。
单片机汇编语言经典一百例
单片机汇编语言经典一百例汇编语言是一种底层的程序设计语言,是一种将汇编指令直接翻译成机器指令的语言。
在单片机编程中,掌握汇编语言是非常重要的,因为它可以充分发挥单片机的性能,并且提高程序的运行效率。
本文将介绍一百个经典的单片机汇编语言例子,帮助读者更好地理解汇编语言的使用。
1. 点亮LED灯```ORG 0x0000 ; 程序起始地址MOV P1, #0xAA ; P1口输出高电平,LED灯点亮END ; 程序结束```2. LED流水灯效果```ORG 0x0000 ; 程序起始地址MOV P1, #0x01 ; P1口输出低电平,第一个LED点亮CALL DELAY ; 调用延时函数MOV P1, #0x02 ; P1口输出低电平,第二个LED点亮CALL DELAY ; 调用延时函数MOV P1, #0x04 ; P1口输出低电平,第三个LED点亮CALL DELAY ; 调用延时函数MOV P1, #0x08 ; P1口输出低电平,第四个LED点亮CALL DELAY ; 调用延时函数…DELAY: ; 延时函数MOV R0, #100 ; 设置延时时间DELAY_LOOP:DJNZ R0, DELAY_LOOP ; 循环减一RET ; 返回END ; 程序结束```3. 数码管动态扫描显示```ORG 0x0000 ; 程序起始地址CLR P0.0 ; P0.0口输出低电平,选择第一个数码管MOV P2, #0x7E ; 将数码管对应的值存放到P2口CALL DELAY ; 调用延时函数CLR P0.1 ; P0.1口输出低电平,选择第二个数码管MOV P2, #0x30 ; 将数码管对应的值存放到P2口CALL DELAY ; 调用延时函数CLR P0.2 ; P0.2口输出低电平,选择第三个数码管MOV P2, #0x6D ; 将数码管对应的值存放到P2口CALL DELAY ; 调用延时函数CLR P0.3 ; P0.3口输出低电平,选择第四个数码管MOV P2, #0x79 ; 将数码管对应的值存放到P2口CALL DELAY ; 调用延时函数…DELAY: ; 延时函数MOV R0, #100 ; 设置延时时间DELAY_LOOP:DJNZ R0, DELAY_LOOP ; 循环减一RET ; 返回END ; 程序结束```...通过以上例子,我们可以看到单片机汇编语言的应用非常广泛,可以实现各种各样的功能。
AVR汇编百例 - 输入输出
;时钟日历芯片62×42×读写程序,时钟日历数据读入到显示缓存区$6C--$73 ;范例24 ;USE 8515!使用DSPA子程序.EQU RTCH=$40 ;rtc地址高八位RDATE: RCALL BSYT ;初始化,兼冻结RTCLDI XL,$6D ;数据缓存区首地址LDI YL,$06 ;首指日单元RDLP: LD R16,Y+ ;$6b 6c 6d 6e 6f 70 71 72 73ANDI R16,15 ; 2 9(D) - 1 0(M) - 0 2(Y)CPI R16,10BRCS RDL1ANDI R16,$7F ;容错处理RDL1: ST X,R16$DEC R26CPI R26,$6BBRNE RDLP1LDI XL,$70RDLP1: CPI R26,$6EBRNE RDLP2LDI R16,$14 ;送‘-’到$6E单元ST X,R16LDI XL,$73RDLP2: CPI R26,$71BRNE RDLPLDI R16,$14ST X,R16 ;送‘-’到$71单元并结束子程序RDINVL: RJMP WCRTRTIME: RCALL FIL2 ;请除缓存区RCALL BSYTLDI XL,$73LDI YL,$02 ;指向分单元(只读时分)RCL: LD R16,Y+ANDI R16,15CPI R16,10BRCS RCL0ANDI R16,$7F ;容错处理RCL0: ST X,R16DEC R26CPI R26,$71BRNE RCL1LDI R16,$14 ;写入‘-’ST X,R16DEC R26RCL1: CPI R26,$6E ;$6c 6d 6e 6f 70 71 72 73BRNE RCL ; 1 6 - 3 5CLR R16ST Y,R16LDS R17,$9FFB ;时制存储单元LDS R16,$6fSW AP R16LDS R15,$70ADD R16,R15 ;合成小时SUBI R16,$24 ;模24RCALL SUDAA ;BCD码减法调整BRCC RCL2 ;够减,转SUBI R16,-36 ;否则恢复被减数RCL2: CPI R17,2BRNE PRTD1 ;24小时制,转SUBI R16,$12RCALL SUDAABRCC PRTD1 ;12小时制处理SUBI R16,-18PRTD1: MOV R17,R16SW AP R16ANDI R16,$0FANDI R17,$0FSTS $6F,R16STS $70,R17 ;小时数据送入显示区RJMP WCRTWDATE: RCALL WRTC ;将显示缓存区中日期数据写入RTC LDI XL,$6FLD R16,XCPI R16,10BRCC WDRT ;非法数据,退出LDI YL,6WDLP: LD R16,XDEC R26CPI R16,$24 ;SPC?BRNE WD0CLR R16 ;变为0WD0: ST Y+,R16CPI R26,$6DBRNE WD1 ;$6d 6e 6f 70 71 72 73LDI XL,$71 ; 2 9(日) 1 1(月) 0 2 (年)RJMP WDLPWD1: CPI R26,$6fBRNE WD2WD2: CPI R26,$71BRNE WDLPLWDRT: RJMP WCRTWTIME: RCALL WRTC ;将显示缓存区中时间数据写入RTC LDI R26,$73LD R16,XCPI R16,10BRCC WCRT ;非法数据,退出LDI YL,2WLOP: LD R16,XCPI R16,$24BRNE WT1CLR R16 ;容错处理WT1: ST Y+,R16DEC R26WLP: CPI R26,$6FBRNE WLOP ;$6E 6f 70 71 72 73WCRT: CLR R16 ; 1 5 3 8LDI YL,$0DST Y,R16 ;解除对RTC之冻结IN R16,MCUCRCBR R16,$C0OUT MCUCR,R16 ;禁止读写外部RAMRET;对rtc初始化/冻结时钟BSYT: LDI YH,RTCH ;rtc地址高八位LDI YL,$0D ;指向D寄存器IN R16,MCUCRSBR r16,$C0 ;允许读写外部RAM并选一个时钟周期等待时间OUT MCUCR,R16LDI R16,5 ;设置冻结位和中断申请位ST Y,R16CLR XHBSRT: RET;写RTC初始化子程序WRTC: RCALL BSYTLDI YL,$0E ;指向寄存器ELDI R16,6ST Y+,R16 ;指向寄存器FLDI R16,1 ;设置时制位ST Y,R16LDI R16,4 ;选24小时制CLR R16 ;请除时制位ST Y,R16RJMP BSYT;范例25 ;显示保护子程序/晶振4MHZDSPRV: LDI R16,HIGH(ramend)OUT SPH,R16LDI R16,LOW(ramend)OUT SPL,R16CLR R2 ;调DSPY次数寄存器清除WDRLDI R16,$0D ;启动看门狗,溢出时间为0.49sOUT WDTCR,R16 ;写入看门狗控制寄存器CLR XHLDI XL,$6CDSPVL: ST X+,XH ;清显示缓存区($6c-$73)CPI XL,$74BRNE DSPVLDSPV0: LDI R16,$66MOV R9,R16LDI R16,$82 ;$6582=25986,高位字节增1为$66MOV R10,R16 ;调25986次DSPA耗时120sDSNEX: LDI XL,$74 ;将显示区十进制数据增1以演示数据变化DSLOP: LD R16,-X ;实用时可以采样数据更新显示(参考范例96)INC R16ST X,R16CPI R16,$0ABRNE DSPRV1CLR R16ST X,R16CPI R26,$6CBRNE DSLOP ;增1后如有进位则调整DSPRV1: DEC R10BRNE DSPGNDEC R9BRNE DSPGN ;2分钟定时到?DSCLOS: RCALL FIL2 ;将显示缓存区充入空白($24)RCALL DSPA ;其效果相当于关显SBRC R16,7RJMP DSCLOSRJMP DLFUNC ;有键按下,转出;否则继续关显DSPGN: RCALL DSPA ;未到,显示数据RJMP DSNEX ;无键按下,继续显示DLFUNC: CPI R16,12 ;关显键键值为12BEEQ DSCLOS ;关显键按下,转关闭显示;.;.;.;.;(其他键值处理,参考范例26 DEALKY程序)RJMP DSPV0 ;执行功能后转入二分钟定时;范例26 ;键值处理程序DEALKY: LDI R16,HIGH(ramend)OUT SPH,R16LDI R16,LOW(ramend)OUT SPL,R16CLR R2 ;调DSPY次数寄存器清除WDRLDI R16,$0D ;启动看门狗,溢出时间为0.49”OUT WDTCR,R16 ;写入看门狗控制寄存器DEALK0: RCALL DSPASBRC R16,7RJMP DEALK0 ;无键按下,反复查询CPI R16,10BRCC FNCKY ;功能键按下,跳转RCALL FIL2 ;键值<10为数字键,先清除显示缓存区NUMKY: RCALL LSDD8 ;8位数字左移,新键值加入序列尾DSLP: RCALL DSPASBRC R16,7RJMP DSLP ;无键按下,继续显示CPI R16,11BRCS NUMKY ;键入数字形成左移序列/按清除键则清除所有键入数据BRNE DSLP ;键值大于11无效;11为回车键,对键入数字进行处理(如将其两两合并为BCD;码,再转为二进制数等)RJMP DEALK0 ;转回FNCKY: SUBI R16,10 ;功能键散转处理,先计算键值偏移量LDI R31,HIGH(FKYTB)LDI R30,LOW(FKYTB);散转表表首ADD R30,R16CLR R16ADC R31,R16 ;偏移量加入指针IJMP ;散转FKYTB: RJMP CLTTL ;10:清除累加和RJMP DSTTL ;11:显示累加和RJMP DSCLS ;12:关显示RJMP SLFTS ;13:自检RJMP FDPAP ;14:打印机走纸RJMP PRSMP ;15:打印采样RJMP PRTTL ;16:打印累加和RJMP DSCLK ;17:显示系统时钟;............. ;.........;............. ;.........CLTTL: ;............. ;程序内容略;.............RJMP DEALK0 ;程序执行完毕,转回DSTTL: RCALL BRTTL ;分解累加和送显示缓存区RCALL DSPA ;显示累加和SBRC R16,7RJMP DSTTL ;任一键按下,结束显示累加和RJMP DEALK0 ;程序执行完毕,转回DSCLS: RJMP DSCLOS ;转去关显示SLFTS: ;.............;.............RJMP DEALK0 ; 自检程序执行完毕,转回FDPAP: ;.............;.............RJMP DEALK0 ; 走纸程序执行完毕,转回PRSMP: ;.............;.............RJMP DEALK0 ; 打印采样程序执行完毕,转回PRTTL: ;.............;.............RJMP DEALK0 ;打印累加和程序执行完毕,转回DSCLK: RCALL BRCLK ;分解系统时钟送入显示缓存区RCALL DL1S ;延时1秒RCALL DSPA ;显示时钟SBRC R16,7 ;任一键按下,结束显示时钟RJMP DSCLKRJMP DEALK0 ;程序执行完毕,转回;.............;............. ;其他功能键处理略;.............;范例27 ;主显子程序DSPA: SBRC R16,7 ;USE R0,R2,R11,R12,r13,r14,r15,r16,r17&Z,X POINTERS RJMP DSA2 ;无键按下,跳转DSA0: CLR R12INC R12 ;有键按下,将计数器置1DSA1: RCALL DSPYDEC R12BRNE DSA1 ;等待键释放DSA2: RCALL DSPYLDS R16,$A3SBRS R16,7 ;有进入功能表程序标志?RET ;没有返回SBI PORTA,0 ;SBIS PINA,0 ;退出功能表程序吗?RETCBR R16,$80 ;是,清除进入功能表程序标志($A3,7)STS $A3,R16RCALL FIL2LDI R16,$0F ;'F'STS $6C,R16LDI R16,$0E ;'E'STS $6E,R16LDI R16,$17 ;'n'STS $6F,R16LDI R16,$0D ;'d'STS $70,R16 ;显示‘F End'RCALL DL2S ;2秒后RJMP DIPA1 ;转到主程序(包括对堆栈)初始化DL2S: RCALL DL1S ;延时2秒子程序DL1S: LDI R16,217 ;延时1秒子程序/4MHz clkMOV R11,R16 ;4.618×217=1000msDLCOM: RCALL DSPADEC R11BRNE DLCOMRET;范例28 ;基显子程序,显示缓存区:$6C--$73,执行时间4.618ms/晶振4MHZ ;主程序应对看门狗初始化,设置溢出时间为0.49秒!DSPY: LDI R17,$0F ;使用R0,R2,R12,R13,R14,R15,R16&R17/z&x pointer!OUT DDRA,R15 ;PA7--PA4为键列值输入CLR R15COM R15OUT DDRB,R15OUT DDRC,R15 ;口B:段选输出,口C:位选输出OUT PORTC,R15 ;关显DPY1: LDI R26,$6C ;指向显示缓存区首址:$6C CLR R27LDI R17,$7FMOV R13,R17 ;位选初始化(首显最高位)L0D: LD R17,X+LDI R31,HIGH(table*2)LDI R30,LOW(table*2)ADD R30,R17ADC R31,R27L0C: LPM ;取段选码OUT PORTB,R0 ;送段选口OUT PORTC,R13 ;位选口SEC ;ROR R13 ;指下一位位选LDI R17,3 ;4MHz(6 if 8MHz)CLR R14DLOP: DEC R14BRNE DLOPDEC R17BRNE DLOP ;延时0.5762毫秒IN R16,PORTAORI R16,$F0 ;保护PA3--PA0输出OUT PORTA,R16 ;提拉PA7-PA4IN R14,PINA ;读入列值NEX: ROL R14 ;use high 4bits!BRCC L1 ;有键按下,跳转NEX1: INC R17 ;指向下一列CPI R17,4BRNE NEX ;各列都查完?NEX2: SER R17OUT PORTC,R17 ;将$FF写入位选口(关显)CPI R26,$74BRNE L0D ;每位LED都显示一遍??MOV R16,R15 ;YESINC R2 ;增一调DSPY次数寄存器MOV R17,R2CPI R17,100 ;到100次?BRNE NEX3CLR R2 ;清除看门狗定时器时间到计数器/4.618ms×100=0.462s(<0.49s) WDR ;看门狗定时器复位NEX3: RETL1: LDS R16,$73 ;计算键值代码/查键值SUB R16,R26 ;$73-(r26)-->r16LSL R16LSL R16 ;行值*4ADD R16,R17 ;键值代码=行值*4+列值LDI R30,LOW(TABL0*2)ADD R30,R16LDI R31,HIGH(TABL0*2)ADC R31,R27LA00: LPM ;查出键值MOV R15,R0 ;放在R15LA10: INC R12 ;计数器增1以备判断键释放RJMP NEX1 ;转回查下一列TABL0: .DB 10,0,11,20,1,2,3,16,4,5,6,22,7,8,9,18,12,15,19,23,14,17,21,13TABLE: .DB $3F,$06,$5B,$4F,$66,$6D,$7D,$07,$7F,$67,$77,$7C,$39 ;0--C .DB $5E,$79,$71,$6F,$74,$04,$1F,$40,$38,$37,$54,$5C ;'d'---'o'.DB $73,$67,$50,$6D,$78,$1C,$3E,$7E,$F8,$6E,$49,$00.DB $48,$52,$D3,$76 ;$25(=),$26(/)$27(?) END AT $28(H).DB $BF,$86,$DB,$CF,$E6,$ED,$FD,$87,$FF,$E7;THE 0.($29)--9.($32).DB $D7,$C9,$80 ;THE 'X.' 'Z.' &'.'($33--$35).DB $DE,$EF,$B8,$F3,$E7,$D0,$DC,$ED,$86,$F9,$B9H,$F7,$F1,$B7,$D4 ;the d.,g.,L.,p.,q.,r.,o.,s.,l.,E.,C.,A.,F.,M.,n.(36--44h);范例29 ;键入数字序列左移处理子程序LSDD8: LDI R26,$6C ;8bcd码($6C--$73H)LDS R27,$A3CBR R27,8 ;清$A3,3STS $A3,R27CLR R27CPI R16,10 ;10为清除键BRNE DDLRCALL FIL2 ;清除显示缓存区($6c-$73)!LDS R16,$A3SBR R16,8STS $A3,R16 ;建清除显示缓存区标志$A3,3=1RETDDL: INC R26 ;数字键按下,序列左移LD R16,X ;SUBI R16,$29 ;数字带小数点?BRCC DD4 ;若带则将其复原(参考DSPY子程序段码表)SUBI R16,$D7 ;恢复DD4: ST -X,R16 ;移入左邻单元DD5: INC R26CPI R26,$73BRNE DDL ;各数字都左移了一位?ST X,R15 ;新键入数字进入数字序列末位LDI R26,$6CDEL: LD R16,XCPI R16,10 ;是BCD码?BRCS DEL2CPI R16,$29BRCC DELRT ;大于$29为错误!DELA: INC R26 ;0--9/$24/$14为有效!CPI R26,$73BRNE DEL ;缓存区检查完毕?RJMP DELRTDEL2: CPI R16,0BRNE DELRTLDI R16,$24 ;0改为空白ST X,R16RJMP DELA ;DELRT: LDS R16,$A0 ;小数点位置单元TST R16BREQ DDRET ;($a0)=0,无小数点NEG R16ADD R16,$73MOV R26,R16 ;找到缓存区内带小数点的数据位LD R16,XSUBI R16,$D7 ;加上小数点ST X,R16CPI R16,$4D ;在空白码加了小数点($24(空白)+$29=$4d)?BRNE STLR1LDI R16,$29ST X,R16 ;是,将其改为'0.'STLR1: CPI R26,$73BREQ DDRET ;并将其后所有空白都改为0INC R26LD R16,XCPI R16,$24BRNE DDRETCLR R16ST X,R16RJMP STLR1DDRET: RETFIL2: LDI R26,8 ;在显示缓存区内填充空白MOV R14,R26FIL2A: LDI R26,$6CFIL: CLR R27LDI R16,$24FILP: ST X+,R16DEC R14BRNE FILPRET;范例30 ;双键输入检查数据子程序,Ky1数据键/Ky2回车键KYIN2: LDI R26,$60 ;寄存器地址:portb:$18/ddrb:$17/pinb:$16 CLR R27 ;指向数据区首地址CBI DDRB,7CBI DDRB,6 ;pb7和pb6皆为输入口SER R17OUT DDRC,R17 ;c口为数据显示口LA0: LD R17,X ;取数据CPI R17,$0ABRCS LA1CLR R17LA1: LDI R31,HIGH(table*2)LDI R30,LOW(table*2);DSPY段选码表ADD R30,R17ADC R31,R27LPMCOM R0 ;段选码取出并取反OUT PORTC,R0 ;送C口SBI PORTB,7SBIC $16,7RJMP NXA1 ;数字键未按下,转RCALL DL50 ;否则延时XA2: SBI PORTB,6SBIC $16,6RJMP XA0 ;只有数字键按下,转XA20: RCALL DL50 ;两键都按下,先延时50mS SBI PORTB,6SBIS $16,6RJMP XA20SBI PORTB,7SBIS $16,7RJMP XA20 ;等两键都释放RCALL DL50XA21: SBI PORTB,6SBIS $16,6RJMP XA21 ;等待释放SBI PORTB,7SBIS $16,7RJMP XA21 ;再次等待释放RJMP NXA6 ;先按数字键,再按回车键,待2都键释放后退出子程序XA0: SBI PORTB,7SBIS $16,7RJMP XA2 ;等待数字键释放XA1: RCALL DL50 ;延时SBI PORTB,7SBIS $16,7RJMP XA1 ;再次等待释放INC R17 ;数字增1CPI R17,10BRCS NXA1CLR R17 ;超过10,将键值归为0NXA1: SBI PORTB,6SBIC $16,6RJMP LA1 ;回车键也未按下,重新查键RCALL DL50 ;延时NXA3: SBI PORTB,6SBIS $16,6RJMP NXA3 ;再次等待回车键释放RCALL DL50SBI PORTB,6SBIS $16,6RJMP NXA3ST X+,R17 ;数字转入缓存区SER R17OUT PORTB,R17 ;关显RCALL DL50 ;CPI R26,$70 ;到规定数字个数?BRNE LA0 ;LDI R17,$86 ;显示'E'ndOUT PORTC,R17 ;NXA4: SBI PORTB,6SBIS $16,6RJMP NXA5 ;回车键按下,转SBI PORTB,7SBIC $16,7 ;数字键按下,转RJMP NXA4 ;否则反复查键NXA40: RCALL DL50SBI PORTB,7SBIS $16,7RJMP NXA40SBI PORTB,7SBIS $16,7RJMP NXA40 ;等待键释放RJMP KYIN2 ;转检查键入数据NXA5: RCALL DL50SBI PORTB,6SBIS $16,6RJMP NXA5SBI PORTB,6SBIS $16,6RJMP NXA5 ;等回车键释放NXA6: SER R17OUT PORTB,R17 ;关显,结束子程序RETDL50: ;RCALL DL25 ;延时50毫秒子程序/8Mhz(去掉指令前“;”号)DL25: CLR R14 ;延时50毫秒子程序/4MhzCLR R15DL50L: DEC R15NOPBRNE DL50LDEC R14BRNE DL50LRET;范例31LPRNT: SER R17 ;宽行打印机检测及控打程序OUT DDRC,R17 ;C口为打印机输出口!SBI DDRD,7CBI DDRD,3 ;pd7为选通输出口,pd3(INT1)查忙输入口SBI PORTD,3SBIC PIND,3 ;查打印机忙信号RJMP ERR5 ;打印机尚未工作忙信号即已为高,打印机不能打印LDI R17,$0D ;写回车命令给打印机OUT PORTC,R17CBI PORTD,7 ;发出选通信号NOPNOPNOPSBI PORTD,7 ;strobeLDI R16,50TSPRT: SBI PORTD,3SBIc PIND,3RJMP LPRT2 ;50次内忙信号高起来为正常DEC R16 ;否则为非正常状态BRNE TSPRTERR5: LDI R16,5RCALL ERRX ;显示5号错误RJMP DIPA1 ;转主程序初始化LPRT2: LDI R25,1CLR R24 ;point to $100LDI R17,$80OUT GIMSK,R17 ;允许int1中断LDI R17,$0AOUT MCUCR,R17 ;INT1下降沿中断SEI ;general interrupt enableRETEX_INT1:PUSH R26PUSH R27IN R27,SREGPUSH R27PUSH R17 ;保护现场MOV R27,R25 ;取数据指针MOV R26,R24LD R17,X+ ;MOV R25,R27MOV R24,R26 ;增1后将指针送回CPI R17,3 ;是停止符?BRNE INT1SDCLR R17OUT GIMSK,R17 ;禁止INT1中断RJMP INT1EDINT1SD: OUT PORTC,R17 ;打印数据输出到打印口CBI PORTD,7 ;clr ($12,7)NOPNOPNOPSBI PORTD,7 ;向打印机发出选通INT1ED: POP R17POP R27OUT SREG,R27POP R27POP R26 ;恢复现场RETI。
AVR学习笔记
PC = progammer counter //程序计数器ACC = accumulate //累加器PSW = progammer status word //程序状态字SP = stack point //堆栈指针DPTR = data point register //数据指针寄存器IP = interrupt priority //中断优先级IE = interrupt enable // 中断使能TMOD = timer mode //定时器方式 (定时器/计数器控制寄存器)ALE = alter (变更,可能是)PSEN = progammer saving enable //程序存储器使能(选择外部程序存储器的意思) EA = enable all(允许所有中断)完整应该是 enable all interruptPROG = progamme (程序)SFR = special funtion register //特殊功能寄存器TCON = timer control //定时器控制PCON = power control //电源控制MSB = most significant bit//最高有效位LSB = last significant bit//最低有效位CY = carry //进位(标志)AC = assistant carry //辅助进位OV = overflow //溢出ORG = originally //起始来源DB = define byte //字节定义EQU = equal //等于DW = define word //字定义E = enable //使能OE = output enable //输出使能RD = read //读WR = write //写中断部分:INT0 = interrupt 0 //中断0INT1 = interrupt 1//中断1T0 = timer 0 //定时器0T1 = timer 1 //定时器1TF1 = timer1 flag //定时器1 标志 (其实是定时器1中断标志位)IE1 = interrupt exterior //(外部中断请求,可能是)IT1 = interrupt touch //(外部中断触发方式,可能是)ES = enable serial //串行使能ET = enable timer //定时器使能EX = enable exterior //外部使能(中断)PX = priority exterior //外部中断优先级PT = priority timer //定时器优先级PS = priority serial //串口优先级第一部分二极管发光的条件是正负极相差达1V以上。
AVR学习笔记
一、AVR的PC口正常使用:1、在程序中连续写入两条语句:MCUCSR |= BIT(7);( 或者是MCUCSR =(1<<7); )。
2、将熔丝位OCDEN 和JTAGEN 设置为0,关闭仿真功能。
编译时出现错误警告:!E <library>(72): area 'data' not large enough解决方法:project----compiler----勾上Treat"const"as"_flash"解释:将定义的const较大数组装入flash.二、如何通过AVR_fighter对EEPROM编程:在运用ICCAVR编程时对需要写入EEPROM的数据作如下处理:///////////////////////////////////////////////////////#pragma data:eepromunsigned char table[]={0x01,0x02} //定义要写入EEROM的数据#pragma data:data并将#include <eeprom.h> 加入C代码中。
////////////////////////////////////////////////////////通过以上处理后的数据在编译时会被ICCAVR编译生成*.eep文件,将此文件加入AVR_fighter的装EEPROM ,AVR_fighter在编程flash时相应会编程EEPROM。
三、将SPI初始化为主机,进行简单的数据发送。
例子中SSR_SIP必须由实际的数据方向寄存器代替。
void spi_maxterinit (void){DDR_SPI = (I<<DD_MOSI)|(1<<DD_SCK); //设置MOSI和SCK为输出,其他为输入SPCR = (1<<SPE)|(1<<SPR0); //使能SPI主机模式,设置时钟速率为fck/16}void SPI_MasterTransimt(char cData){SPDR = cData; //启动数据传输while(!(SPRS & (1<<SPIF))); //等待传输结束}///////////////////////////////////////////////////////////////////////////////////////////////////////////例子假定已经饱含了正确的头文件:Void SIP_SlaveInit(void){DDR_SPI = (1<<DD_MISO); //设置MISO为输出,其他为输入SPCR = (1<<SPE); //使能SPI}Char SPI_SlaveReceive(void){While (!( SPSR & (1<<SPIF ))){};Return SPDR;}四、对一个十六进制数的某一位取反Num = num^( 1<< wei );五、STC自动下载:Include <reg52.h>Sfr ISP_CONTR =0XE7;sbit ISP=P3^0;void main(void){TMOD |= 0X01;TH0=0X00;TL0=0X00;EA=1;ET0=1;TR0 =1;}void Timer0_isr(void) interrupt 1 using 1{TH0=0x00; //重新赋值TL0=0x00;while(ISP==0){ISP_CONTR=0XE0;}}。
AVR单片机学习笔记
AVR单片机学习笔记
Atmega16A
一、寄存器
1.特殊功能寄存器SFIOR
位2-PUD为上拉电阻禁止位。
置位时即使DDRxn和PORTxn配置位使能上拉电阻,I/O 端口的上拉电阻也会被禁止。
PA端口:
2.端口A数据寄存器PORTA
确定PA口的工作状态;
PORTAn(n=0-7)初始值为0x00(十六进制)。
3.端口A方向寄存器DDRA
指定PA端口是作为输入还是输出口用;
DDRAn(n=0-7)初始值为0x00(十六进制)。
4.端口A输入引脚PINA
用来访问端口A的逻辑值且只允许进行读操作。
PB端口:
5.端口B数据寄存器PORTB
确定PB口的工作状态;
PORTBn(n=0-7)初始值为0x00(十六进制)。
6.端口B方向寄存器DDRB
指定PB端口是作为输入还是输出口用;
DDRBn(n=0-7)初始值为0x00(十六进制)。
7.端口B输入引脚PINB
用来访问端口B的逻辑值且只允许进行读操作。
PC端口、PD端口同上
二、数码管
1.段选数据输出-->>位选数据输出-->>数码管显示数字
2.段选
选择数码管的序号i,使第i个数码管发光(i为一整型数)。
3.位选
选择第i个数码管的发光位置,使其显示特定的数字。
AVR单片机笔记
A VR单片机笔记说明:主要使用的编译环境为IAR,使用A VR的ATmega16 和128目录IO (2)时钟: (2)MCU控制寄存器-MCUCR (2)MCU控制和状态寄存器-MCUCSR (2)看门狗定时器控制寄存器-WDTCR (3)外部中断控制寄存器A -EICRA (4)外部中断控制寄存器B -EICRB (4)外部中断屏蔽寄存器-EIMSK (4)外部中断标志寄存器-EIFR (5)中断矢量表 (5)在IAR环境中AVR中断程序的格式 (6)定时器 (6)定时器/计数器0和2: (6)定时器/计数器1和3: (7)使用IAR调试注意事项 (7)IIC(TWI) (8)o8515.h头文件 (10)IOPort A-G:都含有内部上拉电阻数据:PORTA-G;方向DDRA-G;PINA-G 时钟:XTAL 分频控制寄存器-XDIVMCU控制寄存器-MCUCRMCU控制和状态寄存器-MCUCSR• Bit 4 – JTRF: JTAG 复位标志通过JTAG 指令A VR_RESET 可以使JTAG 复位寄存器置位,并引发MCU 复位,并使JTRF 置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 3 – WDRF: 看门狗复位标志看门狗复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 2 – BORF: 掉电检测复位标志掉电检测复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 1 – EXTRF: 外部复位标志外部复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 0 – PORF: 上电复位标志上电复位发生时置位。
只能通过写”0” 来清除。
看门狗定时器控制寄存器-WDTCR• Bits 7..5 – Res: 保留保留位,读操作返回值为零。
• Bit 4 – WDCE: 看门狗修改使能清零WDE 时必须先置位WDCE,否则不能禁止看门狗。
avr学习笔记
MCU控制寄存器—MCUCRBit 1 – IVSEL: 中断向量选择IVSEL为"0―时,中断向量位于Flash存储器的起始地址;IVSEL 为"1―时,中断向量转移到Boot 区的起始地址。
实际的Boot 区起始地址由熔丝位BOOTSZ 确定。
为了防止无意识地改变中断向量表,修改IVSEL 时需要遵循如下过程:1. 置位中断向量修改使能位IVCE2. 在紧接的4 个时钟周期里将需要的数据写入IVSEL,同时对IVCE 写‖0‖执行上述序列时中断自动被禁止。
其实,在置位IVCE 时中断就被禁止了,并一直保持到写IVSEL 操作之后的下一条语句。
如果没有IVSEL 写操作,则中断在置位IVCE 之后的4个时钟周期保持禁止。
需要注意的是,虽然中断被自动禁止,但状态寄存器的位I并不会因此而受到影响。
Note: 若中断向量位于Boot Loader区,且Boot锁定位BLB02被编程,则执行应用区的程序时中断被禁止;若中断向量位于应用区,且Boot锁定位BLB12 被编程,则执行Boot Loader区的程序时中断被禁止。
有关Boot锁定位的细节请参见P241‖Boot Loader 支持RWW自编程,ATmega88 与ATmega168‖ 。
该位在ATmega48 中无效。
• 位0 – IVCE: 中断向量修改使能改变IVSEL 时IVCE 必须置位。
在IVCE 写入4 个时钟周期或IVSEL 写操作之后,IVC被硬件清零。
如前面所述,置位IVCE 将禁止中断。
代码如下:void Move_interrupts(void){/* 使能中断向量的修改*/MCUCR = (1<<IVCE); /* 将中断向量转移到boot区*/ MCUCR = (1<<IVSEL);}• 位7 – I: 全局中断使能Sei();全局中断使能,cli();对I清零。
• 位6 – T: 位拷贝存储位拷贝指令BLD 和BST 利用T 作为目的或源地址。
AVR汇编百例 - 串行通讯
;范例40.ORG 0 ;8535UART串行通讯程序,晶振4MHZ.EQU DTPINT=$180 ;UBRR=12 波特率19200(REL.ERR.=0.16%).EQU DRPINT=$1D0STRT30: RJMP RST30.ORG $00BRJMP U_RXC ;UART接收完成中断.ORG $00CRJMP U_TXC ;UART发送寄存器空中断.ORG $011RST30: LDS R16,$A3 ;CBR R16,3STS $A3,R16 ;清完整ASCII数据块接收到标志($A3,1),错误标志(FE/OR)($A3,0) LDI R16,12OUT UBRR,R16 ;BAUD RA TE=FCP/16(UBRR+1)=19200LDI R27,HIGH(DIPINT)MOV R6,R27LDI R26,LOW(DTPINT)MOV R7,R26 ;发送数据指针在r6r7(dtpint)CLR R11INC R11LDI R16,$30 ;发送数据块长度为$30MOV R12,R16RCALL CRC0 ;得到CRC检测之余式(冲掉$0D&$0A)INC XLINC XLLDI R16,$0DST X+,R16LDI R16,$0AST X,R16 ;在数据块末尾加$0D&$0A,实际发送数据块长度为$32LDI R16,$B8 ;允许UART发送和接收,接收中断,发送寄存器空中断,8位数据OUT UCR,R16LDI R16,HIGH(DRPINT)MOV R8,R16LDI R16,LOW(DRPINT)MOV R9,R16 ;r8,r9:接收缓存区指针(FIRST POINT TO $1D0)CLR R10 ;接收数据块长预先清除SEI ;HH30: LDS R16,$A3SBRC R16,0 ;错误接收?RJMP RCVER ;错误处理SBRS R16,1 ;接收数据完成?RJMP HH30 ;否,转再查询RCVEF: CLR R11 ;块长予处理INC R11DEC R10DEC R10 ;$0D&$0A不算块长度之内(故将块长减2)MOV R12,R10 ;(R11,R12):块长LDI XH,HIGH(DRPINT)MOV R8,XHLDI XL,LOW(DRPINT)MOV R9,XLRCALL CRC0 ;恢复出CRC余式LDI R16,$0DCP R16,R14BRNE CRCERLDI R16,$0ACP R16,R15 ;恢复出$0D$0A为正确接收BREQ HH30CRCER: ;. ;循环冗余检测错误处理;.;.RJMP STRT30RCVER: CBI UCR,RXCIE;. ;接收错误(FE/OR)处理;. ;(过程略);.RJMP STRT30:UART接收数据块程序U_RXC: PUSH R16IN R16,SREGPUSH R16PUSH R26PUSH R27RSC1: IN R16,USR ;UART状态寄存器ANDI R16,$18 ;FE/OR ERROR?BRNE RVERR ;错误转INC R10 ;块长加1MOV XH,R8MOV XL,R9 ;r8r9:接收数据指针,首指$1D0IN R16,UDRST X+,r16 ;MOV R8,XHMOV R9,XLCPI R16,$0A ;收到最末字符(回车命令LF)?BRNE RSCOMLDS R16,$A3SBR R16,2 ;建立数据块接收完毕标志STS $A3,R16CBI UCR,RXCIE ;禁止接收中断RJMP RSCOMRVERR: LDS R16,$A3SBR R16,1STS $A3,R16 ;$A3,0:FE/OR错误接收标志RSCOM: POP R27POP R26POP R16OUT SREG,R16POP R16RETI; UART发送数据块程序U_TXC: PUSH R16IN R16,SREGPUSH R16PUSH R26PUSH R27SPSV1: MOV XH,R6MOV XL,R7 ;发送数据指针,首指$180LD R16,X+ ;取发送数据,调指针MOV R6,XHMOV R7,XLSPS11: OUT UDR,R16 ;送入数据寄存器,移入发送移位寄存器后即引起数据寄存器空中断CPI R16,$0ABRNE SPCOMCBI UCR,UDRIE ;发送最末字符后禁止发送寄存器空中断LDI R16,HIGH(DRPINT)MOV R8,R16LDI R16,LOW(DRPINT)MOV R9,R16 ;接收数据指针初始化,指向$1D0;CBI USR,6 ;SPCOM: POP R27POP R26POP R16OUT SREG,R16POP R16RETI.DSEG.ORG $180DTPINT:.BYTE $32;$41,$45,$65,$73,$46,$42,$40,$6F,$33,$44,$66,$8C,$4D,$4B,$2F,$67;$42,$4F,$66,$78,$47,$45,$44,$63,$32,$48,$60,$7C,$6D,$45,$2A,$63;$43,$56,$55,$53,$4D,$4F,$40,$2E,$31,$42,$67,$4C,$47,$4A,$38,$39;$0D,$0A.EQU DRPINT=$1D0.ORG $1D0DRPINT: .BYTE $34 ;(内容略);范例41 ;外部中断int0接收ASCII码数据块.ORG 0 ;8515/8535/晶振4MHZSTRT31: RJMP RST31RJMP EX_INT0.ORG $00D ;8535外部中断0RST31: LDI R17,HIGH(ramend)OUT SPH,R17LDI R17,LOW(ramend)OUT SPL R17LDI R17,2OUT TCCR1B,R17 ;4mhz/8分频,计数单位为2微秒,TCCR1B:$2e LDI R17,$40OUT GIMSK,R17 ;gimsk,6(允许int0中断)LDI R17,2OUT MCUCR,R17 ;设INT0为下降沿中断(mcucr'b1&b0=10)CBI DDRD,2 ;int0 为输入;.;. ;其他初始化略SEI ;CLRBUF: LDI R27,1CLR R26 ;接收数据缓存区首址$100LDI R17,$40OUT GIMSK,R17 ;gimsk,6CLR R17CLRLOP: ST X+,R17CPI R26,$48BRNE CLRLOP ;清接收缓存区($100--$147)LDS R16,$A3CBR R16,$60STS $A3,R16 ;接收错误($A3,6)和接收完成($A3,5)标志清除CLR5: ;.;. ;背景程序略RJMP CLR5 ;RCVST: CBI DDRD,2 ;int0 为输入SER R16 ;接收开始OUT PORTC,R16 ;关显LDI R27,1CLR R26 ;接收数据指针,首指$100LDI R17,18 ;接收18个字符,其末尾为$0D$0AMOV R14,R17RCALL RVBYT1 ;接收第一个字符RJMP RVBYTRVBLOP: RCALL RVBYT2 ;接收第二个字符及其后字符RVBYT: LDS R17,$A3SBRC R17,6RJMP CLRBUF ;接收出错,转去清除$100--$14FSBRC R17,5RJMP DTCOM ;接收完整数据块,转去处理ST X+,R16DEC R14BRNE RVBLOP ;未收完18个字符,继续CPI R26,$42 ;指针达到$142?BREQ DTCOM ;接收完整数据块,转去处理DEC R26DEC R26 ;$0D$0A(CR&LF)丢掉RCVLP: LDI R17,18MOV R14,R17RJMP RVBLOPDTCOM: LDI R27,1CLR R26 ;接收数据首地址:$100DLLOP: CLR R29LDI R28,$90 ;处理ASCII码程序acum要求将数据放在$90--$9f LD R16,XCPI R16,$50 ;第一个字符约定为‘P’才有效BRNE RVCOM1 ;也是判断处理结束符DLLOP1: LD R16,X+ST Y+,R16CPI R28,$A0BRNE DLLOP1 ;传16个字符PUSH R26PUSH R27RCALL ACUM ;ASCII变BCD再变为二进制数,累加POP R27POP R26BRTS RVCOM1 ;ASCII码无效,转出!RJMP DLLOPRVCOM1:CLTRJMP CLRBUF ;转去清缓存区,重新接收;晶振采用4MHZ,指令(DEC+BRNE)耗时0.75微秒)! EX_INT0:POP R16 ;int0中断服务子程序POP R16 ;废弃返回地址LDI R16,HIGH(RCVST)PUSH R16LDI R16,LOW(RCVST)PUSH R16 ;设置返回地址IN R16,GIMSK ;禁止int0中断CBR R16,$40OUT GIMSK,R16RETIRVBYT1: LDI R17,2 ;查到0接收时,再做一次接收MOV R15,R17LDI R17,50 ;第一个起始位半位延时(50*0.75=38微秒)MOV R12,R17RJMP RVBCMRVBYT2: LDI R17,2MOV R15,R17RVBY2: LDI R17,147 ;110微秒>1位宽/9600baud,110/0.75=147 MOV R12,R17TEST3: SBI PORTD,2SBIS PIND,2 ;停止位超宽测试RJMP RVSTDEC R12BRNE TEST3LDS R16,$A3 ;110微秒内查到低电平为起始位ORI R16,$20STS $A3,R16 ;否则为接收结束,令$A3,5=1RETRVST: LDI R17,60 ;60*0.75=45微秒(半位延时)MOV R12,R17RVBCM: DEC R12BRNE RVBCMLDI R17,9 ;1位起始+8位数据MOV R13,R17SBI PORTD,2SBIC PIND,2RJMP RVER1 ;无效起始位(半位测试)RVLOP: LDI R17,130 ;may be 128-132/位延时常数MOV R12,R17RVLP1: DEC R12 ;0.25微秒BRNE RVLP1 ;0.5微秒/if condition is trueSECSBI PORTD,2SBIS PIND,2CLCDEC R13BRNE OVRRC ;不是停止位,转数据位接收BRCC RVER1 ;无效停止位,出错TST R16 ;BRNE RBYRT ;不为0,收到一个有效字符DEC R15BRNE RVBY2 ;2次接收到$00,出错RVER1: LDS R16,$A3ORI R16,$40 ;接收出错标志CBR R16,$20STS $A3,R16RBYRT: RETOVRRC: ROR R16 ;组织数据RJMP RVLOP ;100.7微秒/程序实设位宽;范例42 ;8535'T0中断发送ASCII码程序,晶振4MHZ .EQU DATA2=$150.ORG $000STRT32: RJMP RST32.ORG 009RJMP T0_OVF.ORG $011RST32: SER R17OUT DDRB,R17 ;B口为输出OUT PORTB,R17 ;输出高电平LDI R16,2 ;0B00000010/8 DIVIDED(4fc/8:2微秒)OUT $33,R17 ;写入tccr0LDI R16,204 ;(256-204)*2=104微秒/9600baud 104微秒/位!OUT TCNT0,R17 ;LDI R17,HIGH(ramend)OUT SPH,R17LDI R17,LOW(ramend)OUT SPL,R17LDI R25,HIGH(DA TA2)LDI R24,LOW(DATA2);发送数据指针LDS R17,$A3CBR R17,$14 ;发送出错标志($A3,4)/发送完毕标志位($A3,2)清除!STS $A3,R17SEILDI R17,1OUT TIMSK,R17 ;允许T/C0溢出中断CLR R17 ;位计数器请除HH32: LDS R16,$A3SBRC R16,4RJMP HHER32 ;出错SBRS R16,2 ;RJMP HH32 ;查询等待数据块发送完成;. ;其他程序略;. ;可安排接收对方发来数据程序,见STRT33 RJMP RST32HHER32:;.;. ;错误处理略RJMP RST32T0_OVF: PUSH R16IN R16,SREGPUSH R16PUSH R26PUSH R27IN R16,TCNT0INC R16SUBI R16,52 ;重写入一位定时常数(带修正)OUT TCNT0,R16MOV R26,R24 ;数据指针MOV R27,R25CPI R17,10BREQ SND10TST R17BRNE SND9SND0: CBI PORTB,0 ;发起始位(0)RJMP SVCOMSND9: CPI R17,9BRNE SND18 ;1-8为数据位SBI PORTB,0 ;9为停止位(1)CLR R17 ;停止位发完后,位计数器清除ADIW R24,1 ;指针增1,指下一位数据LD R16,XCPI R16,$0A ;本次发送的是$0A?BRNE SVCOM1LDI R17,10 ;停止位标志RJMP SVCOM1SND10: LDS R16,$A3SBR R16,4 ;发送完成标志STS $A3,R16 ;SND11: CLR R16OUT TCCR0,R16 ;关闭T/C0CLR R17 ;清位计数器LDI R24,LOW(DATA2);发送指针初始化LDI R25,HIGH(DA TA2)RJMP SVCOM1SENDER: LDS R16,$A3SBR R16,$10STS $A3,R16 ;建出错标志RJMP SND11SND18: BRCC SENDER ;大于10为错误LD R16,XROR R16 ;发送位传到进位CBRCC S182SBI PORTB,0 ;C(=1)-->PB0($18,0)BRCS S183S182: CBI PORTB,0 ;C(=0)-->PB0($18,0)S183: LD R16,XROR R16 ;ST X,R16 ;保存剩余位MOV R24,R26 ;存数据指针MOV R25,R27SVCOM: INC R17 ;位计数器增1SVCOM1: POP R27POP R26POP R16OUT SREG,R16POP R16 ;恢复现场RETI;范例43 ;8515/8535/晶振4MHZ RECEIVING ASCII CHAR. BY TCNT0&PB0 .EQU DATA3=$100 ;UES R11 SA VE SREG, R12 R13:数据指针DATA3;R14: 块长(BLOCK LENGTH),R15:接收字符暂存寄存器.ORG 0 ;R16:(THE BIT SEQUENCE COUNTER)位序列计数器;R17:WORKING REG.R18:FLAG UNIT,BAUD RATE:9600 STRT33: RJMP RST33 ;X&Y:POINTER/接收数据缓存区首地址:$100 .ORG $009 ;$007(8515)RJMP T0_OVF1.ORG $011 ;$00D(8515)RST33: LDI R17,HIGH(ramend)OUT SPH,R17LDI R17,LOW(ramend)OUT SPL,R17LDI R17,HIGH(DA TA3)MOV R12,R17LDI R17,LOW(DATA3)MOV R13,R17 ;R12R13:接收数据指针CLRBF1: CLR R16CLRLP: ST X+,R16CPI R26,$48BRNE CLRLP ;接收数据缓存区请除CLR R18 ;标志寄存器请除/R18,2:完整数据块收到,R18,1;第一字符(块长)收到:R18,0:出错LDI R17,$02 ;8535:$01OUT TIMSK,R17 ;允许T/C0溢出中断LDI R17,6 ;外部脉冲下降沿计数OUT TCCR0,R17CBI DDRB,0 ;PB0为输入LDI R17,$FFOUT TCNT0,R17 ;计一个数即中断;SEI ;TEST1: RCALL DSPL Y3 ;调串行移位显示子程序SBRC R18,0 ;RJMP DLERR ;出错,转错误处理SBRS R18,2 ;数据块接收完成?RJMP TEST1LDI R16,128DECLP: DEC R16BRNE DECLPRJMP DTCOM0 ;先延时,再转处理数据块DLERR: ;. ;出错处理;.;.RCALL DL50 ;延时50毫秒后RJMP RST33 ;重新接收DTCOM0: LDI R27,1CLR R26 ;数据存储区首地址$100DLLOP0: CLR R29LDI R28,$90 ;ASCII码处理区为$90--$9fLD R16,XCPI R16,$50 ;字母P打头才有效BRNE RVCOM0 ;否则为无效字串或ASCII码处理结束DLLO1: LD R16,X+ST Y+,R16CPI R28,$A0BRNE DLLO1 ;传送16个字符PUSH R26PUSH R27RCALL ACUM ;处理一组ASCII码数据POP R27POP R26BRTC DLLOP0 ;T=1,ASCII码数据无效CLT;. ;错误处理RJMP STRT33RVCOM0:;. ;错误处理;.RJMP STRT33T0_OVF1:IN R11,SREG ;T/C0中断服务PUSH R17CPI R16,0 ;起始位下降沿中断?BRNE T0SV10LDI R17,2 ;YESOUT TCCR0,R17 ;改为内定时(4MHZ/8分频)LDI R17,232 ;半位时间常数24 定48微秒(<52)OUT TCNT0,R17RJMP T0SV6T0SV10: CPI R16,1 ;1,半位定时到BRNE T0SV2SBI PORTB,0SBIC PINB,0RJMP T0ERR ;高电平,错误RJMP T0SV60 ;低电平,有效起始位T0SV2: CPI R16,10 ;BRNE T0SV3SBI PORTB0 ;10,接收停止位SBIS PINB,0RJMP T0ERR ;低电平,错误LDI R17,6OUT TCCR0,R17 ;改为外部脉冲下降沿计数,为接受下一位字符准备LDI R17,$FF ;计一个数即中断OUT TCNT0,R17CLR R16 ;位计数器请除SBRC R18,1 ;是第一个字符(r18,1=0)?RJMP T0SV21 ;否,为块内数据MOV R14,R15 ;块长转入r14SBR R18,2 ;块长已收到RJMP T0SV61T0SV21: PUSH XLPUSH XHMOV XH,R12MOV XL,R13 ;取缓存区指针ST X+,R15 ;字符送入缓存区MOV R12,XHMOV R13,XLPOP XHPOP XLDEC R14BRNE T0SV61SBR R18,4 ;块长减为0,完整数据块收到CLR R16OUT TCCR0,R16 ;停止TCNT0RJMP T0SV61T0SV3: BRCC T0ERR ;出错(大于10)CLC ;2--9:数据位SBI PORTB,0 ;接收一位数据SBIC PINB,0SECROR R15 ;数据组织到R15T0SV60: IN R17,TCNT0 ;读TCNT0计数值INC R17 ;SUBI R17,52OUT TCNT0,R17 ;写入补偿后的时间常数T0SV6: INC R16 ;位序列计数器增1T0SV61: POP R17OUT SREG,R11RETIT0ERR: CLR R16T0ERL: SBR R18,1 ;错误接收标志OUT TCCR0,R16 ;停止TCNT0RJMP T0SV61;范例44.ORG 0 ;8535多机通讯主机程序/振4MHZ.EQU DTPINT=$180 ;UBRR=12,波特率19200(REL.ERR.=0.16%).EQU DRPINT=$1C0 ;主机发往#1,#2,#3,#分机数据在;$180-18F,$190-19F,$1A0-1AF和$1B0-1BFSTRT34: RJMP RST34 ;主机接收#1,#2,#3,#4分机之数据块分别在;$1C0-1CF,$1D0-1DF,$1E0-1EF和$1F0-1FF.ORG $00BRJMP U_RXC ;UART接收完成中断.ORG $00CRJMP U_TXC ;UART 发送完成中断.ORG $011RST34: LDI R16,12OUT UBRR,R16 ;BAUD RA TE=FCP/16(UBRR+1)=4000000/(16*13)=19200 CLR R15 ;分机号初始化LDI R27,HIGH(DTPINT)LDI R26,LOW(DTPINT);发送数据指针,首指$180LDI R29,HIGH(DRPINT)LDI R28,LOW(DRPINT);接收数据指针(POINT TO $1C0) NEXTNO: LDI R16,$18OUT UCR,R16 ;允许UART接收和发送,8位数据模式INC R15 ;指向分机OUTLP: OUT UDR,R15 ;呼分机号TSLOP: IN R16,USRSBRS R16,7RJMP TSLOP ;分机返回机号?IN R16,UDRCP R16,R15 ;与发送分机号符合?BRNE OUTLP ;不符再发TXLOP: LD R16,X+OUT UDR,R16 ;向分机发送数据块TESTL: IN R17,USRSBRS R17,5 ;发送寄存器空?RJMP TESTLCPI R16,$0ABRNE TXLOP ;发完整个数据块?RXTST: IN R17,USRSBRS R17,7 ;RXC=1 分机发来数据RJMP RXTSTIN R16,UDRST Y+,R16 ;接收数据转入内存CPI R16,$0ABRNE RXTST ;接收完整数据块后MOV R16,R15CPI R16,4 ;转与下一分机通讯(只有4台分机)BRNE NEXTNO ;直到轮询完毕HH34: RJMP HH34 ;可改为处理分机发来数据,再转入下一周轮询.DSEG.ORG $180DTPINT:.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 $1C0DRPINT: .BYTE $40;范例45.ORG 0 ;8535多机通讯1#分机程序,晶振4MHZ.EQU DTPIT1=$180 ;UBRR=12 波特率19200(REL.ERR.=0.16%).EQU DRPNT1=$1C0STRT35: RJMP RST35.ORG $00BRJMP UARXC ;UART接收完成中断.ORG $00CRJMP UATXC ;UART发送寄存器空中断.ORG $011RST35:CLR R18 ;请除主机发来完整数据块标志(R18,7)/主机呼号选中分机;标志(R18,6)LDI R16,12OUT UBRR,R16 ;[BAUD RATE=FCP/16(UBRR+1)]LDI R16,HIGH(DRPNT1)MOV R8,R16LDI R16,LOW(DRPNT1)mov R9,R16 ;r8,r9:接收数据指针(FIRST POINT TO $1C0)LDI R16,$98 ;允许UART发送,接收,接收完成中断OUT UCR,R16SEICLR R15INC R15 ;1#分机设为1/2#分机设为2/3#分机设为3/4#分机设为4 RXDTS: SBRS R18,6 ;收到主机发来呼号?RJMP RXDTSOUT UDR,R15 ;将分机号反还主机TXDON: IN R16,USRSBRS R16,5RJMP TXDON ;发送寄存器空?RCVBLK: SBRS R18,7RJMP RCVBLK ;等待接收主机发来数据块LDI R16,HIGH(DTPIT1)MOV R6,R16LDI R16,LOW(DTPIT1)MOV R7,R16 ;设置发送数据指针r6r7,首指$180SBI UCR,5 ;UDRIE=1 ,引起发送寄存器空中断TXDN: SBIC UCR,5RJMP TXDNRJMP RST35 ;等待UDRIE=0 ,向主机发送数据块完毕后,转下一轮通讯:UART中断接收程序UARXC: IN R14,SREGTST R18BREQ NUMB ;无主机呼号选中标志,查机号PUSH R26PUSH R27IN R17,UDR ;读入接收数据MOV XH,R8MOV XL,R9 ;r8r9:接收数据缓存区指针,首指$1C0ST X+,R17MOV R8,XHMOV R9,XLCPI R17,$0A ;收到换行符?BRNE RSCOM1SBR R18,$80 ;建立数据块接收完毕标志RSCOM1: POP R27POP R26DRETI: OUT SREG,R14RETINUMB: IN R17,UDRCP R17,R15 ;主机呼号与本分机号符合?BRNE DRETI ;不符,转SBR R18,$40 ;建选中标志RJMP DRETI; UART中断发送数据程序UA TXC: IN R16,SREG ;r6 r7:the sendDATA pointer(FIRST POINT TO $180) PUSH R16PUSH R26PUSH R27MOV XH,R6MOV XL,R7 ;发送数据指针LD R16,X+MOV R6,XHMOV R7,XLOUT UDR,R16 ;发送数据写入数据寄存器CPI R16,$0A ;发送LF?BRNE SDCOMCBI UCR,5 ;禁止数据寄存器空中断(清UDRIE)LDI R16,HIGH(DRPINT)MOV R8,R16LDI R16,LOW(DRPINT)MOV R9,R16 ;为接收作准备(FIRST POINT TO $1C0)SDCOM: POP R27POP R26POP R16OUT SREG,R16POP R16RETI.DSEG.ORG $180DTPIT1: .BYTE $10;$41 $45 $65 $73 $46 $42 $40 $6F $33 $44 $66 $5C $4D $4B $0D $0A.ORG $1C0DRPNT1: .BYTE $10;$41 $45 $65 $73 $46 $42 $40 $6F $33 $44 $66 $5C $4D $4B $0D $0A;范例46.ORG $000 ;RS232<->RS485通讯标准转换/晶振4MHZSTRT36: RJMP RST485 ;使用8515!.ORG $009RJMP U_RXC ;UART 接收中断.ORG $00DRST485: LDI R16,2OUT SPH,R16LDI R16,$5f ;OUT SPL,R16LDI R16,$98 ;允许UART接收和发送,允许接收中断OUT UCR,R16LDI R16,12OUT UBRR,R16 ;波特率19200SBI DDRB,7SBI DDRB,6 ;PB7,PB6为输出CBI PORTB,7CBI PORTB,6 ;PB7控制485发送(高有效)PB6控制485接收(低有效) SEIHERE0: CPI R16,3 ;收到停止符?BRNE HERE0 ;未收到循环等待HERE1: SBIS USR,6 ;RJMP HERE1 ;等待停止符发送完毕CBI PORTB,7 ;禁止485发送CBI PORTB,6 ;允许485接收SBI USR,6 ;写‘1’清除发送完成标志!CLR R16RJMP HERE0 ;转等待下一轮中转U_RXC: SBI PORTB,7 ;允许485发送SBI PORTB,6 ;禁止485接收,IN R16,UDR ;读出接收数据,同时清除接收中断标志TSAGN: SBIS USR,6 ;上一数据发送完毕?RJMP TSAGNSBI USR,6 ;清除发送完成标志OUT UDR,R16 ;转发本次接收数据RETI;范例47.EQU DATA4=$220.ORG $000 ;同步串口通讯主机程序,晶振4MHZSTRT37: RJMP RST37.ORG $00A ;8535 SPI中断矢量(8515为$008)RJMP SPINT.ORG $011 ;$00D(8515)RST37: LDI R16,2OUT SPH,R16LDI R16,$5fOUT SPL,R16 ;堆栈指针初始化LDI R16,$A0OUT DDRB,R16 ;SCK,MOSI为输出LDI R16,$DCOUT SPCR,R16 ;允许SPI中断,先发送高位,主控方式,时钟为主频4分;频,后沿有效LDI XH,HIGH(DATA4)LDI XL,LOW(DA TA4);数据指针LDI R16,$30MOV R15,R16 ;数据块长LDI R16,12 ;0.25微秒SPI0: DEC R16 ;0.25微秒BRNE SPI0 ;0.5微秒总延时9微秒LD R16,XOUT SPDR,R16 ;写发送数据寄存器,启动发送SEIHH37: RJMP HH37 ;背景程序略SPINT: IN R14,SREGIN R16,SPDR ;读出接收数据ST X+,R16DEC R15BRNE SPI1 ;数据收发完毕?OUT SPCR,R15 ;是,停止收发OUT SREG,R14RETISPI1: LDI R16,6 ;0.25微秒SPI1A: DEC R16 ;0.25微秒BRNE SPI1A ;0.5微秒总共4.5微秒LD R16,XOUT SPDR,R16 ;发下一个数据OUT SREG,R14RETI;范例48.ORG $000STRT37S:RJMP RST37S ;同步串口通讯从机程序(8515) 晶振4MHZ .ORG $008 ;$00A(8535)RJMP SPINTS ;同步串口中断矢量.ORG $00D ;$011(8535)RST37S: LDI R16,2OUT SPH,R16LDI R16,$5fOUT SPL,R16LDI R16,$40OUT DDRB,R16 ;MISO为输出LDI R16,$CCOUT SPCR,R16 ;允许SPI中断,先发送高位,从控方式,时钟为主频4分频,后沿有效LDI YH,HIGH(DATA4)LDI YL,LOW(DA TA4);数据指针LDI R16,$30 ;数据长度LD R15,YOUT SPDR,R15 ;写入数据寄存器SEIHH37S: RJMP HH37S ;背景程序从略SPINTS: IN R14,SREGIN R15,SPDR ;读接收数据ST Y+,R15DEC R16BRNE SPI2 ;数据块收发完毕OUT SPCR,R16 ;停止中断收发RJMP SPI3SPI2: LD R15,YOUT SPDR,R15 ;发下一数据SPI3: OUT SREG,R14RETI;范例49 以模拟串口与串行移位寄存器74165通讯,以74165驱动LED显示子程序DSPL Y3: SBI DDRC,1 ;PC1,串行数据输出SBI DDRC,0 ;PC0,移位时钟CBI PORTC,0 ;LDI R17,8 ;8字节显示缓存区$60(高)--$67(低))MOV R8,R17CLR XHLDI XL,$60 ;指针,首指最高位($60)SRDLOP: LDI R17,8 ;8位/字节MOV R9,R17LD R10,X+LDI ZH,HIGH(TABLE*2)LDI ZL,LOW(TABLE*2);使用DSPY子程序段选表ADD ZL,R10 ;加代码寻址BRCC DSPL1INC ZHDSPL1: LPM ;取段选码COM R0 ;取为反码SENDLP: ROR R0 ;段选码右移一位C<--R0最低位CBI PORTC,1BRCC SNDL1 ;进位C传给PC1SBI PORTC,1SNDL1: SBI PORTC,0 ;移位时钟,上升沿有效CBI PORTC,0 ;移位时钟变低DEC R9BRNE SENDLP ;8位段选码循环右移DEC R8BRNE SRDLOP ;8位LED显示数据都更新一遍?RET ;是,结束。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
自学AVR单片机使用,不可私自商用定点运算和定点数制转换;范例1LSDAA: ADC R16,R16 ;十进制数(在R16中)左移调整子程序ADDAA: IN R6,SREG ;bcd码相加调整子程序,先保存相加后的LDI R17,$66 ;状态the old statusADD R16,R17 ;再将和预加立即数$66IN R17,SREG ;输入相加后新状态(the new status)OR R6,R17 ;新旧状态相或SBRS R6,0 ;相或后进位置位则跳行SUBI R16,$60 ;否则减去$60(十位bcd不满足调整条件)SBRS R6,5 ;半进位置位则跳行SUBI R16,6 ;否则减去$06(个位bcd不满足调整条件)ROR R6 ;向高位字节BCD返还进位位!RET;范例2SUDAA: BRCC SBD1 ;bcd码减法调整子程序,差在R16中BRHC SBD3SUBI R16,$66 ;进位半进位都置位,将差减去立即数$66SEC ;并恢复借位CRET ;ret. with seCSBD1: BRHC SBD2 ;进位半进位都清位,返回SUBI R16,6 ;进位清除而半进位置位,将差减去6SBD2: RET ;ret. with clCSBD3: SUBI R16,$60 ;进位置位而半进位清除,将差减去$60SEC ;并恢复借位CRET ;ret. with seC;范例3RSDAA: SBRC R16,7 ;bcd码(在R16中)右移调整子程序SUBI R16,$30 ;十位BCD高位为1(代表8),将其变为5(否则跳行)SBRC R16,3SUBI R16,3 ;个位BCD高位为1(代表8),将其变为5(否则跳行)RET;范例4ADBCD4: MOV R16,R15 ;4字节压缩bcd码相加子程序ADD R16,R11 ;R12,R13,R14,R15内为被加数,R8,R9,R10,R11内为加数RCALL ADDAA ;相加后调整MOV R15,R16 ;并返还调整后结果MOV R16,R14ADC R16,R10RCALL ADDAAMOV R14,R16MOV R16,R13ADC R16,R9RCALL ADDAAMOV R13,R16MOV R16,R12ADC R16,R8RCALL ADDAAMOV R12,R16RET;范例5ADBCD: LDI R16,4 ;多字节压缩bcd码相加子程序MOV R7,R16 ;(r7):字节数CLCADLOP: LD R16,-X ;X-1指向被加数;LD R6,-Y ;Y-1指向加数ADC R16,R6RCALL ADDAA ;相加后调整ST X,R16 ;返还调整后结果DEC R7BRNE ADLOPRET;范例6SUBCD4: MOV R16,R15 ;4字节压缩bcd码减法子程序SUB R16,R11 ;R12,R13,R14,R15内为被减数,R8,R9,R10,R11内为减数 RCALL SUDAA ;相减后调整MOV R15,R16 ;并返还调整后结果MOV R16,R14SBC R16,R10RCALL SUDAAMOV R14,r16MOV R16,R13SBC R16,R9RCALL SUDAAMOV R13,R16MOV R16,R12SBC R16,R8RCALL SUDAAMOV R12,R16RET;范例7SUBCD: LDI R16,4 ;多字节压缩bcd码相减子程序MOV R7,R16 ;(r7):压缩bcd码字节数CLCSUBLP: LD R16,-X ;X-1指向被减数LD R6,-Y ;Y-1指向减数SBC R16,R6RCALL SUDAA ;相减后调整ST X,R16 ;返还调整后结果DEC R7BRNE SUBLPRET;范例8 ;16位被乘数*16位乘数-->32位积MUL16: LDI R16,17 ;(r10r11)*(r14r15)-->r12r13r14r15ClR R12ClR R13 ;积的高位字预清除CLC ;第1次只右移,不相加MLOOP: BRCC MUL1 ;ADD R13,R11 ;乘数右移移出位为1,将被乘数加入部分积ADC R12,R10MUL1: ROR R12ROR R13ROR R14ROR R15 ;部分积连同乘数整体右移1位DEC R16BRNE MLOOP ;17次右移后结束RET;范例9 ;16位整数被乘数*16位小数乘数-->16位整数积,精确到0.5 MUL165: RCALL MUL16 ;先得到32位积SBRS R14,7 ;积小数部分高位为1,将整数部分加1RET ;否则返回LDI R17,255SUB R13,R17SBC R12,R17 ;以减去-1($FFFF)替代加1RET;范例10 ;32位被除数/16位除数-->16位商,精确到1DIV16: LDI R16,16 ;(r12r13r14r15)/(r10r11)-->r14r15DLOOP: LSL R15ROL R14ROL R13ROL R12 ;被除数左移1位BRCS DI1SUB R13,R11SBC R12,R10 ;移出位为0,被除数高位字减去除数试商BRCC DI2 ;够减,本位商为1ADD R13,R11ADC R12,R10 ;否则恢复被除数RJMP DI3 ;本位商0DI1: SUB R13,R11SBC R12,R10 ;移出位为1,被除数高位字减去除数DI2: INC R15 ;本位商1DI3: DEC R16BRNE DLOOPRET;范例11 ;32位被除数/16位除数-->16位商,精确到0.5;可能产生溢出!例$7FFFC000/$8000=$FFFF.8->$10000!DIV165: RCALL DIV16 ;(r12r13r14r15)/(r10r11)-->r14r15LSL R13ROL R12 ;余数乘2BRCS D165 ;有进位,转5入SUB R13,R11SBC R12,R10 ;否则,余数乘2减去除数BRCS D164 ;不够减,转4舍D165: CLR R13 ;否则将商增1SECADC R15,R13ADC R14,R13ADC R13,R13 ;若有溢出,溢出位在R13中RETD164: CLR R13RET;范例12 ;32位整数/16位整数->16整数+16位小数->4字节浮点数 ;(r12r13r14r15)/(r10r11)-->r12r13r14r15DIV16F: RCALL DIV16 ;先做整数除法MOV R9,r15MOV R8,r14 ;保存整数部分CLR R15CLR R14RCALL DIV16 ;除得小数部分MOV R11,R15MOV R15,R14MOV R13,R8MOV R14,R9 ;整数部分在r13r14,小数部分在r15r11LDI R17,$90 ;预设阶码$90(整数为16位)MOV R12,R17LDI R17,32 ;设32次右移DIV16L: SBRC R13,7RJMP NMLDN ;高位为1,已完成规格化LSL R11 ;否则继续右移R13,R14,R15,R11ROL R15ROL R14ROL R13DEC R12 ;阶码减1DEC R17BRNE DIV16LCLR R12 ;右移达32次,浮点数为零,置零阶RETNMLDN: SBRS R11,7RJMP DIVRT ;欲舍去部分(R11)高位为0,转4舍RCALL INC3 ;否则尾数部分增1BRNE DIVRTINC R12 ;尾数增1后变为0,改为0.5,并将阶码增1DIVRT: LDI R17,$7F ;将尾数高位清除,表示正数(负数不要清除)AND R13,R17 ;规格化浮点数在R12(阶码)R13R14R15(尾数)中RET;范例13 ;(R16,R12,R13,R14,R15)/(R10,R11)-->R13,R14,R15 DIV24: CLR R16 ;32位整数/16位整数->24位整数,要求(R10)不为0;否则 ;要求(R12)<(R11)DIV40: LDI 17,24 ;40位整数/16位整数->24位整数要求(R16,R12) LXP: LSL R15 ; <(R10,R11)ROL R14ROL R13ROL R12ROL R16BRCC LXP1SUB R12,R11 ;右移后C=1 够减SBC R16,R10 ;被除数减去除数RJMP DIV0 ;本位商为1LXP1: SUB R12,R11 ;C=0SBC R16,R10 ;被除数减去除数试商BRCC DIV0 ;C=0 够减,本位商1ADD R12,R11ADC R16,R10 ;否则恢复被除数,本位商0RJMP DIV1DIV0: INC R15 ;记本位商1DIV1: DEC R17BRNE LXPLSL R12ROL R16BRCS GINC ;C=1,5入SUB R12,R11SBC R16,R10BRCS RET3 ;不够减,舍掉GINC: RCALL INC3 ;将商增1RET3: RET;范例14 ;定点整数(大$FFFFFFFF)开平方子程序INTSQR: LDI R16,17 ;SQR(R12,R13,R14,R15)-->(r15r8r9)CLR R8 ;R8,R9存储平方根CLR R9 ;r10,r11,r12,r13,r14,r15CLR R10 ; r8, r9(根) r16 (counter)CLR R11 ;r10,r11:被开平方数扩展字节LDI R17,$40SQR0: SUB R12,R17SBC R11,R9SBC R10,R8BRCS SQR1SEC ;试根够减,本位根1RJMP SQR2SQR1: ADD R12,R17ADC R11,R9ADC R10,R8CLC ;否则恢复被开平方数,本位根0SQR2: DEC R16BRNE SQR3 ;when the No.17bit of root be getting SQR20:ADC R9,R15 ;R15 HAVE BEEN CLEARED!ADC R8,R15ADC R15,R15 ;将开出之根4舍5入,使根大可达65536(=$10000)!RET ;for example:sqr.($ffff0001)≈$10000SQR3: ROL R9ROL R8 ;记本位根LSL R15ROL R14ROL R13ROL R12ROL R11ROL R10 ;被开平方数连同其扩展字节左移一位LSL R15ROL R14ROL R13ROL R12ROL R11ROL R10 ;被开平方数连同其扩展字节再次左移一位/左移2位开出1位根 BRCS SQR20 ;被开平方数左移2位后,若进位置位,则仅表明第17位根;已被提前开出且该位根=1,将平方根增1,开平方结束RJMP SQR0 ;否则转试下一位根;范例15 ;定点整数二翻十CONV1: LDI R17,24 ;r12r13r14r15<--(r9r10r11)左移24次MOV R7,R17 ;例:16777215<--$FFFFFFCLR R12CLR R13 ;68719476735<--$FFFFFFFFFCLR R14 ;1099511627775<--$FFFFFFFFFFCLR R15 ;十进制数存储区予清除CV1: LSL R11ROL R10ROL R9 ;二进制数整体左移一位MOV R16,R15RCALL LSDAAMOV R15,R16MOV R16,R14RCALL LSDAAMOV R14,R16MOV R16,R13RCALL LSDAAMOV R13,R16MOV R16,R12RCALL LSDAA ;十进制数左移并调整MOV R12,R16DEC R7BRNE CV1RET;范例16 ;定点整数十翻二CONV2: LDI R17,24 ;(r9r10r11)-->r13r14r15,右移24次CLR R31 ;例:999999-->$0F423FMOV R7,R17 ; 99999999-->$05F5E0FFCV2: LSR R9ROR R10ROR R11ROR R13ROR R14ROR R15 ;十进制数连同二进制数右移一位LDI R30,12 ;数据指针CV2L: LD R16,-ZRCALL RSDAA ;十进制数右移调整ST Z,R16CPI R30,9 ;十进制数各字节调整完毕?BRNE CV2LDEC R7 ;右移次数(24次)完成?BRNE CV2RET;范例17 ;定点小数二翻十CONV3: LDI R17,24 ;(r13r14r15)--->r9r10r11r12右移24次CONV31: MOV R7,R17CLR R9CLR R10 ;例:$0.FFFFFF-->0.99999994CLR R11 ;$0.FFFFFFFF-->0.999999999767CLR R12 ;$0.FFFFFFFFF->0.999999999985448CLR R31CV3: LSR R13ROR R14ROR R15ROR R9ROR R10ROR R11ROR R12 ;二进制数连同十进制数右移一位LDI R30,9CV3L: LD R16,ZRCALL RSDAA ;十进制数右移调整ST Z+,r16CPI R30,13BRNE CV3L ;十进制数各字节调整完毕?DEC R7BRNE CV3 ;右移次数(24次)完成?RET;范例18 ;定点小数十翻二CONV4: LDI R17,32 ;r12r13r14r15<--r8r9r10r11<--(r12r13r14r15) MOV R7,R17 ;左移32次CV4: CLC ;例:$0.FFFFFFD5<--0.99999999MOV R16,R15 ;$0.FFFFFFFF92<--0.9999999999RCALL LSDAAMOV R15,R16MOV R16,R14RCALL LSDAAMOV R14,R16MOV R16,R13RCALL LSDAAMOV R13,R16MOV R16,R12RCALL LSDAAMOV R12,R16 ;定点十进制小数左移并调整ROL R11ROL R10ROL R9ROL R8 ;定点二进制小数带进位位左移一位DEC R7BRNE CV4MOV R12,R8 ;终结果转入R12--R15MOV R13,R9MOV R14,R10MOV R15,R11RETAVR实用程序;范例19 ;等步距线性内插计算子程序.EQU TBLGTH=10CHETA: LDI R16,TBLGTH-1 ;r16<--表长(即字数)-1LDI R31,HIGH(chtbl*2);y0(函数初值)在r14r15,STEP(步长)在r10r11,自变量X在r12r13 LDI R30,LOW(chtbl*2+1);查表指针,首指数据表第1字之高位字节!RCALL CPMR1 ;X与表中第一个字型数据(X0)比较BRCC CHRET ;X<X0 查表结束,Y=Y0CHET1: RCALL CMPR1 ;X与表中下一个数据比较BRCC NX33 ;X<X(i+1) 找到插值区间ADD R15,R11 ;否则Y0中加入一个STEP:Yk=Y0+k*step(步距为负时则;减去|STEP|)ADC R14,R10DEC R16BRNE CHET1 ;未查到表格终值,循环;否则结束,Y取得大值YnCHRET: RETNX33: SBIW R30,5 ;指针退回(-5),指向XiMOV R8,R14MOV R9,R15 ;保存Y0+i*STEPRCALL SUBS ;(X-Xi)-->r16r17MOV R15,R17MOV R14,R16 ;转入r14r15RCALL MUL16 ;(X-Xi)*STEP-->r12r13r14r15MOV R10,R12MOV R11,R13 ;保存乘积高位字LPM ;X(i+1)低位字节MOV R13,R0ADIW R30,1LPM ;X(i+1)高位字节MOV R12,R0SBIW R30,3 ;指针指向XiRCALL SUBS ;X(i+1)-Xi-->r16r17MOV R12,R10MOV R13,R11 ;取回乘积高位字MOV R10,R16MOV R11,R17 ;X(i+1)-Xi-->r10r11RCALL DIV165 ;(X-Xi)*STEP/[X(i+1)-Xi]-->r14r15ADD R15,R9ADC R14,R8 ;Y0+i*STEP+(X-Xi)*STEP/[X(i+1)-Xi]-->r14r15RET ;若STEP为负值则改为计算(r8r9)减去(r14r15)之值CMPR1: LPM ;取数据高位字节ADIW R30,2 ;指向下一数据的高位字节CP R0,R12 ;与X高位字节相比较BRNE CPRT1 ;不相等即转出SBIW R30,3 ;否则调整指针LPM ;取数据低位字节ADIW R30,3 ;指向下一数据的高位字节CP R0,R13 ;与X低位字节相比较CPRT1: RET ;以进位C带回比较结果SUBS: LPM ;计算(X-Xi)或[X(i+1)-Xi]并送入r16r17MOV R5,R0 ;取Xi低位字节ADIW R30,1LPM ;取Xi高位字节SBIW R30,1 ;仍指向Xi低位字节SUB R13,R5MOV R17,R13SBC R12,R0MOV R16,R12 ;计算差并将其转入R16R17RET;自变量x表长为12字CHTBL:DW 19214,23404,27600,32799,37009,40211,45414,48618,51821,55029,57787,60070 ;步距表长为11字STEPT: DW 356,366,379,395,415,440,471,509,555,603,657;不等步距线性内插计算子程序,步距表首址在R6R7中;自变量X在R12R13之中,函数初值Y0在R14R15中;范例20 ;表长(字个数)-1在R16中CHTSTP: LDI R31,HIGH(chtbl*2)LDI R30,LOW(chtbl*2+1);查表指针LDI R16,LOW(stept*2)MOV R7,R16LDI R16,HIGH(stept*2)MOV R6,R16 ;步距表指针LDI R16,TBLGTH-1 ;r16<--表长(字个数)-1RCALL CMPR1 ;X与表首数据比较BRCC CHSTPT ;X<X0 查表结束,有Y=Y0CHSTP1: RCALL CMPR1 ;否则与表中下一数据比较BRCC CHSTP3 ;X<X(i+1),找到插值区间!RCALL GTSTP ;查表取STEP字型变量ADD R15,R11 ;Y0<--Y0+STEPkADC R14,R10DEC R16BRNE CHSTP1 ;未查到表格终值循环;否则结束,Y取得大值Yn CHSTPT: RETCHSTP3: SBIW R30,5 ;指针退回,指向Xi低位字节MOV R8,R14MOV R9,R15 ;Y0+∑STEPk送入r14 r15RCALL SUBS ;(X-Xi)->r16r17MOV R15,R17MOV R14,R16 ;(X-Xi)转入R14R15RCALL GTSTP ;查表取STEPi-->R10R11RCALL MUL16 ;(X-Xi)*STEPi-->R12R13R14R15MOV R10,R12MOV R11,R13 ;保存积高位字LPMMOV R13,R0ADIW R30,1LPMMOV R12,R0SBIW R30,3RCALL SUBS ;(X(i+1)-Xi)-->r16 r17MOV R12,R10MOV R13,R11MOV R10,R16MOV R11,R17 ;取回积高位字 &(X(i+1)-Xi)-->r10r11RCALL DIV165 ;(X-Xi)*STEPi/[X(i+1)-Xi]-->r14r15ADD R15,R9 ;ADC R14,R8 ;Y0+∑STEPk+(X-Xi)*STEPi/[X(i+1)-Xi]-->r14r15RETGTSTP: MOV R5,R6 ;查取STEP字型变量/POINTER in r6r7!MOV R6,R30MOV R30,R5MOV R5,R7MOV R7,R31MOV R31,R5 ;(r6r7)<-->ZLPMMOV R11,R0ADIW R30,1LPMMOV R10,R0 ;STEPk取到r10r11ADIW R30,1MOV R5,R6MOV R6,R30MOV R30,R5MOV R5,R7MOV R7,R31MOV R31,R5 ;指针增2后送回r6r7RET;范例21 ;功能表程序FUNC2: LDS R16,$A3 ;use r0,r8,r9,r10,r11,r16&r17/& subprogram dspa SBR R16,$80 ;功能表程序标志STS $A3,R16LDI YH,2LDI YL,0 ;功能内容表SRAM地址RCALL FLFUNC ;CLR r27!LDI R16,2ST X,R16 ;显示'FUNC.2'RCALL DL2SCLR R9 ;功能内容寻址偏移量R9!CLR R8 ;功能名称寻址偏移量(R8)=(r9)*3FFUNC0: RCALL DSF_ ;显示'F- 'FF0: RCALL DSPA ;in subprogram dspy clr. r27!CPI R16,11 ;回车键按下?BRNE FF2PFF0C: RCALL COMBNO ;合成功能名称送入r16CPI R16,20 ;是后一个功能名称?BRNE FF1CLR R9 ;是,两偏移量初始化!CLR R8FF1: LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2);功能名称表指针ADD ZL,R8ADC ZH,R27 ;(r27)=0 ALWAYSLPMMOV R16,R0RCALL BRA3A ;分解新功能名称到$6E/$6FFF0G: LDI R28,0ADD R28,R9 ;功能内容指针加偏移量LD R16,YLDI R26,$72RCALL BRAX ;将新功能内容分解到$72/$73FF0A: RCALL DSPA ;显示新功能名称/内容CPI R16,11BRNE FF0B ;回车键按下?INC R8INC R8INC R8 ;是,功能名称寻址偏移量加3INC R9 ;功能内容寻址偏移量加1RJMP FF0C ;转回FF2P: RJMP FF2FF0B: CPI R16,10BRNE FF0DRCALL DSF_ ;清除键按下,清除显示区后,显示‘F-’FF1B: RCALL DSPACPI R16,11BREQ FF1 ;转恢复当前显示CPI R16,10BRCC FF1BRJMP FF2D ;只有数字键按下才转出去处理FF0D: CPI R16,10BRCC FF0AFF1D: LDI R17,$24 ;STS $73,R17 ;数字键处理,先在缓存区内放一空白FF0E: LDS R17,$73STS $72,R17 ;键入数字左移STS $73,R16 ;存入新数字FF0F: RCALL DSPACPI R16,10BREQ FF0G ;清除键按下,恢复显示旧功能内容BRCS FF0E ;键入数字左移更新CPI R16,11BRNE FF0FLDS R26,$72 ;回车键按下RCALL COMBA ;合成新功能内容(combin $72&$73 into binary(r16)) MOV R17,R8INC R17LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R17 ;取当前功能内容下限ADC ZH,R27 FF1F:LPMCP R16,R0BRCS DSER2 ;新功能内容小于下限,错误INC R17LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R17 ;取当前功能内容上限ADC ZH,R27LPMCP R0,R16BRCS DSER3 ;新功能内容大于上限,错误FF7: LDI R28,0ADD R28,R9 ;功能内容表首地址为$200!ST Y,R16 ;合法的新功能内容进入功能内容表INC R9INC R8INC R8INC R8 ;调整偏移量,进入下一个功能显示RJMP FF0CFF1P: RJMP FF1DSER2: RCALL FERR2 ;显示'F Err.2'2秒RCALL EXCH0RJMP FF0G ;恢复原数据显示DSER3: RCALL FERR3 ;显示'F Err.3'2秒RCALL EXCH0RJMP FF0G ;恢复原数据显示FF2: CPI R16,10BRCS FF2D ;功能键按下,转初始RJMP FF0FF2D: LDI R17,$24 ;数字键按下,在显示缓存区内左移STS $6F,R17 ;FF3: LDS R17,$6FSTS $6E,R17STS $6F,R16FF4: RCALL DSPACPI R16,10BRNE FF41RCALL DSF_ ;清除数字,显示‘F-’FF40: RCALL DSPACPI R16,11BREQ FF1P ;转回显示当前功能名称及内容CPI R16,10BRCC FF40 ;无效键按下,转回RJMP FF2D ;否则转数字处理FF41: BRCS FF3CPI R16,11BRNE FF4RCALL COMBNO ;合成新功能名称CLR R10 ;功能名称偏移量计数器清除CLR R11 ;功能内容偏移量计数器清除SFFLP: LDI ZH,HIGH(FTABL*2)LDI ZL,LOW(FTABL*2)ADD ZL,R10ADC ZH,R27LPMCP R0,R16 ;BREQ SFFND ;在功能名称表中找到新名称INC R11 ;INC R10INC R10INC R10 ;调整偏移量LDI R17,60CP R10,R17 ;功能名称指针偏移量超过59?BRCS SFFLP ;否,继续查功能名称表RCALL FERR1 ;查完功能名称表未查到键入功能名称!RJMP FFUNC0 ;转回恢复原显示SFFND: MOV R9,R11 ;得到功能内容指针偏移量MOV R8,R10 ;得到功能名称指针偏移量RJMP FF0G ;转显示新功能名称及内容FTABL: .DB 1,0,1,2,1,8,3,0,2,4,0,1 5,1,2,6,0,4,7,1,4,8,1,2,9,2,7,10,1,5,11,1.DB 5,12,0,5,13,1,2,14,1,7,15,1,10,16,1,4,17,2,4,18,2,5,19,1,2,20,1,3 COMBNO: LDI XL,$6E ;取$6E$6F中的BCD码,合成新功能名称子程序COMBA: LD R16,X+CPI R16,$24BRNE CMBACLR R16CMBA: MOV R0,R16LSL R16LSL R16ADD R16,R0LSL R16 ;高位BCD乘10LD R0,XADD R16,R0 ;加低位BCDRETDSF_: RCALL FIL8 ;准备显示'F- 'LDI R16,$0FSTS $6C,R16LDI R16,$14STS $6D,R16RETBRA3A: LDI XL,$6E ;二进制数转换为两位BCD码并显示BRAX: LDI R17,$24 ;十位为0时显示空白ST X,R17BRHOUR: CLR R0 ;BRX0: SUBI R16,10 ;减10BRCS BRX2INC R0RJMP BRX0BRX2: SUBI R16,-10 ;不够减恢复出十位BCDTST R0BREQ BRX1ST X,R0 ;放入显示区BRX1: INC R26ST X,R16BRART: RETFERR1: LDI XL,$71 ;显示'F Err.1'LDI R16,1ST X,R16RJMP FER123FERR2: RCALL MOVE1 ;显示'F Err.2'LDI R16,2STS $71,R16RJMP FER123FERR3: RCALL MOVE1 ;显示'F Err.3'LDI R16,3STS $71,R16 FER123:LDI XL,$6CLDI R16,$0FST X+,R16LDI R16,$24ST X+,R16LDI R16,$0EST X+,R16LDI R16,$1BST X+,R16LDI R16,$3BST X+,R16 ;显示'F Err.1/2/3'LDI R16,$24 ;2秒STS $72,R16STS $73,R16RCALL DL2SRETFIL8: LDI R26,8 ;将显示缓存区充空白MOV R10,R26LDI R26,$6CCLR R27LDI R16,$24FILP: ST X+,R16DEC R10BRNE FILPRETFLFUNC: RCALL FIL8 ;准备显示'Func.'LDS R26,$6CLDI R16,$0F ;'F'ST X+,R16LDI R16,$1E ;'u'ST X+,R16LDI R16,$17 ;'n'ST X+,R16LDI R16,$40 ;'c.'ST X+,R16RETEXCH0: LDI ZL,$14 ;将显示缓存区内容转移$6C-$73<-->$214-$21B LDI ZH,2LDI XL,$6CEXL: LD R16,XLD R17,ZST X+,R17ST Z+,R16CPI R26,$74BRNE EXLRETMOVE1: LDI ZL,$14 ;将显示缓存区内容传送到$214-$21BLDI ZH,2LDI XL,$6CMV1: LD R16,X+ST Z+,R16CPI R26,$74BRNE MV1RET;EEPROM 读写程序;范例22 ;读出EEPROM子程序REEP: LDI YH,1LDI YL 0 ;EEPROM 读出首地址:$100LDI XL,$60 ;读出数据存放首地址:$60CLR XHREEP1: SBIC $1C,1 ;查EEWE位,EEWE=1为当前尚有写入操作未结束 RJMP REEP1 ;等待EEWE=0OUT $1F,YHOUT $1E,YL ;读出地址写入EEPRO地址寄存器SBI $1C,0 ;设置读出使能位(EERE)IN R16,$1D ;从EEPROM数据寄存器中读出数据ST X+R16 ;存入缓存区INC YLBRNE REEP1 ;INC YHCPI YH,2 ;EEPROM末数据(地址为$1FF)读完?BRNE REEP1RET;范例23 ;写入EEPROM子程序WEEP: LDI YH,1LDI YL 0 ;EEPROM 写入之首地址:$100LDI XL,$60 ;写入数据存储区首地址:$60CLR XHWEEP1: SBIC $1C,1 ;查EEWE位,EEWE=1为当前尚有写入操作未结束RJMP WEEP1 ;等待EEWE=0OUT $1F,YHOUT $1E,YL ;送写入地址到EEPRO地址寄存器LD R16,X+ ;取写入数据并调整数据指针OUT $1D,R16 ;送到EEPROM数据寄存器SBI $1C,2 ;设置EEPROM写入总使能位EEMWESBI $1C,1 ;设置EEPROM写入使能位EEWEINC YLBRNE WEEP1INC YHCPI YH,2 ;EEPROM末写入单元地址为$1FFBRNE WEEP1RET;时钟日历芯片62×42×读写程序,时钟日历数据读入到显示缓存区$6C--$73 ;范例24 ;USE 8515!使用DSPA子程序.EQU RTCH=$40 ;rtc地址高八位RDATE: RCALL BSYT ;初始化,兼冻结RTCLDI XL,$6D ;数据缓存区首地址LDI YL,$06 ;首指日单元RDLP: LD R16,Y+ ;$6b 6c 6d 6e 6f 70 71 72 73ANDI R16,15 ; 2 9(D) - 1 0(M) - 0 2(Y)CPI R16,10BRCS RDL1ANDI R16,$7F ;容错处理RDL1: ST X,R16$DEC R26CPI R26,$6BBRNE RDLP1LDI XL,$70RDLP1: CPI R26,$6EBRNE RDLP2LDI R16,$14 ;送‘-’到$6E单元ST X,R16LDI XL,$73RDLP2: CPI R26,$71BRNE RDLPLDI R16,$14ST X,R16 ;送‘-’到$71单元并结束子程序RDINVL: RJMP WCRTRTIME: RCALL FIL2 ;请除缓存区RCALL BSYTLDI XL,$73LDI YL,$02 ;指向分单元(只读时分)RCL: LD R16,Y+ANDI R16,15CPI R16,10BRCS RCL0ANDI R16,$7F ;容错处理RCL0: ST X,R16DEC R26CPI R26,$71BRNE RCL1LDI R16,$14 ;写入‘-’ST X,R16DEC R26RCL1: CPI R26,$6E ;$6c 6d 6e 6f 70 71 72 73BRNE RCL ; 1 6 - 3 5CLR R16ST Y,R16LDS R17,$9FFB ;时制存储单元LDS R16,$6fSWAP R16LDS R15,$70ADD R16,R15 ;合成小时SUBI R16,$24 ;模24RCALL SUDAA ;BCD码减法调整BRCC RCL2 ;够减,转SUBI R16,-36 ;否则恢复被减数RCL2: CPI R17,2BRNE PRTD1 ;24小时制,转SUBI R16,$12RCALL SUDAABRCC PRTD1 ;12小时制处理SUBI R16,-18PRTD1: MOV R17,R16SWAP R16ANDI R16,$0FANDI R17,$0FSTS $6F,R16STS $70,R17 ;小时数据送入显示区RJMP WCRTWDATE: RCALL WRTC ;将显示缓存区中日期数据写入RTC LDI XL,$6FLD R16,XCPI R16,10BRCC WDRT ;非法数据,退出LDI YL,6WDLP: LD R16,XDEC R26CPI R16,$24 ;SPC?BRNE WD0CLR R16 ;变为0WD0: ST Y+,R16CPI R26,$6DBRNE WD1 ;$6d 6e 6f 70 71 72 73LDI XL,$71 ; 2 9(日) 1 1(月) 0 2 (年)RJMP WDLPWD1: CPI R26,$6fBRNE WD2LDI R26,$73WD2: CPI R26,$71BRNE WDLPLWDRT: RJMP WCRTWTIME: RCALL WRTC ;将显示缓存区中时间数据写入RTCLDI R26,$73LD R16,XCPI R16,10BRCC WCRT ;非法数据,退出LDI YL,2WLOP: LD R16,XCPI R16,$24BRNE WT1CLR R16 ;容错处理WT1: ST Y+,R16DEC R26WLP: CPI R26,$6FBRNE WLOP ;$6E 6f 70 71 72 73WCRT: CLR R16 ; 1 5 3 8LDI YL,$0DST Y,R16 ;解除对RTC之冻结IN R16,MCUCRCBR R16,$C0OUT MCUCR,R16 ;禁止读写外部RAMRET;对rtc初始化/冻结时钟BSYT: LDI YH,RTCH ;rtc地址高八位LDI YL,$0D ;指向D寄存器IN R16,MCUCRSBR r16,$C0 ;允许读写外部RAM并选一个时钟周期等待时间 OUT MCUCR,R16LDI R16,5 ;设置冻结位和中断申请位ST Y,R16CLR XHBSRT: RET;写RTC初始化子程序WRTC: RCALL BSYTLDI YL,$0E ;指向寄存器ELDI R16,6ST Y+,R16 ;指向寄存器FLDI R16,1 ;设置时制位ST Y,R16LDI R16,4 ;选24小时制ST Y,R16CLR R16 ;请除时制位ST Y,R16RJMP BSYT;范例25 ;显示保护子程序/晶振4MHZDSPRV: LDI R16,HIGH(ramend)OUT SPH,R16LDI R16,LOW(ramend)OUT SPL,R16CLR R2 ;调DSPY次数寄存器清除WDRLDI R16,$0D ;启动看门狗,溢出时间为0.49sOUT WDTCR,R16 ;写入看门狗控制寄存器CLR XHLDI XL,$6CDSPVL: ST X+,XH ;清显示缓存区($6c-$73)CPI XL,$74BRNE DSPVLDSPV0: LDI R16,$66MOV R9,R16LDI R16,$82 ;$6582=25986,高位字节增1为$66MOV R10,R16 ;调25986次DSPA耗时120sDSNEX: LDI XL,$74 ;将显示区十进制数据增1以演示数据变化DSLOP: LD R16,-X ;实用时可以采样数据更新显示(参考范例96) INC R16ST X,R16CPI R16,$0ABRNE DSPRV1CLR R16ST X,R16CPI R26,$6CBRNE DSLOP ;增1后如有进位则调整DSPRV1: DEC R10BRNE DSPGNDEC R9BRNE DSPGN ;2分钟定时到?DSCLOS: RCALL FIL2 ;将显示缓存区充入空白($24)RCALL DSPA ;其效果相当于关显SBRC R16,7RJMP DSCLOSRJMP DLFUNC ;有键按下,转出;否则继续关显DSPGN: RCALL DSPA ;未到,显示数据SBRC R16,7RJMP DSNEX ;无键按下,继续显示DLFUNC: CPI R16,12 ;关显键键值为12BEEQ DSCLOS ;关显键按下,转关闭显示;.;.;.;.;(其他键值处理,参考范例26 DEALKY程序)RJMP DSPV0 ;执行功能后转入二分钟定时;范例26 ;键值处理程序DEALKY: LDI R16,HIGH(ramend)OUT SPH,R16LDI R16,LOW(ramend)OUT SPL,R16CLR R2 ;调DSPY次数寄存器清除WDRLDI R16,$0D ;启动看门狗,溢出时间为0.49”OUT WDTCR,R16 ;写入看门狗控制寄存器DEALK0: RCALL DSPASBRC R16,7RJMP DEALK0 ;无键按下,反复查询CPI R16,10BRCC FNCKY ;功能键按下,跳转RCALL FIL2 ;键值<10为数字键 ,先清除显示缓存区NUMKY: RCALL LSDD8 ;8位数字左移,新键值加入序列尾DSLP: RCALL DSPASBRC R16,7RJMP DSLP ;无键按下,继续显示CPI R16,11BRCS NUMKY ;键入数字形成左移序列/按清除键则清除所有键入数据BRNE DSLP ;键值大于11无效;11为回车键,对键入数字进行处理(如将其两两合并为BCD ;码,再转为二进制数等)RJMP DEALK0 ;转回FNCKY: SUBI R16,10 ;功能键散转处理,先计算键值偏移量LDI R31,HIGH(FKYTB)LDI R30,LOW(FKYTB);散转表表首ADD R30,R16CLR R16ADC R31,R16 ;偏移量加入指针IJMP ;散转FKYTB: RJMP CLTTL ;10:清除累加和RJMP DSTTL ;11:显示累加和RJMP DSCLS ;12:关显示RJMP SLFTS ;13:自检RJMP FDPAP ;14:打印机走纸RJMP PRSMP ;15:打印采样RJMP PRTTL ;16:打印累加和RJMP DSCLK ;17:显示系统时钟 ;............. ;.........;............. ;.........CLTTL: ;............. ;程序内容略 ;.............RJMP DEALK0 ;程序执行完毕,转回DSTTL: RCALL BRTTL ;分解累加和送显示缓存区RCALL DSPA ;显示累加和SBRC R16,7RJMP DSTTL ;任一键按下,结束显示累加和RJMP DEALK0 ;程序执行完毕,转回DSCLS: RJMP DSCLOS ;转去关显示SLFTS: ;.............;.............RJMP DEALK0 ; 自检程序执行完毕,转回FDPAP: ;.............;.............RJMP DEALK0 ; 走纸程序执行完毕,转回PRSMP: ;.............;.............RJMP DEALK0 ; 打印采样程序执行完毕,转回PRTTL: ;.............;.............RJMP DEALK0 ;打印累加和程序执行完毕,转回DSCLK: RCALL BRCLK ;分解系统时钟送入显示缓存区RCALL DL1S ;延时1秒RCALL DSPA ;显示时钟SBRC R16,7 ;任一键按下,结束显示时钟RJMP DSCLKRJMP DEALK0 ;程序执行完毕,转回;.............;............. ;其他功能键处理略 ;.............;范例27 ;主显子程序DSPA: SBRC R16,7 ;USE R0,R2,R11,R12,r13,r14,r15,r16,r17&Z,X POINTERS RJMP DSA2 ;无键按下,跳转DSA0: CLR R12INC R12 ;有键按下,将计数器置1DSA1: RCALL DSPYDEC R12BRNE DSA1 ;等待键释放DSA2: RCALL DSPYLDS R16,$A3SBRS R16,7 ;有进入功能表程序标志?RET ;没有返回SBI PORTA,0 ;SBIS PINA,0 ;退出功能表程序吗?RETCBR R16,$80 ;是,清除进入功能表程序标志($A3,7)STS $A3,R16RCALL FIL2LDI R16,$0F ;'F'STS $6C,R16LDI R16,$0E ;'E'STS $6E,R16LDI R16,$17 ;'n'STS $6F,R16LDI R16,$0D ;'d'STS $70,R16 ;显示‘F End'RCALL DL2S ;2秒后RJMP DIPA1 ;转到主程序(包括对堆栈)初始化DL2S: RCALL DL1S ;延时2秒子程序DL1S: LDI R16,217 ;延时1秒子程序/4MHz clkMOV R11,R16 ;4.618×217=1000msDLCOM: RCALL DSPADEC R11BRNE DLCOMRET;范例28 ;基显子程序,显示缓存区:$6C--$73,执行时间4.618ms/晶振4MHZ ;主程序应对看门狗初始化,设置溢出时间为0.49秒!DSPY: LDI R17,$0F ;使用R0,R2,R12,R13,R14,R15,R16&R17/z&x pointer!OUT DDRA,R15 ;PA7--PA4为键列值输入CLR R15COM R15OUT DDRB,R15OUT DDRC,R15 ;口B:段选输出,口C:位选输出OUT PORTC,R15 ;关显DPY1: LDI R26,$6C ;指向显示缓存区首址:$6CCLR R27LDI R17,$7FMOV R13,R17 ;位选初始化(首显高位)L0D: LD R17,X+LDI R31,HIGH(table*2)LDI R30,LOW(table*2)ADD R30,R17ADC R31,R27L0C: LPM ;取段选码OUT PORTB,R0 ;送段选口OUT PORTC,R13 ;位选口SEC ;ROR R13 ;指下一位位选LDI R17,3 ;4MHz(6 if 8MHz)CLR R14DLOP: DEC R14BRNE DLOPDEC R17BRNE DLOP ;延时0.5762毫秒IN R16,PORTAORI R16,$F0 ;保护PA3--PA0输出OUT PORTA,R16 ;提拉PA7-PA4IN R14,PINA ;读入列值NEX: ROL R14 ;use high 4bits!BRCC L1 ;有键按下,跳转NEX1: INC R17 ;指向下一列CPI R17,4BRNE NEX ;各列都查完?NEX2: SER R17OUT PORTC,R17 ;将$FF写入位选口(关显)CPI R26,$74BRNE L0D ;每位LED都显示一遍??MOV R17,R2CPI R17,100 ;到100次?BRNE NEX3CLR R2 ;清除看门狗定时器时间到计数器/4.618ms×100=0.462s(<0.49s) WDR ;看门狗定时器复位NEX3: RETL1: LDS R16,$73 ;计算键值代码/查键值SUB R16,R26 ;$73-(r26)-->r16LSL R16LSL R16 ;行值*4ADD R16,R17 ;键值代码=行值*4+列值LDI R30,LOW(TABL0*2)ADD R30,R16LDI R31,HIGH(TABL0*2)ADC R31,R27LA00: LPM ;查出键值MOV R15,R0 ;放在R15LA10: INC R12 ;计数器增1以备判断键释放RJMP NEX1 ;转回查下一列TABL0: .DB 10,0,11,20,1,2,3,16,4,5,6,22,7,8,9,18,12,15,19,23,14,17,21,13 TABLE: .DB $3F,$06,$5B,$4F,$66,$6D,$7D,$07,$7F,$67,$77,$7C,$39 ;0--C.DB $5E,$79,$71,$6F,$74,$04,$1F,$40,$38,$37,$54,$5C ;'d'---'o'.DB $73,$67,$50,$6D,$78,$1C,$3E,$7E,$F8,$6E,$49,$00.DB $48,$52,$D3,$76 ;$25(=),$26(/)$27(?) END AT $28(H).DB $BF,$86,$DB,$CF,$E6,$ED,$FD,$87,$FF,$E7;THE 0.($29)--9.($32).DB $D7,$C9,$80 ;THE 'X.' 'Z.' &'.'($33--$35).DB $DE,$EF,$B8,$F3,$E7,$D0,$DC,$ED,$86,$F9,$B9H,$F7,$F1,$B7,$D4;the d.,g.,L.,p.,q.,r.,o.,s.,l.,E.,C.,A.,F.,M.,n.(36--44h) ;范例29 ;键入数字序列左移处理子程序LSDD8: LDI R26,$6C ;8bcd码($6C--$73H)LDS R27,$A3CBR R27,8 ;清$A3,3STS $A3,R27CLR R27CPI R16,10 ;10为清除键BRNE DDLRCALL FIL2 ;清除显示缓存区($6c-$73)!LDS R16,$A3SBR R16,8STS $A3,R16 ;建清除显示缓存区标志$A3,3=1RETDDL: INC R26 ;数字键按下,序列左移LD R16,X ;SUBI R16,$29 ;数字带小数点?BRCC DD4 ;若带则将其复原(参考DSPY子程序段码表)SUBI R16,$D7 ;恢复DD4: ST -X,R16 ;移入左邻单元DD5: INC R26CPI R26,$73BRNE DDL ;各数字都左移了一位?ST X,R15 ;新键入数字进入数字序列末位LDI R26,$6CBRCS DEL2CPI R16,$29BRCC DELRT ;大于$29为错误!DELA: INC R26 ;0--9/$24/$14为有效!CPI R26,$73BRNE DEL ;缓存区检查完毕?RJMP DELRTDEL2: CPI R16,0BRNE DELRTLDI R16,$24 ;0改为空白ST X,R16RJMP DELA ;DELRT: LDS R16,$A0 ;小数点位置单元TST R16BREQ DDRET ;($a0)=0,无小数点NEG R16ADD R16,$73MOV R26,R16 ;找到缓存区内带小数点的数据位LD R16,XSUBI R16,$D7 ;加上小数点ST X,R16CPI R16,$4D ;在空白码加了小数点($24(空白)+$29=$4d)?BRNE STLR1LDI R16,$29ST X,R16 ;是,将其改为'0.'STLR1: CPI R26,$73BREQ DDRET ;并将其后所有空白都改为0INC R26LD R16,XCPI R16,$24BRNE DDRETCLR R16ST X,R16RJMP STLR1DDRET: RETFIL2: LDI R26,8 ;在显示缓存区内填充空白MOV R14,R26FIL2A: LDI R26,$6C FIL:CLR R27LDI R16,$24FILP: ST X+,R16DEC R14BRNE FILPRET;范例30 ;双键输入检查数据子程序,Ky1数据键/Ky2回车键KYIN2: LDI R26,$60 ;寄存器地址:portb:$18/ddrb:$17/pinb:$16CLR R27 ;指向数据区首地址CBI DDRB,7CBI DDRB,6 ;pb7和pb6皆为输入口SER R17CPI R17,$0ABRCS LA1CLR R17LA1: LDI R31,HIGH(table*2)LDI R30,LOW(table*2);DSPY段选码表ADD R30,R17ADC R31,R27LPMCOM R0 ;段选码取出并取反OUT PORTC,R0 ;送C口SBI PORTB,7SBIC $16,7RJMP NXA1 ;数字键未按下,转RCALL DL50 ;否则延时XA2: SBI PORTB,6SBIC $16,6RJMP XA0 ;只有数字键按下,转XA20: RCALL DL50 ;两键都按下,先延时50mSSBI PORTB,6SBIS $16,6RJMP XA20SBI PORTB,7SBIS $16,7RJMP XA20 ;等两键都释放RCALL DL50XA21: SBI PORTB,6SBIS $16,6RJMP XA21 ;等待释放SBI PORTB,7SBIS $16,7RJMP XA21 ;再次等待释放RJMP NXA6 ;先按数字键,再按回车键,待2都键释放后退出子程序XA0: SBI PORTB,7SBIS $16,7RJMP XA2 ;等待数字键释放XA1: RCALL DL50 ;延时SBI PORTB,7SBIS $16,7RJMP XA1 ;再次等待释放INC R17 ;数字增1CPI R17,10BRCS NXA1CLR R17 ;超过10,将键值归为0NXA1: SBI PORTB,6SBIC $16,6RJMP LA1 ;回车键也未按下,重新查键RCALL DL50 ;延时NXA3: SBI PORTB,6SBIS $16,6RJMP NXA3 ;再次等待回车键释放RCALL DL50SBI PORTB,6ST X+,R17 ;数字转入缓存区SER R17OUT PORTB,R17 ;关显RCALL DL50 ;CPI R26,$70 ;到规定数字个数?BRNE LA0 ;LDI R17,$86 ;显示'E'ndOUT PORTC,R17 ;NXA4: SBI PORTB,6SBIS $16,6RJMP NXA5 ;回车键按下,转SBI PORTB,7SBIC $16,7 ;数字键按下,转RJMP NXA4 ;否则反复查键NXA40: RCALL DL50SBI PORTB,7SBIS $16,7RJMP NXA40SBI PORTB,7SBIS $16,7RJMP NXA40 ;等待键释放RJMP KYIN2 ;转检查键入数据NXA5: RCALL DL50SBI PORTB,6SBIS $16,6RJMP NXA5SBI PORTB,6SBIS $16,6RJMP NXA5 ;等回车键释放NXA6: SER R17OUT PORTB,R17 ;关显,结束子程序RETDL50: ;RCALL DL25 ;延时50毫秒子程序/8Mhz(去掉指令前“;”号)DL25: CLR R14 ;延时50毫秒子程序/4MhzCLR R15DL50L: DEC R15NOPBRNE DL50LDEC R14BRNE DL50LRET;范例31LPRNT: SER R17 ;宽行打印机检测及控打程序OUT DDRC,R17 ;C口为打印机输出口!SBI DDRD,7CBI DDRD,3 ;pd7为选通输出口,pd3(INT1)查忙输入口SBI PORTD,3SBIC PIND,3 ;查打印机忙信号RJMP ERR5 ;打印机尚未工作忙信号即已为高,打印机不能打印 LDI R17,$0D ;写回车命令给打印机OUT PORTC,R17NOPNOPSBI PORTD,7 ;strobeLDI R16,50TSPRT: SBI PORTD,3SBIc PIND,3RJMP LPRT2 ;50次内忙信号高起来为正常 DEC R16 ;否则为非正常状态BRNE TSPRTERR5: LDI R16,5RCALL ERRX ;显示5号错误RJMP DIPA1 ;转主程序初始化LPRT2: LDI R25,1CLR R24 ;point to $100LDI R17,$80OUT GIMSK,R17 ;允许int1中断LDI R17,$0AOUT MCUCR,R17 ;INT1下降沿中断SEI ;general interrupt enable RETEX_INT1:PUSH R26PUSH R27IN R27,SREGPUSH R27PUSH R17 ;保护现场MOV R27,R25 ;取数据指针MOV R26,R24LD R17,X+ ;MOV R25,R27MOV R24,R26 ;增1后将指针送回CPI R17,3 ;是停止符?BRNE INT1SDCLR R17OUT GIMSK,R17 ;禁止INT1中断RJMP INT1EDINT1SD: OUT PORTC,R17 ;打印数据输出到打印口CBI PORTD,7 ;clr ($12,7)NOPNOPNOPSBI PORTD,7 ;向打印机发出选通INT1ED: POP R17POP R27OUT SREG,R27POP R27POP R26 ;恢复现场RETI;范例32 ;步进电机控制程序.ORG 0STRT10: RJMP RST10 ;8535/8515/晶振4MHZ.ORG $011。