📄 语音播放程序.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 + -