使用verilog语言通过quartusII实现电子琴的设计

jianning   2010-6-19 21:43 楼主
                八音电子琴要求:
    要求:
1.能发出1、2、3、4、5、6、7、1八个音;
2.用按键作为键盘;
3.C调到B调对应频率为。
调        频率(HZ)
C(大)       261.63*2
B        493.88
A        440.00
G        392.00
F        349.23
E        329.63
D        293.66
C        261.63

回复评论 (8)

只看到过C51的发音设计,VERILOG的还没见过,发出来看看有点启示没
点赞  2010-6-19 21:53
/* ----------------------------------------------------------- */
/* 曲谱存贮格式 uchar code 数组名{音高,音长,音高,音长....} */
/* 音高由三位数字组成: */
/* 个位是表示 1~7 这七个音符. */
/* 十位是表示音符所在的音区,1-低音,2-中音,3-高音; */
/* 百位表示这个音符是否要升半音 0(不写)-不升,1-升半音。 */
/* 音长最多由三位数字组成: */
/* 个位表示音符的时值,其对应关系是: */
/* 数值(n) 0 1 2 3 4 5 6 */
/* --------------------------------------------- */
/* 几分音符 1 2 4 8 16 32 64 */
/* 即:音符=2^n ,这样做的目的是为了节省曲谱的存贮空间。 */
/* 十位表示音符的演奏效果(0-2),0-普通,1-连音,2-顿音。 */
/* 百位是符点位,0(不写)-无符点,1-有符点。 */
/* ----------------------------------------------------------- */
/* 调用演奏子程序的方法为: */
/* play(乐曲数组名,调号,升降八度,演奏速度,开始指针,结束指针) */
/* 调号(0-11)是指乐曲升多少个半音演奏;升降八度(1-3)是指在演奏 */
/* 在哪个八度演奏: 1-降八度,2-不升不降,3-升八度.开始指针(0- ) */
/* 是从哪个音符开始演奏,结束指针是演奏到哪个音符为止. */
/* ----------------------------------------------------------- */

//本程序用T0来产生音调,用T1产生音长
#include
#define uchar unsigned char
#define yx 4/5                                                  /* 定义普通音符演奏的长度分率 */
#define plen 2                                                  /* 定义晶振的时钟周期(us) */
#define uchar unsigned char
#define uint unsigned int
sbit speaker=P1^0;
/* ------------------下面是曲谱 ------------------------------ */
uchar code sound[100]=
{25,2,23,3,25,3,31,1,26,2,31,3,26,3,25,1,25,2,21,3,22,3,23,2,22,3,21,3,22,0,
25,2,23,3,25,3,31,102,27,3,26,2,31,2,25,1,25,2,22,3,23,3,24,102,17,3, 21,0};
uchar tc0,tc1,sc0,sc1;                                          /* 音长和音符两个计数器初值暂存 */
void play(sound,dh,sj,speed,point1,point2)

uchar code sound[];                                             /* 接受乐曲数组的地址 */
uchar speed,sj,dh;                                              /* 速度、八度、调号 */
uint point1,point2;                                             /* 乐曲开始、结束指针 */
{
        uint code fftab[12]={262,277,294,311,330,349,369,392,415,440,466,494}; /* 频率表*/
        uchar code stab[7]={0,2,4,5,7,9,11};                    /* 1~7在频率表中的位置 */
        uchar code ltab[7]={1,2,4,8,16,32,64};
        uchar tl,ts,sl,sm,sh,slen,xg,ii,fd;
        uint point,hz,tc,sc,len,len0,len1,len2,len4,i,ftab[12];
        speaker=1;
        for(i=0;i<12;i++)                                       /* 根据调号及升降八度来计算音符频率 */
        {
                ii=i+dh;
                if(ii>11)
                {
                        ii=ii-12;
                        ftab=fftab[ii]*2;
                }
                else    ftab=fftab[ii];
                if(sj==1) ftab>>=2;
                if(sj==3) ftab<<=2;
        }
        point=point1;
        ts=sound[point];
        tl=sound[point+1];                                      /* 读出第一个音符和它时时值 */
        tc=65535-10000/plen;                                    /* 算出10ms的初装值 */
        tc0=tc%256;                                             /* 计算TL1应装入的初值 */
        tc1=tc/256;                                             /* 计算TH1应装入的初值 */
        len0=12000/speed;                                       /* 算出1分音符的长度(几个10ms) */
        len4=len0/4;                                            /* 算出4分音符的长度 */
        len4=len4-len4*yx;                                      /* 普通音最长间隔标准 */
        TMOD=0x11;
        TH1=tc1; TL1=tc0;
        ET0=1; EA=1;
        TR0=0; TR1=1;
        while(point<=point2)
        {               
                sl=ts%10;                                       /* 计算出音符 */      
                sh=ts/100;                                      /* 计算出是否升半 */
                sm=ts/10%10;                                    /* 计算出高低音 */
                hz=ftab[stab[sl-1]+sh];                         /* 查出对应音符的频率 */
                if(sl!=0)
                {
                        if (sm==1) hz>>=2;                      /* 若是低音 */
                        if (sm==3) hz<<=2;                      /* 若是高音 */
                        sc=(50000/hz)*10/plen;                  /* 计算脉冲个数 */
                        sc=65536-sc;                            /* 计算计数器初值 */
                        sc0=sc%256;                             /* 算出TL0应装初值 */
                        sc1=sc/256;                             /* 算出TH0应装初值 */
                        TH0=sc1;                                /* 装入初值 */
                        TL0=sc0+12;                             /* 加12是对中断延时的补偿 */
                }
                slen=ltab[tl%10];                               /* 算出是几分音符 */
                xg=tl/10%10;                                    /* 算出音符类型(0普通1连音2顿音) */
                fd=tl/100;
                len=len0/slen;                                  /* 算出连音音符演奏的长度(多少个10ms)*/
                if (fd==1) len=len+len/2;
                if(xg!=1)
                        if(xg==0)                               /* 算出普通音符的演奏长度 */
                                if (slen<=4)
                                        len1=len-len4;
                                else    len1=len*yx;
                        else    len1=len/2;                     /* 算出顿音的演奏长度 */
                else    len1=len;
                if(sl==0) len1=0;
                len2=len-len1;                                  /* 算出不发音的长度 */
                if (sl!=0)
                {
                        TR0=1;
                        for(i=len1;i>0;i--)                     /* 发规定长度的音 */
                        {
                                while(TF1==0);
                                TH1=tc1; TL1=tc0;
                                TF1=0;
                        }
                }
                if(len2!=0)
                {
                        TR0=0; speaker=1;
                        for(i=len2;i>0;i--)                     /* 音符间的间隔 */
                        {
                                while(TF1==0);
                                TH1=tc1; TL1=tc0;
                                TF1=0;
                        }
                }
                point+=2;                                       /* 音符指针下移 */
                ts=sound[point]; tl=sound[point+1];             /* 读出下一个音符和它时时值 */
        }
}
void yin() interrupt 1                                          /* 音符发生程序(中断服务程序)*/
{
        speaker=~speaker;
        TH0=sc1; TL0=sc0;
}
//==============================================
void main(void)
{
        while(1)
        {
                play(sound,0,2,60,0,57);
                play(sound,0,1,60,0,57);
                play(sound,0,3,60,0,57);
                play(sound,0,2,40,0,57);
                play(sound,5,2,60,0,57);
                play(sound,0,2,80,0,57);
        }
}
点赞  2010-6-19 21:54
听以前做VERILOG硬件设计的同事说C语言可以作为电路设计的根据
点赞  2010-6-19 21:56
可以按那个思路来 我之前见过一个 不过没深研究过 帮顶
点赞  2010-6-20 09:00
学习中,51的做过
点赞  2010-6-20 11:07
引用: 引用 2 楼 cbyibby 的回复:

/* ----------------------------------------------------------- */
/* 曲谱存贮格式 uchar code 数组名{音高,音长,音高,音长....} */
/* 音高由三位数字组成: */
/* 个位是表示 1~7 这七个音符. */
/* 十位是表示音符所在的音区,1-低音,2-中音,3-高音; */
/* 百位表示这……

能不能用verilog实现??谢谢
点赞  2010-6-20 16:37
不知道楼主有结果没有?我同求啊
点赞  2010-6-20 16:51
等待结果
点赞  2010-6-28 15:32
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复