单片机音频发生器程序设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
TF0=(65536-fosc/(12.0*freq)); //频率定时初值
TZ1=(65536-(fosc*zkb)/(12.0*100*freq)); //占空比定时初值
TIMER0_H=(uint)TF0/256; //计算定时器0和定时器1的初值
TIMER0_L=(uint)TF0%256;
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
times--;
if(times==0)
{
flag=1;
TR1=0;
}
思考题
1、根据实验内容1,说明输出频率与理论有什么差别?
答:频率会比理论大,因为delay(1000);
TR0=0;
beef=1;
i++;
if(i==5)
实验三
实验目的
1、进一步掌握单片机定时器的用法。
2、了解用单片机的IO口输出方波的方法。
3、理解用单片机产生简单音频的方法。
实验仪器
单片机开发板、万利仿真机、稳压电源、计算机
实验原理
1、单片机IO口产生音频脉冲的原理
我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机某个口线的“高”电平或“低”电平,则在该口线上就能产生一定频率的方波,接上喇叭就能发出一定频率的声音,若通过程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。喇叭驱动电路如图4-13所示。
delay(1000);
TR0=0;
beef=1;
i++;
if(i==5)
i=0;
}
}
void time0() interrupt 1
{
TH0=table[i]/256;
TL0=table[i]%256;
beef=~beef;
}
程序二:
include<reg51.h>
#include<intrins.h>
TR1=1;
while(flag==0);
i++;
if(i==22)
i=0;
}
}
void timer0() interrupt 1
{
TH0=chuzhi[gepu[i]]/256;
TL0=chuzhi[gepu[i]]%256;
if(flag==1)
TR0=0;
else
laba=~laba;
}
void timer1() interrupt 3
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]%256;
TR0=1;
简谱码
9
A
B
C
D
E
F
注:上表定时器工作于模式1
2、音乐节拍的生成
要唱出一首歌,只产生出音频脉冲还不够,还要考虑发出音频时间的长短(即节拍)。如果一拍为0.4秒,则1/4拍是0.1秒,只要设定延迟时间就可获得节拍的时间。我们也可以设1/8拍为1个延迟单位时间,则1拍应该是8个延迟单位时间,以此类推,所以,只要求得1/8拍的DELAY时间,其余的节拍就是它的倍数。详见下表
图4-14音频发生器程序流程图
实验内容
1、在单片机P1.2口产生下列频率方波
1KHz,2KHz,5KHz,10KHz,学号后两位*100
2、在P1.2口产生简谱对应频率方波(简谱频率如上文)
3、在P1.2口播放简谱音乐。
程序一:
#include "reg52.h"
#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;
Hale Waihona Puke Baidui=0;
这些语句也要占用时间。
2、如何产生占空比可调的方波?
答:void keyscan() interrupt 0 //外部中断0
{float TF0,TZ1;
EX0=0; //关中断
delay(10); //延时消抖
if(P1 !=0x0f) //判断是否有键按下
{ if(KEY1==0) freq+=100; //按键为1号,频率加100
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,
if(KEY2==0) freq+=10; //按键为2号,频率加10
if(freq>500) freq=50; //频率大于500Hz,重新赋50Hz
if( KEY3==0) zkb+=10; //按键为3号,占空比加10
if( KEY4==0) zkb++ ; //按键为4号,占空比加1
if(zkb>99) zkb=1; //占空比大于99,重新赋值为1
表4-2 节拍与节拍码对照表
节拍数
1/8拍
1/4拍
2/4拍
3/4拍
1拍
延迟数
1
2
4
6
8
时间
0.05秒
0.1秒
0.2秒
0.3秒
0.4秒
节拍数
1又1/4拍
1又1/2拍
2拍
2又1/2拍
3拍
延迟数
10
14
16
20
24
时间
0.5秒
0.6秒
0.8秒
1秒
1.2秒
3、简谱发生器程序设计
由前面的分析可知,音符频率有14种,节拍有10种,我们定义每个音节占用一个字节,字节的低4位代表音符的频率,高4位表示该音符的节拍。定义一个音符频率表、一个音符节拍表。程序首先读取一个音节,并从音符频率表和节拍表中读取音符频率所对应的定时器初始和节拍对应的延时参数。利用单片机内部定时器0、1分别产生频率和节拍。定时器0的初始值由音符的频率决定,定时器1的初始值是50ms对应的值。每当一个音符输出完成就取出下一个音符,直到取出的是0FFH。代表所有音符全部输出完成。程序停止或重新开始。程序流程图如图4-14所示。
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;
音符
1
2
3
4
5
频率Hz
440
494
523
578
659
698
784
初值T
64400
64524
64580
64684
64777
64820
64898
简谱码
2
3
4
5
6
7
8
音符
6
7
频率Hz
880
988
1046
1175
1318
1397
1568
初值T
64968
65030
65058
65110
65157
65178
65217
图4-13喇叭驱动电路
例如,要产生中音1。从下表可知,中音1的频率为523Hz,周期T=1/523=1912μs,其半周期为1912/2=956μs,因此只要在SPEAKER接口上产生半周期为956μs的方波,即可听到持续的1音。C调部分音符频率与计数初值的对应表如下:
表4-1 C调部分音符频率、计数初值与设置简谱码的对应关系
TIMER1_H=(uint)TZ1/256;
TIMER1_L=(uint)TZ1%256;
}
P1=0x0f; //给键盘扫描口赋初值
EX0=1; //开中断
}
3、用STC单片机的可编程时钟模块如何实现上述功能,请分析并写出程序。
心得体会:
通过这次实验,认识到单片机功能的强大性,不仅有控制功能,显示功能等,还能控制蜂鸣器的发声。通过本次试验,了解到音调和节拍都可以通过控制频率来实现的,这次实验自己受益匪浅。
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]]%256;
times=jiepai[i];
flag=0;
TR0=1;
相关文档
最新文档