设计报告

时间:2024.3.31

1设计题目要求

1.1 单片机部分(必做部分)

1.1.1 基于51单片机的多路数据采集系统

设置3个功能键:当某一功能键被按下后,进入相应的功能模式。3个功能有:

1) 8路数据采集功能

通过调节可变电阻实现0-5V的电压输出作为8路输入信号使用,每路信号用2位LED显示采集的结果。报警:任意一路超过某一门限(可自己设定)时,发出报警(声音+灯闪烁,并通过灯指示是哪一路报警),同时停止采集。

2) 计数功能

利用计数功能键,实现每按一次按键,LED显示加1,从0-99计数。

3) 秒表功能

只用一个键控制。按下一个按键后时钟启动,从零开始计时,计时间隔0.01秒,再按一次后停止。再按一次后清零。如此循环。

1.1.2 电子琴

1) 8个键盘(实现中音1~7和高音1共8个音),8位LED数码管可以记忆并显示最近8个按下的音,用喇叭送出按下的音。要求必须使用8255/8155扩展实现键盘和显示部分。

2) 长时间(如2s)按下某一键(可自己定义),可播放某一歌曲。

1.2  FPGA部分(选做部分)

1.2.1 基于VHDL的多人抢答器

抢答器不少于4路,要求该系统应具备以下功能:

(1) 抢答器线路测试功能

为了保证比赛的正常进行,比赛前需要调试线路能否正常工作。有指示灯显示该系统现在是否工作正常。

(2) 第一抢答信号的鉴别和锁存功能

可以判断哪一路最先抢到回答的资格,在数码管上显示选手的号码或者让其相应的指示灯显示为绿灯表示抢答成功,并具有锁存功能,此后其他人不能抢答,一直到下一题开始。

(3) 犯规警示功能

可以判断出参赛者有没有在主持人读题的期间按下抢答器,有则声音报警并显示该选手号码或相应的红灯闪烁,同时取消其本轮抢答资格。

(4) 计时功能

可以预置时间,可以进行倒计时并且将时间显示出来。离计时结束还有10秒时有声音提示。

(5) 计分功能

可以实现加分和减分,并且显示出来。

(6) 声音提示及报警功能

在犯规和计时将结束时,要求有此功能。

(7) 有清零键和启动开关的功能

清零键:主持人可以按此键清除所有分数。

启动开关:主持人可以按此键启动抢答开始。

流程参考:

①  接通电源后,先按清零键,清除所有分数;启动开关处于关闭状态,禁止所有抢答器;

②  主持人开始读题,读题完毕后按“启动键”开始抢答,并计时开始,有数码管显示;若未在按“启动键”之前抢答视为犯规,有声音报警,并显示选手号码或者令其相应指示灯显示为红灯闪烁,取消此次答题机会,再按抢答键无效;

③  开始抢答后,若有人抢答时,有声音提示,并显示选手号码或者令其相应的指示灯显示为绿灯闪烁,表明哪一路为第一抢答者,同时禁止其他路的抢答信号,直至下一题开始,主持人再次按“启动键”。

④  抢答者在规定时间内回答正确,用“加分键”相应加一分,回答错误则用“减分键”扣一分;在即将到达规定时间时的前10秒,有声音提示。

2基于51单片机的多路数据采集系统

2.1 芯片介绍

2.1.1 ADC0808

1.综述:ADC0808是采样分辨率为8位的、以逐次逼近原理进行模/数转换的器件。其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。ADC0808是ADC0809的简化版本,功能基本相同。一般在硬件仿真时采用ADC0808进行A/D转换,实际使用时采用ADC0809进行A/D转换。

2.引脚功能:ADC0808芯片有28条引脚,采用双列直插式封装,如右图所示。各引脚功能如下:

  1~5和26~28(IN0~IN7):8路模拟量输入端。

  8、14、15和17~21:8位数字量输出端。

  22(ALE):地址锁存允许信号,输入,高电平有效。

  6(START): A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。

  7(EOC): A/D转换结束信号,输出,当A/D转换结束时,此端输出一个高电平(转换期间一直为低电平)。

  9(OE):数据输出允许信号,输入,高电平有效。当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。

  10(CLK):时钟脉冲输入端。要求时钟频率不高于640KHZ。

  12(VREF(+))和16(VREF(-)):参考电压输入端

  11(Vcc):主电源输入端。

  13(GND):地。

  23~25(ADDA、ADDB、ADDC):3位地址输入线,用于选通8路模拟输入中的一路

本设计中ADC0808的接法如下图所示:

2.2 C语言程序设计

#include<reg52.h>

#define uc unsigned char

#define ui unsigned int

//共阴极数码管编码(无小数点)

uc code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//共阴极数码管编码(有小数点)

uc code table_point[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

uc number=255,shi,ge,second,second_behind,function,flag_watch,time[4],Voltage_Integer,Voltage_Decimal;

ui AD_Digital,AD_Analog;

sbit DULA=P2^0;         //申明段选锁存器的锁存端

sbit WELA1=P2^1;       //申明位选锁存器1的锁存端

sbit WELA2=P2^2;       //申明位选锁存器2的锁存端

sbit LEDLA=P2^3; //申明LED锁存器的锁存端

sbit K1=P2^4;        //功能键1

sbit K2=P2^5;        //功能键2

sbit K3=P2^6;        //功能键3

sbit LED=P2^7;            //报警灯

sbit A1=P1^0;              //地址线A

sbit A2=P1^1;        //地址线B

sbit A3=P1^2;        //地址线C

sbit ST=P1^3;        //A/D转换启动信号

sbit OE=P1^4;              //数据输出允许信号

sbit EOC=P1^5;            //A/D转换结束信号

sbit CLK=P1^6;            //时钟脉冲输入信号

sbit BEEP=P1^7;        //蜂鸣器

//延时(单位ms)

void delayms(ui xms)

{

       ui i,j;

       for(i=xms;i>0;i--)

              for(j=31;j>0;j--);

}

//报警

void alarm(uc n)

{    

       switch(n)

       {

              case 1:

                     LEDLA=1;P0=0xfe;LEDLA=0;break;

              case 2:

                     LEDLA=1;P0=0xfd;LEDLA=0;break;

              case 3:

                     LEDLA=1;P0=0xfb;LEDLA=0;break;

              case 4:

                     LEDLA=1;P0=0xf7;LEDLA=0;break;

              case 5:

                     LEDLA=1;P0=0xef;LEDLA=0;break;

              case 6:

                     LEDLA=1;P0=0xdf;LEDLA=0;break;

              case 7:

                     LEDLA=1;P0=0xbf;LEDLA=0;break;

              case 8:

                     LEDLA=1;P0=0x7f;LEDLA=0;break;

       }

       while(K2==1&&K3==1)     

       {

              BEEP=~BEEP;

              LED=~LED;

              switch(n)

              {

                     case 1:

                            WELA1=1;P0=0xfe;WELA1=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA1=1;P0=0xfd;WELA1=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 2:    

                            WELA1=1;P0=0xfb;WELA1=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA1=1;P0=0xf7;WELA1=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 3:    

                            WELA1=1;P0=0xef;WELA1=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA1=1;P0=0xdf;WELA1=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 4:    

                            WELA1=1;P0=0xbf;WELA1=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA1=1;P0=0x7f;WELA1=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 5:    

                            WELA2=1;P0=0xfe;WELA2=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA2=1;P0=0xfd;WELA2=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 6:    

                            WELA2=1;P0=0xfb;WELA2=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA2=1;P0=0xf7;WELA2=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 7:    

                            WELA2=1;P0=0xef;WELA2=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA2=1;P0=0xdf;WELA2=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

                     case 8:    

                            WELA2=1;P0=0xbf;WELA2=0;

                            DULA=1;P0=table_point[Voltage_Integer];DULA=0;

                            delayms(4);

                            WELA2=1;P0=0x7f;WELA2=0;

                            DULA=1;P0=table[Voltage_Decimal];DULA=0;

                            delayms(4);break;

              }

       }

       LEDLA=1;P0=0xff;LEDLA=0;

       BEEP=1;

       LED=1;

}

//按键检测

void keyscan()

{

       if(K1==0)

       {

              delayms(10);

              if(K1==0)

              {     

                     function=1;                  

                     while(!K1);

              }

       }

       if (K2==0)

       {    

              delayms(10);

              if (K2==0)

              {

                     function=2;

                     if(number==100)

                            number=0;     

                     while(!K2);

                     number++;

              }

       }

       if (K3==0)

       {    

              delayms(10);

              if (K3==0)

              {           

                    while(!K3);

                     function=3;

                     flag_watch=flag_watch+1;

                     if(flag_watch==4)

                     {

                            flag_watch=1;

                     }

                     switch(flag_watch)

                     {

                            case 1:

                                   TR0=1;          //启动定时器0

                                   break;

                            case 2:

                                 TR0=0;        //关闭定时器0

                                  break;

                            case 3:

                                  second=0;       //清零

                                   second_behind=0;

                                  break;

                     }    

              }

       }

}

//功能1

void function1()

{

       TR1=1;

       number=255;

       second=0;

       second_behind=0;

       flag_watch=0;

       OE=0;

       LEDLA=0;

       WELA2=0;

       //IN0

       A3=0;A2=0;A1=0;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);           //等待转换完成

       OE=1;

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA1=1;P0=0xfe;WELA1=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA1=1;P0=0xfd;WELA1=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(1);

       }

      

       //IN1

       A3=0;A2=0;A1=1;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                         //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA1=1;P0=0xfb;WELA1=0; P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA1=1;P0=0xf7;WELA1=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(2);

       }

      

       //IN2

       A3=0;A2=1;A1=0;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                         //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA1=1;P0=0xef;WELA1=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA1=1;P0=0xdf;WELA1=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(3);

       }

       //IN3      

       A3=0;A2=1;A1=1;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                         //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA1=1;P0=0xbf;WELA1=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA1=1;P0=0x7f;WELA1=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(4);

       }

       WELA1=1;P0=0xFF;WELA1=0;

       WELA1=0;

       //IN4

       A3=1;A2=0;A1=0;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                         //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA2=1;P0=0xfe;WELA2=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA2=1;P0=0xfd;WELA2=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(5);

       }

       //IN5      

       A3=1;A2=0;A1=1;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                  //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA2=1;P0=0xfb;WELA2=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA2=1;P0=0xf7;WELA2=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(6);

       }

       //IN6

       A3=1;A2=1;A1=0;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                  //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA2=1;P0=0xef;WELA2=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA2=1;P0=0xdf;WELA2=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(7);

       }

             

       //IN7

       A3=1;A2=1;A1=1;

       ST=0;ST=1;ST=0;         //启动A/D转换

       while(EOC==0);  //等待转换完成

       OE=1;                  //允许输出信号

       AD_Digital=P3;

       AD_Analog=50*AD_Digital/255;

       Voltage_Integer=AD_Analog/10;

       Voltage_Decimal=AD_Analog%10;

       WELA2=1;P0=0xbf;WELA2=0;P0=0x00;

       DULA=1;P0=table_point[Voltage_Integer];DULA=0;

       delayms(1);

       WELA2=1;P0=0x7f;WELA2=0;P0=0x00;

       DULA=1;P0=table[Voltage_Decimal];DULA=0;

       delayms(1);

       OE=0;

       if(AD_Digital>204)

       {

              alarm(8);

       }

       WELA2=1;P0=0xFF;WELA2=0; 

}

//功能2

void function2()

{

       TR1=0;  

       WELA2=0;     //锁住数码管后四位

       second=0;

       second_behind=0;

       flag_watch=0;

       shi=number/10;

       ge=number%10;

       LEDLA=0;

       WELA1=1;

       P0=0xfe; //点亮左边第一个数码管

       WELA1=0;

       DULA=1;

       P0=table[shi];

       DULA=0;

       delayms(5);

       WELA1=1;

       P0=0xfd;  //点亮左边第二个数码管

       WELA1=0;

       DULA=1;

       P0=table[ge];

       DULA=0;

       delayms(5);

}

//功能3

void function3()

{    

       TR1=0;

       WELA2=0;     //锁住数码管后四位

       number=255; 

       time[3]=second/10;

       time[2]=second%10;

       time[1]=second_behind/10;

       time[0]=second_behind%10;

       LEDLA=0;

       WELA1=1;

       P0=0xfe; //左边第一个数码管

       WELA1=0;

       DULA=1;

       P0=table[time[3]];

       DULA=0;

       delayms(5);

       WELA1=1;

       P0=0xfd;  //左边第二个数码管

       WELA1=0;

       DULA=1;

       P0=table_point[time[2]];

       DULA=0;

       delayms(5);

       WELA1=1;

       P0=0xfb;  //左边第三个数码管

       WELA1=0;

       DULA=1;

       P0=table[time[1]];

       DULA=0;

       delayms(5);

       WELA1=1;

       P0=0xf7;   //左边第四个数码管

       WELA1=0;

       DULA=1;

       P0=table[time[0]];

       DULA=0;

       delayms(5);   

}

//初始化

void init()

{

       TMOD=0x21;                   //设置定时器0为工作方式1,定时器1为工作方式2

       TH0=(65536-10000)/256;     //装初值,10ms一次中断

       TL0=(65536-10000)%256;

       TH1=0xfe;                          

       TL1=0xfe;

       EA=1;                                //开总中断

       ET0=1;                             //开定时器0中断

       ET1=1;                             //开定时器1中断

}

//主程序

void main()

{

       init();

      

       while(1)

       {

              keyscan();

              if(function==1)

              {

                     function1();   

              }

              if(function==2)     

              {

                     function2();   

              }

              if(function==3)     

              {

                     function3();

              }

       }

}

//T0定时器中断给ADC0808提供时钟信号

void T0_time() interrupt 1

{

       TH0=(65536-10000)/256;

       TL0=(65536-10000)%256;

       second_behind=second_behind+1;

       if(second_behind==100)

       {

              second_behind=0;

              second++;

       }

}

//T1定时器中断给ADC0808提供时钟信号

void T1_time() interrupt 3

{

       CLK=~CLK;

}

2.3 Proteus仿真结果

2.3.1 功能1

1.正常状态:

2.报警状态:

2.3.2 功能2

2.3.3 功能3

3电子琴

3.1 芯片介绍

3.1.1 8255A

Intel 8086/8088 系列的可编程外设接口电路(Programmable Peripheral Interface)简称 PPI,型号为8255(改进型为8255A及8255A-5),具有24条输入/输出引脚、可编程的通用并行输入/输出接口电路。它是一片使用单一+5V电源的40脚双列直插式大规模集成电路。8255A的通用性强,使用灵活,通过它CPU可直接与外设相连接。

  8255A在使用前要写入一个方式控制字,选择A、B、C三个端口各自的工作方式,共有三种;

  方式0 :基本的输入输出方式,即无须联络就可以直接进行的 I/O方式。其中A、B、C口的高四位或低四位可分别设置成输入或输出。

  方式1 :选通I/O,此时接口和外围设备需联络信号进行协调,只有A口和B口可以工作在方式1,此时C口的某些线被规定为A口或B口与外围设备的联络信号,余下的线只有基本的I/O功能,即只工作在方式0.

  方式2: 双向I/O方式,只有A口可以工作在这种方式,该I/O线即可输入又可输出,此时C口有5条线被规定为A口和外围设备的双向联络线,C口剩下的三条线可作为B口方式1的联络线,也可以和B口一起方式0的I/O线。

  8255A是一个并行输入、输出器件,具有24个可编程设置的I/O口,包括3组8位的I/O为PA口、PB口、PC口,又可分为2组12位的I/O口:A组包括A口及C口高4位,B组包括B口及C组的低4位。

A口可以设置为方式0、方式1、方式2,B口与C口只能设置为方式0或方式1。

本设计中8255A的接法如下图所示:

3.2 C语言程序设计

#include<reg52.h>

#include<absacc.h>

#define uc unsigned char

#define ui unsigned int

//PA、PB、PC端口及命令端口地址定义

#define PA XBYTE[0xfff8]

#define PB XBYTE[0xfff9]

#define PC XBYTE[0xfffA]

#define COM XBYTE[0xfffB]

sbit sounder=P3^0;

sbit play=P1^7;

uc note;

ui key,H0,L0;

ui code yin[]={0,64580,64684,64777,64820,64898,64968,65030,65058};//{空 DO RE MI FA SO LA XI DO}

ui code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

ui duan[]={0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40};

 //《两只老虎》数据表

uc code MUSIC[]={5,2,2, 6,2,2, 7,2,2, 5,2,2,                          //两只老虎

                             5,2,2, 6,2,2, 7,2,2, 5,2,2,                         //两只老虎

                            7,2,2, 1,3,2, 2,3,4,                                          //跑得快

                            7,2,2, 1,3,2, 2,3,4,                                          //跑得快

                            2,3,1, 3,3,1, 2,3,1, 1,3,1, 7,2,2, 5,2,2,       //一只没有眼睛

                            2,3,1, 3,3,1, 2,3,1, 1,3,1, 7,2,2, 5,2,2,       //一只没有耳朵

                            6,2,2, 2,2,2, 5,2,4,                                          //真奇怪

                             6,2,2, 2,2,2, 5,2,4,                                          //真奇怪

                         0,0,0};

//音阶频率表 高八位

uc code FREQH[]={0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,

                 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC,

                 0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,

                 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF} ;

//音阶频率表 低八位

uc code FREQL[]={0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,

                 0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F,

                 0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,

                 0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16};

//延时(单位ms)

void delayms(ui xms)

{

       ui i,j;

       for(i=xms;i>0;i--)

              for(j=110;j>0;j--);

}

//单音

void tone(uc note)

{

       H0=yin[note]/256;

       L0=yin[note]%256;

       TR0=1;

}

//数组左移

void left()

{

       uc i;

       for(i=0;i<7;i++)

       {

              duan[i]=duan[i+1];

       }

}

//显示

void show()

{

       uc i;

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

       {

              PB=wei[i];

              PA=duan[i];

              delayms(1);

       }

}

//T1延时1ms

void delay_T1(ui t)

{

       while(t--!=0)

       {

              TH1=0xFC;

              TL1=0x66;                   //定时1mS

              TR1=1;                        //开启T1

              while(!TF1);          //等待T1溢出

              TR1=0;                        //关闭T1

              TF1=0;                         //清除溢出标志位

       }

}

//节拍延时                                                                   

void delay_beat(uc t)

{

    uc i;

       for(i=0;i<t;i++)

           delay_T1(250);

    TR0=0;

}

//播放音乐

void song()

{

       uc i,k,t;

     i=0;

       PB=0x00;                                        //数码管全亮

       PA=0xff;                                    //数码管全亮

    while(i<96)

       {        

              k=MUSIC[i]+7*MUSIC[i+1]-1;   //去音符振荡频率所需数据

              H0=FREQH[k];

              L0=FREQL[k];

              t=MUSIC[i+2];                   //节拍时长

              i=i+3;

              TH0=H0;                              //赋值定时器时间,决定频率

              TL0=L0;

              TR0=1;                                  //打开定时器

              delay_beat(t);                             //延时所需要的节拍 

        }

}

//主函数

void main()

{

       COM=0x89;          //8255工作方式0,PA、PB输出,PC输入

       TMOD=0x11;

       EA=1;

       ET0=1;

       TR0=0;

       sounder=0;    

       while(1)

       {

              show();

              switch(PC)

              {

                     case 0xfe: tone(1);left();duan[7]=0x06;break;

                     case 0xfd: tone(2);left();duan[7]=0x5b;break;     

                     case 0xfb: tone(3);left();duan[7]=0x4f;break;     

                     case 0xf7: tone(4);left();duan[7]=0x66;break;

                     case 0xef: tone(5);left();duan[7]=0x6d;break;

                     case 0xdf: tone(6);left();duan[7]=0x7d;break;

                     case 0xbf: tone(7);left();duan[7]=0x07;break;

                     case 0x7f: tone(8);left();duan[7]=0x7f;break;

              }

              while(PC!=0xff)

                     show();        //key=0xff无键按下while(0)跳出循环,有键按下则执行循环

              TR0=0;

              sounder=0;

              if(play==0)

              {

                     PB=0x00;

                     PA=0x3f;

                     delayms(1000);            //等1秒

                     if(play==0)

                     {

                            PB=0x00;

                            PA=0x3f;

                            delayms(1000);      //再等1秒

                            if(play==0)

                                   song();  

                     }

              }                  

       }

}

void T0_time() interrupt 1

{

       TH0=H0;

       TL0=L0;

       sounder=~sounder;

}

3.3 Proteus仿真结果

以12345678分别表示单音DO、RE、MI、FA、SO、LA、XI、高音DO,依次按下若干按键后,结果如下图所示:

当长按自定义键2s时,数码管LED全部点亮,并播放音乐《两只老虎》

3基于VHDL的多人抢答器

3.1 芯片介绍

3.1.1 EPM7128

1.简介:EPM7128是可编程的大规模逻辑器件,为ALTERA公司的MAX7000系列产品,具有高阻抗、电可擦等特点,可用门单元为2500个,管脚间最大延迟为5ns,工作电压为+5V。

2.基本参数:

可编程逻辑类型:PLD

  逻辑芯片功能:Programmable ISP

  逻辑芯片基本号:7128

  输入/输出线数:84

  宏单元数:128

  频率:95.2MHz

  输入/输出接口标准:TTL, CMOS

  电源电压 最小:3V

  电源电压 最大:3.6V

  封装类型:TQFP

  工作温度范围:0°C to +85°C

  SVHC(高度关注物质):Cobalt dichloride

  IC标号:7128

  传播延迟时间:10ns

  器件标号:7128

  封装类型:剥式

  电源电压:3.3V

  表面安装器件:表面安装

  输入数:84

  逻辑功能号:7128

  针脚数:100

  门电路数:2500

3.2 QuartusII顶层原理图

3.3 各部分Verilog程序

3.3.1 抢答部分

module qiangda(clk,

                        key_in,

                        rst_n,reset1,

                        k1,k2,k3,k4,

               led

                       );

input clk;     

input [4:1]key_in;//四个抢答输入

input rst_n,reset1;    

output reg k1,k2,k3,k4;

output [4:1]led;

//reg [4:1]key_val;

reg lock;

always@(posedge clk or posedge rst_n or posedge reset1)

begin

if(rst_n|reset1)     

       begin

              lock <= 0;

              k1 <= 0;

              k2 <= 0;

              k3 <= 0;

              k4<= 0;

     end

else  

begin     

              if((key_in[1] == 1)&&(lock == 0))

                     begin

                            k1 <= 1;

                            lock <= 1;

                     end

               else if((key_in[2] == 1)&&(lock == 0))

                     begin

                            k2 <= 1;

                            lock <= 1;

                     end

               else if((key_in[3] == 1)&&(lock == 0))

                     begin

                            k3 <= 1;

                            lock <= 1;

                     end

               else if((key_in[4] == 1)&&(lock == 0))

                     begin

                           k4 <= 1;

                            lock <= 1;

                     end

                     else lock<=1;

end

end

      

assign led={~k4,~k3,~k2,~k1};          

endmodule

/*

//-----------按键消抖----------------------

reg [4:1] key_samp1, key_samp1_locked;

always @ (posedge clk , posedge rst_n)       

  if(rst_n)

    key_samp1 <= 4'h0;

  else        

    key_samp1 <= key_in;

// 将key_samp1锁存至key_samp1_locked

always @ (posedge clk, posedge rst_n)        

  if(rst_n)

    key_samp1_locked <= 4'h0;

  else        

    key_samp1_locked <= key_samp1;

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++

wire [4:1] key_changed1;

// 当key_samp1由1变为0时

// key_changed1由0变为1,只维持一个时钟周期

assign key_changed1 = key_samp1_locked & (~key_samp1);

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++

reg [15:0] cnt1;

// 一旦有按键按下,cnt立即被清零

always @ (posedge clk, posedge rst_n)

  if(rst_n)

    cnt1 <= 16'h0;                        

  else if(key_changed1)                    

    cnt1 <= 16'h0;

  else

    cnt1<= cnt1 + 1'b1;

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++

reg [4:1] key_samp2, key_samp2_locked;

// 只有当按键不变化(不抖动),且维持20ms      

always @ (posedge clk, posedge rst_n)

  if(rst_n)

    key_samp2 <= 4'h0;

  else if(cnt1 == 16'hFFFF)          

    key_samp2 <= key_in;

always @ (posedge clk, posedge rst_n)

  if(rst_n)

    key_samp2_locked <= 4'h0;

  else

    key_samp2_locked <= key_samp2;

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++

wire [4:1] key_changed2;

// 当key_samp2由1变为0时

// key_changed2由0变为1,只维持一个时钟周期

assign key_changed2 = key_samp2_locked & (~key_samp2);

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++

always @ (posedge clk, posedge rst_n)

  if(rst_n)

    key_val<= 4'h0;

  else

   key_val <=key_changed2;

//--------------------------------------

*/

//assign key_val=key_in;

3.3.2 计时部分

module t(

       clk,rst_n,

       k1,k2,k3,k4,reset1,

       t1,beep

);

input clk;

input rst_n,reset1;

input k1,k2,k3,k4;

output reg [7:0]t1;

output reg beep;

reg [3:0]t;

reg flag;                      

parameter T1S=22'd3_999_999;

reg [21:0]Count_t;

always@(posedge clk or posedge rst_n)

       begin  

    if(rst_n)

              Count_t<=22'd0;

       else if(Count_t==T1S)

              Count_t<=22'd0;

       else

              Count_t<=Count_t+1'b1;

    end

wire timer1 = Count_t[18];                   // 2^19/4M

wire timer2 = Count_t[20];                   // 2^21/4M

wire beep_en = timer1&timer2;

always@(posedge clk or posedge rst_n or posedge reset1)  //dao ji shi

              if(rst_n|reset1)

                  begin

                     t<=4'd9;

                     beep<=0;

                     end

              else if(k1|k2|k3|k4)

                         begin

                                   if(Count_t==T1S)

                                   begin

                                     if(t[3:0] != 4'b0000)

                                      begin

                                           t[3:0] <= t[3:0] - 4'b1;

                                       if(t==4'd4|t==4'd3)

                                          begin

                                                 if(beep_en)          

                                                        beep<=1;

                                                 else

                                                        beep<=0;

                                          end

                                      end

                                     else

                                      begin

                                          beep<=1;

                                          end

                                   end

                            end        

always@(t)                               //xian shi

       case(t)

          4'd0: t1=8'b11000000;

          4'd1: t1=8'b11111001;

          4'd2: t1=8'b10100100;

          4'd3: t1=8'b10110000;

          4'd4: t1=8'b10011001;

          4'd5: t1=8'b10010010;

          4'd6: t1=8'b10000011;

          4'd7: t1=8'b11111000;

          4'd8: t1=8'b10000000;

          4'd9: t1=8'b10011000; 

        default t1=8'b11111111;

        endcase             

endmodule                    

3.3.3 计分部分

module score(up,down,

             clk,rst_n,reset1,

                      k1, k2, k3, k4,

                      scorea, scoreb, scorec, scored

             );

input  up ;  //加分信号

input down; //减分信号

input clk;   //时钟信号

input rst_n; //复位信号

input reset1; //chong xin kai shi

input k1,k2,k3,k4;   

output reg [7:0]scorea, scoreb, scorec, scored ;

reg [3:0]score1, score2, score3, score4 ;

reg flag;

always@(posedge clk or posedge reset1 or posedge rst_n)

       if(reset1)

       begin

               score1 <= 4'd3;

               score2 <= 4'd3;

               score3 <= 4'd3;

               score4 <= 4'd3;

               flag<=1;

    end       

   else if(rst_n)

              flag<=1;

   else if(up==1&&flag==1)

              begin

                     flag<=0;

                     if(k1 == 1)

                            begin

                            if(score1== 4'b1001)

                            score1<= 4'b0;

                            else

                            score1<= score1+1'b1;

                            end

                     if(k2 == 1)

                            begin

                            if(score2== 4'b1001)

                            score2<= 4'b0;

                            else

                            score2 <= score2 + 1'b1;

                            end

                     if(k3 == 1)

                            begin

                            if(score3 == 4'b1001)

                                   score3 <= 4'b0;

                            else

                                   score3<= score3 + 1'b1;

                            end

                     if(k4 == 1)

                            begin

                            if(score4 == 4'b1001)

                                   score4 <= 4'b0;

                            else

                                   score4<= score4 + 1'b1;

                            end 

              end

else if(down==1&&flag==1)

              begin

              flag<=0;

              if(k1 == 1&&score1!= 4'b0000)

                     score1 <= score1 - 1'b1;

        if(k2 == 1&&score2!=4'b0000)

                     score2 <= score2 - 1'b1;

             if(k3 == 1&&score3!=4'b0000)

                     score3 <= score3 - 1'b1;

              if(k4 == 1&&score4!=4'b0000)

                     score4 <= score4 - 1'b1;

              end

always@(score1)

       case(score1)

          4'd0: scorea=8'b11000000;

          4'd1: scorea=8'b11111001;

          4'd2: scorea=8'b10100100;

          4'd3: scorea=8'b10110000;

          4'd4: scorea=8'b10011001;

          4'd5: scorea=8'b10010010;

          4'd6: scorea=8'b10000011;

          4'd7: scorea=8'b11111000;

          4'd8: scorea=8'b10000000;

          4'd9: scorea=8'b10011000;

        default scorea=8'b11111111;

        endcase

always@(score2)

       case(score2)

          4'd0: scoreb=8'b11000000;

          4'd1: scoreb=8'b11111001;

          4'd2: scoreb=8'b10100100;

          4'd3: scoreb=8'b10110000;

          4'd4: scoreb=8'b10011001;

          4'd5: scoreb=8'b10010010;

          4'd6: scoreb=8'b10000011;

          4'd7: scoreb=8'b11111000;

          4'd8: scoreb=8'b10000000;

          4'd9: scoreb=8'b10011000;

        default scoreb=8'b11111111;

        endcase         

always@(score3)

       case(score3)

          4'd0: scorec=8'b11000000;

          4'd1: scorec=8'b11111001;

          4'd2: scorec=8'b10100100;

          4'd3: scorec=8'b10110000;

          4'd4: scorec=8'b10011001;

          4'd5: scorec=8'b10010010;

          4'd6: scorec=8'b10000011;

          4'd7: scorec=8'b11111000;

          4'd8: scorec=8'b10000000;

          4'd9: scorec=8'b10011000;

        default scorec=8'b11111111;

        endcase                  

always@(score4)

       case(score4)

          4'd0: scored=8'b11000000;

          4'd1: scored=8'b11111001;

          4'd2: scored=8'b10100100;

          4'd3: scored=8'b10110000;

          4'd4: scored=8'b10011001;

          4'd5: scored=8'b10010010;

          4'd6: scored=8'b10000011;

          4'd7: scored=8'b11111000;

          4'd8: scored=8'b10000000;

          4'd9: scored=8'b10011000; 

        default scored=8'b11111111;

        endcase         

endmodule

更多相关推荐:
产品设计报告书

郑州航空工业管理学院《人机工程学》课程设计报告书09级工业设计专业0914061班级题目:卡通挖耳勺设计报告书姓名:袁**学号:***指导教师二ОXX年10月27日目录1.市场调研与现有市场分析1.1挖耳勺的市…

设计总结报告

设计工作报告中交第一公路勘察设计研究院有限公司设计工作总结高速公路起点K15168段工程已全部完工该段工程无论在外部几何尺寸还是内在质量上均达到了设计要求较好地执行了设计意图设计单位中交第一公路勘察设计研究院有...

设计报告格式及要求

设计报告格式及要求一报告的基本格式与层次编排1基本格式报告题目居中3号黑体摘要顶格小4宋加粗或小4黑摘要正文200300字可另起行也可与摘要2字之间空1字接排小4宋体关键词35个顶格小4宋体关键词与正文之间空两...

设计报告格式

吉林师范大学博达学院计算机与信息科学系课程设计报告课程名称设计题目画笔程序专业信息科学技术姓名李瑞雪班级学号指导教师侯锟吕凯20xx年3月目录课程设计题目审批表2完成情况一览表3摘要4一设计分析5二设计要求5三...

实验设计报告心得体会精选

部分学生的反应按时打算大三的实验心得体会在做测试技术的实验前我以为不会难做就像以前做物理实验一样做完实验然后两下子就将实验报告做完直到做完测试实验时我才知道其实并不容易做但学到的知识与难度成正比使我受益匪浅在做...

项目设计报告

江阴职业技术学院项目设计报告项目:数字钟的设计与实现专业应用电子技术专业学生姓名**班级09应用电子(2)班学号**指导教师**完成日期20XX年4月30日摘要近年来随着计算机在社会领域的渗透和大规模集成电路的…

设计报告模板

Java与面向对象技术课程设计报告20xx20xx年度第1学期日历记事本专业计算机科学与技术朱浩M计算机1221251404214许秋艳20xx年11月11日学生姓名班学级号指导教师完成日期目录1概述111课程...

全国大学生电子设计竞赛设计报告格式及要求

设计报告格式及要求一报告的基本格式与层次编排1基本格式报告题目居中3号黑体摘要顶格小4宋加粗或小4黑摘要正文200300字可另起行也可与摘要2字之间空1字接排小4宋体关键词35个顶格小4宋体关键词与正文之间空两...

C++设计报告

C课程设计班级通信0702姓名学号020xx05230指导老师摘要C是由C发展而来的与C兼容所以它可以用于面向过程的结构化程序设计但是它又有自己的特点它也可以用于面向对象的程序设计是一种功能强大的混合型的程序设...

设计报告

1工程设计概述11工程概况南盘石水库电站位于永福溪主干流中游地处漳平市永福镇官田乡境内是永福溪流域开发的第三级枢纽工程坝址座落在永福镇南盘石村下游约10km处的峡谷距漳平城区39km厂址位于官田乡下浙村上游05...

博客网站的设计报告

第一章绪论11课题的提出原因及意义越来越多的网络用户希望能够在网络平台上更多地展现自己的个性更方便地与人互动交流在传统的WEB10时代无论是论坛社区还是个人网站都试图在这些方面进行努力随着WEB20时代的到来一...

报告,,设计

天津职业技术师范大学电子工程学院电子技术课程设计报告同组学生姓名学号付磊3刘俞辰9陈小伟23谭鹏37班级应电0914任务分工设计电路付磊电路焊接付磊刘俞辰谭鹏实验报告付磊陈小伟设计时间20xx年12月13日20...

设计报告(28篇)