51单片机实验,电子琴

51单片机实验,电子琴

实验是可播放音乐可演奏的电子琴。可分别播放内部存储的三首歌曲,或者通过按键弹奏音乐。屏幕在弹奏音乐时显示姓名学号,在播放音乐时显示歌曲名字。

原理图

单片机实验

实验代码

  1. #include<reg51.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define LCDPORT P0
  6. sbit BEEP = P3 ^ 7;//把p3接口用BEEP表示,下同
  7. sbit BEEP1 = P3 ^ 0; //???
  8. sbit BEEP2 = P3 ^ 4;
  9. sbit LCDE = P2 ^ 2;
  10. sbit LCDRW = P2 ^ 1;
  11. sbit LCDRS = P2 ^ 0;
  12. sbit BCD1= P2 ^ 5;
  13. sbit BCD2 = P2 ^ 6;
  14. sbit BCD3 = P2 ^ 7;
  15. sbit BCD4 = P2 ^ 8;
  16. uchar KeyNo; //???
  17. //???
  18. unsigned char code name[] = " zhaeng";//定义数组,名字
  19. unsigned char code num[] = " 211691";//定义数组,学号
  20. unsigned char code tab1[] = “PLAYING MUSIC IS”;//定义数组显示歌曲
  21. unsigned char code tab2[] = “TWO TIGER”;//歌曲名字,下同
  22. unsigned char code tab3[] = “THE TONE IS”;
  23. unsigned char code tab4[] = “TWO BUFFER”;
  24. uint code Tone_Delay_Table1[] =//定义音符延时表,用于按键播放音乐
  25. { 64021,64103,64260,64400,64524,64580,64684,64777,
  26. 64820,64898,64968,65030,65058,65110,65157,65178 };
  27. uint code Tone_Delay_Table[] =//定义音符延时表,用于播放音乐
  28. { 62018,62401,62491,62895,63184,63441,63506,
  29. 63773,63965,64137,64215,64360,64488,64603,
  30. 64654,64751,64836,64876,64948,65012,65067,65535 };
  31. uchar code Song1_Tone[] =//歌曲一的音调
  32. { 13,0,13,1,13,2,13,0,13,0,13,1,13,2,13,0,13,2,13,3,
  33. 13,4,13,13,13,2,13,3,13,4,13,13,13,4,5,4,3,2,13,0,
  34. 13,4,5,4,3,2,13,0,13,2,13,11,13,0,13,13,2,13,11,13,0,13,13,0xFF };
  35. uchar code Song1_Time[] =//歌曲一的时间,下同
  36. { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  37. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  38. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  39. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xFF };
  40. uchar code Song2_Tone[] = {
  41. 13,0,0,4,4,5,5,4,13,3,3,2,2,1,1,0,13,4,4,3,3,2,2,1,13,4,4,3,3,2,2,1,0xFF };
  42. uchar code Song2_Time[] = {
  43. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0xFF };
  44. uchar code Song3_Tone[] = {
  45. 13,2,2,3,4,4,3,2,1,0,0,1,2,2,1,1,13,2,2,3,4,4,3,2,1,0,0,1,2,1,13,0,0,13,1,1,2,0,1,3,2,0,1,3,2,1,0,1,12,13,0xFF };
  46. uchar code Song3_Time[] = {
  47. 3,3,3,3,3,3,3,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0xFF };
  48. uchar Song_Index = 0, Tone_Index = 0;//音乐片段索引,音符索引
  49. uchar* Song_Tone_Pointer, * Song_Time_Pointer;//音符指针和延时指针
  50. uchar tool = 0;//工具人
  51. uchar* trans = &tool;//定义指针,用于匹配歌曲和屏幕显示
  52. uchar i = 0;
  53. void DelayMS(uint ms)//音乐播放的延时
  54. {
  55. uchar t;  
    
  56. while (ms--) for (t = 0; t < 120; t++);  
    
  57. }
  58. //*****************
  59. void Delay()//屏幕显示的延时
  60. {
  61. uint uiCount;  
    
  62. for (uiCount = 0; uiCount < 250; uiCount++);  
    
  63. }
  64. void WriteCMD(uchar Command)//屏幕显示部分已经讲过
  65. {
  66. Delay();      
    
  67. LCDE = 1;       
    
  68. LCDRS = 0;  
    
  69. LCDRW = 0;  
    
  70. LCDPORT = Command;    
    
  71. Delay();  
    
  72. LCDE = 0;       
    
  73. }
  74. void WriteData(uchar dat)
  75. {
  76. Delay();        
    
  77. LCDE = 1;        
    
  78. LCDRS = 1;  
    
  79. LCDRW = 0;  
    
  80. LCDPORT = dat;      
    
  81. LCDE = 0;        
    
  82. }
  83. void inicry()
  84. {
  85. LCDRW = 0;  
    
  86. LCDE = 0;  
    
  87. WriteCMD(0x38);  
    
  88. WriteCMD(0x0f);  
    
  89. WriteCMD(0x07);  
    
  90. WriteCMD(0x01);  
    
  91. }
  92. void mydelay(int x)
  93. {
  94. int i, y;  
    
  95.    for (i = x; i > 0; i--)  
    
  96.        for (y = 255; y > 0; y--);  
    
  97. }
  98. void Key_Press() interrupt 0//外部中断控制的音乐切换
  99. {
  100.    TR0 = 0;/*定时器开始和启动的标志,  
    
  101.            任何时刻,当TR0/TR1为1时,T0/T1定时器计数;  
    
  102.            当TR0/TR1为0时,T0 定时器停止计数。*/  
    
  103.    Song_Index = (Song_Index + 1) % 3;//切换到下一个音乐,因为只有3首  
    
  104.    switch (Song_Index)//通过switch case来选择音乐  
    
  105.    {  
    
  106.    case 0: Song_Tone_Pointer = Song1_Tone;  
    
  107.        Song_Time_Pointer = Song1_Time;  
    
  108.        *trans = 0;//屏幕与歌曲的匹配  
    
  109.        break;  
    
  110.    case 1: Song_Tone_Pointer = Song2_Tone;  
    
  111.        Song_Time_Pointer = Song2_Time;  
    
  112.        *trans = 1;  
    
  113.        break;  
    
  114.    case 2: Song_Tone_Pointer = Song3_Tone;  
    
  115.        Song_Time_Pointer = Song3_Time;  
    
  116.        *trans = 2;  
    
  117.        break;  
    
  118.    }  
    
  119.    i = 0;//从另一个音乐第0个音符开始  
    
  120.    TR0 = 1;//定时器开始。作用是让外部中断的优先级更高  
    
  121. }
  122. //–通过T0定时器控制播放
  123. void Timer0_Play_Music() interrupt 1
  124. {
  125.    BEEP2 = 0xFF;//判断是模式1还是2  
    
  126.    if (BEEP2 != 0XFF)  
    
  127.    {  
    
  128.        TH0 = Tone_Delay_Table[Tone_Index] / 256;  
    
  129.        TL0 = Tone_Delay_Table[Tone_Index] % 256;  
    
  130.        BEEP = ~BEEP;对应不同的播放器  
    
  131.    }  
    
  132.    else  
    
  133.    {  
    
  134.        TH0 = Tone_Delay_Table1[KeyNo] / 256;  
    
  135.        TL0 = Tone_Delay_Table1[KeyNo] % 256;  
    
  136.        BEEP1 = ~BEEP1;  
    
  137.    }  
    
  138. }
  139. //————————————————
  140. //键盘矩阵扫描
  141. //---------------------------------------------------------------------------------------------------
  142. void Keys_Scan()
  143. {
  144.    uchar Tmp, k;  
    
  145.    //高四位置0,放入四行  
    
  146.    P1 = 0x0F;//p18对应的最高位,p10对应的最低位  
    
  147.    DelayMS(2);  
    
  148.    //按键后,00001111变成0000xxxx。x中有1个0,3个1  
    
  149.    //下面的异或操作,讲0变成1,将1变成0  
    
  150.    Tmp = P1 ^ 0x0F;  
    
  151.    //相同的变0,不同的变1  
    
  152.    //判断按键发生在0-3的哪一列  
    
  153.    switch (Tmp)  
    
  154.    {  
    
  155.    case 1:k = 0; break;  
    
  156.    case 2:k = 1; break;  
    
  157.    case 4:k = 2; break;  
    
  158.    case 8:k = 3; break;  
    
  159.    default:return;    //没有按键按下  
    
  160.    }  
    
  161.    //低四位置0,放入四列  
    
  162.    P1 = 0XF0;  
    
  163.    DelayMS(2);  
    
  164.    //按键后,11110000变成xxxx0000。x中有1个0,3个1  
    
  165.    //下面的操作会将高四位移动到低四位,并将唯一的0变为1  
    
  166.    Tmp = (P1 >> 4) ^ 0X0F;//>>:是整数位操作运算符中的右移运算符  
    
  167.    //对0-3行分别赋初始值,0,4,8,12  
    
  168.    switch (Tmp)  
    
  169.    {  
    
  170.    case 1:k += 0; break;  
    
  171.    case 2:k += 4; break;  
    
  172.    case 4:k += 8; break;  
    
  173.    case 8:k += 12; break;  
    
  174.    default:return;  
    
  175.    }  
    
  176.    KeyNo = k;//这个时候的k就是按键的名字  
    
  177. }
  178. //---------------------------------------------------------------------------------------------------
  179. //---------------------------------------------------------------------------------------------------
  180. /*void Play_Tone() interrupt 1
  181. {
  182.    TH0 = Tone_Delay_Table1[KeyNo] / 256; 
    
  183.    TL0 = Tone_Delay_Table1[KeyNo] % 256; 
    
  184.    BEEP1 = ~BEEP1; 
    
  185. }*/
  186. //-------------------------------------------------------------------------------
  187. void main()
  188. {
  189.    uchar y, x, z;  
    
  190.    TMOD = 0x01;//定时器均工作在模式一(片内部的寄存器)  
    
  191.    IP = 0x01;//INT0设为高优先级  
    
  192.    IE = 0x83;//允许INT0和T0中断  
    
  193.    TR0 = 0;//定时器停止  
    
  194.    Song_Tone_Pointer = Song1_Tone;//给指针指向1  
    
  195.    Song_Tone_Pointer = Song1_Time;//  
    
  196.    inicry();//屏幕初始化  
    
  197.    while (1)  
    
  198.    {  
    
  199.        BEEP2 = 0xFF;//选定模式1还是2  
    
  200.        if (BEEP2 != 0XFF)//模式1,播放音乐,BEEP2按下了  
    
  201.        {  
    
  202.            BCD1 = 1; BCD2 = 0; BCD3 = 0; BCD4 = 0;  
    
  203.            WriteCMD(0x80);/*这个是1602的程序bai,每行16个显示单元, 
    
  204.                           第一行地址du从0x80~0x80+16,第二行0xc0~0xc0+16*/  
    
  205.            for (y = 0; y < 16; y++)  
    
  206.            {  
    
  207.                WriteData(tab1[y]);//写这首歌是啥这句话  
    
  208.                mydelay(5);  
    
  209.            }  
    
  210.            //Tone_Index = Song_Tone_Pointer[i];//判断是第几个音符  
    
  211.            if (tool == 0)//是第一首歌,进行的屏幕操作  
    
  212.            {  
    
  213.                WriteCMD(0x80 + 0x40);  
    
  214.                for (z = 0; z < 9; z++)  
    
  215.                {  
    
  216.                    WriteData(tab2[z]);       
    
  217.                    mydelay(5);  
    
  218.                }  
    
  219.            }  
    
  220.            if (tool == 1)  
    
  221.            {  
    
  222.                WriteCMD(0x80 + 0x40);  
    
  223.                for (z = 0; z < 10; z++)  
    
  224.                {  
    
  225.                    WriteData(tab3[z]);       
    
  226.                    mydelay(5);  
    
  227.                }  
    
  228.            }  
    
  229.            if (tool == 2)  
    
  230.            {  
    
  231.                WriteCMD(0x80 + 0x40);  
    
  232.                for (z = 0; z < 10; z++)  
    
  233.                {  
    
  234.                    WriteData(tab4[z]);  
    
  235.                    mydelay(5);  
    
  236.                }  
    
  237.            }  
    
  238.            Tone_Index = Song_Tone_Pointer[i];//判断是第几个音符  
    
  239.            if (Tone_Index == 0xFF)//到结束了,最后一个字符了  
    
  240.            {  
    
  241.                i = 0;//从第一个字符开始  
    
  242.                DelayMS(2000);//每首歌播放完之后停顿一会  
    
  243.                continue;//继续播放  
    
  244.            }  
    
  245.            TR0 = 1;//定时器工作  
    
  246.            DelayMS(Song_Time_Pointer[Tone_Index] * 240);//延时,每个时间段乘以240  
    
  247.            TR0 = 0;//定时器开始。通过T0来控制频率。延时的时间段就是定时器响的时间段  
    
  248.            i++;//字符向后走  
    
  249.        }  
    
  250.        else//模式2  
    
  251.        {  
    
  252.            BCD1 = 0; BCD2 = 1; BCD3 = 0; BCD4 = 0;  
    
  253.            P1 = 0XF0;//设定初值,判断是否扫描   
    
  254.            /*p1端口接一组按键,如果按键中有一个或者多个按下时,即使P1被赋值,也会改变*/  
    
  255.            if (P1 != 0XF0)//有按键按下,p1是不等于这个的                             
    
  256.            {  
    
  257.                Keys_Scan();                        
    
  258.                TR0 = 1;   //     启用定时器,根据KeyNo发音                          
    
  259.            }  
    
  260.            else  
    
  261.            {  
    
  262.                TR0 = 0;//没有按键按下,停止发音                
    
  263.            }  
    
  264.            DelayMS(2);  
    
  265.            WriteCMD(0x80);//下面是写名字和学号  
    
  266.            for (y = 0; y < 13; y++)  
    
  267.            {  
    
  268.                WriteData(name[y]);  
    
  269.                mydelay(10);  
    
  270.            }  
    
  271.            mydelay(5);  
    
  272.            WriteCMD(0x80 + 0x40);  
    
  273.            for (z = 0; z < 14; z++)  
    
  274.            {  
    
  275.                WriteData(num[z]);  
    
  276.                mydelay(10);  
    
  277.            }  
    
  278.            mydelay(5);  
    
  279.            for (x = 0; x < 19; x++)  
    
  280.            {  
    
  281.                WriteCMD(0x18);  
    
  282.                mydelay(5);  
    
  283.            }  
    
  284.            mydelay(5);  
    
  285.        }  
    
  286.    }  
    
  287. }

流程图

流程图

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值