单片机教程实战2 蜂鸣器唱歌Word格式文档下载.docx
《单片机教程实战2 蜂鸣器唱歌Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《单片机教程实战2 蜂鸣器唱歌Word格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
电子爱好者社区d_R
d_r\,x!
|
此外,结束符和体止符可以分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;
若查表结果为FFH,则产生相应的停顿效果。
_I&
O_?
_iK_g_c_k1N0 为了产生手弹的节奏感,在某些音符(例如两个相同音符)音插入一个时间单位的频率略有不同的音符。
3q2}/\(q7[_T7K9Z5R_l0 程序框图如图2所示。
电子爱好者社区_G0G_y{!
LV;
t_k_s
下面给出程序序请单,可直接在TD-III型学习机上演奏,对其它不同型号的学习机,只需相应地改变一下地址即可。
本程序演奏的是民歌“八月桂花遍地开”,C调,节奏为94拍/分。
读者也可以自行找出一首歌,按表1和表2给定的常数,将乐曲翻译成码表输入机器,而程序不变。
本实验方法简便,即使不懂音乐的人,将一首陌生的曲子翻译成代码也是易事,和着机器的演奏学唱一首歌曲,其趣味无穷。
A6n_?
_I_O#F!
W_x'
I
程序清单(略,请参看源程序的说明)。
电子爱好者社区#v_Q_T1Z1Q_Y_cl
《无线电》1992年第3期。
电子爱好者社区6K%SN_z_e_e
硬件连接说明:
电子爱好者社区1Qi_F%s'
or_k}
随便找一个仿真机或者什么单片机实验板,只要能工作的就行,将程序输入,运行,然后找个音箱(你计算机旁边应当就有一对吧)拨出插头,插头的前端接在P1。
0上,后面部分找根线接单片机的地,就应当有声了,然后怎么改进硬件连接就是你的事了。
。
你
单片机教程实战3键盘扫描识别
02
150次
键盘是由若干按键组成的开关矩阵,它是微型计算机最常用的输入设备,用户可以通过键盘向计算机输入指令、地址和数据。
一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。
b_e?
F_p-mS0 1、按键开关的抖动问题电子爱好者社区_jW_F*y_I
_u$s2y/x/Y#K+vu|_[#j_K6V0
电子爱好者社区$|_K_])k%x
图1电子爱好者社区(D_v~-V_f_\
电子爱好者社区_t_m%h_K_D
_PF+R-[_i0
图2
+r1]_\
i;
[_jq5g0
电子爱好者社区4a1`_xK,t_^
组成键盘的按键有触点式和非触点式两种,单片机中应用的一般是由机械触点构成的。
在下图中,当开关S未被按下时,P1。
0输入为高电平,S闭合后,P1。
0输入为低电平。
由于按键是机械触点,当机械触点断开、闭合时,会有抖动动,P1。
0输入端的波形如图2所示。
这种抖动对于人来说是感觉不到的,但对计算机来说,则是完全可以感应到的,因为计算机处理的速度是在微秒级,而机械抖动的时间至少是毫秒级,对计算机而言,这已是一个“漫长”的时间了。
前面我们讲到中断时曾有个问题,就是说按键有时灵,有时不灵,其实就是这个原因,你只按了一次按键,可是计算机却已执行了多次中断的过程,如果执行的次数正好是奇数次,那么结果正如你所料,如果执行的次数是偶数次,那就不对了。
电子爱好者社区3t_r2L!
@_?
.z_A
为使CPU能正确地读出P1口的状态,对每一次按键只作一次响应,就必须考虑如何去除抖动,常用的去抖动的方法有两种:
硬件方法和软件方法。
单片机中常用软件法,因此,对于硬件方法我们不介绍。
软件法其实很简单,就是在单片机获得P1。
0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P1。
0口,如果仍为低,说明S1的确按下了,这实际上是避开了按键按下时的抖动时间。
而在检测到按键释放后(P1。
0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。
不过一般情况下,我们通常不对按键释放的后沿进行处理,实践证明,也能满足一定的要求。
当然,实际应用中,对按键的要求也是千差万别,要根据不同的需要来编制处理程序,但以上是消除键抖动的原则。
电子爱好者社区0s_`:
~4{_H
2、键盘与单片机的连接电子爱好者社区(b"
X_j,w_o
.Z3j_t+M1Zn_a"
J
l0
_SD#J%P)z2^(wFV:
E0
图3电子爱好者社区2u
j_e0L%K,a
_^i0t,S:
O,T_h0
_HH6}*G9G_E"
x0电子爱好者社区X__'
lj#P0`_H
%P\"
`_h_u?
_Q1\_Z0
_I_]+@5Z_j'
`0
图4电子爱好者社区#e2D4u,s`*Y!
J_S_E%Z_W#^
6iH7sQ&
F_M-a0 1、通过1/0口连接。
将每个按键的一端接到单片机的I/O口,另一端接地,这是最简单的方法,如图3所示是实验板上按键的接法,四个按键分别接到P3.2、P3.3、P3.4和P3.5。
对于这种键各程序可以采用不断查询的方法,功能就是:
检测是否有键闭合,如有键闭合,则去除键抖动,判断键号并转入相应的键处理。
下面给出一个例程。
其功能很简单,四个键定义如下:
_l_vW7L_K_U_k*Y0P3.2:
开始,按此键则灯开始流动(由上而下)
-n_B6|/h}4t8f%A&
S0P3.3:
停止,按此键则停止流动,所有灯为暗电子爱好者社区@4T_Pa8YU_DZ
P3.4:
上,按此键则灯由上向下流动电子爱好者社区:
N.D:
{&
C
H_T9y'
n!
n8i4R:
G
P3.5:
下,按此键则灯由下向上流动
R$N)Sa+WA!
b0UpDownEQU00H;
上下行标志电子爱好者社区:
?
_uP7et
StartEndEQU01H;
起动及停止标志电子爱好者社区x_O_`_Z_Z_N6w3V
LAMPCODEEQU21H;
存放流动的数据代码电子爱好者社区%[(M_ef_@|bL
ORG0000H
_J{@
ki_g_H_q0AJMPMAIN
aV9V_T_S2r$U/]9K0ORG30H电子爱好者社区}_h5A7n_K;
_+F_R8F
MAIN:
_G_H_R5Y_d-P0MOVSP,#5FH电子爱好者社区_c(MM5h%t_R:
N6D
MOVP1,#0FFH
_w_Y'
a_h-],J0CLRUpDown;
启动时处于向上的状态电子爱好者社区B.}q_yE"
m
CLRStartEnd;
启动时处于停止状态电子爱好者社区_d_q_bC_BM
MOVLAMPCODE,#0FEH;
单灯流动的代码电子爱好者社区_t4]_w_r3m|_E(C_Z!
t
LOOP:
%d7Wr:
I]0ACALLKEY;
调用键盘程序电子爱好者社区
pm_o(m_g"
qA_R
JNBF0,LNEXT;
如果无键按下,则继续
TG_ZI_`_p_P_F_g0ACALLKEYPROC;
否则调用键盘处理程序电子爱好者社区_Q$\_g%t_S,Qz_f_M!
Ce3P
LNEXT:
'
v_mX"
a+__S/nr_S___}0ACALLLAMP;
调用灯显示程序电子爱好者社区_K.\r0h_D%g
AJMPLOOP;
反复循环,主程序到此结束
__:
S!
z_@:
^m,Q&
V$u5m0;
---------------------------------------
T_P)W(K|y_f_A
O0DELAY:
电子爱好者社区Q_O%f6a*m_E_pW
MOVR7,#100
_G_i_B!
t9y"
}+r0D1:
MOVR6,#100电子爱好者社区/kd+Z_~_G9J
DJNZR6,$电子爱好者社区___jQ
k_F8\_]_x
DJNZR7,D1电子爱好者社区_S_q%S)jT_j,u
RET电子爱好者社区7~[$E&
Q5s_e%b_E_w
;
----------------------------------------延时程序,键盘处理中调用
_q_?
_i_pj0KEYPROC:
_k3O_\^_?
0MOVA,B;
从B寄存器中获取键值
*E3~-F_z
|#j0JBACC.2,KeyStart;
分析键的代码,某位被按下,则该位为1(因为在键盘程序中已取反)电子爱好者社区_Q_h/yn-K
JBACC.3,KeyOver电子爱好者社区Ku0d_G_U_L_X_Y
JBACC.4,KeyUp电子爱好者社区_r_K/c_v_]*Z;
d:
]_P
JBACC.5,KeyDown
_M_G_M+c(s/F7H0AJMPKEY_RET电子爱好者社区A_q3z_k_?
_l_I_{
KeyStart:
_t_Y#I_~__0SETBStartEnd;
第一个键按下后的处理
#D7R_p3A_[0AJMPKEY_RET电子爱好者社区+g_o:
y'
w1|_E9z)v!
h
KeyOver:
电子爱好者社区_x_^6M&
~_}_O)s#X-X
第二个键按下后的处理电子爱好者社区!
_(w:
{_ZdA4pu4W1j_A
AJMPKEY_RET
_q2c_~_ro0KeyUp:
SETBUpDown;
第三个键按下后的处理电子爱好者社区'
i:
Fw_y_A3s)@
_R)AG;
e9r-[^0KeyDown:
电子爱好者社区%_1]4U_E_n[__
CLRUpDown;
第四个键按下后的处理
)k'
BL.E;
Cz(s1F4LB0KEY_RET:
RET
_f_U_Q/B_By_U5U/~"
F0KEY:
电子爱好者社区_?
_y_N_y_n9R_T
CLRF0;
清F0,表示无键按下。
K4F:
K$N_F6X)l0ORLP3,#00111100B;
将P3口的接有键的四位置1
_s&
Or0k_]Y0MOVA,P3;
取P3的值电子爱好者社区_H_w*y_|6D*y_u8q&
b/s_x
ORLA,#11000011B;
将其余4位置1电子爱好者社区_J1b1}_e_[pk
CPLA;
取反电子爱好者社区,Wn|_c_]_k_l
JZK_RET;
如果为0则一定无键按下
_g*a*J\+@0ACALLDELAY;
否则延时去键抖电子爱好者社区6li2m%Az_?
_p_{
ORLP3,#00111100B电子爱好者社区_O_|_`+N_c_S
MOVA,P3电子爱好者社区_j_Q!
n_aa
Xw~
ORLA,#11000011B
q5?
2m*__?
#G0CPLA电子爱好者社区_f_G9K#f_z_Z@
JZK_RET电子爱好者社区2~8~5y$mV5i_`_s/v.t
MOVB,A;
确实有键按下,将键值存入B中
.P
F-UB/h_m0SETBF0;
设置有键按下的标志
&
sT_wO-g_]_xB_a"
`0K_RET:
电子爱好者社区(c4U(o__s6s
ORLP3,#00111100B;
此处循环等待键的释放电子爱好者社区-]:
o_JJ'
vD-B_g0F_j
MOVA,P3电子爱好者社区_y._~&
D_G_E
ORLA,#11000011B电子爱好者社区'
O4Q_G_H_]g
CPLA
Q:
l5b)L;
QsZ'
j0JZK_RET1;
直到读取的数据取反后为0说明键释放了,才从键盘处理程序中返回电子爱好者社区&
Ak'
J_e}_N$d
AJMPK_RET
_tr/C_x_hq|0K_RET1:
电子爱好者社区6v3W_?
D_L_Z5}
SB2M_u_F_x/`0;
-----------------------------------电子爱好者社区_n1~:
M+Cw_B
D500MS:
;
流水灯的延迟时间
Q_l_|_E9|"
N_g0PUSHPSW电子爱好者社区.H_Q_X_V_c+fYM
SETBRS0电子爱好者社区*O_O5]E_Q_aI_T_m&
s
MOVR7,#200电子爱好者社区_B_s_S/K#S*L_ht
D51:
MOVR6,#250
_E_\_nT_E
z.a%Tg_r0D52:
NOP电子爱好者社区C_d$^K_[,u5}_b
NOP电子爱好者社区!
l_J2J0P!
a5^_jG
NOP电子爱好者社区.W_I1x:
\2B%D'
NOP
_f_v
k!
A_t%^*n0DJNZR6,D52
_S;
_%x_x'
S
g8uI0DJNZR7,D51电子爱好者社区_a(k_J#o'
s___y_O
POPPSW电子爱好者社区0a%e_m5D'
n-u)U
RET电子爱好者社区_s9G&
F)I_~_Ld,PY_
-----------------------------------电子爱好者社区/C}0i_H_Q2o_q)c#f
LAMP:
/A/~_c8]_q4`-^-`)S_O0JBStartEnd,LampStart;
如果StartEnd=1,则启动
4`_A,K5x~_SX;
G1r0MOVP1,#0FFH
0oh_T8q_fv0AJMPLAMPRET;
否则关闭所有显示,返回
p_czs/^;
zi_d"
U9bQ0LampStart:
*[J!
d]x2_:
DQ0JBUpDown,LAMPUP;
如果UpDown=1,则向上流动电子爱好者社区_u!
C_@_u_z#`
MOVA,LAMPCODE电子爱好者社区t&
Fckj3c-@
RLA;
实际就是左移位而已
_Fd_x_F1l_A0MOVLAMPCODE,A电子爱好者社区_W$W3W([&
[_el~_M
MOVP1,A电子爱好者社区_F9J!
m__m&
{
A/t_UF
LCALLD500MS
6Q4H5I_D.D_S0AJMPLAMPRET电子爱好者社区_o_Pd_k_t?
_z;
H
LAMPUP:
电子爱好者社区_E9J'
k7d*R'
]_\"
]&
MOVA,LAMPCODE电子爱好者社区_M$[:
E9F_~
RRA;
向下流动实际就是右移电子爱好者社区4l/|2C'
hC3r
MOVLAMPCODE,A电子爱好者社区_*V_Zt_n,v_p
MOVP1,A
_HX_I_|7O9P_`0LCALLD500MS
0w7K__&
oo
F_u0LAMPRET:
g-l_N_`#vxS0RET电子爱好者社区+`2F%X6D)N1J
END
_t/O9f_A1Ic#L_C0T_t0 以上程序功能很简单,但它演示了一个键盘处理程序的基本思路,程序本身很简单,也不很实用,实际工作中还会有好多要考虑的因素,比如主循环每次都调用灯的循环程序,会造成按键反应“迟钝”,而如果一直按着键不放,则灯不会再流动,一直要到松开手为止,等等,大家可以仔细考虑一下这些问题,再想想有什么好的解决办法。
1J,m2K_w_nQ"
u8U_h0 2、采用中断方式:
如图4所示。
各个按键都接到一个与非上,当有任何一个按键按下时,都会使与门输出为低电平,从而引起单片机的中断,它的好处是不用在主程序中不断地循环查询,如果有键按下,单片机再去做相应的处理
单片机音乐程序设计
作者:
佚名文章来源:
点击数:
3744更新时间:
2009/4/115:
25:
50
热
★★★
单片机的基本发音实验我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单处机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的矩形波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。
例如,要产生200HZ的音频信号,按图1接入喇叭(若属临时实验,也可将喇叭直接接在P1口线上),实验程序为:
其中子程序DEL为延时子程序,当R3为1时,延时时间约为20us,R3中存放延时常数,对200HZ音频,其周期为1/200秒,即5ms。
将上述程序键入学习机,并持续修改R3的常数能感到音调的变化。
乐曲中,每一音符对应着确定的频率,表1给出C调时各音符频率及其对应的时间常数。
读者能根据表1所供给的常数,将其16进制代码送入R3,反复练习体会。
根据表1能奏出音符。
音符的节拍我们能用定时器T0来控制,送入不一样的初值,就能产生不一样的定时时间。
但时,由于T0的最大定时时间只能为131毫秒,因此不可能直接用改变T0的时间初值来实现不一样节拍。
我们能用T0来产生10毫秒的时间基准,然后设置一个中断计数器,通过判别中断计数器的值来控制节拍时间的长短。
例如对1/4拍音符,定时时间为0.16秒,对应的时间常数为16(即10H);
对3拍音符,定时时间为1.92秒,对应时间长数为192(即C0H)。
我们将每一音符的时间常数和其对应的节拍常数作为一组,按次序将乐曲中的所有常数排列成一个表,然后由查表程序依次取出,产生音符并控制节奏,就能实现演奏效果。
此外,结束符和体止符能分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;
若查表结果为FFH,则产生对应的停顿效果。
为了产生手弹的节奏感,在某些音符(例如两个相同音符)音插入一个时间单位的频率略有不一样的音符。
下面给出程序序清单,可直接在TD-III型学习机上演奏,对其它不一样型号的学习机,只需对应地改变一下地址即可。
读者也能自行找出一首歌,按表1和表2给定的常数,将乐曲翻译成码表输入机器,而程序不变。
本实验办法简便,即使不懂音乐的人,将一首陌生的曲子翻译成代码也是易事,和着机器的演奏学唱一首歌曲,其趣味无穷。
程序清单(略,请参看源程序的说明)。
程序框图如图2所示。
<
单片机音乐程序的设计图>
单片机教程网
硬件连接说明:
随便找一个仿真机或者什么单片机实验板,只要能工作的就行,将程序输入,运行,然后找个音箱(你计算机旁边应当就有一对吧)拨出插头,插头的前端接在P1。
音乐程序汇编代码代码1-------------Voice.asm--------------------------
LJMPSTART
ORG000BH
INC20H;
中断服务,中断计数器加1
MOVTH0,#0D8H
MOVTL0,#0EFH;
12M晶振,形成10毫秒中断
RETI
START:
MOVSP,#50H
MOVTL0,#0EFH
MOVTMOD,#01H
MOVIE,#82H
MUSIC0:
MOVDPTR,#DAT;
表头地址送DPTR
MOV20H,#00H;
中断计数器清0
MOVB,#00H;
表序号清0
MUSIC1:
CLRA
MOVCA,@A+DPTR;
查表取代码
JZEND0;
是00H,则结束
CJNEA,#0FFH,MUSIC5
LJMPMUSIC3
MUSIC5:
MOVR6,A
INCDPTR
MOVA,B
取节拍代码送R7
MOVR7,A
SETBTR0;
启动计数
MUSIC2:
CPLP1.0
MOVA,R6
MOVR3,A
LCALLDEL
MOVA,R7
CJNEA,20H,MUSIC2;
中断计数器(20H)=R7否?
不等,则继续循环
等于,则取下一代码
INCB
LJMPMUSIC1
MUSIC3:
CLRTR0;
休止100毫秒
MOVR2,#0DH
MUSIC4:
MOVR3,#0FFH
LCA