📄 实验25.asm
字号:
;---------------------------------------------------------------------------------------
;50%占空比下PWM正反转调速实验参考程序(实验25.asm)
;---------------------------------------------------------------------------------------
LIST P=16F877 ;COUNTER、TEMP、COUNT
INCLUDE "P16F877.INC" ;S1H、S1L、R1H、R1Z、R1L变量已定义
;---------------------------------------------------------------------------------------
FSR_TEP EQU 50H ;FSR保护缓冲器
INF_TEP EQU 51H ;INDF保护缓冲器
PR2_TEP EQU 52H
CCPR1L_TEP EQU 53H
;---------------------------------------------------------------------------------------
;主程序
;---------------------------------------------------------------------------------------
ORG 0000H ;系统复位地址
NOP ;MPLAB需要
GOTO ST ;转到主程序
;---------------------------------------------------------------------------------------
;中断服务程序
;---------------------------------------------------------------------------------------
ORG 0004H
GOTO IEIE ;跳转中断服务程序
ST MOVLW .30 ;设置连续按下时间,定时的倍数
MOVWF TIMES
BSF STATUS,RP0 ;选择数据存储器体1
CLRF TRISD ;设置RD端口为输出
MOVLW B'10000111' ;设置TMR0基本定时65536 s
MOVWF OPTION_REG
MOVLW 0FFH ;定义周期寄存器
MOVWF PR2
MOVWF PR2_TEP
MOVLW 1FH ;定义RB端口低5位为输入
MOVWF TRISB
MOVLW B'11010000' ;定义RC3/SCK、RC5/SDO输出、RC4/SDI输入
MOVWF TRISC
CLRF SSPSTAT ;清除SMP、CKE位
BCF STATUS,RP0 ;选择数据存储器体0
MOVLW 01H
MOVWF PORTD ;RD0端线输出为高电平
MOVLW 0CH ;定义CCP为PWM调制方式
MOVWF CCP1CON
MOVLW B'00000011' ;定义定时器TMR1工作方式
MOVWF T2CON
MOVLW B'00110010' ;设置SSP控制方式:取FOSC/64、SPI主控、CKP=1
MOVWF SSPCON
CALL CHUSHIHUA ;调用初始化子程序
MOVLW 80H ;1s参数送入脉宽变量及后备脉宽变量
MOVWF CCPR1L ;定义脉宽初值
MOVWF CCPR1L_TEP
CALL XSCHULI ;调用数据处理子程序
MOVLW B'10100000' ;开放TMR0中断
MOVWF INTCON
CLRF TMR0 ;时间常数清零
BSF T2CON,TMR2ON ;启动TMR2定时
RB0 BTFSS PORTB,0 ;判断RB0是否按下
GOTO RB1 ;没有按下转判RB1
CALL DELAY10MS ;RB0按下,调用10ms延时
BTFSS PORTB,0 ;再判RB0是否按下
GOTO RB1 ;没有按下转判RB1
PP0 BTFSC PORTB,0 ; RB0按下,转判RB0是否释放
GOTO PP0 ;没有释放等待
CALL DELAY10MS ;RB0释放,调用10ms延时
BTFSC PORTB,0 ;再判断RB0是否释放
GOTO PP0 ;没有释放等待
MOVF PR2_TEP,W ;取出后备周期寄存器
SUBLW 0FFH ;与0FFH相减
BTFSC STATUS,Z ;是否相等
GOTO ADDRB0
INCF PR2_TEP,1 ;未到0FFH直接加1
ADDRB0 CALL XSCHULI ;已是0FFH不再加1,直接进入数据处理
RB1 BTFSS PORTB,1 ;判断RB1是否按下
GOTO RB2 ;没有按下转判RB2
CALL DELAY10MS ;RB1按下,调用10ms延时
BTFSS PORTB,1 ;再判RB1是否按下
GOTO RB2 ;没有按下转判RB2
PP1 BTFSC PORTB,1 ;RB1按下,转判RB1是否释放
GOTO PP1 ;没有释放等待
CALL DELAY10MS ;RB1释放,调用10ms延时
BTFSC PORTB,1 ;再判断RB1是否释放
GOTO PP1 ;没有释放等待
MOVF PR2_TEP,W ;取出后备周期寄存器
SUBLW 00H ;比较是否到0
BTFSC STATUS,Z ;是否相等
GOTO SUBRB1 ;相等,不再减1,直接进入数据处理
DECF PR2_TEP,1 ;不相等(后备周期大于后备周脉宽),直接减1
SUBRB1 CALL XSCHULI ;调用数据处理子程序
RB2 BTFSS PORTB,2 ;判断RB2是否按下
GOTO RB3 ;没有按下转判RB3
CALL DELAY10MS ;RB2按下,调用10ms延时
BTFSS PORTB,2 ;再判RB2是否按下
GOTO RB3 ;没有按下转判RB3
PP2 BTFSC PORTB,2 ; RB2按下,转判RB2是否释放
GOTO PP2 ;没有释放等待
CALL DELAY10MS ;RB2释放,调用10ms延时
BTFSC PORTB,2 ;再判断RB2是否释放
GOTO PP2 ;没有释放等待
BSF PORTD,0 ;RD0端口引脚输出为高电平(正转)
MOVLW 01H
MOVWF 67H ;在八段显示器的最高位输出1
CALL XSHI ;调用显示子程序
RB3 BTFSS PORTB,4 ;判断RB4是否按下
GOTO RB0 ;没有按下转判RB0
CALL DELAY10MS ;RB4按下,调用10ms延时
BTFSS PORTB,4 ;再判RB0是否按下
GOTO RB0 ;没有按下转判RB0
PP3 BTFSC PORTB,4 ; RB4按下,转判RB4是否释放
GOTO PP3 ;没有释放等待
CALL DELAY10MS ;RB4释放,调用10ms延时
BTFSC PORTB,4 ;再判断RB4是否释放
GOTO PP3 ;没有释放等待
BCF PORTD,0 ;RD0端口引脚输出为低电平(反转)
CLRF 67H ;在八段显示器的最高位输出0
CALL XSHI ;调用显示子程序
GOTO RB0
;------------------------------------------------------------------------------------------
;10MS软件延时子程序DELAY10MS
;------------------------------------------------------------------------------------------
DELAY10MS MOVLW 0DH ;外循环常数
MOVWF 20H ;外循环寄存器
LOOP1 MOVLW 0FFH ;内循环常数
MOVWF 21H ;内循环寄存器
LOOP2 DECFSZ 21H ;内循环寄存器递减
GOTO LOOP2 ;继续内循环
DECFSZ 20H ;外循环寄存器递减
GOTO LOOP1 ;继续外循环
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;数据处理子程序
;------------------------------------------------------------------------------------------
XSCHULI BCF STATUS,C ;进位标志清零
RRF PR2_TEP,W ;除2
MOVWF CCPR1L ;送给脉宽寄存器
MOVF PR2_TEP,W ;取出后备周期参数
BSF STATUS,RP0 ;选择数据存储器体1
MOVWF PR2 ;后备周期参数送入周期寄存器
BCF STATUS,RP0 ;选择数据存储器体0
MOVWF S1L ;周期参数送入口变量
CLRF S1H
CALL BINTOBCD ;调用二进制至BCD码转换
MOVF R1Z,W ;百位直接送入62H
MOVWF 62H
MOVF R1L,W ;分离十位和个位分别送入61H、60H
ANDLW 0FH ;屏蔽高4位送数据缓冲区60H
MOVWF 60H
SWAPF R1L,W
ANDLW 0FH ;屏蔽高4位送数据缓冲区61H
MOVWF 61H
MOVF PORTD
CALL XSHI ;调用显示子程序
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;二进制到BCD码转换子程序
;------------------------------------------------------------------------------------------
BINTOBCD MOVLW 10H ;循环向左移位16次
MOVWF COUNT
CLRF R1H ;输出类变量清0
CLRF R1Z
CLRF R1L
LOOP RLF S1L ;二进制数据单元逐位移入BCD码单元
RLF S1H ;右移一位
RLF R1L ;右移一位
RLF R1Z ;右移一位
RLF R1H ;右移一位
DECFSZ COUNT ;递减判断是否为0
GOTO ADJDET
RETLW 00H ;返回
ADJDET MOVLW R1L
MOVWF FSR
CALL ADJBCD ;调整低8位R1L
MOVLW R1Z
MOVWF FSR
CALL ADJBCD ;调整中8位R1Z
MOVLW R1H
MOVWF FSR
CALL ADJBCD ;调整高8位R1H
GOTO LOOP
;------------------------------------------------------------------------------------------
;逐位调整
;------------------------------------------------------------------------------------------
ADJBCD MOVLW 03H
ADDWF INDF,W ;是否LSD加3
MOVWF TEMP
BTFSC TEMP,3 ;是否大于4
MOVWF INDF ;确定LSD加3
MOVLW 30H
ADDWF INDF,W ;是否MSD加3
MOVWF TEMP
BTFSC TEMP,7 ;是否大于4
MOVWF INDF ;确定MSD加3
RETLW 00H
;------------------------------------------------------------------------------------------
;显示驱动子程序
;------------------------------------------------------------------------------------------
XSHI CLRF PORTE ;清0
MOVLW 67H ;设置显示缓冲器的数据地址
MOVWF FSR
LO1P MOVF INDF,W ;取出数据
CALL BMA ;查询对应编码
CALL OUTXSH ;利用SPI方式输出编码数据
DECF FSR
BTFSS FSR,4 ;直到8位数码全部输出
GOTO LO1P
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;SPI方式输出编码数据子程序
;------------------------------------------------------------------------------------------
OUTXSH MOVWF SSPBUF ;送至SSPBUF后开始逐位发送
LO1P1 BSF STATUS,RP0 ;选择体1
BTFSS SSPSTAT,BF ;是否发送完毕
GOTO LO1P1 ;否,继续查询
BCF STATUS,RP0 ;发送完毕,选择体0
MOVF SSPBUF,W ;移空SSPBUF
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;8位数码全暗,仅仅最高位给出"-"键控提示符
;------------------------------------------------------------------------------------------
JKZT MOVLW 60H ;除最高位外,均设置为全暗
MOVWF FSR
TUN MOVLW 0AH
MOVWF INDF ;采用间接寻址送数
INCF FSR
BTFSS FSR,3 ;是否完成8个单元置数
GOTO TUN
MOVLW 01H ;最高位67H单元送"-"编码
MOVWF 67H
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;初始化子程序(67H-60H缓冲存储器分别赋值01-07),从数码最高位67H开始点亮,延时1S
;------------------------------------------------------------------------------------------
CHUSHIHUA
CALL JKZT ;首先调用监控子程序
CALL XSHI ;输出显示
MOVLW 67H
MOVWF FSR ;从最低位赋值,采用间接寻址
MOVLW 00H
MOVWF COUNTER ;给出赋值数据,从1开始
QT MOVF COUNTER,W
MOVWF INDF ;采用间接寻址
MOVF FSR,W
MOVWF FSR_TEP ;保护FSR
CALL XSHI ;数码刷新
CALL DELAY ;调用1S延时
MOVF FSR_TEP,W ;恢复FSR
MOVWF FSR
DECF FSR ;地址减1
INCF COUNTER ;赋值数据加1
BTFSS COUNTER,3 ;8位赋值是否结束
GOTO QT
CALL JKZT ;首先调用监控子程序
CALL XSHI ;数码显示刷新
RETURN ;子程序返回
;------------------------------------------------------------------------------------------
;编码查询
;------------------------------------------------------------------------------------------
BMA ADDWF PCL,F ;加偏移量
RETLW 3FH ;"0" 编码
RETLW 06H ;"1" 编码
RETLW 5BH ;"2" 编码
RETLW 4FH ;"3" 编码
RETLW 66H ;"4" 编码
RETLW 6DH ;"5" 编码
RETLW 7DH ;"6" 编码
RETLW 07H ;"7" 编码
RETLW 7FH ;"8" 编码
RETLW 6FH ;"9" 编码
RETLW 00H ;"暗" 编码
RETLW 40H ;"-" 编码
;------------------------------------------------------------------------------------------
;中断服务子程序
;------------------------------------------------------------------------------------------
IEIE BCF INTCON,T0IF ;清除中断标志位
DECFSZ TIMES,F ;中断倍数递减是否为零
GOTO POP ;不为零,直接中断返回
TP0 BTFSC PORTB,0 ;为零,TMR0定时倍数时间到,判断RB0按下否?
GOTO XYZ0 ;RB0按下
GOTO TP1 ;RB0没有按下, 跳去判断RB1
XYZ0 MOVF PR2_TEP,W ;周期寄存器是否为FFH
SUBLW 0FFH
BTFSC STATUS,Z ;考察Z标志位
GOTO IERB0 ;为FFH不再递增
INCF PR2_TEP,F ;不为FFH,执行递增
IERB0 CALL XSCHULI ;转入数据处理
CALL DELAY100MS ;延时100ms
GOTO TP0 ;再次重复判断
TP1 BTFSC PORTB,1 ;判断RB1按下否?
GOTO XYZ1 ;RB1按下
GOTO POP1 ;RB1没有按下, 直接中断返回
XYZ1 MOVF PR2_TEP,W ;周期寄存器是否为00H
SUBLW 00H
BTFSC STATUS,Z ;考察Z标志位
GOTO IERB1 ;为00H不再递减
DECF PR2_TEP,F ;不为00H,执行递减
IERB1 CALL XSCHULI ;转入数据处理
CALL DELAY100MS ;延时100ms
GOTO TP1 ;再次重复判断
POP CLRF TMR0 ;TMR0单次时间常数清零
RETFIE ;中断返回
POP1 CLRF TMR0 ;TMR0单次时间常数清零
MOVLW .30 ;重新设置连续按下时间的定时倍数
MOVWF TIMES
RETFIE ;中断返回
;----------------------------------------------------------------------------------------
;100MS延时子程序
;----------------------------------------------------------------------------------------
DELAY100MS
MOVLW 83H ;外循环常数
MOVWF 20H ;外循环寄存器
LO2 MOVLW 0FFH ;中循环常数
MOVWF 21H ;中循环寄存器
L01 DECFSZ 21H,F ;中循环寄存器递减
GOTO L01 ;继续中循环
DECFSZ 20H,F ;外循环寄存器递减
GOTO LO2 ;继续外循环
RETURN ;返回
;------------------------------------------------------------------------------------------
;1S延时
;------------------------------------------------------------------------------------------
DELAY MOVLW 06H ;外循环常数
MOVWF 22H ;外循环寄存器
LQ3 MOVLW 0EBH ;中循环常数
MOVWF 20H ;中循环寄存器
LQ2 MOVLW 0ECH ;中循环寄存器递减
MOVWF 21H ;继续中循环
LQ1 DECFSZ 21H,F ;外循环寄存器递减
GOTO LQ1 ;继续外循环
DECFSZ 20H,F ;外循环寄存器递减
GOTO LQ2
DECFSZ 22H,F ;继续外循环
GOTO LQ3
RETURN
;------------------------------------------------------------------------------------------
END
;------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -