用单片机轻松实现多线程
近来,公司给了个任务,要用51芯片实现2个扬声器放不同的音乐。
大家都知道音乐程序的音节与音调的计算是十分复杂的,于是我就在网上搜到了2首现成音乐,刚开始我还挺乐观的,
我先把程序合到一起,再给他们分配了不同的TIMER,第一首音乐我用T0来控制音节与音调,第二首用T1,我想这下
大家满意了吧。可是不做不知道啊,一做完蛋了,怎么2首音乐全跑调了。
于是我开始追查原因:
首先我先分别把2首音乐程序烧进去,扬声器都正常响起了音乐,排除了硬件的问题,单独的程序也是没问题的。
然后我再仔细分析了合起来的程序,没错呀!资源没冲突,是不是没程序烧好?于是我又烧了几片芯片,可是结果都
一样,全跑调了。
这可把我愁坏了,突然我想起来了,一边骂自己笨,一边又发起愁来。单片机都是顺序执行指令的,在响应T0中断处
理第一首音乐的音节与音调时,T1中断是不执行的,反过来也一样,这样程序里音节与音调的延时就要重新计算。别
说我是个音盲了,就是这计算量也会把我累死。
于是我又到网上寻求帮助,哈哈,功夫不负有心人,被我无意中看到一款刚上市的51芯片——LS2051,具有双核功能,
只要把第2道程序当函数一样调用,就可以分别执行,互不影响。这不正是我要的嘛! 于是我抱着把死马当活马医的态度申请了样片,哈,还提供个烧录器(也是免费的哦)。我按照LS2051的使用说明把程
序合好,见下:
ORG 0000H LJMP START ORG 000BH INC 20H ;中断服务,中断计数器加1 MOV TH0, #0D8H MOV TL0, #0EFH ;12M晶振,形成10毫秒中断 RETI ORG 001BH INC 21H ;中断服务,中断计数器加1 MOV TH1, #0D8H MOV TL1, #0EFH ;12M晶振,形成10毫秒中断 RETI START: MOV SP, #50H MOV TH0, #0D8H MOV TL0, #0EFH MOV TH1, #0D8H MOV TL1, #0EFH MOV TMOD, #11H MOV IE, #8aH MOV 0FFH, #MUSIC0_1 ;调用第2道程序 MUSIC0: NOP MOV DPTR, #DAT ;表头地址送DPTR MOV 20H, #00H ;中断计数器清0 MUSIC1: NOP CLR A MOVC A, @A+DPTR ;查表取代码 JZ END0 ;是00H,则结束 CJNE A, #0FFH, MUSIC5 ;如果是休止符,往下执行 LJMP MUSIC3 MUSIC5: NOP MOV R6, A ;R6=18H音符的频率 INC DPTR ; DPTR加一 MOV A, #0 MOVC A, @A+DPTR ;取节拍代码送R7 MOV R7, A ;R7=30H音符发音的时间 SETB TR0 ;启动计数 MUSIC2: NOP CPL P3.0 ;P3.0是音乐输出引脚 MOV A, R6 MOV R3, A ;R3=R6=18H LCALL DEL MOV A, R7 CJNE A, 20H, MUSIC2 ;中断计数器(20H)=R7否?;不等,则继续循环 MOV 20H, #00H ;等于,则取下一代码 INC DPTR LJMP MUSIC1 MUSIC3: NOP ;休止100毫秒 CLR TR0 MOV R2, #0DH ;R2=13 MUSIC4: NOP MOV R3, #0FFH ;R3=255 LCALL DEL DJNZ R2, MUSIC4 INC DPTR LJMP MUSIC1 END0: NOP MOV R2, #0FFH ;歌曲结束,延时1秒后继续 MUSIC6: MOV R3, #00H LCALL DEL DJNZ R2, MUSIC6 LJMP MUSIC0 DEL: NOP DEL3: MOV R4, #02H DEL4: NOP DJNZ R4, DEL4 NOP DJNZ R3, DEL3 RET NOP DAT: DB 18H, 30H, 1CH, 10H DB 20H, 40H, 1CH, 10H DB 18H, 10H, 20H, 10H DB 1CH, 10H, 18H, 40H DB 1CH, 20H, 20H, 20H DB 1CH, 20H, 18H, 20H DB 20H, 80H, 0FFH, 20H DB 30H, 1CH, 10H , 18H DB 20H, 15H, 20H , 1CH DB 20H, 20H, 20H , 26H DB 40H, 20H , 20H , 2BH DB 20H, 26H, 20H , 20H DB 20H, 30H , 80H , 0FFH DB 20H, 20H, 1CH , 10H DB 18H, 10H, 20H , 20H DB 26H, 20H , 2BH , 20H DB 30H, 20H , 2BH , 40H DB 20H, 20H , 1CH , 10H DB 18H, 10H, 20H, 20H DB 26H, 20H , 2BH, 20H DB 30H, 20H, 2BH , 40H DB 20H, 30H, 1CH , 10H DB 18H, 20H , 15H , 20H DB 1CH, 20H , 20H , 20H DB 26H, 40H, 20H , 20H DB 2BH, 20H, 26H , 20H DB 20H, 20H, 30H , 80H DB 20H, 30H, 1CH , 10H DB 20H, 10H, 1CH , 10H DB 20H, 20H, 26H , 20H DB 2BH, 20H, 30H , 20H DB 2BH, 40H, 20H , 15H DB 1FH, 05H, 20H , 10H DB 1CH, 10H, 20H , 20H DB 26H, 20H, 2BH , 20H DB 30H, 20H, 2BH , 40H DB 20H, 30H, 1CH , 10H DB 18H, 20H , 15H , 20H DB 1CH, 20H , 20H , 20H DB 26H, 40H, 20H , 20H DB 2BH, 20H, 26H , 20H DB 20H, 20H, 30H, 30H DB 20H, 30H, 1CH, 10H DB 18H, 40H, 1CH, 20H DB 20H, 20H, 26H, 40H DB 13H, 60H, 18H , 20H DB 15H, 40H, 13H , 40H DB 18H, 80H, 00H MUSIC0_1: NOP MOV DPTR, #DAT_1 ;表头地址送DPTR MOV 20H, #00H ;中断计数器清0 MOV B, #00H ;表序号清0 MUSIC1_1: NOP CLR A MOVC A, @A+DPTR ;查表取代码 JZ END0_1 ;是00H,则结束 CJNE A, #0FFH, MUSIC5_1 LJMP MUSIC3_1 MUSIC5_1: NOP MOV R6, A INC DPTR MOV A, B MOVC A, @A+DPTR ;取节拍代码送R7 MOV R7, A SETB TR1 ;启动计数 MUSIC2_1: NOP CPL P1.0 MOV A, R6 MOV R3, A LCALL DEL_1 MOV A, R7 CJNE A, 20H, MUSIC2_1 ;中断计数器(20H)=R7否?;不等,则继续循环 MOV 20H, #00H ;等于,则取下一代码 INC DPTR LJMP MUSIC1_1 MUSIC3_1: NOP CLR TR1 ;休止100毫秒 MOV R2, #0DH MUSIC4_1: NOP MOV R3, #0FFH LCALL DEL_1 DJNZ R2, MUSIC4_1 INC DPTR LJMP MUSIC1_1 END0_1: NOP MOV R2, #64H ;歌曲结束,延时1秒后继续 MUSIC6_1: MOV R3, #00H LCALL DEL_1 DJNZ R2, MUSIC6_1 LJMP MUSIC0_1 DEL_1: NOP DEL3_1: MOV R4, #02H DEL4_1: NOP DJNZ R4, DEL4_1 NOP DJNZ R3, DEL3_1 RET NOP DAT_1: db 26h,10h,20h,10h,20h,10h,26h,08h,20h,08h,20h,40h,26h,10h,30h,10h db 30h,10h,39h,08h,30h,08h,30h,40h,26h,10h,20h,10h,20h,10h,1ch,10h db 20h,40h,2bh,10h,26h,10h,20h,10h,2bh,08h,26h,08h,2bh,40h,26h,10h db 30h,10h,30h,10h,39h,08h,26h,08h,26h,30h,40h,08h,39h,08h,26h,10h db 30h,10h,30h,10h,39h,08h,26h,08h,26h,40h,26h,10h,2bh,08h,2bh,08h db 2bh,10h,30h,08h,39h,08h,26h,08h,2bh,08h,2bh,10h,2bh,20h,40h,10h db 20h,08h,20h,08h,2bh,08h,26h,18h,30h,40h,18h,10h,18h,10h,26h,10h db 20h,10h,20h,20h,26h,10h,2bh,10h,30h,10h,30h,10h,1ch,10h,20h,10h db 20h,40h,1ch,10h,1ch,10h,1ch,10h,30h,10h,30h,30h,39h,08h,30h,08h db 20h,10h,2bh,08h,26h,08h,2bh,08h,26h,08h,26h,08h,2bh,08h,2bh,40h db 18h,10h,18h,10h,26h,10h,20h,10h,20h,30h,26h,08h,2bh,10h,30h,10h db 30h,10h,1ch,10h,20h,10h,20h,40h,26h,10h,30h,08h,30h,08h,30h,10h db 39h,10h,26h,08h,2bh,08h,2bh,10h,2bh,20h,40h,08h,40h,08h,20h,08h db 20h,08h,2bh,08h,26h,18h,30h,40h,00H end
真的可以啊!两个扬声器响起了两首音乐,而且都没跑调,真是捡到宝了。如此轻松的就实现了多线程,解决了我的烦 恼,把我高兴坏了,于是我赶紧把我的经验送上,供各位大大参考。好东西要大家分享嘛,也希望大家有更好的方法, 可以告诉我哦! QQ:16953411 |