首页 > 技术文章 > 单片机

guohaomeng 2021-02-04 15:04 原文

单片机作业

7.2

  1. 代码

代码如下:

ORG 0000H

LJMP  MLED

ORG   0003H

LJMP   K0L0

ORG   0013H

LJMP   K1L1

data0  EQU  30H

data1  EQU  31H

data2  EQU  32H

       ORG  0050H

MLED:

   ORL  P1,#0F3H

   ANL TCON,#00H

   ANL IP,#0F5H

MOV IE,#85H

DIS: 

   CLR  P1.4

   MOV  R7,#data2

   LCALL  DELAY

   SETB  P1.4

   CLR  P1.5

   MOV  R7,#data2

   LCALL  DELAY

   SETB  P1.5

   CLR   P1.6

   MOV  R7,#data2

   LCALL  DELAY

   SETB  P1.6

   CLR  P1.7

   MOV  R7,#data2

   LCALL  DELAY

   SETB  P1.7

   AJMP  DIS

 

K0L0: PUSH  PSW

      MOV PSW,#18H

    CLR  P1.0

    MOV  R7,#data0

    LCALL  DELAY

    SETB  P1.0

    POP  PSW

    RETI

 

K1L1: PUSH  PSW

      MOV  PSW,#10H

    CLR  P1.1

    MOV  R7,#data1

    LCALL  DELAY

    SETB  P1.1

    POP  PSW

    RETI

ORG   09A0H

DELAY:MOV R6,#0FH

TM1:  MOV R5,#0FFH

TM0:  DJNZ R5,TM0

      DJNZ R6,TM1

      DJNZ R7,DELAY

      RET

    END

  1. 电路接线图

  1. 题目
    1. 电源接通后,L4-L7开始流水,若按下s0/s1,则流水停止,同时L0/L1亮一段时间,之后熄灭,流水灯重新开始流水。
    2. 只需要将开启总中断的语句MOV IE,#85H放到流水灯结束之后即可,即放到AJMP  DIS前一句。
    3. 这是为了保证每个流水灯之间的时间间隔都是一样的。如果只在L4后赋值,那么除了L4延时未设置的值R7*FFH*0FH外,其余的由于最外层循环R7初值为00H,减一后变为0FFH,也就是说计数初值变为FFH。其余小灯的流水时间间隔将明显变大。
    4. 长时间按下S0/S1L0/L1会保持常量,并且小灯停止流水,直到再次松开。

 

蜂鸣器演奏

  1. 代码

ORG   0000H

LJMP  MAIN

ORG   000BH

LJMP    LIN0

ORG   09A0H

;单片机晶振采用11.0592MHz

;频率-半周期数据表 高八位     本程序共保存了四个八度的28个频率数据

TAB1:

DB  0F2H,0F3H,0F5H,0F5H,0F6H,0F7H,0F8H      ;低音1234567

DB  0F9H,0F9H,0FAH,0FAH,0FBH,0FBH,0FCH,0FCH ;1,2,3,4,5,6,7,i

DB  0FCH,0FDH,0FDH,0FDH,0FDH,0FEH           ;高音 234567

DB  0FEH,0FEH,0FEH,0FEH,0FEH,0FEH,0FFH      ;超高音 1234567 

;频率-半周期数据表 低八位

ORG 0AA0H

TAB2:

DB  42H0C1H17H0B6H0D0H0D1H0B6H   ;低音1234567

DB  21H0E1H8CH0D8H68H0E9H5BH8FH ;1,2,3,4,5,6,7,i

DB  0EEH44H6BH0B4H0F4H2DH         ;高音 234567

DB  47H77H0A2H0B6H0DAH0FAH16H ;超高音 1234567

ORG 0BA0H

SONG:

DB  522622522422322222126516 

;我和我的祖国

DB  1223221327226233215212      

;一刻也不能分割

DB  622722622522422322226616  

;无论我走到哪里

DB  7126125125221232213212      

;都唱出一首赞歌

DB  522622522422322222126516  

;我歌唱每一座高山

DB  1223221327222331316212      

;我歌唱每一条河

DB  132722622526                  ;袅袅炊烟

DB  622522422326                    ;小小村落

DB  7146125142221212              ;路上一道辙 

DB  8222323322328226227226233215212;我最亲爱的祖国

DB  8222323322328226227225233216212;我永远紧依着你的心窝 

DB  522422322226712612512326,426224122,1210;你用你那母亲的脉搏和我诉说

DB  0,0,0,0,0,0;END

;一个音符有三个数字。前为第几个音、中为第几个八度、后为时长(以半拍为单位)。

;6, 2, 3 分别代表:6中音3个半拍;

;5, 2, 1 分别代表:5中音1个半拍;

MAIN:

    MOV TMOD,#01H ;设置TR0为模式1

    SETB ET0

    SETB EA

INIT:

    MOV R0,#00H   ;R0   i

    MOV R1,#00H   ;TAB偏移量

    MOV R2,#00H   ;R2为第几个音符 ,存放TH0

    MOV R3,#00H   ;R3为该音符为几个八度  ,存放TL0

    MOV R4,#01H   ;R4为该音符时间长度-节拍数

    MOV R7,#00H   ;R7为延时长度-R4复制而来

    MOV B,#07H

TIME:

    MOV DPTR,#0BA0H;R2R3R4取值

      MOV A,R0

    MOVC A,@A+DPTR

    MOV R2,A

    INC R0

    MOV A,R0

    MOVC A,@A+DPTR

    MOV R3,A

    INC R0

    MOV A,R0

    MOVC A,@A+DPTR;time

    MOV R4,A

    INC R0

    MOV A,R3

    MUL AB

    MOV R3,A

    DEC R3    ;R3*7-1

    MOV A,R2    ;折算出偏移量

    ADD A,R3    ;此时A,R3所存为对应音阶的偏移量

    MOV R3,A

    MOV DPTR,#09A0H ;从数据表中读出频率数值

    MOVC A,@A+DPTR  ;实际上是定时的时间长度

    MOV R2,A

    MOV A,R3

    MOV DPTR,#0AA0H

    MOVC A,@A+DPTR

    MOV R3,A

    LCALL SING    ;发出一个音符

    MOV A,R4

    JNZ TIME

    LJMP INIT

ORG 1500H

SING:         ;演奏音符程序

    MOV TH0,R2  ;控制音调

    MOV TL0,R3

    SETB TR0    ;启动T0, T0输出方波去发音

    MOV A,R4

    MOV R7,A    ;R7控制发音时间

    LCALL DELAY

    RET

DELAY:    ;延时程序,控制发音的时间长度

      MOV R6,#00H   ;双重循环共延时R7个半拍

TM1:    MOV R5,#00H ;延时期间可进入T0中断去发音

TM0:    DJNZ R5,TM0 ;

        DJNZ R6,TM1

        DJNZ R7,DELAY

    CLR TR0     ;关闭T0, 停止发音

        RET

LIN0:   ;T0中断程序,控制发音的音调

    CLR TR0   ;先关闭T0

    CPL P1.5    ;输出方波发音

    MOV TH0,R2  ;下次的中断时间这个时间控制音调高低

    MOV TL0,R3  ;启动T0

    SETB TR0

    RETI

 

END     

 

程序分析

要想靠蜂鸣器自身来演奏音乐是不行的,这是由于蜂鸣器只能发出一个声音,所以我们需要在蜂鸣器引脚上加上不同频率的方波,就能让其发出不同音调。本程序设置了28种频率,分别是低音1234567、中音1234567、高音1234567、超高音1234567共四个八度的28种声音。这样就能使用蜂鸣器来演奏不同的音符。并奏出音乐了。每个音符的发声频率都不同,但都是通过计时器T0来输出方波的。通过改变计时器的初值(也就是之前设置好的28种频率),便能控制发出方波的频率。发声时间则是通过DELAY程序来控制。一开始程序从SONG数据块中取得待演唱音符的音数、八度和时间,并通过音数和八度数计算出对应的频率在频率表中断位置,便开始执行SING子程序,子程序将频率(也就是计数初值)赋给定时器T0,开启T0T0便发出方波,开始发出该频率的音。当该音符的发音时间(R7)到后,便关掉蜂鸣器,这样就完成了发出一个音符的操作。如此循环,取出SONG中存的音符并演奏,就能用蜂鸣器唱出整首歌了。

课堂作业

输出2ms20ms方波

  1. 代码

  1. 仿真结果截图

推荐阅读