⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 语音播放程序.asm

📁 基于 语音单片机的 语音播放程序
💻 ASM
字号:

TIME30MS BIT 00H   ;30ms时间到标志

MOSI     BIT P1.5
MISO     BIT P1.6
SCLK     BIT P1.7

U104ADR  DATA 2EH
ISDSS    BIT U104ADR.1  ;先定义后引用!
MIC_C    BIT U104ADR.3

ISDBUF   DATA 50H  ;ISD语音芯片命令缓冲区
                   ;50H单元存放命令码(C4-C0)及段高3位地址(A10-A8)
                   ;51H单元存放段低8位地址(A7-A0)

XmtDat  DATA 60H   ;播放语音段缓冲区
ISDBUFSP DATA 52H  ;播放指针
TASK3    DATA 53H  ;语音播放作业指针

ORG 0000H
LJMP MAIN

ORG 0003H
LJMP INT0       ;外中断INT0中断服务程序入口地址

ORG 002BH
LJMP CTC2       ;定时/计数器T2中断服务程序入口地址

ORG 0050H

PROC MAIN
MAIN:
     MOV SP, #0DFH     ;对于具有256字节内部RAM芯片来说,
                       ;将0E0H-0FFH,共计32字节作为堆栈区

     ;---复位后,将01H-0FF内部RAM单元清0。
     MOV R0, #01H
LOOPIC1:
     MOV @R0, #0
     INC R0
     CJNE R0, #0, LOOPIC1

     MOV DPTR, #8000H  ;关闭蜂鸣器
     MOV A, #0FFH
     MOV U104ADR, A    ;初始化映象地址!
     MOVX @DPTR, A

     ;初始化定时器T2(每10ms)中断一次
     MOV TH2, #0DCH
     MOV TL2, #00H          ;初值0DC00送定时器T2(12时钟模式)
     MOV RCAP2H, #0DCH
     MOV RCAP2L, #00H       ;初始化重装初值
     MOV T2CON, #00000100B  ;初始化T2工作方式(自动重装初值、定时)
                            ;并启动了T2
     ;外中断INT0的初始化
     SETB IT0               ;下降沿触发
     SETB ET2               ;允许T2中断
     CLR EX0                ;外中断INT0由播放程序打开
     SETB EA

     ;---语音播放初始化开始--
     MOV R0, #XmtDat       ;清除播放语音段缓冲区
     MOV R7, #16
LOOP1:
     MOV @R0, #0FFH        ;语音缓冲区置为0FFH
     INC R0
     DJNZ R7, LOOP1
     ;装入待播放的语音信息
     MOV R0, #XmtDat
     MOV @R0, #0           ;初始化语音段缓冲区
     INC R0
     MOV @R0, #0B8H
     INC R0
     MOV @R0, #0B9H
     INC R0
     MOV @R0, #0E0H
     INC R0
     MOV @R0, #0E1H
     INC R0
     MOV @R0, #0E2H
     INC R0
     MOV @R0, #67H
     INC R0
     MOV @R0, #68H
     INC R0
     MOV @R0, #69H
     INC R0
     MOV @R0, #6AH
     INC R0
     MOV @R0, #6BH

     MOV ISDBUFSP, #0      ;初始化播放指针
     MOV TASK3, #80H       ;启动,并执行上电操作
     ;---语音播放初始化结束--

HERE:
     LCALL ISDOUT          ;调用允许播放程序
     SJMP HERE

END


PROC CTC2                 ;每10ms中断一次
CTC2:
    PUSH PSW
    PUSH ACC
    CLR  RS1        ;使用1区
    SETB RS0

    MOV A, TASK3
    ANL A, #3FH         ;保留时间字节
    JZ YUDEXIT
    DEC A
    ANL TASK3, #0C0H
    ORL TASK3, A        ;回写了延迟时间

YUDEXIT:
    POP ACC
    POP PSW
    CLR TF2               ;清除定时器T2中断标志
    RETI
END


;控制命令送ISD4000语音芯片(16位命令格式)
;入口参数:16位命令码(两字节)存放在ISDBUF缓冲区内
;出口参数:无
;使用资源:R0、R6、R7及Acc、PSW、DPTR(使用进位标志C)

PROC SPIBW      ;SPI总线控制命令写入子程序
SPIBW:
    CLR EA
    CLR SCLK           ;空闲时SCLK处于高电平,以减小功耗。
                       ;而,ISD采用正极性SCLK脉冲头。
                       ;因此,在片选信号SS为低电平前先将SCLK置为低电平
    CLR ISDSS          ;片选信号为低
    MOV A, U104ADR     ;取出U104芯片在内存中的映象地址
    MOV DPTR, #8000H
    MOVX @DPTR, A      ;输出片选信号SS

    MOV R0, #ISDBUF+1  ;取命令码低位字节
    MOV R6, #2         ;传送两字节
LOOP2:
    MOV A, @R0
    MOV R7, #08H       ;移动次数
LOOP1:
    RRC A              ;带Cy右移。
    MOV MOSI, C        ;CPU输出数据。
    SETB SCLK          ;利用SCLK上升沿锁存输入的数据。
    NOP                ;由于SCLK信号时钟频率最高为1MHz,即高低
                       ;电平时间必须大于400uS,可根据晶振频率插入
                       ;0-2条NOP指令(对于晶振频率在12MHz以内时,不用)
    CLR SCLK           ;时钟信号为低电平
    DJNZ R7,LOOP1
    DEC  R0            ;指针减1,指向下一字节
    DJNZ R6, LOOP2

    SETB ISDSS         ;执行结束后将SS引脚置为高电平。
    MOV A, U104ADR     ;取出U104芯片在内存中的映象地址
    MOV DPTR, #8000H
    MOVX @DPTR, A      ;输出片选信号SS

    SETB SCLK          ;空闲时SCLK处于高电平,以减小功耗。
    SETB EA
    RET
END

;把语音缓冲区语音段送IDS4000芯片播放子程序
;入口参数:TASK3置为80H
;00-表示空闲;10(未执行上电操作)-11(上电延迟)-00(播放等待中断)
;-10(表示播放间隙延迟)

PROC ISDOUT
ISDOUT:
    MOV A, TASK3
    ANL A, #0C0H       ;保留b7、b6标志位
    CJNE A, #00H, NEXT1
    ;b7、b6为00,不执行
    JMP EXIT           ;退出
NEXT1:
    CJNE A, #80H, NEXT2
    ;b7、b6为10,尚未执行上电延迟

    ;上电时也打开麦克风、功率放大器电源开关
    CLR MIC_C
    MOV A, U104ADR   ;取出U104芯片在内存中的映象地址
    MOV DPTR, #8000H
    MOVX @DPTR, A      ;开功放电源开关

    ;先上电
    MOV R0, #ISDBUF   ;语音命令缓冲首地址送R0
    MOV @R0, #20H     ;00100XXX,执行上电操作
    LCALL SPIBW       ;调用SPI总线控制命令写入子程序
    MOV TASK3, #11000100B   ;延迟4*10(即40ms)
    ;b7、b6置为11,作为已经执行了上电延迟命令标志
    SJMP EXIT

NEXT2:
    CJNE A, #0C0H, NEXT3
    ;b7、b6为11,即正处于上电延迟期间
    MOV A, TASK3
    ANL A, #3FH     ;检查上延迟时间是否已到!
    JZ NEXT31
    ;不是0,说明延迟时间未到
    SJMP EXIT         ;退出,继续等待!
NEXT31:
    MOV A, #XmtDat
    ADD A, ISDBUFSP
    MOV R0, A
    MOV A, @R0       ;取出播放语音段编号
    MOV B, #2        ;由于每一个字占用两段
    MUL AB           ;段地址
    MOV R0, #ISDBUF+1;语音命令缓冲首地址送R0
    MOV @R0, A       ;段地址低8位送命令缓冲
    DEC R0
    MOV A, B         ;段地址高位送A
    ORL A, #11100000B;形成地址设置控制码11100(SET PLAY)
    MOV @R0, A       ;送命令码缓冲区
    LCALL SPIBW      ;调用SPI总线控制命令写入子程序

    ;执行PLAY命令
    MOV R0, #ISDBUF  ;语音命令缓冲首地址送R0
    MOV @R0, #0F0H   ;11110XXX,执行PLAY命令
    LCALL SPIBW      ;调用SPI总线控制命令写入子程序
    ;开始播放!
    MOV TASK3, #00H  ;b7、b6置为00(修改作业号)
    SETB EX0         ;打开INT0中断,等待播放结束
    SJMP EXIT
NEXT3:
    CJNE A, #40H, EXIT
    ;b7、b6置为01   ;属于播放期间的延迟
    MOV A, TASK3
    ANL A, #3FH     ;检查上延迟时间是否已到!
    JNZ EXIT        ;不是0,说明播放延迟时间未到,退出!
    SJMP NEXT31      ;延迟时间已到,继续播放
EXIT:
    RET
END

PROC INT0            ;通过中断检测是否已经播放结束
INT0:
     PUSH PSW
     PUSH ACC
     PUSH DPH
     PUSH DPL

     CLR  RS1         ;使用1区
     SETB RS0

     INC ISDBUFSP     ;指向缓冲区内下一段
     MOV A, ISDBUFSP
     CJNE A, #16, NEXT1
NEXT1:
     JNC CLKISD       ;缓冲指针大于16

     MOV A, #XmtDat
     ADD A, ISDBUFSP
     MOV R0, A
     MOV A, @R0       ;取出播放语音段编号
     CJNE A, #0FFH, NEXT2
     ;缓冲区已经发现没有需要播放的语音段!
CLKISD:
     MOV R0, #ISDBUF  ;语音命令缓冲首地址送R0
;     MOV @R0, #50H    ;0101X XXX,执行STOP WRDN命令,停止放音
     MOV @R0, #10H    ;0001X XXX,执行STOP WRDN命令,停止放音
     LCALL SPIBW      ;调用SPI总线控制命令写入子程序

     SETB MIC_C       ;关闭麦克风、功率放大器电源
     MOV A, U104ADR   ;取出U104芯片在内存中的映象地址
     MOV DPTR, #8000H
     MOVX @DPTR, A    ;关闭功放电源开关

     MOV TASK3, #00   ;将b7、b6置为00,结束播放
     SJMP EXIT
NEXT2:
     CJNE A, #16, NEXT3
NEXT3:
     JNC NEXT31
     ;小于16,属于0-F的数码,语音播放间隔应适当增大,以获得更好的听觉效果
     MOV TASK3, #01000110B  ;将b7、b6置为01;延迟6*10ms
     SJMP EXIT
NEXT31:
     MOV TASK3, #01000011B  ;将b7、b6置为01;延迟3*10ms
EXIT:

     CLR EX0          ;禁止INT0中断(由播放程序打开)
     POP DPL
     POP DPH
     POP ACC
     POP PSW
     RETI
END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -