51单片机 独立按键控制LED流水灯实验

 本实验使用的是伟福V系列编译器,芯片为STC89C52RC。

一、实验目的 

1、掌握独立按键的结构和工作原理

2、掌握外部中断和定时器/计数器的结构和工作原理 

3、掌握外部中断处理独立按键的原理

4、掌握定时器中断精确定时的原理

5、掌握主程序+中断子程序的程序设计结构

6、掌握精确定时和实时处理按键动作的程序设计

二、实验内容

汇编语言程序实现,独立按键接P3.3 ,按键控制流水灯的运行状态。

1、开机后,P2连接的8个发光二极管运行,运行的方式是从左至右,再从右至左依次闪烁,每个发光二极管亮1s,周而复始,循环不息。

2、用定时器T2定时,捕获方式,定时50ms中断,晶振频率12MHz;

3、当按键按下,闪烁的二极管暂停运行;再按下,暂停的二极管继续运行。

三、背景知识

1、中断系统结构

本实验的中断请求源为INT1,对应引脚为P3.3,IT1置1,跳沿触发。

2、定时器T2设置为16位捕捉方式

注意,由T2CON特殊功能寄存器中的EXEN2位的不同设置引起的T2捕捉方式有两种情况,这里采用第(1)种。

3、关于标志位TF2

TF2必须手动清零!!!

四、代码及主要代码注释

ORG 0000H
LJMP MAIN
ORG 0013H;外部中断1(P3.3)入口地址
LJMP EX1_SUB
ORG 002BH;定时器T2中断入口地址
LJMP ET2_SUB

ORG 30H
MAIN:
    MOV SP,#60H
    MOV B,#20 ;20*50ms=1s
    MOV DPTR,#TAB
    MOV R6,#16
    MOV T2MOD,#0
    MOV T2CON,#1;定时器T2捕捉方式,EXEN2=0时,就是普通定时器
    MOV TL2,#0B0H;定时器T2赋初值,转化成十进制为15536,(65536-15536)*1us=50ms
    MOV TH2,#3CH
    SETB IT1;外部中断1跳沿触发
    SETB EX1;允许外部中断1产生中断
    SETB ET2;允许定时器T2中断
    SETB TR2;启动T2计数
    SETB EA;总中断允许
    LJMP $;原地踏步,等待中断产生

ORG  100H
ET2_SUB:
    CLR TF2 ;标志位清零
    MOV TL2,#0B0H;T2重新赋初值
    MOV TH2,#3CH
    DJNZ B,RETURN
    MOV B,#20

    MOV A,#0
    MOVC A,@A+DPTR
    MOV P2,A
    INC DPTR
    DJNZ R6,RETURN
    MOV R6,#16
    MOV DPTR,#TAB

RETURN:
    RETI

ORG 150H
EX1_SUB:
    CPL TR2 ;外部中断1到来,取反,定时器T2取相反的工作状态
    RETI

ORG 200H ;以从左至右再从右至左为一个查表周期
TAB:DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH,0BFH,0DFH,0EFH,0F7H,0FBH,0FDH,0FEH

本文章主要用于作者自主学习,欢迎大佬批评指正。

51单片机中,通过独立按键控制流水灯通常涉及到以下几个步骤: 1. **硬件连接**: - 将按键接到单片机的输入端口,如P0、P1等,作为输入中断源。 - 使用8个LED或数码管连接到单片机的输出端口,形成流水灯效果。 2. **初始化**: - 初始化输入端口为查询模式,以便检测按键状态变化。 - 对输出端口设置初始状态,如将所有LED关掉。 3. **主循环**: - 循环读取按键的状态,如果按键按下,则改变输出端口的一个LED状态(比如顺时针移动一位),然后释放按键。 - 如果按键松开并且上一次按键操作已经完成(例如,等待一定延时),则恢复流水灯的状态(顺向或逆向移动)。 4. **中断处理**: - 当按键被按下时,会触发中断,此时进入中断服务程序(ISR)。检查按键状态,记录按下位置并退出中断。 5. **中间返回代码示例**: ```c #include <reg52.h> //假设是AT89S51系列 // 定义按键和LED的端口地址 sbit keyA = P2^0; // 按键A sbit led1 = P1^0; // LED1 sbit led2 = P1^1; // LED2 ... 等待8个LED void delay(unsigned int time) { // 添加适当延迟函数 } void interrupt() __attribute__((interrupt("KEYB"))) { if (keyA == 1) { // 检测按键A是否按下 led1 = !led1; // 切换LED1状态 // 更新其他LED状态... keyA = 0; // 记录按键已按,退出中断 } } void main() { TRIS_P1 = 0xFF; // 输出模式,所有LED都是输出 TRIS_P2 = 0x00; // 输入模式,按键A是输入 while(1) { if(keyA == 0) { // 非常简单地判断按键是否松开 for(int i=0; i<8; i++) { // 逐位切换流水灯 led1 = led2; led2 = led3; // 更改下一个LED // ... led7 = led1; // 回到第一个LED delay(100); // 延迟一段时间再继续 } } } }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值