大三第二学期单片机课程设计-上机篇
设计前练习:
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/8155.jpg)
0.asm
设计题目: 倒计时秒表
设计所使用的电路图(注意与上面的电路图的微小区别, 差别就体现在代码中)
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/8155_2.jpg)
1. 在显示器显示任意4位十六进制数.
1.asm
2.
2.asm
对应代码下载:
0.asm
1.asm
主程序流程:
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/60timer_1.jpg)
主程序代码段
显示子函数
按键功能
重置代码段
开始功能代码段
暂停功能代码段
停止功能代码段
其他功能代码段
中断定时代码段
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/8155.jpg)
0.asm
ORG 000H
LJMP MAIN
ORG 1000H
MAIN: MOV 53H, #00H ;初始化各数据
MOV 52H, #00H
MOV 51H, #00H
MOV 50H, #00H
MOV R5, #53H
KEYSUB: MOV A, #03H ;键盘扫描, 设置8155的工作方式 , PA, PB输出, PC口输入
MOV DPTR, #7F00H ;向8155写入命令字
MOVX @DPTR, A
BEGIN: ACALL DIS ;调用显示函数
ACALL CLEAR
ACALL CCSCAN ;调用扫描函数
JNZ INK1 ;若有键按下,则听到INK1, 否则重新扫描
AJMP BEGIN
INK1: ACALL DIS
ACALL DL1MS ;延时去抖
ACALL DL1MS ;延时去抖
ACALL CLEAR
ACALL CCSCAN ;再次扫描, 确保去抖后, 还能检测到有键按下
JNZ INK2
AJMP BEGIN
INK2: MOV R2, #0FEH ;先扫描最左边列的按键
MOV R4, #00H
COLUM: MOV DPTR, #7F01H ;拉低某一列
MOV A, R2
MOVX @DPTR, A
INC DPTR
INC DPTR
MOVX A, @DPTR ;读取PC口, 即扫描行
JB A.0, LONE ;若第一行没有有键按下, 则跳到LONE
MOV A, #00H ;第一行有键按下, A为0
AJMP KCODE
LONE: JB A.1, NEXT ;判断是否第二行有键按下
MOV A, #04H ;第二行有键按下, A为4
KCODE: ADD A, R4
ACALL PUTBUF ;将键码存入存储区, 先从53H到50H
PUSH A
KON: ACALL DIS ;按键释放检测
ACALL CLEAR
ACALL CCSCAN
JNZ KON ;若一直有键被按下, 则一直等待键被释放
POP A
NEXT: INC R4 ;扫描列左移
MOV A, R2
JNB A.3 KERR ;全部列已扫描完, 则重新开始
RL A ;列左移一位
MOV R2, A
AJMP COLUM 扫描行
KERR: AJMP BEGIN
CCSCAN: MOV DPTR, #7F01H ;扫描检测是否有键被按下函数, 若有键被按下, A不为0, 没有则A为0
MOV A, #00H
MOVX @DPTR, A
INC DPTR
INC DPTR
MOVX A, @DPTR
CPL A ;取反后, 没有键按下时, 低2位都为0, 有键按下时, 低2位都为1
ANL A, #03H ;使A是否为0取决于低2位的值
RET
CLEAR: MOV DPTR, #7F02H ;消除余辉
MOV A, #00H
MOVX @DPTR, A
RET
DIS: PUSH A ;显示函数, 将当前50H~53H单元中的数据显示在数码管上
PUSH 00H ;前三条指令用于现场保护
PUSH 03H
MOV A, #03H ;键盘扫描, 设置8155的工作方式 , PA, PB输出, PC口输入
MOV DPTR, #7F00H
MOVX @DPTR, A
MOV R0, #50H
MOV R3, #0F7H ; 先从最左边这位数码管开始显示
MOV A, R3
AGAIN: MOV DPTR, #7F01H ;选中一个数码管
MOVX @DPTR, A
MOV A, @R0
MOV DPTR, #TABLE
MOVC A, @A+DPTR
MOV DPTR, #7F02H ;送入7段码
MOVX @DPTR, A
ACALL DL1MS
INC R0
MOV A, R3
JNB A.0, OUT ;已显示完4单元数据, 退出显示函数
RR A
MOV R3, A
AJMP AGAIN ;显示下一个单元
OUT: POP 03H
POP 00H
POP A
RET
TABLE: DB 03FH, 06H, 05BH, 04FH, 066H, 06DH, 07DH, 07H
DL1MS: MOV R7, #01H ;延时函数, 延时1ms
DL0: MOV R6, #0FFH
DL1: DJNZ R6, DL1
DJNZ R7, DL0
RET
PUTBUF:PUSH 00H ;将键码存入存储器单元的函数
PUSH A
MOV A, R5
MOV R0, A
POP A
MOV @R0, A
DEC R5
CJNE R5, #04FH, GOBACK
MOV R5, #53H
GOBACK: POP 00H
RET
END
LJMP MAIN
ORG 1000H
MAIN: MOV 53H, #00H ;初始化各数据
MOV 52H, #00H
MOV 51H, #00H
MOV 50H, #00H
MOV R5, #53H
KEYSUB: MOV A, #03H ;键盘扫描, 设置8155的工作方式 , PA, PB输出, PC口输入
MOV DPTR, #7F00H ;向8155写入命令字
MOVX @DPTR, A
BEGIN: ACALL DIS ;调用显示函数
ACALL CLEAR
ACALL CCSCAN ;调用扫描函数
JNZ INK1 ;若有键按下,则听到INK1, 否则重新扫描
AJMP BEGIN
INK1: ACALL DIS
ACALL DL1MS ;延时去抖
ACALL DL1MS ;延时去抖
ACALL CLEAR
ACALL CCSCAN ;再次扫描, 确保去抖后, 还能检测到有键按下
JNZ INK2
AJMP BEGIN
INK2: MOV R2, #0FEH ;先扫描最左边列的按键
MOV R4, #00H
COLUM: MOV DPTR, #7F01H ;拉低某一列
MOV A, R2
MOVX @DPTR, A
INC DPTR
INC DPTR
MOVX A, @DPTR ;读取PC口, 即扫描行
JB A.0, LONE ;若第一行没有有键按下, 则跳到LONE
MOV A, #00H ;第一行有键按下, A为0
AJMP KCODE
LONE: JB A.1, NEXT ;判断是否第二行有键按下
MOV A, #04H ;第二行有键按下, A为4
KCODE: ADD A, R4
ACALL PUTBUF ;将键码存入存储区, 先从53H到50H
PUSH A
KON: ACALL DIS ;按键释放检测
ACALL CLEAR
ACALL CCSCAN
JNZ KON ;若一直有键被按下, 则一直等待键被释放
POP A
NEXT: INC R4 ;扫描列左移
MOV A, R2
JNB A.3 KERR ;全部列已扫描完, 则重新开始
RL A ;列左移一位
MOV R2, A
AJMP COLUM 扫描行
KERR: AJMP BEGIN
CCSCAN: MOV DPTR, #7F01H ;扫描检测是否有键被按下函数, 若有键被按下, A不为0, 没有则A为0
MOV A, #00H
MOVX @DPTR, A
INC DPTR
INC DPTR
MOVX A, @DPTR
CPL A ;取反后, 没有键按下时, 低2位都为0, 有键按下时, 低2位都为1
ANL A, #03H ;使A是否为0取决于低2位的值
RET
CLEAR: MOV DPTR, #7F02H ;消除余辉
MOV A, #00H
MOVX @DPTR, A
RET
DIS: PUSH A ;显示函数, 将当前50H~53H单元中的数据显示在数码管上
PUSH 00H ;前三条指令用于现场保护
PUSH 03H
MOV A, #03H ;键盘扫描, 设置8155的工作方式 , PA, PB输出, PC口输入
MOV DPTR, #7F00H
MOVX @DPTR, A
MOV R0, #50H
MOV R3, #0F7H ; 先从最左边这位数码管开始显示
MOV A, R3
AGAIN: MOV DPTR, #7F01H ;选中一个数码管
MOVX @DPTR, A
MOV A, @R0
MOV DPTR, #TABLE
MOVC A, @A+DPTR
MOV DPTR, #7F02H ;送入7段码
MOVX @DPTR, A
ACALL DL1MS
INC R0
MOV A, R3
JNB A.0, OUT ;已显示完4单元数据, 退出显示函数
RR A
MOV R3, A
AJMP AGAIN ;显示下一个单元
OUT: POP 03H
POP 00H
POP A
RET
TABLE: DB 03FH, 06H, 05BH, 04FH, 066H, 06DH, 07DH, 07H
DL1MS: MOV R7, #01H ;延时函数, 延时1ms
DL0: MOV R6, #0FFH
DL1: DJNZ R6, DL1
DJNZ R7, DL0
RET
PUTBUF:PUSH 00H ;将键码存入存储器单元的函数
PUSH A
MOV A, R5
MOV R0, A
POP A
MOV @R0, A
DEC R5
CJNE R5, #04FH, GOBACK
MOV R5, #53H
GOBACK: POP 00H
RET
END
设计题目: 倒计时秒表
设计所使用的电路图(注意与上面的电路图的微小区别, 差别就体现在代码中)
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/8155_2.jpg)
1. 在显示器显示任意4位十六进制数.
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
2.
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
对应代码下载:
0.asm
1.asm
60分钟倒计时秒表
功能:
1. 带有启动键Start, 暂停键Pause, 停止键Stop, 复位键Reset;
2. 4位数码管显示分(两位)秒(两位);
3. 按启动键启动从60分开始倒计时, 按暂停键暂停,显示保持原来计时时间, 再次按启动键继续计时, 按停止键停止计时, 复位键复位, 到零停止计时.
4. 按停止键后, 可按中间的4个键, 分别对应分的十位(2键), 个位(4键), 和秒的十位(5键), 个位(9键), 按动一下, 相应的位增1, 并保证时间的正确值, 再按一次停止键, 保存设置值, 按其它键则放弃设置时间值, 恢复原来的时间.
电路图:
计时器工作模式:
编码(54H单元) |
当前工作模式 |
00H |
Reset |
01H |
Start |
02H |
Pause |
03H |
Stop |
主程序流程:
![](https://www.cnblogs.com/images/cnblogs_com/fengmk2/60timer_1.jpg)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)