跪求一个51单片机开发板的电子琴程序

跪求一个51单片机开发板的电子琴程序,第1张

电子琴程序

信号发生器设计报告

电子琴程序

2009-08-30 13:47:34| 分类: 默认分类

| 标签: |举报 |字号大中小 订阅

电子琴程序发送部分:

/*

本程序是用AD9851的DDS模块做的电子琴,

电子琴的音符完整,共21个按键,分别是低1--7,中1--7,高1--7。本程序为双机通信的发送部分,可以显示频率

*/

#include <REG51.H> //

单片机内部专用寄存器定义

/**************************************/

sbit K1= P1^0 //

键K1输入引脚定义

sbit K2= P1^1 // 键K2输入引脚定义

sbit K3= P1^2 //

键K3输入引脚定义

sbit K4= P1^3 // 键K4输入引脚定义

sbit K5= P1^4 //

键K5输入引脚定义

sbit K6= P1^5 // 键K6输入引脚定义

sbit K7= P1^6 //

键K7输入引脚定义

sbit K8= P1^7 //

键K15输入引脚定义

/**************************************/

sbit K9= P2^0 //

键K8输入引脚定义

sbit K10= P2^1 // 键K9输入引脚定义

sbit K11= P2^2 //

键K10输入引脚定义

sbit K12= P2^3 // 键K11输入引脚定义

sbit K13= P2^4 //

键K12输入引脚定义

sbit K14= P2^5 // 键K13输入引脚定义

sbit K15= P2^6 //

键K14输入引脚定义

sbit K16= P2^7 //

键K16输入引脚定义

/**************************************/

sbit K17= P3^2 //

键K17输入引脚定义

sbit K18= P3^3 // 键K18输入引脚定义

sbit K19= P3^4 //

键K19输入引脚定义

sbit K20= P3^5 // 键K20输入引脚定义

sbit K21= P3^7 // 键K21输入引脚定义

/******************延时程序********************/

void delay(unsigned int

k)

{

unsigned int i,j

for(i=0i<ki++){

for(j=0j<121j++)

{}}

}

/*****************串口初始化程序*****************/

void

init

(void)

{

TMOD=0x20

TH1=0xfd

TL1=0xfd

SCON=0x50

TR1=1

}

/*****************串口发送程序*****************/

void chuan(shu)

{

SBUF=shu

TI=0

}

/******************主程序********************/

void main(void)

{

init()

while(1)

{

if(K1==0) chuan(1)

else if(K2==0)

chuan(2)

else if(K3==0) chuan(3)

else if(K4==0) chuan(4)

else

if(K5==0) chuan(5)

else if(K6==0) chuan(6)

else if(K7==0)

chuan(7)

else if(K8==0) chuan(8)

else if(K9==0) chuan(9)

else

if(K10==0) chuan(10)

else if(K11==0) chuan(11)

else if(K12==0)

chuan(12)

else if(K13==0) chuan(13)

else if(K13==0)

chuan(13)

else if(K14==0) chuan(14)

else if(K15==0)

chuan(15)

else if(K16==0) chuan(16)

else if(K17==0)

chuan(17)

else if(K18==0) chuan(18)

else if(K19==0)

chuan(19)

else if(K20==0) chuan(20)

else if(K21==0)

chuan(21)

elsechuan(0)

}

}

电子琴接收部分:

/*

本程序是用AD9851的DDS模块做的电子琴,

电子琴的音符完整,共21个音符,分别是低1--7,中1--7,高1--7。本程序为双机通信的接受部分。有直接演奏方式,录音演奏方式,录音后放音方式

,可以显示频率 */

#include <STC12C5410AD.H>

#include<intrins.h>

#include <stdio.h> /* prototype

declarations for I/O functions */

#define uchar unsigned char

#define uint unsigned int

sbit

E_CLK =P2^6//clock input 同步时钟输入端

sbit RW_SID

=P2^5//data input/output 串行数据输入、输出端

sbit RS_DI

=P2^4 // 4号脚 jichunqiinput

sbit DataIn_AD9851=P2^3

//控制子串传送位

sbit DDS_CLK=P2^2//接外部晶振时钟 这里为30M

sbit

DDS_FQUD=P2^1 //更新发送频率

sbit RST_AD9851= P2^0//复位

unsigned char Control_AD9851 = 0x01// Phase0 ,power on mode and 6 REFCLK

Multiplier enable

/* T0_int 定时 时间常数 5ms=5000=1388H->EC78H f=12MH */

#define

time_5ms_H 0xC2 /* 定时时间为1/64s */

#define time_5ms_L 0xF7

charshu, bb

unsigned char p=0

unsigned char

point=0

unsigned char recode_n=0

unsigned char xdata

array[50]={0}

unsigned int xdata arrayt[50]={0}

float const

ton[]={0.00,261.63,293.67,329.63,349.23,391.99,440.00,494.00,

523.25,587.33,659.25,698.46,783.99,880.00,987.76,

1046.50,1174.66,1381.51,1396.92,1567.98,1760.00,1975.52}

unsigned int ttt,

nnn

unsigned char mode=0

sbit KEY_rec =P3^5

sbit KEY_play=P3^7

/*************************延时程序***************************/

void

delay(uint k)

{

uint i,j

for(i=0i<ki++)

{for(j=0j<121j++)

{}}

}

/*************************串行发送一字节数据***************************/

void SendByte(unsigned char dat)

{

unsigned

char i

RS_DI=1

for(i=0i<8i++)

{

E_CLK=0

if(dat&0x80)RW_SID=1

else RW_SID=0

E_CLK=1

dat=dat<<1

}

}

/*************************写控制命令***************************/

void

SendCMD(unsigned char dat)

{

SendByte(0xF8)//11111,00,0

RW=0,RS=0 同步标志

SendByte(dat&0xF0)//高四位

SendByte((dat&0x0F)<<4)//低四位

}

/************************写显示数据或单字节字符 ****************************/

void SendDat(unsigned char dat)

{

SendByte(0xFA)//11111,01,0 RW=0,RS=1

SendByte(dat&0xF0)//高四位

SendByte((dat&0x0F)<<4)//低四位

}

/************************显示字符串****************************/

void

hzkdis(unsigned char code *s)

{ while(*s>0)

{

SendDat(*s)

s++

delay(5)

}

}

/************************显示数据子程序****************************/

void

Display(unsigned char x_add,unsigned long date,unsigned char dot)

{

unsigned char date0,date1,date2,date3,date4,date5//

date5=(date%1000000)/100000

date4=(date%100000)/10000

date3=(date%10000)/1000

date2=(date%1000)/100

date1=(date%100)/10

date0=date%10

SendCMD(x_add)

if(dot==0x02) //100---9999.99

{

SendDat(0x30+date5)

SendDat(0x30+date4)

SendDat(0x30+date3)

SendDat(0x30+date2)

SendDat(0x2e)

SendDat(0x30+date1)

SendDat(0x30+date0)

SendDat(0x48)

SendDat(0x7a)

}

}

/*************************设置AD9851频率***************************/

void

SentFreq(unsigned long int freq)

{

unsigned char i=0

unsigned int

temp

DDS_FQUD=0

for(i=0i<32i++) //串口数据

输入频率控制字

{

DDS_CLK =

0

temp=((freq>>i)&1)

DataIn_AD9851 = temp

DDS_CLK =

1

}

for(i=0i<8i++)//phase-b4 ph-b3 ph-b2 ph-b1 ph-b0 Power-down

Logic0* 6*REFCLK Multiplier_En

{

DDS_CLK = 0

temp=((Control_AD9851>>i)&1)

DataIn_AD9851 = temp

DDS_CLK = 1

}

DDS_CLK = 0

DDS_FQUD = 1

DDS_FQUD =

0

}

/**************************换算频率,并输出***********************/

void

Set_Freq(float Freqency)

{unsigned long int freq_temp

freq_temp=

(unsigned long int)(23.861*Freqency)// SYSCLK = 180 MHz

2^32/180000000=23.861

SentFreq(freq_temp)

}

/*************************T0作定时器,T1作波特率发生器,初始化*************************/

void

init (void)

{

TMOD= 0x01 /* 0001$0001 T1 &T0 are 16bit

timers */

TH0 = time_5ms_H/* T0 timer 5ms */

TL0 =

time_5ms_L

/* TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 */

TCON= 0x10 /* 0 0 0 1 0 0 0 0 */

/*start T0xint1 xint0 */

IE= 0x82/* 1000 0010,

EA=ET0=1,

*/

TMOD=0x20

TH1=0xfd

TL1=0xfd

TR1=1

SCON=0x50

ES=1

EA=1

}

/*************************设置AD9851初始化*************************/

void

AD9851Init(void) //DDS初始化函数,包括DDS复位和初始化为串行发送

{

DDS_CLK=0

DDS_FQUD=0

RST_AD9851=0

RST_AD9851=1//复位AD9851

RST_AD9851=1

RST_AD9851=1

RST_AD9851=0

DDS_CLK=1

DDS_CLK=0

DDS_FQUD=1

DDS_FQUD=0

}

/**************************初始化LCM

**************************/

void initlcm(void)

{

delay(100)

SendCMD(0x30)//功能设置,一次送8位数据,基本指令集

SendCMD(0x0C)//0000,1100 整体显示,游标off,游标位置off

SendCMD(0x14)

SendCMD(0x01)//0000,0001 清DDRAM 即清屏

SendCMD(0x02)//0000,0010 DDRAM地址归位

SendCMD(0x80)//1000,0000

设定DDRAM 7位地址000,0000到地址计数器AC

//SendCMD(0xb8|page)翻页

}

/**********************主程序******************************/

void

main(void)

{

uchar t

init()

AD9851Init()

initlcm()//12864初始化程序

shu=0

bb=255

while(1)

{

switch(mode)

{

case 0: //

演奏方式

SendCMD(0x80)//第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)

hzkdis("

音乐播放频率:")

if (shu!=bb)

{

Set_Freq(ton[shu])

Display(0x93,(unsigned

long)100*ton[shu],0x02)

bb=shu

}

if

(KEY_rec==0)

{

mode=1

point=0

recode_n=0

shu=0

bb=255

nnn=0

}

else if (KEY_play==0)

{

mode=2

p=1

}

break

case

1: // 录音方式

// SendCMD(0x01)//0000,0001 清DDRAM 即清屏

//

delay(10)

SendCMD(0x80)//第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)

hzkdis("

音乐录制频率:")

if (shu!=bb)

{

arrayt[point]=nnn // 记录上一音阶时间

Set_Freq(ton[shu])

Display(0x93,(unsigned long)100*ton[shu],0x02)

nnn=0

bb=shu

recode_n++

}

if ((recode_n>=50) || (KEY_play==0))

//停止录音

{

Set_Freq(0.0)

p=0

mode=0

shu=0

bb=20

}

break

case 2: //

放音方式

SendCMD(0x80)//第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)

hzkdis("

音乐重播频率:")

for(t=0t<recode_nt++)

{

Set_Freq(ton[array[p]])

Display(0x93,(unsigned

long)*ton[array[p]],0x02)

ttt=arrayt[p]

while

(ttt)

delay(100)

p++

}

if

(p>recode_n)

{

Set_Freq(0.0)

p=0

mode=0

shu=0

bb=20

}

break

}

}

}

//*==================================*/

/* 串口中断接收

*/

/*==================================*/

void s_receive() interrupt 4

//串行中断

{

if(RI==1) //接收中断标志位

{

RI=0//中断标志清零

shu=SBUF //RXData赋值

}

else

TI=0

}

1,数据管显示就没什么了,找几个简单的数码管驱动程序改改就可以了,一般都是先选中数码管,然后设置值,就可以显示了,不过需要注意刷新,10ms刷新一个应该就可以了,刷新频率比较低的话会闪闪的,这个你应该明白。

2,蜂鸣器发do音,这个硬件实现我就不知道了,也许有硬件可以 编码控制自动生成对应频率的值。我想如果通过软件实现的话,不妨考虑一下定时器。假设do音是1000Hz的频率(没有查,不清楚,假设的),那么你可以控制定时器的触发频率为1000hz,触发一次,对应的输出到蜂鸣器的口的电平跳变一下,如果定时器的频率为1000hz的话,那么应该有500hz的频率,一个周期需要一高一低嘛!中断读取按键信号,分析按键,然后设定定时器的频率,启动定时器,设置一个响的时间,然后到时间关闭定时器,这样你按下k1就会发出一声do的声音,然后停了。

3,按键读取程序,中断或者查询方式,自己选择吧,别忘了延迟5ms左右再次读取按键,这个是消抖的。

4,建议模块化编程,先搞定按键的,然后搞定数码管的,然后搞定定时器的,然后再考虑如何把它们组合起来。好了不说了,说得有点多了,再说会我都回到大学时代了,哈哈。总之自己一点一点的做,应该不难,51熟练,c语言熟练,板子焊接的结构比较清晰的话,很快就可以搞定的。

5,还是建议你自己写一份各个模块的驱动的代码,例如按键的,数码管的,led的,温度传感器的,光敏的,蜂鸣器的,遥控器的,定时器的,中断的,等等等等模块(可以借鉴别人写的,自己一定要会),然后需要的时候,copy过来,改改就行,快而且bug少。建议keil c语言编程,用汇编编码太耗时了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11453369.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存