🚀write in front🚀
🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝💬本系列哔哩哔哩江科大51单片机的视频为主以及自己的总结梳理📚
前言:
本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记,在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了江协科技51单片机教学视频和链接中的内容。
引用:
51单片机入门教程-2020版 程序全程纯手打 从零开始入门_哔哩哔哩_bilibili
c51语言变量语句意思,C51中循环语句-CSDN博客
音乐简谱乐理:
【51单片机实验笔记】声学篇(一) 蜂鸣器与扬声器的基本控制_交流蜂鸣器需要给蜂鸣器一个脉冲才会响。我们用单片机的p1.5口实现一种这样高低电-CSDN博客
正文:
0. 🌿概述
在淘宝上购买了江协科技51单片机开发板套件(普中科技STC51单片机A2型号),就上在上一篇博文里说的自己计划学习下江协科技51单片机开发教程,通过STC51单片机这种MCU这种贴近于裸机的开发来增加对于系统硬件层面知识的了解和掌握。
术语和缩略语:
缩写 | 全称 | 说明 |
RTC | Real Time Clock | 实时时钟 |
1. 🚀蜂鸣器介绍
蜂鸣器分为有源蜂鸣器和无源蜂鸣器
🧃有源蜂鸣器:自带震荡电路,只要给蜂鸣器同上电,蜂鸣器就会按照固定的频率发出鸣叫声音。
🧃无源蜂鸣器:没有震荡电路,需要外部输入震荡信号才能发出输入信号频率的声音,如果一直输入信号则就在刚通电的时候线圈到达顶位置然后保持在顶部位置不能发出声音。
主要区别就是有源蜂鸣器自带震荡电路只要输入高电平或者低电平有源蜂鸣器就会按照固定的频率鸣叫,而无源蜂鸣器需要外部输入震荡信号才会发出和输入震荡信号相同的频率,如果无源蜂鸣器输入直流信号无源蜂鸣器的线圈就一直卡在顶部位置不能发出声音。
一般开发板上带的都是有源蜂鸣器,有源蜂鸣器只能发出固定频率的声音。无源蜂鸣器的频率和外部输入信号的频率相同,无源蜂鸣器才能作为演奏音乐的器件,因为无源蜂鸣器发出的声音的频率可以通过输入信号的频率调整。
蜂鸣器驱动电路:
单片机IO引脚输出高电平或者输入低电平时驱动能力有限,单片机IO引脚可以通过的电流有限,通过单片机IO引脚直接驱动蜂鸣器因为单片机IO引脚能够通过电流比较小将无法驱动蜂鸣器发出声音。所以需要将单片机的IO引脚输出作为控制信号来控制驱动电路的开关来控制蜂鸣器的电路通断,一般使用 三极管 作为驱动电路。
本实验中因为开发板上又一个 ULN2003 驱动芯片的引脚没有使用,所以本开发板使用了 LN2003的一个引脚作为了驱动蜂鸣器的驱动电路。
一般不会使用 ULN2003 驱动芯片单独作为驱动蜂鸣器的驱动芯片,因为成本比较高,比使用三极管高,本开发板是使用了 ULN2003 驱动芯片 步进电机驱动芯片的一个剩余IO口,刚好利用起来作为蜂鸣器的驱动IO口。
UL2003 是达林顿两级晶体管阵列电路,通过电流能力较强,单个引脚输出可以达到 500mA电流,
🧃 当ULN2003 1B引脚输入为1时,1C输出为0,
🧃 当 ULN2003 1B引脚输入为0时,1C输出为高阻态
2. 乐谱乐理介绍
乐谱的乐理介绍,以钢琴的按键区为例介绍钢琴安检区的不同按键的对应的音符频率。
- 🧃大字组
- 🧃小字组
- 🧃小字1组
- 🧃小字2组
从左往右是: 大字组、小字组、小字1组、小字2组
按照一组音调依次分成4组:大字组、小字组、小字1组、小字2组。组与组之间相差“8度”;相邻的两个键之间(包括白键与黑键)相差半音; 数字简谱左上标“#”表示升高半音,“b”表示降低半音,升降号在本小节有效。 下图8-6给出了“小字组、小字1组、小字2组”音符与频率的对应关系。也就是说,每一个音符都对应了一个特定的频率。
- 🧃数字简谱左上标“#”表示升高半音,“b”表示降低半音,升降号在本小节有效
而为了按照正常的节奏演奏出整首音乐,还需要调整每个音符所占用的时间。下图8-7给出了不同的音符的时值比,可以看出在音符的右侧和下面加横线可以实现2的幂次的调整,而在右侧加点则表示乘以1.5倍。 一般设置四分音符的持续时间为500ms。
于是根据下面两张图,整体思路如下:钢琴五线谱→数字简谱→蜂鸣器频率。 通过不断改变定时器的复位值,进而控制蜂鸣器的频率变化。
其中,以中央A键a1为基准,其标准频率为440Hz,根据十二平均律,各音阶之间以等比数列分配频率,每12个音阶频率扩大一倍。
简谱的音符是相对音高,它与绝对音高存在映射关系,一共有12个大调音阶:C大调、bD大调、D大调、 bE大调、E大调、F大调、bG大调、 G大调、bA大调、 A大调、bB大调、 B大调。
全音符,2分音符,4分音符,
常用变音记号
- 降记号(b)表示将基本音级的音高降低半音,根据该记号所在的线或间而降音。
- 还原记号(#)表示把已经升高或降低的音还原。
- 升记号(#)表示将基本音级的音高升高半音,根据该记号所在的线或间而降音。
使用Excel计算处乐谱简谱的不同音符对应的频率:
以中央C作为基准频率 440Hz,每往右12个音符升高1倍变为880Hz。
往右每个音符频率 = 440 * 2^(1/12 *n)
使用Excel表格计算出音符的频率,周期时长(微秒),周期时长的一半,定时器装载值。
C调
3. 单片机演奏音乐实验
小星星简谱
天空之城简谱
实现音乐简谱《小星星》演奏的代码如下:
main.c
#include <REGX52.H>
#include <INTRINS.H>
#include "Delay.h"
#include "Nixie.h"
#include "Key.h"
#include "Beep.h"
#include "Timer0.h"
sbit Beeper = P2^5;
unsigned char KeyNum = 0;
unsigned char FreqSelect = 0;
unsigned int code FreqTabble[] = {
63776, 63877, 63967, 64058, 64139, 64218, 64293, 64362, 64427, 64490, 64548, 64604,
64656, 64705, 64751, 64795, 64836, 64875, 64913, 64948, 64981, 65012, 65041, 65069,
65095, 65119, 65143, 65165, 65186, 65205, 65223, 65241, 65258, 65273, 65288, 65302,
0
};
//C调
//低音组
#define L1 0
#define L1_ 1
#define L2 2
#define L2_ 3
#define L3 4
#define L4 5
#define L4_ 6
#define L5 7
#define L5_ 8
#define L6 9
#define L6_ 10
#define L7 11
中音组
#define M1 12
#define M1_ 13
#define M2 14
#define M2_ 15
#define M3 16
#define M4 17
#define M4_ 18
#define M5 19
#define M5_ 20
#define M6 21
#define M6_ 22
#define M7 23
//高音组
#define H1 24
#define H1_ 25
#define H2 26
#define H2_ 27
#define H3 28
#define H4 29
#define H4_ 30
#define H5 31
#define H5_ 32
#define H6 33
#define H6_ 34
#define H7 35
#define PERID 125
unsigned char code Music[] = {
//第1小节,4拍
M1, 4,
M1, 4,
M5, 4,
M5, 4,
//第2小节,4拍
M6, 4,
M6, 4,
M5, 4+4,
//M5,
//第3小节,4拍
M4, 4,
M4, 4,
M3, 4,
M3, 4,
//第4小节,4拍
M2, 4,
M2, 4,
M1, 4+4,
//M1,
//第5小节,4拍
M5, 4,
M5, 4,
M4, 4,
M4, 4,
//第6小节,4拍
M3, 4,
M3, 4,
M2, 4+4,
//M2,
//第7小节,4拍
M5, 4,
M5, 4,
M4, 4,
M4, 4,
//第8小节,4拍
M3, 4,
M3, 4,
M2, 4+4,
//第9小节,4拍
M1, 4,
M1, 4,
M5, 4,
M5, 4,
//第10小节,4拍
M6, 4,
M6, 4,
M5, 4+4,
//第11小节,4拍
M6, 4,
M6, 4,
M3, 4,
M3, 4,
M2, 4,
M2, 4,
M1, 4+4,
//结束
0
};
void main()
{
P0 = 0x0;
Beeper = 0;
Timer0_Init();
while(1)
{
if(Music[FreqSelect]){
TR0 = 1;
Delay(PERID*Music[FreqSelect+1]);
FreqSelect++;
TR0 = 0;
Delay(2);
FreqSelect++;
}
else if(Music[FreqSelect] == 0){
while(1);
}
}
}
/**
* @brief 定时器0中断处理函数模版
* @param 无
* @retval 无
*/
void Timer_Routine(void) interrupt 1
{
Beeper = !Beeper;
//定时器溢出之后需要重新装载
TH0 = FreqTabble[Music[FreqSelect]] / 256; //12MHz晶振,12分频
TL0 = FreqTabble[Music[FreqSelect]] % 256; //
}
Timer0.c
#include <REGX52.H>
#include "timer0.h"
/**
* @brief 定时器0初始化函数, 1ms 12MHz
* @param 无
* @retval 无
*/
void Timer0_Init()
{
//AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//中断部分寄存器
ET0 = 1; //允许定时器T0中断
EA = 1; //允许中断
PT0 = 0; //定时器T0中断优先级
}
/**
* @brief 定时器0中断处理函数模版
* @param 无
* @retval 无
*/
//void Timer_Routine(void) interrupt 1
//{
// static unsigned int count = 0;
//
// count++;
// //P2_0 = 0;
// if(count >= 500) //定时器T0每1ms中断一次,进入1000次经过了1s
// {
// P2_0 = ~P2_0;
// count = 0;
// }
//
// //定时器溢出之后需要重新装载
// TH0 = (65535 - 1000) / 256; //12MHz晶振,12分频
// TL0 = (65535 - 1000) % 256 + 1; //
//}
Delay.c
#include <INTRINS.H>
#include "delay.h"
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
_nop_();
if(xms == 0)
return;
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
4. 音乐简谱《小星星》通过蜂鸣器演奏
控制蜂鸣器按照音乐简谱,通过在指定的节拍里让无源蜂鸣器发出指定频率的声音发发出了《小星星》的音乐声,控制蜂鸣器声音频率是通过C51单片机的定时器/计时器Timer0来控制的,通过在定时器中断处理函数中控制定时器装载值来控制定时器中断进入的频率,在定时中断里翻蜂鸣器从而控制了蜂鸣器发出声音的频率。