当前位置:首页 > 单片机音频发生器程序设计
实验三 单片机音频发生器程序设计
实验目的
1、进一步掌握单片机定时器的用法。
2、了解用单片机的IO口输出方波的方法。 3、理解用单片机产生简单音频的方法。
实验仪器
单片机开发板、万利仿真机、稳压电源、计算机
实验原理
1、 单片机IO口产生音频脉冲的原理 我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机某个口线的“高”电平或“低”电平,则在该口线上就能产生一定频率的方波,接上喇叭就能发出一定频率的声音,若通过程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。喇叭驱动电路如图4-13所示。
图4-13 喇叭驱动电路
例如,要产生中音1。从下表可知,中音1的频率为523Hz,周期T=1/523=1912μs,其半周期为1912/2=956μs,因此只要在SPEAKER接口上产生半周期为956μs的方波,即可听到持续的1音。C调部分音符频率与计数初值的对应表如下:
表4-1 C调部分音符频率、计数初值与设置简谱码的对应关系
音符 频率Hz 初值T 简谱码 音符 频率Hz 初值T 简谱码 6 ?7 ?1 523 64580 4 2 578 64684 5 3 659 64777 6 4 698 64820 7 5 784 64898 8 440 64400 2 494 64524 3 6 880 64968 9 7 988 65030 A 1 1046 65058 B ?2 1175 65110 C ?3 1318 65157 D ?4 1397 65178 E ?5 1568 65217 F ?注:上表定时器工作于模式1
2、 音乐节拍的生成
要唱出一首歌,只产生出音频脉冲还不够,还要考虑发出音频时间的长短(即节拍)。
如果一拍为0.4秒,则1/4拍是0.1秒,只要设定延迟时间就可获得节拍的时间。我们也可以设1/8拍为1个延迟单位时间,则1拍应该是8个延迟单位时间,以此类推,所以,只要求得1/8拍的DELAY时间,其余的节拍就是它的倍数。详见下表
表4-2 节拍与节拍码对照表
节拍数 延迟数 时间 1/8拍 1 0.05秒 1/4拍 2 0.1秒 2/4拍 4 0.2秒 2拍 16 0.8秒 3/4拍 6 0.3秒 2又1/2拍 20 1秒 1拍 8 0.4秒 3拍 24 1.2秒 节拍数 1又1/4拍 1又1/2拍 延迟数 时间 10 0.5秒 14 0.6秒 3、 简谱发生器程序设计 由前面的分析可知,音符频率有14种,节拍有10种,我们定义每个音节占用一个字节,字节的低4位代表音符的频率,高4位表示该音符的节拍。定义一个音符频率表、一个音符节拍表。程序首先读取一个音节,并从音符频率表和节拍表中读取音符频率所对应的定时器初始和节拍对应的延时参数。利用单片机内部定时器0、1分别产生频率和节拍。定时器0的初始值由音符的频率决定,定时器1的初始值是50ms对应的值。每当一个音符输出完成就取出下一个音符,直到取出的是0FFH。代表所有音符全部输出完成。程序停止或重新开始。程序流程图如图4-14所示。
T1节拍 T0频率 主程序 保护现场 重写初始值 初始化(定时器0高优 节拍完成? 先级,定时器1低优先 N Y 输出取反 级) ,音节定位指针, 显示缓冲区 取下一个音节 返回 是否结束? Y N 取出第一个音节,根据 音节取得定时器0,1取得频率参数,节 的参数,启动定时器 拍参数,并写入 调用显示程序 恢复现场 返回 图4-14 音频发生器程序流程图 实验内容
1、在单片机P1.2口产生下列频率方波
1KHz,2KHz,5KHz,10KHz,学号后两位*100
2、在P1.2口产生简谱对应频率方波(简谱频率如上文) 3、在P1.2口播放简谱音乐。
程序一:
#include \
#define uchar unsigned char #define uint unsigned int sbit beef=P1^2;
uint code table[]={65036,65286,65436,65486,65258}; // 1KHz,2KHz,5KHz,10KHz,1.8KH uint i; 的初值 void init() { TMOD=0x01; EA=1; ET0=1; }
void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }
void main() { init(); beef=1; while(1) { TH0=table[i]/256; TL0=table[i]%6; TR0=1; delay(1000); TR0=0; beef=1; i++; if(i==5) i=0; } }
void time0() interrupt 1 { TH0=table[i]/256;
TL0=table[i]%6; beef=~beef; }
程序二:
include
typedef unsigned int uint16; typedef unsigned char uint8; sbit laba=P1^2;
uint8 code gepu[]={5,3,7,5,5,4,3,2,8,2,2,4,5,6,2,4,1,1,1,2,3,5};//歌谱 uint16 code chuzhi[]={64400,64524,64580,64684,64777,
64820,64898,64968,65030,65058,65110,65157,65178,65217};//各个音调的初始值 uint8 code jiepai[]={4,8,1,2,14,10,20,24,8,1,2,4,2,1,2,8,24,16,4,6,6,2};//节拍 uint8 times,i; bit flag; void init() { TMOD=0x11; EA=1; ET0=1; ET1=1; }
void main() { init(); while(1) { TH0=chuzhi[gepu[i]]/256; TL0=chuzhi[gepu[i]]%6; times=jiepai[i]; flag=0; TR0=1; TR1=1; while(flag==0); i++; if(i==22) i=0; } }
共分享92篇相关文档