网上有很多使用51单片及制作电子琴的示例,基本的方案是使用微动按键作为琴键,蜂鸣器作为发声单元,按下不同好的按键产生不同频率的PWM,驱动蜂鸣器发出不同频率的声音。
普通按键及蜂鸣器
普通按键的手感和蜂鸣器的音质都不是很理想,本篇文章给大家推荐一个不同的方案来实现简单的电子琴。采用如下图所示的鼠标按键作为琴键,2308扬声器代替蜂鸣器。
鼠标按键及2308扬声器
电子琴的外观设计参考了非洲的民族乐器卡琳巴琴,使用上图所示鼠标按键代替卡琳巴琴的金属琴键。
卡琳巴琴
硬件设计
该作品使用的核心元器件是STC15W204S型号51单片机,适合学习了C语言和单片机,并且有一定PCB设计能力的同学制作(使用其他型号的单片机也可以)。原理图如下图所示:
原理图
布线参考
渲染图
所有设计均在立创广场开源,开源地址:https://oshwhub.com/Dr.Zhang/kalinba
从上图可以看出,该设计采用MicroUSB接口进行供电和调试,板载一个CH340 USB转串口芯片用于烧录程序,当然如果自己有串口烧录器的话可以省去这个元器件。整个乐器一共有13个按键,可以发出13个音,发声原理是通过单片机产生不同频率的PWM波驱动扬声器发出不同频率的声音(注意我们这里使用的是扬声器不是蜂鸣器,蜂鸣器声音很差)。13个按键分别连接在13个IO口上,当程序检测到有按键按下时,根据按下按键的不同,配置PWM相关的寄存器,在扬声器引脚上产生对应的波形。没有按键按下时无波形输出。
软件设计
软件采用Keil开发,核心代码如下:
#include "stc15.h" #define MAIN_Fosc 24000000 //时钟频率24M typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; sbit P_PWM = P1^4; //PWM引脚 u16 PWM_high; void Pin_Init() { P1 = P3 = P5 = 0xff; P_PWM = 0; P1M1 &= ~(1 << 4); P1M0 |= (1 << 4); } u16 cur_tune = 0; //用来记录当前频率 void PWM_SetTune(u16 tune) { cur_tune = tune; if(tune == 0) { TR0 = 0; PT0 = 0; TMOD = 00; TMOD = 0; INT_CLKO = 0; P1M0 = 0; P_PWM = 0; } else { EA = 0; PT0 = 1; P1M0 |= (1 << 4); TR0 = 0; PT0 = 1; TMOD &= ~0x03; TMOD &= ~0x04; INT_CLKO |= 0x01; PWM_high =65535UL - 1000000UL/tune; TH0 = (u8)(PWM_high >> 8); TL0 = (u8)PWM_high; TR0 = 1; } } char last_value[13]= {1,1,1,1,1,1,1,1,1,1,1,1,1}; //记录13个按键上次的按键值 char now_value[13] = {1,1,1,1,1,1,1,1,1,1,1,1,1}; //记录13个按键当前的按键值 //每个按键对应的频率,采用的是五声音接 u16 tune[13] = {262, 294, 330,392,440,523, 587, 660,784,880, 1046,1174,1318}; void main() { int i = 0; Pin_Init(); PWM_SetTune(0); while (1) { now_value[0] = P10; now_value[1] = P37; now_value[2] = P11; now_value[3] = P36; now_value[4] = P12; now_value[5] = P33; now_value[6] = P13; now_value[7] = P32; now_value[8] = P15; now_value[9] = P31; now_value[10] = P54; now_value[11] = P30; now_value[12] = P55; for(i=0; i<13; i++) { if(last_value[i] != now_value[i]) // { if(now_value[i] == 0) { PWM_SetTune(tune[i]); } else if (cur_tune == tune[i]) { PWM_SetTune(0); } last_value[i] = now_value[i]; } } if( (last_value[0] == 1) && (last_value[1] == 1) && (last_value[2] == 1) && (last_value[3] == 1) && (last_value[4] == 1) && (last_value[5] == 1) && (last_value[6] == 1) && (last_value[7] == 1) && (last_value[8] == 1) && (last_value[9] == 1) && (last_value[10] == 1) && (last_value[11] == 1) && (last_value[12] == 1)) { PWM_SetTune(0); } } }
使用Keil创建一个空白的51工程,将上述代码复制到main.c,编译下载就可以了。
这个作品我也曾将其用在课堂上,作为学生的电子实训项目,下图是之前在课堂上制作的电路板,与本文中的描述有些许差异,各位读者如要制作请以本文资料为准。
旧版本卡琳巴琴
制作过程及视频演示如下:https://www.bilibili.com/video/BV135411w73B?p=3
备注:视频里面演示的是旧版本,后面做了些许修正,设计资料以本文章为准。
附元器件列表:
名称 | 型号 | 封装 | 数量 | 备注 |
USB接口 | MicroUSB | 贴片 | 1 | |
串口芯片 | CH340N | SOP-8 | 1 | 可选 |
电容 | 0.1uF(104) | 0805 | 2 | |
二极管 | 1N4148 | 直插 | 2 | |
开关 | MSS22D18G2 | 直插 | 1 | |
单片机 | STC15W204 | SOP-16 | 1 | 可替换为直插封装 |
扬声器 | 2308 | 直插 | 1 | |
鼠标按键 | * | 直插 | 13 | 三脚带弯柄 |