用汇编语言在msc-51单片机p0、p2口,设计一个8位led数码管显示器,动态显示方式;在p1口,设计一个8个按键的独立式键盘;上电或复位后显示信息 “p.“ 设计要求: (1)按下某个按键,“p.”从左往右,按照秒频率循环移动; (2)、按下某个按键,“p.”从右往左,按照秒频率循环移动; (3)、按下某个按键,"p"在原始位置,按照秒频率闪烁; (4)、按下某个按键“p”在原始位置常亮,“”按照秒频率闪烁; (5)、假设键盘上的8个按键,分别代表数字键 “0” 、“1”、“2” 、“3”、“4”、“5”、“6”、“7”,则要求在连续按下不同数字按键时,从右往左以此显示按下的数字键键值; (6)、假设键盘上的8个按键,分别代表数字键 “0” 、“1”、“2” 、“3”、“4”、“5”、“6”、“7”,则要求在连续按下不同数字按键时,从左往右以此显示按下的数字键键值。


# 51单片机8位数码管显示与键盘控制设计 以下是一个完整的MCS-51单片机汇编程序,实现了8位数码管动态显示和8个独立按键的功能,满足所有设计要求。 ```assembly ; 定义端口 P0 EQU 80H ; 数码管段选 P1 EQU 90H ; 键盘输入 P2 EQU A0H ; 数码管位选 P3 EQU B0H ; 其他功能 ; 定义变量地址 DIS_BUF EQU 30H ; 显示缓冲区(8字节) KEY_VAL EQU 38H ; 按键值 MODE EQU 39H ; 工作模式 COUNT EQU 3AH ; 计数器 FLASH EQU 3BH ; 闪烁标志 DIR EQU 3CH ; 移动方向(0=左到右,1=右到左) DELAY EQU 3DH ; 延时计数器 ; 定义模式常量 MODE_STOP EQU 0 ; 停止模式(显示"p.") MODE_LEFT EQU 1 ; 从左到右移动 MODE_RIGHT EQU 2 ; 从右到左移动 MODE_FLASH_P EQU 3 ; "p"闪烁 MODE_FLASH_DOT EQU 4 ; "."闪烁 MODE_INPUT_R EQU 5 ; 从右到左输入 MODE_INPUT_L EQU 6 ; 从左到右输入 ; 程序开始 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV SP, #60H ; 设置堆栈指针 MOV MODE, #MODE_STOP ; 初始模式 MOV FLASH, #0 ; 闪烁标志清零 MOV DIR, #0 ; 方向初始为左到右 MOV DELAY, #0 ; 延时计数器清零 ; 初始化显示缓冲区为"p......." MOV DIS_BUF, #0CH ; 'p' MOV DIS_BUF+1, #0AH ; '.' MOV R0, #DIS_BUF+2 MOV R1, #6 INIT_LOOP: MOV @R0, #0FH ; 空(不显示) INC R0 DJNZ R1, INIT_LOOP ; 主循环 LOOP: LCALL KEY_SCAN ; 扫描键盘 LCALL DISPLAY ; 显示处理 LCALL DELAY_1MS ; 延时1ms SJMP LOOP ; 键盘扫描子程序 KEY_SCAN: MOV P1, #0FFH ; 准备读取键盘 MOV A, P1 CPL A ; 取反 ANL A, #0FFH ; 屏蔽高8位 JZ NO_KEY ; 无按键 ; 消抖延时 LCALL DELAY_10MS MOV A, P1 CPL A ANL A, #0FFH JZ NO_KEY ; 确认按键 ; 获取按键值(0-7) MOV R2, #0 ; 按键计数器 MOV R3, A ; 保存按键状态 KEY_CHECK: RRC A ; 右移一位 JC KEY_FOUND ; 找到按键 INC R2 ; 按键值加1 CJNE R2, #8, KEY_CHECK KEY_FOUND: ; 根据按键值设置模式 CJNE R2, #0, KEY1 MOV MODE, #MODE_LEFT ; 按键0:从左到右移动 SJMP KEY_END KEY1: CJNE R2, #1, KEY2 MOV MODE, #MODE_RIGHT ; 按键1:从右到左移动 SJMP KEY_END KEY2: CJNE R2, #2, KEY3 MOV MODE, #MODE_FLASH_P ; 按键2:"p"闪烁 SJMP KEY_END KEY3: CJNE R2, #3, KEY4 MOV MODE, #MODE_FLASH_DOT ; 按键3:"."闪烁 SJMP KEY_END KEY4: CJNE R2, #4, KEY5 MOV MODE, #MODE_INPUT_R ; 按键4:从右到左输入 SJMP KEY_END KEY5: CJNE R2, #5, KEY6 MOV MODE, #MODE_INPUT_L ; 按键5:从左到右输入 SJMP KEY_END KEY6: CJNE R2, #6, KEY7 MOV MODE, #MODE_STOP ; 按键6:停止模式 SJMP KEY_END KEY7: ; 按键7:复位显示 MOV MODE, #MODE_STOP MOV DIS_BUF, #0CH ; 'p' MOV DIS_BUF+1, #0AH ; '.' MOV R0, #DIS_BUF+2 MOV R1, #6 RESET_LOOP: MOV @R0, #0FH ; 空 INC R0 DJNZ R1, RESET_LOOP KEY_END: MOV KEY_VAL, R2 ; 保存按键值 RET NO_KEY: MOV KEY_VAL, #0FFH ; 无按键 RET ; 显示处理子程序 DISPLAY: ; 根据模式处理显示 MOV A, MODE CJNE A, #MODE_STOP, NOT_STOP ; 停止模式:显示"p." MOV DIS_BUF, #0CH ; 'p' MOV DIS_BUF+1, #0AH ; '.' MOV R0, #DIS_BUF+2 MOV R1, #6 CLEAR_LOOP: MOV @R0, #0FH ; 空 INC R0 DJNZ R1, CLEAR_LOOP SJMP DISP_END NOT_STOP: CJNE A, #MODE_LEFT, NOT_LEFT ; 从左到右移动 INC DELAY MOV A, DELAY CJNE A, #100, DISP_END ; 约1秒移动一次 MOV DELAY, #0 ; 移动显示 MOV R0, #DIS_BUF+7 MOV R1, #7 MOVE_LEFT: MOV A, @R0 DEC R0 MOV @R0, A INC R0 DJNZ R1, MOVE_LEFT MOV DIS_BUF+7, DIS_BUF MOV DIS_BUF, #0FH ; 最左位置空 SJMP DISP_END NOT_LEFT: CJNE A, #MODE_RIGHT, NOT_RIGHT ; 从右到左移动 INC DELAY MOV A, DELAY CJNE A, #100, DISP_END ; 约1秒移动一次 MOV DELAY, #0 ; 移动显示 MOV R0, #DIS_BUF MOV R1, #7 MOVE_RIGHT: MOV A, @R0 INC R0 MOV @R0, A DJNZ R1, MOVE_RIGHT MOV DIS_BUF, DIS_BUF+7 MOV DIS_BUF+7, #0FH ; 最右位置空 SJMP DISP_END NOT_RIGHT: CJNE A, #MODE_FLASH_P, NOT_FLASH_P ; "p"闪烁 INC DELAY MOV A, DELAY CJNE A, #100, DISP_END ; 约1秒闪烁一次 MOV DELAY, #0 MOV A, DIS_BUF XRL A, #0CH ; 切换'p'和空 MOV DIS_BUF, A SJMP DISP_END NOT_FLASH_P: CJNE A, #MODE_FLASH_DOT, NOT_FLASH_DOT ; "."闪烁 INC DELAY MOV A, DELAY CJNE A, #100, DISP_END ; 约1秒闪烁一次 MOV DELAY, #0 MOV A, DIS_BUF+1 XRL A, #0AH ; 切换'.'和空 MOV DIS_BUF+1, A SJMP DISP_END NOT_FLASH_DOT: CJNE A, #MODE_INPUT_R, NOT_INPUT_R ; 从右到左输入 MOV A, KEY_VAL CJNE A, #0FFH, INPUT_R ; 有新按键 SJMP DISP_END INPUT_R: ; 移动已有数字 MOV R0, #DIS_BUF+1 MOV R1, #6 SHIFT_RIGHT: MOV A, @R0 INC R0 MOV @R0, A DJNZ R1, SHIFT_RIGHT ; 在最左位置显示新数字 MOV A, KEY_VAL ADD A, #0 ; 数字0-7对应显示码 MOV DIS_BUF+1, A SJMP DISP_END NOT_INPUT_R: CJNE A, #MODE_INPUT_L, DISP_END ; 从左到右输入 MOV A, KEY_VAL CJNE A, #0FFH, INPUT_L ; 有新按键 SJMP DISP_END INPUT_L: ; 移动已有数字 MOV R0, #DIS_BUF+6 MOV R1, #6 SHIFT_LEFT: MOV A, @R0 DEC R0 MOV @R0, A DJNZ R1, SHIFT_LEFT ; 在最右位置显示新数字 MOV A, KEY_VAL ADD A, #0 ; 数字0-7对应显示码 MOV DIS_BUF+6, A DISP_END: ; 动态显示数码管 MOV R0, #DIS_BUF ; 显示缓冲区指针 MOV R1, #0 ; 位选计数器 MOV R2, #8 ; 8位数码管 DISP_LOOP: MOV A, R1 ; 获取位选值 MOV DPTR, #BIT_TABLE MOVC A, @A+DPTR MOV P2, A ; 设置位选 MOV A, @R0 ; 获取段选值 MOV DPTR, #SEG_TABLE MOVC A, @A+DPTR MOV P0, A ; 设置段选 LCALL DELAY_1MS ; 延时1ms INC R0 ; 指向下一个显示数据 INC R1 ; 下一个位选 DJNZ R2, DISP_LOOP ; 循环显示8位 RET ; 段码表 (共阳极数码管) SEG_TABLE: DB 0C0H ; 0 DB 0F9H ; 1 DB 0A4H ; 2 DB 0B0H ; 3 DB 099H ; 4 DB 092H ; 5 DB 082H ; 6 DB 0F8H ; 7 DB 080H ; 8 DB 090H ; 9 DB 08CH ; P DB 0BFH ; - DB 0FFH ; 空 DB 07FH ; . DB 0A1H ; = DB 086H ; E DB 08EH ; F ; 位选表 BIT_TABLE: DB 0FEH ; 第1位 DB 0FDH ; 第2位 DB 0FBH ; 第3位 DB 0F7H ; 第4位 DB 0EFH ; 第5位 DB 0DFH ; 第6位 DB 0BFH ; 第7位 DB 07FH ; 第8位 ; 延时子程序 DELAY_1MS: MOV R7, #2 DL1: MOV R6, #250 DJNZ R6, $ DJNZ R7, DL1 RET DELAY_10MS: MOV R7, #20 DL2: MOV R6, #250 DJNZ R6, $ DJNZ R7, DL2 RET END ``` ## 程序说明 1. 硬件连接: - P0口连接数码管的段选(a-g,dp) - P2口连接数码管的位选(8个位) - P1口连接8个独立按键 2. 功能实现: - 上电或复位后显示"p." - 按键0: "p."从左往右循环移动(每秒移动一位) - 按键1: "p."从右往左循环移动(每秒移动一位) - 按键2: "p"在原始位置闪烁(每秒闪烁一次) - 按键3: "p"常亮,"."闪烁(每秒闪烁一次) - 按键4: 从右往左显示按下的数字键(0-7) - 按键5: 从左往右显示按下的数字键(0-7) - 按键6: 停止模式(显示"p.") - 按键7: 复位显示(清除所有输入) 3. 数码管显示: - 使用动态扫描方式,每位显示1ms - 共阳极数码管,段码表已定义 4. 键盘处理: - 使用消抖延时(10ms) - 检测按键并转换为0-7的值 ## 注意事项 1. 数码管类型: - 程序中使用的是共阳极数码管,如果使用共阴极数码管,需要修改段码表。 2. 时钟频率: - 延时子程序基于12MHz时钟设计,如果使用不同频率的晶振,需要调整延时参数。 3. 按键防抖: - 程序中使用了10ms的消抖延时,如果按键抖动严重,可以适当增加延时时间。 4. 显示刷新率: - 8位数码管每位显示1ms,整个扫描周期为8ms,刷新率约为125Hz,无闪烁现象。 5. 模式切换: - 每次按键后会立即切换到相应模式,并执行相应操作。 [2025-06-04 00:27:31 | AI写代码神器 | 3571点数解答]
- 循环点亮 led 灯: (1) 使用定时器to 的方式 1,实现 8个 led 由上至下间隔 1s 流动,其中每个 led 亮 0.5s,灭0.5s,一直重复。。 (2) 使用定时器 to 的方式 1,实现 8个 led 逐个点亮,间隔 1s,一直重复。。(1193点数解答 | 2024-12-27 15:10:29)207
- 外部中断 0 由边沿触发,控制 P2 口的 8 个发光二极管依次点亮。C51 程序如下: #include <reg51.h> void ex0_isr() interrupt 0 { static unsigned char led = 0x01; P2 = led; led = (led << 1) | (led >> 7); } void main() { IT0 = 1; EX0 = 1; EA = 1; P2 = 0x01; while(1); } (228点数解答 | 2025-06-22 23:18:42)80
- #include <reg51.h> void ex0_isr() interrupt 0 { static unsigned char led = 0x01; P2 = led; led = (led << 1) | (led >> 7); } void main() { IT0 = 1; EX0 = 1; EA = 1; P2 = 0x01; while(1); }(214点数解答 | 2025-06-22 23:19:09)100
- #include <reg51.h> 3 sbit button=p1^0; 4 sbit led=pl^1; 5 6 bit led_state=0; 7 8日void delay(unsigned int ms){ 9 unsigned int i,j: 10 for(i=ms;i>0;i--) 11 for(j=110;j>0;j--); 12 } 13 14日void main(){ 15 while(1){ 16 白 if (button==0){ 17 delay(20); 18 if (button-=0){ 19 while (button==ah; 20 led state=~led state; 21 led=led state; 22 } 写详细注释(697点数解答 | 2024-10-29 14:54:31)224
- 如下图,p1口(p1.0~p1.7)接了8个开关,p2口(p2.0~p2.7)接了8个发光二极管led,p3.3(/int1)外接消抖电路用于产生中断请求信号,当消抖电路的开关来回拔动一次将产生一个下降沿信号,通过p3.3(/int1)向cpu申请中断。要求:初始时发光二极管全黑,每中断一次,p1.0~p1.7所接的开关状态反映到p2.0~p2.7所接的8个发光二极管上,且要求开关合上的对应发光二极管闪烁5次后常亮(约1秒闪一次),开关断开的对应发光二极管熄灭。试编程实现之。(421点数解答 | 2024-11-11 12:43:19)152
- 如下图,p1口(p1.0~p1.7)接了8个开关,p2口(p2.0~p2.7)接了8个发光二极管led,p3.3(/int1)外接消抖电路用于产生中断请求信号,当消抖电路的开关来回拔动一次将产生一个下降沿信号,通过p3.3(/int1)向cpu申请中断。要求:初始时发光二极管全黑,每中断一次,p1.0~p1.7所接的开关状态反映到p2.0~p2.7所接的8个发光二极管上,且要求开关合上的对应发光二极管闪烁5次后常亮(约1秒闪一次),开关断开的对应发光二极管熄灭。(1343点数解答 | 2024-11-11 19:35:36)261
- p1口(p1.0~p1.7)接了8个开关,p2口(p2.0~p2.7)接了8个发光二极管led,p3.3(/int1)外接消抖电路用于产生中断请求信号,当消抖电路的开关来回拔动一次将产生一个下降沿信号,通过p3.3(/int1)向cpu申请中断。要求:初始时发光二极管全黑,每中断一次,p1.0~p1.7所接的开关状态反映到p2.0~p2.7所接的8个发光二极管上,且要求开关合上的对应发光二极管闪烁5次后常亮(约1秒闪一次),开关断开的对应发光二极管熄灭。使用c52编程(1029点数解答 | 2024-11-11 19:37:19)211
- p1口(p1.0~p1.7)接了8个开关,p2口(p2.0~p2.7)接了8个发光二极管led,p3.3(/int1)外接消抖电路用于产生中断请求信号,当消抖电路的开关来回拔动一次将产生一个下降沿信号,通过p3.3(/int1)向cpu申请中断。要求:初始时发光二极管全黑,每中断一次,p1.0~p1.7所接的开关状态反映到p2.0~p2.7所接的8个发光二极管上,且要求开关合上的对应发光二极管闪烁5次后常亮(约1秒闪一次),开关断开的对应发光二极管熄灭。使用c51编程(1077点数解答 | 2024-11-11 19:37:27)246
- #include <reg51.h> sbit LED = P1^0; sbit KEY = P1^1; void delay(unsigned int ms) { unsigned int i; for(; ms>0; ms--) for(i=0; i<120; i++); } void main() { while(1) { if(KEY == 0) { delay(20); if(KEY == 0) { LED = ~LED; while(KEY == 0); } } } } (326点数解答 | 2025-06-22 23:19:40)103
- 使用继承,实现“剪刀石头布的游戏”。 小时候很喜欢玩一个游戏,“剪刀石头布”,可以是出拳的形式,或跳格子的形式。现在我们用计算机来玩这个游戏。 电脑用随机数产生剪刀石头布,游戏玩家用输入1,2,3的方式出拳。 游戏玩家输入1或2或3,分别 代表剪刀(1)石头(2)布(3)。 电脑胜出时,显示"winner is computerplayer." 游戏玩家胜出时,显示“winner is personplayer.” 平局时显示"a draw." 函数接口定义: 根据主方法内容,实现三个类的定义,分别是是computerplayer、personplayer、game类。 其中computerplayer、personplayer要继承player类。 根据主方法中的用法,实现game类。 裁判测试程序样例: import java.util.scanner; class player{ string name; player(string name){ this.name = name; } int show() { //出拳方法(451点数解答 | 2024-10-20 19:57:58)324
- #include <reg51.h> 1 2 3 sbit button=p1^0; 4 sbit led=p1^1; 5 bit led state=0; 6 7 8日void delay(unsigned int ms){ 9 unsigned int i,j; 10 for(i=ms;i>0;i--) 11 for(j=110;j>0;j--); 1213 14 void main()【 15 while(1){ 16 if (button==0){ 17 delay(20); 18 if (button==0){ 19 1ed=0; 20 21 } 做详细注释(830点数解答 | 2024-10-29 15:29:41)221
- #include <reg51.h> 1 2 3 sbit button=p1^0; 4 sbit led=p1^1; 5 bit led state=0; 6 7 8日void delay(unsigned int ms){ 9 unsigned int i,j; 10 for(i=ms;i>0;i--) 11 for(j=110;j>0;j--); 1213 14 void main()【 15 while(1){ 16 if (button==0){ 17 delay(20); 18 if (button==0){ 19 1ed=0; 20 21 } 做注释(693点数解答 | 2024-10-29 15:31:00)336