应用外部中断0和外部中断1控制流水灯的流水方向和速度,其中 最大的流水总周期为:1300ms

51单片机用keil软件汇编语言编译实现:流水灯,应用外部中断0和外部中断1控制流水灯的流水方向和速度,其中最大的流水总周期为:1300ms

码字不易,有用望采纳答案参考Chatgpt解答
下面是使用 89C51 单片机汇编语言编写的控制流水灯的程序,其中使用外部中断0和外部中断1控制流水灯的流水方向和速度,最慢一次的流水总周期为1300ms,定时器采用中断方式。

ORG 0H
MOV TMOD, 00000001B    ; 设置定时器0为模式1,用作定时器
MOV TH0, 0FFH          ; 设置定时器0的初始值为0FFH,最大计数
SETB TR0               ; 启动定时器0

MOV P1, #00000001B     ; 设置 P1.0 为输出口,用作流水灯

SETB EA                ; 启用总中断
SETB ET0               ; 启用定时器0中断
SETB EX0               ; 启用外部中断0
SETB EX1               ; 启用外部中断1

MAIN:
  SJMP MAIN            ; 主循环

ORG 0BH                ; 外部中断0的中断向量地址
INT0_ISR:
  CPL P1               ; 反转 P1 的值,改变流水灯的方向
  RETI                 ; 退出中断

ORG 0BH                ; 外部中断1的中断向量地址
INT1_ISR:
  MOV R0, #255         ; 设置计数器初值为255
  ACALL DELAY          ; 调用延时函数
  CPL P1               ; 反转 P1 的值,改变流水灯的速度
  RETI                 ; 退出中断

DELAY:
  MOV R1, #0
LOOP:
  MOV R2, #0
LOOP1:
  MOV R3, #0
LOOP2:
  DJNZ R3, LOOP2       ; R3递减
  DJNZ R2, LOOP1       ; R2递减
  DJNZ R1, LOOP        ; R1递减
  RET                  ; 返回延时函数

END

以上是使用 89C51 单片机汇编语言编写的控制流水灯的程序,其中最慢一次的流水总周期为1300ms,定时器采用中断方式。使用外部中断0来控制流水灯的方向,外部中断1来控制流水灯的速度。

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/679599
  • 你也可以参考下这篇文章:单片机实验 之 广告流水灯中断控制
  • 除此之外, 这篇博客: 按键中断可控流水灯中的 按键中断可控流水灯 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 1.流水灯
    2.什么是中断?
    3.中断的定义?
    4.中断程序的结束与退出
    5.程序的优先级
    6.空程序的运行
    7.数字信号的打印
    8…程序错误的检测

    1.流水灯
    在这里插入图片描述

    void setup(){
      pinMode(7, OUTPUT);
      pinMode(8, OUTPUT);
      pinMode(9, OUTPUT);
      pinMode(10, OUTPUT);
    }
    
    void loop(){
      digitalWrite(7,HIGH);
      delay(1000);
      digitalWrite(7,LOW);
      digitalWrite(8,HIGH);
      delay(1000);
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
      delay(1000);
      digitalWrite(9,LOW);
      digitalWrite(10,HIGH);
      delay(1000);
      digitalWrite(10,LOW);
    
    }
    

    2.什么是中断
    简单的来说就是停止现在的事情来做另一件事情,做完在返回继续一开始的任务

    3.中断的定义
    中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。
    中断系统特点:
    ①分时操作。CPU 可以分时为多个 I/O 设备服务,提高了计算机的利用率;
    ②实时响应。CPU 能够及时处理应用系统的随机事件,系统的实时性大大增强;
    ③可靠性高。CPU 具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高
    中断过程
    对于单片机来讲,中断是指CPU在处理某一时间A时,发生了另一事件B请求CPU立刻去处理(中断发生或中断请求);CPU暂时停止当前的工作(中断响应),转而去处理事件B(中断服务),待CPU处理事件B完成后,再回到原来事件A被中断的地方继续处理事件A(中断返回)。这一过程称为中断,注意是整个过程,而不是单一的停止一件事的意思。
    举例:你打开火,烧上一壶水。然后去洗衣服,在洗衣服的过程中,突然听到水壶发出水开的报警声,这时,你停止洗衣服动作,立即去关掉火,然后将开水灌入暖水瓶中,灌完开水后,你又回去继续洗衣服。这个过程中实际上就发生了一次中断

    在这里插入图片描述
    在这里插入图片描述

    4.中断程序的结束与退出
    在这里插入图片描述
    在这里插入图片描述

    volatile boolean 状态;
    
    void attachInterrupt_fun_FALLING_2() {
      状态 = !状态;
      digitalWrite(4,状态);
    }
    
    void setup(){
      状态 = false;
      pinMode(2, INPUT_PULLUP);
      pinMode(4, OUTPUT);
      attachInterrupt(digitalPinToInterrupt(2),attachInterrupt_fun_FALLING_2,FALLING);
    }
    
    void loop(){
    
    }
    

    按键第一次按进入中断程序,第二次按退出中断
    布尔型变量 只有两种结果 例如非真即假 0和1 这种
    在这里插入图片描述
    注释 :第一次状态为真时,第二次按下就为假,这样便可以达到一开一关的效果
    在这里插入图片描述
    不采用变量实现一开一关
    注释 第一次按下状态假设为1,松开后变0,则第二次的初始状态为0,按下时与前一次状态不同,执行关闭

    5.程序的优先级
    单片机的运行是一个代码运行的,中断程序就相当于一个优先级,可以打断单片机的运行,从而先运行其他程序

    6.空程序的运行

    在这里插入图片描述
    满足条件则运行空格里的程序,可当空语令运行,卡死在这一步,按键按下,数字输入变0,按住不放时,程序不变卡在空语句。状态不变,松开时,数字信号变为高电平1,则跳出中断语句

    执行空语句时,空语句需要放入中断程序中,否则不运行

    7.数字信号的打印
    在这里插入图片描述

    void setup(){
      Serial.begin(9600);
      pinMode(4, INPUT);
    }
    
    void loop(){
      pinMode(4, INPUT);
      Serial.println(digitalRead(4));
    
    }
    

    注释:管脚模式一定要选好是输入还是输出
    在这里插入图片描述
    一开始想打印出按钮按下的数字信号,因为没有设定好管脚模式,导致检测不出来数字信号
    上图所用的按扭为共阴按钮,因此数字信号管脚检测模式要设置为上拉输入,上拉输入可检测出 ##低电平
    在这里插入图片描述
    在这里插入图片描述

    上拉输入的检测原理

    8…程序错误的检测
    先检测主程序是否错误
    在这里插入图片描述
    若串口数据不显示,则为设置程序模块有问题
    跟检测主程序一样,加入打印串口数据,便可检测出是哪一步出现了问题
    在这里插入图片描述
    所有模块
    在这里插入图片描述
    所有模块代码

    #include <PinChangeInt.h>
    
    void attachPinInterrupt_fun_FALLING_2() {
      digitalWrite(5,LOW);
      digitalWrite(6,LOW);
      digitalWrite(7,LOW);
      digitalWrite(7,HIGH);
      while (digitalRead(2) == 0) {
        Serial.println("卡死了");
      }
    }
    
    void setup(){
      Serial.begin(9600);
      pinMode(2, INPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      pinMode(7, OUTPUT);
      pinMode(2, INPUT_PULLUP);
      PCintPort::attachInterrupt(2,attachPinInterrupt_fun_FALLING_2,FALLING);
    }
    
    void loop(){
      digitalWrite(5,HIGH);
      delay(1000);
      digitalWrite(5,LOW);
      digitalWrite(6,HIGH);
      delay(1000);
      digitalWrite(6,LOW);
      digitalWrite(7,HIGH);
      delay(1000);
      digitalWrite(7,LOW);
    
    }
    
  • 您还可以看一下 姜雪伟老师的算法与游戏实战技术课程中的 固定流水线算法实战应用小节, 巩固相关知识点