找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2406|回复: 0
收起左侧

51单片机实现音阶(可调高低音)Proteus仿真代码

[复制链接]
ID:769558 发表于 2021-4-11 21:13 | 显示全部楼层 |阅读模式
51单片机实现音阶,可放歌曲
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png

单片机源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>

  3. #define keyport P1
  4. #define out P0
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. uchar high,low;           //定时器预装值的高8位和低8位

  8. sbit S1 =P1^0;  // 按键
  9. uchar keyvalue; // 键值

  10. uchar code name[] ="Chen xin chen";//显示名字
  11. uchar code stu_num[] =" 1111120028";//显示学号

  12. sbit RS  = P2^0;   //  数据或指令控制线
  13. sbit RW  = P2^1;   // 读写控制线
  14. sbit E   = P2^2;   //使能控制线
  15. /*********************
  16. 延时函数
  17. *********************/
  18. void delay(uint j)
  19.   {
  20.   uchar i = 250;
  21.   for(;j>0;j--)
  22.   {
  23.    while (--i);
  24.    i= 249;
  25.    while(--i);
  26.    i=250;
  27.   }
  28. }
  29. /*********************
  30. 检查忙函数,检查LCD是否处于忙状态
  31. 如果处于忙则持续检查
  32. *********************/
  33. void check_busy(void)
  34. {
  35.     uchar temp;
  36.     do{
  37.         temp =0xff;  //
  38.         E = 0;
  39.         RS= 0;   //
  40.         RW = 1;
  41.         E =1;
  42.         temp = out; //
  43.                         }while(temp&0x80);  // 如果 BF =1 则持续检查
  44.         E = 0;
  45. }
  46. /*********************
  47. 写命令函数
  48. *********************/
  49. void write_command(uchar com)
  50. {
  51.     check_busy();//  首先检查忙
  52.    E= 0;//预置0
  53.    RS =0;
  54.    RW =0; //按LCD写命令控制信号设置
  55.    out = com;
  56.    E =1; //  正脉冲
  57.    _nop_();//
  58.    E = 0; // 还原E
  59.     delay(1);
  60. }
  61. /********************
  62. 写数据函数
  63. ********************/
  64. void write_data(uchar com)
  65. {
  66.   check_busy();
  67.   E=0;    //预置0
  68.   RS= 1;
  69.   RW =0;//按LCD写数据控制信号设置
  70.   out = com;
  71.   E=1;// 正脉冲
  72.   _nop_();
  73.   E =0;
  74. delay(1);
  75.   }
  76. /********************
  77. LCD初始化函数
  78. ********************/  
  79. void lcd_initial(void) //
  80. {
  81.   write_command(0x38); // 八位数据,双列显示,5X7阵
  82.         _nop_();
  83.   write_command(0x0c); //开显示屏,关光标,光标不显示
  84.         _nop_();
  85.   write_command(0x06); //字符不移动,每次字符地址加1
  86.         _nop_();
  87.   write_command(0x01); //清屏
  88.         _nop_();
  89.         delay(100);
  90.   }
  91. /********************
  92. //字符串显函数
  93. ********************/
  94. void string(uchar add, uchar *s) reentrant
  95. {
  96.          write_command(add);//显示地址
  97.          while(*s != '\0')
  98.         {
  99.           write_data(*s++);
  100.         }
  101. }
  102. void interrupt_int(void)
  103. {
  104.         EA =1;//总中断允许
  105.         EX0 =1;//外部中断打开
  106.         EX1 =1;//
  107.         IT0=1;//负跳变
  108.         IT1 =1;//
  109.         IP =0;//同一优先级
  110.         }
  111. void key_1(void) interrupt 0
  112. {
  113. EX0 =0;
  114. lcd_initial();
  115. string(0x83,name); //第一行第四个开始显示学号
  116. string(0xc2,stu_num);//第二行第三个开始显示姓名
  117. EX0 =1;//开启中断
  118. }



  119. sbit speak=P3^0;
  120. sbit gao=P3^5;
  121. sbit di=P3^6;
  122. sbit zdbf=P3^7;
  123. uchar yinjie=1;
  124. uchar time;
  125. uchar n=0;
  126. uchar bo=0;
  127. uchar code fre[][2]= {   0x8c,0xf8,0x5b,0xf9,0x15,0xfa,0x67,0xfa,0x90,0xfb,0xae,0xfb,0x0c,0xfc,  //低音
  128.           0x44,0xfc,0xac,0xfc,0x09,0xfd,0x34,0xfd,0x82,0xfd,0xc2,0xfd,0x06,0xfe, //中音
  129.         0x22,0xfe,0x56,0xfe,0x85,0xfe,0x9a,0xfe,0xc1,0xfe,0xe4,0xfe,0x03,0xff,        //高音
  130.                                           };

  131. void delay(uint );
  132. void ITimer0(void);//定时器初始化
  133. void key(void);
  134. void dtxs(int,int);
  135. void song()
  136. {
  137. TH0=high;
  138. TL0=low;
  139. TR0=1;
  140. delay(time*240);                       
  141. }
  142. void yinyue()//小星星歌曲
  143. {
  144. uchar code hls[]={  1,2,2, 1,2,3, 5,2,2, 5,2,3, 6,2,2, 6,2,3, 5,2,4, 4,2,2, 4,2,3, 3,2,2 ,3,2,3 ,2,2,2, 2,2,3, 1,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4};
  145.         uchar m;
  146.         n=0;
  147.       while(n<174)
  148.           {
  149.                   m=hls[n]+7*(hls[n+1]-1)-1;
  150.                 high=fre[m][1];
  151.                 low=fre[m][0];
  152.                 time=hls[n+2];
  153.                 n=n+3;
  154.                 song();               
  155.            }
  156. }                                       
  157. void main (void)
  158. {
  159.         

  160.         

  161.         uchar num;
  162.         ITimer0();
  163.         speak=0;


  164. interrupt_int();
  165.         

  166. while(1)
  167.         {
  168.                 key();
  169.                 switch(keyport)
  170.                 {
  171.                         case 0xfe:num=1;break;
  172.                         case 0xfd:num=2;break;
  173.                         case 0xfb:num= 3;break;
  174.             case 0xf7:num= 4;break;
  175.             case 0xef:num= 5;break;
  176.             case 0xdf:num= 6;break;
  177.             case 0xbf:num= 7;break;
  178.             case 0x7f:num= 8;break;
  179.             default:num= 0;break;
  180.                 }
  181.                 if(num==0)
  182.                 {
  183.                         TR0=0;
  184.                         speak=0;
  185.                 }
  186.                 else
  187.                 {
  188.                         high=fre[7*yinjie+num-1][1];
  189.                         low=fre[7*yinjie+num-1][0];
  190.                         TR0=1;
  191.                 }
  192.                 dtxs(yinjie,num);
  193.         }
  194. }
  195. void ITimer0(void)
  196. {
  197. TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                    
  198. EA=1;            //总中断打开
  199. ET0=1;           //定时器中断打开
  200. TR0=1;           //定时器开关打开
  201. }
  202. void Timer0_isr(void) interrupt 1
  203. {
  204. TH0=high;
  205. TL0=low;
  206. speak=!speak;
  207. if(zdbf==0)
  208.      {
  209.                  delay(100);
  210.                 if(zdbf==0)
  211.                 {
  212.                            bo++;
  213.                           if(bo/2==1)
  214.                                 {        delay(100);
  215.                                         if(n<174)n=500;                        //n赋值大于174,跳出while,停止音乐
  216.                                         else n=0;
  217.                                         dtxs(3,0);
  218.                                 }
  219.                                 if(bo%2==0)
  220.                                 {        delay(100);
  221.                                         n=500;                        //n赋值大于174,跳出while,停止音乐
  222.                                 }
  223.                 }
  224.         }/**/
  225. }
  226. void key()//按键
  227. {
  228.         if(zdbf==0)
  229.                {delay(100);
  230.                   if(zdbf==0)        
  231.                         yinyue();
  232.                 }
  233.         if(gao==0)
  234.         {
  235.                 delay(100);
  236.                 if(gao==0)
  237.                 {
  238.                         delay(100);
  239.                         if(yinjie==2)
  240.                                 yinjie=1;
  241.                         else yinjie=2;
  242.                 }
  243.         }
  244.     if(di==0)
  245.         {
  246.                 delay(100);
  247.                 if(di==0)
  248.                 {
  249.                         delay(100);
  250.                         if(yinjie==0)
  251.                                 yinjie=1;
  252.                         else yinjie=0;
  253.                 }
  254.         }
  255. }

  256. void dtxs(k,l)//k是按键号,l是工作方式
  257. {
  258. char seg[14]={ 0x3F,/*0*/
  259.         0x06,/*1*/
  260.         0x5B,/*2*/
  261.         0x4F,/*3*/
  262.         0x66,/*4*/
  263.         0x6D,/*5*/
  264.         0x7D,/*6*/
  265.         0x07,/*7*/
  266.         0x7F,/*8*/
  267.         0x6F,/*9*/
  268.                 0x37,/*N*/        
  269.                 0x38,/*L*/
  270.         0x76,/*H*/
  271.                   0x79
  272. };
  273.   P2=0x01;//选择第一个数码管
  274.   P0=seg[l];//显示按键号
  275.   delay(4);
  276.   P2=0x02;//选择第二个数码管
  277.   P0=seg[k+10];//显示工作方式
  278.   delay(4);

  279. }
复制代码

所有资料51hei提供下载:
仿真.7z (100.06 KB, 下载次数: 22)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表