初学单片机,基于51单片机的电子琴程序结构
前面我们用了快一周的时间不断更新制作过程,实物终于打造完成了,到了最后阶段——给单片机编写程序。
这里采用c语言编写单片机程序。在编程之前先来分析一下程序的组成部分:
单片机电子琴设计——程序结构简化图
程序结构:用一张图片来介绍程序的详细结构:
单片机电子琴设计——程序结构图
单片机头文件:由于STC15系列单片机相对于传统51单片机多了很多寄存器和功能,因此最好获取一个头文件,然后在主程序main.c里声明一下,就可以了。在官方软件STC-ISP里面找到“头文件”选项,选择正确的系列,点击“保存文件”,保存到主程序文件所在文件夹里。
从官方工具软件里获取单片机头文件截图
定时器初装值对应频率表格:
开始制作了一个表格,后来针对1T单片机重新制定了一个。这里要说明的是:该系列单片机的定时器时钟既可以设置为1T,也可以设置为12T,前面的担心是多余的。
下面是新制作的“定时器时钟1T模式”表格图片,频率做了删减,保留了12个常用音的频率:
单片机电子琴设计——定时器初装值对应频率表截图
初始化函数:
初始化I/O端口。
信号输出端口P2.6设置为强推挽输出;
按键检测端口设置(开机默认)为准双向(弱上拉)。
初始化定时器0。
初始化不用赋值,不开计数,等到按键按下去再打开计数,定时器中断就会不断取反信号输出端口,产生相应频率的音频信号。
定时器0中断函数:
在中断里面只做一件事情,就是对信号输出端口取反,形成方波信号。
按键检测函数:
需要注意的问题:
不使用“等待按键释放”的函数语句。因为按键按下的时候应该发出声音,如果等待按键释放会产生延时,影响效果。按键松开则关闭定时器计数,音频停止。
同时按下两个或者多个按键的处理方法?这一点应该可以解决,此处暂未修改,当多个按键按下时,应该检测到无效键值,不产生声音。
关于按键检测的详细思路内容较多,本处暂且略过,以后再细聊。
主函数:
需要注意的问题:因“按键检测函数”不使用“等待按键释放”的函数语句,所以按键检测是连续循环的,但是不能不断的给定时器赋值,所以需要定义一个变量来记录按键值,当检测到相同的按键时不需要重复赋值给定时器。
以上是程序设计的结构和需要注意的问题。按照上面结构图中的框架,用kile软件新建一个工程,编写c语言程序,然后编译完生成烧写代码hex文件。
单片机下载hex文件:
用STC-ISP软件,通过串口小板把hex文件下载到单片机里面,单片机就可以工作了。当然一般需要反复修改程序,反复下载代码,直到单片机正常工作为止。
下载单片机代码截图
下载代码时,在新版软件里面,硬件选项里除了频率需要设置为12.000(MHz)以外,其它不用设置,用默认值就可以。
结合本周前面的多篇文章,制作一款基于51单片机的简易电子琴应该很简单了。由于头条没有提供下载附件功能,因此无法上传单片机烧写代码文件,当然办法是有的。
今天就聊到这里,如果您感兴趣,可以关注:头条号/春天说,后续文章会提供单片机代码文件,以及下载方法。欢迎在评论区交流,如果喜欢,也可以分享给更多朋友。
电子琴单片机编程相关知识
音频脉冲的产生:音乐的产生主要是通过单片机的I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半个周期时间,每当计时到后就将输出脉冲的I/O口反相,然后重复计时此半周期时间再对I/O口反相,这样就能在此I/O口上得到此频率的脉冲。
通常,利用单片机的内部定时器0,工作在方式1下,改变计数初始值THO和TLO来产生不同的率。
例如,若单片机采用12MHz晶振,要产生频率为587Hz的音频脉冲时,其音频信号的脉冲周期 T=1/587=1703.5775μs,半周期的时间为852μs,因此只要令计数器计数=852μs/1μs=852,在每计数852时将I/O口反相,就可得到C调中音Re。
计数脉冲值与频率的关系如下:
符
频率Hz
周期us
简谱码(定时初值)
音符
频率Hz
周期
us
简谱码(定时初值)
低1Do
262
3816
63628
高1Do
1047
955
65058
低2Re
294
3401
63835
高2Re
1175
851
65110
低3Mi
330
3030
64021
高3Mi
1319
758
65157
低4Fa
349
2865
64103
高4Fa
1397
751
65160
低5So
392
2551
64260
高5So
1568
637
65217
低6La
440
2272
64400
高6La
1760
568
65252
低7Si
494
2024
64524
高7Si
1967
508
65282
中1Do
523
1912
64580
中2Re
587
1703
64684
中3Mi
659
1517
64777
中4Fa
698
1432
64820
中5So
784
1275
64898
中6La
880
1136
64968
中7Si
988
1012
65030
音符的节拍我们可以举例来说明。在一张乐谱中,我们经常会看到这样的表达式,如1=C 、1=G…… 等等,这里1=C,1=G表示乐谱的曲调,和我们前面所谈的音调有很大的关联,、就是用来表示节拍的。以为例加以说明,它表示乐谱中以四分音符为节拍,每一小结有三拍。比如:
其中1 、2 为一拍,3、4、5为一拍,6为一拍共三拍。1 、2的时长为四分音符的一半,即为八分音符长,3、4的时长为八分音符的一半,即为十六分音符长,5的时长为四分音符的一半,即为八分音符长,6的时长为四分音符长。那么一拍到底该唱多长呢?一般说来,如果乐曲没有特殊说明,一拍的时长大约为400—500ms 。我们以一拍的时长为400ms为例,则当以四分音符为节拍时,四分音符的时长就为400ms,八分音符的时长就为200ms,十六分音符的时长就为100ms。
可见,在单片机上控制一个音符唱多长可采用循环延时的方法来实现。首先,我们确定一个基本时长的延时程序,比如说以十六分音符的时长为基本延时时间,那么,对于一个音符,如果它为十六分音符,则只需调用一次延时程序,如果它为八分音符,则只需调用二次延时程序,如果它为四分音符,则只需调用四次延时程序,依次类推。
相关问答
关于max485与 单片机 连接的问题?[回答]传统的单片机实验系统因其购买成本高、系统使用烦琐,已经越来越不适合当前以培养学生实际能力为主要方向的高等教育,本系统可以帮助学校轻松组建单...