单片机音乐——生日歌(汇编)
- 格式:doc
- 大小:29.00 KB
- 文档页数:2
51单片机课程设计蜂鸣器(生日歌)+温度计+计数器(可调时间)+花样流水灯(6种)#include<reg52.h>#include<intrins.h>#include<stdlib.h>#define uchar unsigned char#define uint unsigned int#define led P1 //将P1口定义位8个leduchar a, count, S1num, xqnum, temp, j, tm, key, coun, L, qdq, mb; //定义变量char yue, ri, shi, fen, miao; //定义月日时分秒int nian; //定义年// ==================定义初始化日历uchar code table0[] = "2020-09-4--FRI--";uchar code table1[] = "08:48:00";uchar code xingqi[][3] = { "MON","TUE","WED","THU","FRI","SAT","SUN" };uint led1[]={0x7e,0xbd,0xdb,0xe7,0xff};// ==================定义初始化日历sbit lcdrs=P2^6; //将lcd1602的RS端口(数据/命令选择端)定义到P2.0 sbit lcdrw=P2^7; //将lcd1602的R/W端口(读/写选择端)定义到P2.1 sbit lcden=P2^5; //将lcd1602的E端口(使能端口)定义到P2.2sbit DQ=P3^7;//ds18b20sbit S1=P3^1; //进入设置退出设置sbit S2=P3^2; //+1 或秒表模式sbit S3=P3^3; //-1 或开始秒表计时sbit S0=P3^0; //进入设置退出设置sbit S4=P3^4; //灯模式切换sbit S5=P3^5;sbit beep = P2^2; //定义蜂鸣器uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0};uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0};//延时unsigned char code str2[16]={" "};uchar data disdata[5];uint value;//温度值温度值uchar flag;//正负标志正负标志void delay1ms(unsigned int ms)//延时1毫秒{unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void write_com1(unsigned char com1)//写指令//{ delay1ms(1);lcdrs=0;lcdrw=0;lcden=0;P0=com1;delay1ms(1);lcden=1;delay1ms(1);lcden=0;}void write_dat1(unsigned char dat1)//写数据// { delay1ms(1);lcdrs=1;lcdrw=0;lcden=0;P0=dat1;delay1ms(1);lcden=1;delay1ms(1);lcden=0;}void lcd_init()//初始化设置//{write_com1(0x38);delay1ms(5);write_com1(0x08);delay1ms(5);write_com1(0x01);delay1ms(5);write_com1(0x06);delay1ms(5);write_com1(0x0c);delay1ms(5);}void display(unsigned char *p)//显示{while(*p!='\0'){write_dat1(*p);p++;delay1ms(1);}}init_play()//初始化显示{lcd_init();write_com1(0xc0);display(str2);}void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{unsigned char x=0;DQ = 1;//DQ复位delay_18B20(4);//延时DQ=0;//DQ拉低delay_18B20(100);//精确延时大于480usDQ=1;//拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{unsigned char i=0;unsigned char dat1 = 0;for (i=8;i>0;i--){DQ = 0; //给脉冲信号dat1>>=1;DQ=1;//给脉冲信号if(DQ)dat1|=0x80;delay_18B20(10);}return(dat1);}void ds1820wr(uchar wdata)/*写数据*/ {unsigned char i=0;for(i=8;i>0;i--){DQ=0;DQ=wdata&0x01;delay_18B20(10);DQ=1;wdata>>=1;}}read_temp()/*读取温度值并转换*/ {uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/?ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();value=b;value<<=8;value=value|a;if(value<0x0fff)flag=0;else{value=~value+1;flag=1;}value=value*(0.625);//温度值扩大10倍,精确到1位小数return(value);}/*******************************************************************/ void ds1820disp()//温度值显示{uchar flagdat;disdata[0]=value/1000+0x30;//百位数disdata[1]=value%1000/100+0x30;//十位数disdata[2]=value%100/10+0x30;//个位数disdata[3]=value%10+0x30;//小数位if(flag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}write_com1(0xc8);write_dat1(flagdat);//显示符号位write_com1(0xc9);write_dat1(disdata[0]);//显示百位write_com1(0xca);write_dat1(disdata[1]);//显示十位write_com1(0xcb);write_dat1(disdata[2]);//显示个位write_com1(0xcc);write_dat1(0x2e);//显示小数点write_com1(0xcd);write_dat1(disdata[3]);//显示小数位}void delay(uint t) //@12.000MHz延时函数{uint x, y;for (x = t; x > 0; x--)for (y = 110; y > 0; y--);}void DelayMS(uint x){uchar t;while(x--) for(t=0;t<120;t++);}void PlayMusic(){uint i=0,j,k;while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) { //播放各个音符,SONG_LONG 为拍子长度for(j=0;j<SONG_LONG[i]*20;j++){beep=~beep;//SONG_TONE 延时表决定了每个音符的频率for(k=0;k<SONG_TONE[i]/3;k++);}DelayMS(10);i++;}}//======================液晶void write_com(uchar com) //液晶写指令{lcdrw = 0;lcdrs = 0;P0 = com;delay(2);lcden = 1;delay(2);lcden = 0;}void write_data(uchar dat) //液晶写数据{lcdrw = 0;lcdrs = 1;P0 = dat;delay(2);lcden = 1;delay(2);lcden = 0;}void write_sfm(uchar add, uchar dat) //写时分秒函数{uchar shi, ge;shi = dat / 10;ge = dat % 10;write_com(0x80 + 0x40 + add);write_data(0x30 + shi);write_data(0x30 + ge);}void write_yr(uchar add, uchar dat) //写月日函数{uchar shi, ge;shi = dat / 10;ge = dat % 10;write_com(0x80 + add);write_data(0x30 + shi);write_data(0x30 + ge);}void write_nian(uchar add, uint dat) //写年函数{uint qian, bai, shi, ge;qian = dat / 1000;bai = dat % 1000 / 100;shi = dat % 100 / 10;ge = dat % 10;write_com(0x80 + add);write_data(0x30 + qian);write_data(0x30 + bai);write_data(0x30 + shi);write_data(0x30 + ge);}void init_lcd() //液晶初始化{lcden = 0;nian = 2020;yue = 1;ri = 3;shi = 0; //初始shi、fen、miaofen = 0;miao = 0;write_com(0x38); //设置16x2显示,5x7点阵,8位数据口write_com(0x0c); //设置开显示,不显示光标write_com(0x06); //写一个字符后地址指针加1write_com(0x01); //显示清0,数据指针清0}//==================液晶void init() //总初始化函数{init_lcd(); //液晶初始化write_com(0x80); //设置显示初始坐标for (a = 0; a < 14; a++) //显示年月日初始值{write_data(table0[a]);delay(3);}write_com(0x80 + 0x40); //设置显示初始坐标for (a = 0; a < 8; a++) //显示时分秒初始值{write_data(table1[a]);delay(3);}write_nian(0, nian);write_sfm(6, miao); //分别将shi、fen、miao送去液晶显示write_sfm(3, fen);write_sfm(0, shi);qdq=0;mb=0;j=0;L=0;coun=0;count = 0;xqnum = 0;S1num = 0;PT0=1;PT1=0;TH1=(65536-50000)/256;TL1=(65536-50000)%256;TR1=1;ET1=1;led=0xfe;key=0;TMOD = 0x011; //设置定时器0工作模式1TH0 = (65536-50000) / 256; //定时器装初始值TL0 = (65536-50000) % 256;EA = 1; //开总中断ET0 = 1; //开定时器0中断TR0 = 1; //启动定时器0}//=======================流水灯void t0isr() interrupt 3 //定时器2,用于流水灯{TH1=(65536-50000)/256;TL1=(65536-50000)%256;tm++;if(tm>=9){tm=0;switch(key) //六种样式{case 0:led=_crol_(led,1);break;case 1:led=_cror_(led,1);break;case 2:led=_cror_(led,1);break;case 3:led=_crol_(led,1);break;case 4:if(led==0x00)led=0xff;else led=led*2;break;case 5:led=~led;break;}}}//=======================流水灯//=========================== 独立键盘扫描函数void keyscan(){//————————————————————————————————————————————进入日历时钟设置if(S5 == 0){ read_temp();//读取温度ds1820disp();//显示}if (S0 == 0){ beep=0;PlayMusic(); //播放生日快乐beep=1;}if (S1 == 0){delay(2); //确认定义键被按下if (S1 == 0){while(!S1); //确认按键松开S1num++; //定义键S1按下次数记录if (S1num == 1) //S1按下一次时{TR0 = 0; //关闭定时器write_com(0xc0 + 7); //光标定位到秒位置write_com(0x0f); //光标闪烁}if (S1num == 2) //S1按下两次时{write_com(0xc0 + 4); //光标定位到分位置}if (S1num == 3) //S1按下三次时{write_com(0xc0 + 1); //光标定位到时位置}if (S1num == 4) //S1按下四次时{write_com(0x80 + 13); //光标定位到星期位置}if (S1num == 5) //S1按下五次时{write_com(0x80 + 9); //光标定位到日位置}if (S1num == 6) //S1按下六次时{write_com(0x80 + 6); //光标定位到月位置}if (S1num == 7) //S1按下七次时{write_com(0x80 + 3); //光标定位到年位置}if (S1num == 8) //退出设置,开启中断{S1num = 0;delay(3);TR0 = 1;write_com(0x0c);}}}if (S1num != 0) //只有定义键按下后S2、S3、S4才有效{if (S2 == 0){delay(2); //防抖if (S2 == 0) //确认按键被按下{while (!S2); //释放按键确认if (S1num == 1) //S1按下一次时{miao++; //调整秒加1if (miao == 60) //满60清零miao = 0;write_sfm(6, miao); //每调节一次送液晶显示一次write_com(0x80 + 0x40 + 6); //显示位置重新回到调节处}if (S1num == 2) //S1按下两次时{fen++; //调整分加1if (fen == 60)fen = 0;write_sfm(3, fen);write_com(0x80 + 0x40 + 3);}if (S1num == 3) //S1按下三次时{shi++; //调整时加1if (shi == 24)shi = 0;write_com(0x80 + 0x40);write_sfm(0, shi);}if (S1num == 4) //星期加调整{xqnum++;if (xqnum == 7)xqnum = 0;write_com(0x80 + 0x0b);for (a = 0; a < 3; a++){write_data(xingqi[xqnum][a]);delay(5);}}if (S1num == 5) //日加调整{ri++;if (yue == 2){if (nian % 400 == 0){if (ri == 30)ri = 1;}if (nian % 400 != 0){if (ri == 29)ri = 1;}}else if (yue <= 7){if (yue % 2 == 0 & yue != 2){if (ri == 31){ ri = 1; }}else if (yue % 2 != 0 & yue != 2){if (ri == 32){ ri = 1; }}}else if (yue >= 8){if (yue % 2 == 0){if (ri == 32){ ri = 1; }}else if (yue % 2 != 0){if (ri == 31){ ri = 1; }}}write_yr(8, ri);}if (S1num == 6) //月加调整{yue++;if (yue == 13)yue = 1;write_yr(5, yue);}if (S1num == 7) //年加调整{nian++;if (nian == 2030)nian = 2019;write_nian(0, nian);}}}if (S3 == 0){delay(2);if (S3 == 0) //确认按键被按下{while (!S3); //确认按键松开if (S1num == 1){miao--; //调整秒减1if (miao == -1) //减到00后再减重新设置为59miao = 59;write_sfm(6, miao);write_com(0x80 + 0x40 + 6);}if (S1num == 2){fen--; //调整分减1if (fen == -1)fen = 59;write_sfm(3, fen);write_com(0x80 + 0x40 + 3);}if (S1num == 3){shi--; //调整时减1if (shi == -1)shi = 23;write_sfm(0, shi);write_com(0x80 + 0x40);}if (S1num == 4){xqnum--; //调整星期减一if (xqnum == -1)xqnum = 6;write_com(0x80 + 0x0b);for (a = 0; a < 3; a++){write_data(xingqi[xqnum][a]);delay(5);}}if (S1num == 5) //调整日{ri--;if (yue == 2){if (nian % 400 == 0){if (ri == 0){ ri = 29; }}if (nian % 400 != 0){if (ri == 0){ ri = 28; }}}else if (yue <= 7){if (yue % 2 == 0 & yue != 2){if (ri == 0){ ri = 30; }}else if (yue % 2 != 0 & yue != 2){if (ri == 0){ ri = 31; }}}else if (yue >= 8){if (yue % 2 == 0){if (ri == 0){ ri = 31; }}else if (yue % 2 != 0){if (ri == 0){ ri = 30; }}}write_yr(8, ri);}if (S1num == 6) //调整月{yue--;if (yue == 0)yue = 12;write_yr(5, yue);}if (S1num == 7) //调整年{nian--;if (nian == 2030)nian = 2019;write_nian(0, nian);}}}}//————————————————————————————————————-推出日历时钟设置//——————————————————————————————————流水灯设置初值if(S4==0){delay(2);if(S4==0) //确认按键按下{while(!S4);qdq=0; //抢答器重置TR1=1;delay(2);while(S4==0);delay(2);key++;key%=6;if(key==0)led=0xfe;else if(key==1)led=0x7f;else if(key==2)led=0x80;else if(key==3)led=0x01;else if(key==4)led=0xfe;else led=0x55;}}//——————————————————————————————————结束流水灯设置初值}//=========================== 独立键盘扫描函数//=======================定时器0中断服务程序,用于日历时钟、秒表void timer0() interrupt 1{TH0 = (65536-50000) / 256; //重装定时器初始值TL0 = (65536-50000) % 256;count++; //中断次数累加//————————————————————————————————————————————日历时钟if (count == 20) //20次50毫秒即一秒{count = 0;miao++;if (miao == 60) //秒加到60时分进位{miao = 0;fen++;if (fen == 60) //分加到60时时进位{fen = 0;shi++;if (shi == 24) //时加到24时清0{shi = 0;xqnum++;ri++;if (yue == 2) //如果是二月{if (nian % 400 == 0) //闰年判断{if (ri == 30){ri = 1;yue++;write_yr(5, yue);}}if (nian % 400 != 0) //平年判断{if (ri == 29){ri = 1;yue++;write_yr(5, yue);}}}else if (yue <= 7 & yue != 2) //一月到七月{if (yue % 2 == 0) //偶数月(除二月){if (ri == 31){ri = 1;yue++;}}else if (yue % 2 != 0) //奇数月{if (ri == 32){ri = 1;yue++;}}write_yr(5, yue);}else if (yue >= 8) //八月到12月{if (yue % 2 == 0) //偶数月(除二月){if (ri == 32){ri = 1;yue++;if (yue == 13) //如果判断月份为12月,则加一后重新定义月份为1{yue = 1;nian++;write_nian(0, nian);}write_yr(5, yue);}}else if (yue % 2 != 0) //奇数月{if (ri == 31){ri = 1;yue++;write_yr(5, yue);}}}write_yr(8, ri);if (xqnum == 7) //星期写入xqnum = 0;write_com(0x80 + 0x0b);for (a = 0; a < 3; a++){write_data(xingqi[xqnum][a]);delay(5);}}write_sfm(0, shi); //重新写入数据}write_sfm(3, fen); //重新写入数据}write_sfm(6, miao); //重新写入数据}//——————————————————————————————————————————日历时钟结束}//=======================定时器0中断服务程序,用于日历时钟void main() //主函数{init(); //初始化while (1){keyscan(); //检测按键是否被按下}}相关视频在哔哩哔哩:BV1ef4y1q7xY。
/*生日快乐歌曲*/#include <reg51.h>#define uint unsigned int#define uchar unsigned charsbit beep = P1^5;uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0};uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0};//延时void DelayMS(uint x){uchar t;while(x--) for(t=0;t<120;t++);}void PlayMusic(){uint i=0,j,k;while(SONG_LONG[i]!=0||SONG_TONE[i]!=0){ //播放各个音符,SONG_LONG 为拍子长度for(j=0;j<SONG_LONG[i]*20;j++){beep=~beep;//SONG_TONE 延时表决定了每个音符的频率for(k=0;k<SONG_TONE[i]/3;k++);}DelayMS(10);i++;}}void main(){beep=0;while(1){PlayMusic(); //播放生日快乐DelayMS(500); //播放完后暂停一段时间}}两只蝴蝶:#include <reg51.h> // 这是单片机音乐代码生成器生成的代码#define uchar unsigned charsbit beepIO=P1^5; // 输出为P1.5 可以修改成其它IO 口uchar m,n;uchar code T[49][2]={{0,0},{0xF8,0x8B},{0xF8,0xF2},{0xF9,0x5B},{0xF9,0xB7},{0xFA,0x14},{0xFA,0x66},{0xFA,0xB9},{0xFB,0x03 },{0xFB,0x4A},{0xFB,0x8F},{0xFB,0xCF},{0xFC,0x0B},{0xFC,0x43},{0xFC,0x78},{0xFC,0xAB},{0xFC,0xDB},{0xFD,0x08},{0xFD,0x33},{0xFD,0x5B},{0xFD,0x8 1},{0xFD,0xA5},{0xFD,0xC7},{0xFD,0xE7},{0xFE,0x05},{0xFE,0x21},{0xFE,0x3C},{0xFE,0x55},{0xFE,0x6D},{0xFE,0x84},{0xFE,0x99},{0xFE,0xAD},{0xFE,0xC0 },{0xFE,0x02},{0xFE,0xE3},{0xFE,0xF3},{0xFF,0x02},{0xFF,0x10},{0xFF,0x1D},{0xFF,0x2A},{0xFF,0x36},{0xFF,0x42},{0xFF,0x4C},{0xFF,0x56},{0xFF,0x60},{ 0xFF,0x69},{0xFF,0x71},{0xFF,0x79},{0xFF,0x81}};uchar code music[][2]={{0,4},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,16},{16,4},{19,4},{21,8},{21,4},{23,4},{21,4},{19 ,4},{16,4},{19,4},{14,24},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,24},{16,4},{19,4},{21,8},{21,4},{23,4},{21,4},{19 ,4},{16,4},{19,4},{21,24},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,16},{16,4},{19,4},{21,8},{21,4},{23,4},{21,4},{19 ,4},{16,4},{19,4},{14,24},{23,4},{26,4},{26,16},{26,4},{28,4},{26,4},{23,24},{21,4},{23,4},{21,8},{21,4},{23,4},{21,4},{19,4},{16 ,4},{16,2},{19,2},{19,24},{0,20},{26,4},{26,4},{28,4},{31,4},{30,4},{30,4},{28,4},{23,4},{21,4},{21,4},{23,16},{0,4},{23,4},{23,4},{26,4} ,{28,8},{28,12},{16,4},{23,4},{21,4},{21,24},{23,4},{26,4},{26,4},{23,4},{26,8},{0,4},{31,8},{30,4},{28,4},{30,4},{23,8},{0,4},{28,4},{28,4},{ 30,4},{28,4},{26,4},{23,4},{21,8},{23,4},{21,4},{23,4},{26,16},{0xFF,0xFF}};void delay(uchar p){uchar i,j;for(;p>0;p--)for(i=181;i>0;i--)for(j=181;j>0;j--);}void pause(){uchar i,j;for(i=150;i>0;i--)for(j=150;j>0;j--);}void T0_int() interrupt 1beepIO=!beepIO;TH0=T[m][0]; TL0=T[m][1];}void main(){uchar i=0;TMOD=0x01; EA=1; ET0=1;while(1){m=music[i][0];n=music[i][1];if(m==0x00){TR0=0;delay(n);i++;}else if(m==0xFF){TR0=0;delay(30);i=0;}else if(m==music[i+1][0]){TR0=1;delay(n);TR0=0;pause();i++;}else{TR0=1;delay(n);i++;}}}祝你平安:#include "reg52.h"unsigned char Count;sbit _Speak =P1^5 ;unsigned char code SONG[] ={ //祝你平安0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20, 0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20, 0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20, 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20, 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10, 0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20, 0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20, 0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20, 0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10, 0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80, 0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20, 0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20, 0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10, 0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00};void Time0_Init(){TMOD = 0x01;IE = 0x82;TH0 = 0xD8;TL0 = 0xEF; //12MZ晶振,10ms}void Time0_Int() interrupt 1{TH0 = 0xD8;TL0 = 0xEF;Count++; //长度加1}/*-------------------------------------------------功能:1MS延时子程序-------------------------------------------------*/ void Delay_xMs(unsigned int x){unsigned int i,j;for( i =0;i < x;i++ ){for( j =0;j<3;j++ );}}void Play_Song(unsigned char i){unsigned char Temp1,Temp2;unsigned int Addr;Count = 0; //中断计数器清0Addr = i * 217;while(1){Temp1 = SONG[Addr++];if ( Temp1 == 0xFF ) //休止符{TR0 = 0;Delay_xMs(100);}else if ( Temp1 == 0x00 ) //歌曲结束符{return;}else{Temp2 = SONG[Addr++];TR0 = 1;while(1){_Speak = ~_Speak;Delay_xMs(Temp1);if ( Temp2 == Count ){Count = 0;break;}}}}}/*------------------------------------------------- 功能:主程序-------------------------------------------------*/ void main(){Time0_Init(); //定时器0中断初始化while(1){Play_Song(0); //播放}}。
实验名称:单片机编程奏音乐“生日之歌”
一、实验电路
二、实验目的
掌握8051内部定时器的工作原理,通过编程并与音频放大电路相连,实现演奏音乐的功能
三、实验器材
(1)单片机CPU板
(2)运算放大器及音频放大实验板
(3)导线
四、实验要点
(1)按图连好线。
(2)要产生音频脉冲,只要算出某一音频的周期,然后将此周期除以2,即为板周期的时间。
利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O
反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率
的脉冲。
(3)利用8051的内部定时器使其工作在计数器模式MODE1下,改变计数值TH0及TL0以产生不同频率的方法。
(4)计数脉冲值与频率的关系公式如下:
N=Fi÷2÷Fr N:计数值
Fi:内部计时一次为1μs,故其频率为1MHz
Fr::要产生的频率
(5)计数值的求法如下:
T=65536-N
(6)每个音符使用一个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,如果1拍为0.4秒,1/4拍是0.1秒,只要设定延迟时间就可求得节拍的时
间。
假设1/4拍为1DELAY,则1拍应为4DELAY,以此类推。
所以只要求得
1/4拍的DELAY时间,其余的节拍就是它的倍数。
单片机蜂鸣器播放音乐代码生日快乐两只蝴蝶祝你平安/*生日快乐歌曲*/#include<reg51.h>#defineuintunsignedint#defineucharunsignedcharsbitbeep=P1^5;ucharcodeSONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,212,212,106,126,159,169,190,119,119,126,159,142,159,0};ucharcodeSONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0};//延时voidDelayMS(uintx){uchart;while(x--)for(t=0;t<120;t++);}voidPlayMusic(){uinti=0,j,k;while(SONG_LONG[i]!=0||SONG_TONE[i]!=0){//播放各个音符,SONG_LONG为拍子长度for(j=0;j<SONG_LONG[i]*20;j++){beep=~beep;//SONG_TONE延时表决定了每个音符的频率for(k=0;k<SONG_TONE[i]/3;k++);}DelayMS(10);i++;}}voidmain(){beep=0;while(1){PlayMusic();//播放生日快乐DelayMS(500);//播放完后暂停一段时间}}两只蝴蝶:#include<reg51.h>//这是单片机音乐代码生成器生成的代码#defineucharunsignedcharsbitbeepIO=P1^5;//输出为P1.5可以修改成其它IO口ucharcodeT[49][2]={{0,0},{0xF8,0x8B},{0xF8,0xF2},{0xF9,0x5B},{0xF9,0xB7},{0xFA,0x14},{0xFA,0x66},{0xFA,0xB9},{ 0xFB,0x03},{0xFB,0x4A},{0xFB,0x8F},{0xFB,0xCF},{0xFC,0x0B},{0xFC,0x43},{0xFC,0x78},{0xFC,0xAB},{0xFC,0xDB},{0xFD,0x08},{0xFD,0x33},{0xFD,0x5B},{ 0xFD,0x81},{0xFD,0xA5},{0xFD,0xC7},{0xFD,0xE7},{0xFE,0x05},{0xFE,0x21},{0xFE,0x3C},{0xFE,0x55},{0xFE,0x6D},{0xFE,0x84},{0xFE,0x99},{0xFE,0xAD},{ 0xFE,0xC0},{0xFE,0x02},{0xFE,0xE3},{0xFE,0xF3},{0xFF,0x02},{0xFF,0x10},{0xFF,0x1D},{0xFF,0x2A},{0xFF,0x36},{0xFF,0x42},{0xFF,0x4C},{0xFF,0x56},{ 0xFF,0x60},{0xFF,0x69},{0xFF,0x71},{0xFF,0x79},{0xFF,0x81}};ucharcodemusic[][2]={{0,4},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,16},{16,4},{19,4},{21,8},{21,4} ,{23,4},{21,4},{19,4},{16,4},{19,4},{14,24},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,24},{16,4},{19,4},{21,8},{21,4} ,{23,4},{21,4},{19,4},{16,4},{19,4},{21,24},{23,4},{21,4},{23,16},{23,4},{21,4},{23,4},{21,4},{19,16},{16,4},{19,4},{21,8},{21,4} ,{23,4},{21,4},{19,4},{16,4},{19,4},{14,24},{23,4},{26,4},{26,16},{26,4},{28,4},{26,4},{23,24},{21,4},{23,4},{21,8},{21,4},{23,4} ,{21,4},{19,4},{16,4},{16,2},{19,2},{19,24},{0,20},{26,4},{26,4},{28,4},{31,4},{30,4},{30,4},{28,4},{23,4},{21,4},{21,4},{23,16},{0,4},{ 23,4},{23,4},{26,4},{28,8},{28,12},{16,4},{23,4},{21,4},{21,24},{23,4},{26,4},{26,4},{23,4},{26,8},{0,4},{31,8},{30,4},{28,4},{30,4},{23,8},{ 0,4},{28,4},{28,4},{30,4},{28,4},{26,4},{23,4},{21,8},{23,4},{21,4},{23,4},{26,16}, {0xFF,0xFF}};voiddelay(ucharp){uchari,j;for(;p>0;p--)for(i=181;i>0;i--)for(j=181;j>0;j--);}voidpause(){uchari,j;for(i=150;i>0;i--)for(j=150;j>0;j--);}voidT0_int()interrupt1{beepIO=!beepIO;TH0=T[m][0];TL0=T[m][1];}voidmain(){uchari=0;while(1){m=music[i][0];n=music[i][1];if(m==0x00){TR0=0;delay(n);i++;}elseif(m==0xFF){TR0=0;delay(30);i=0;}elseif(m==music[i+1][0]){TR0=1;delay(n);TR0=0;pause();i++;}else{TR0=1;delay(n);i++;}}}祝你平安:#include"reg52.h"unsignedcharCount;sbit_Speak=P1^5;unsignedcharcodeSONG[]={//祝你平安0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20, 0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20, 0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20, 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20, 0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10, 0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20, 0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20, 0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20, 0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10, 0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80, 0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20, 0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20, 0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10, 0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00};voidTime0_Init(){TMOD=0x01;IE=0x82;TH0=0xD8;TL0=0xEF;//12MZ晶振,10ms}voidTime0_Int()interrupt1{TH0=0xD8;TL0=0xEF;Count++;//长度加1}功能:1MS延时子程序-------------------------------------------------*/ voidDelay_xMs(unsignedintx){unsignedinti,j;for(i=0;i<x;i++){for(j=0;j<3;j++);}}voidPlay_Song(unsignedchari){unsignedcharTemp1,Temp2;unsignedintAddr;Count=0;//中断计数器清0Addr=i*217;while(1){Temp1=SONG[Addr++];if(Temp1==0xFF)//休止符{TR0=0;Delay_xMs(100);}elseif(Temp1==0x00)//歌曲结束符{return;}else{Temp2=SONG[Addr++];TR0=1;while(1){_Speak=~_Speak;Delay_xMs(Temp1);if(Temp2==Count){Count=0;break;}}}}}功能:主程序-------------------------------------------------*/ voidmain(){Time0_Init();//定时器0中断初始化while(1){Play_Song(0);//播放}}。
单片机播放音乐汇编程序;标题’八月桂花香’发声程序ORG 0000HLJMP STARTORG 000BHINC 20H ;中断服务,中断计数器加1MOV TH0,#0D8HMOV TL0,#0EFH ;12M晶振,形成10毫秒中断RETISTART:MOV SP,#50HMOV TH0,#0D8HMOV TL0,#0EFHMOV TMOD,#01HMOV IE,#82HMUSIC0:NOPMOV DPTR,#DAT ;表头地址送DPTRMOV 20H,#00H ;中断计数器清0MUSIC1:NOPCLR A ;A清零MOVC A,@A+DPTR ;查表取代码JZ END0 ;是00H,则结束CJNE A,#0FFH,MUSIC5 ;如果是休止符,往下执行LJMP MUSIC3MUSIC5:NOPMOV R6,A ;R6=18H音符的频率INC DPTR DPTR加一MOV A,#0MOVC A,@A+DPTR ;取节拍代码送R7MOV R7,A ;R7=30H音符发音的时间SETB TR0 ;启动计数MUSIC2:NOPCPL P2.5 ;P2.5是音乐输出引脚MOV A,R6MOV R3,A ;R3=R6=18HLCALL DELMOV A,R7CJNE A,20H,MUSIC2 ;中断计数器(20H)=R7否?;不等,则继续循环MOV 20H,#00H ;等于,则取下一代码INC DPTRLJMP MUSIC1MUSIC3:NOP ;休止100毫秒CLR TR0MOV R2,#0DH ;R2=13MUSIC4:NOPMOV R3,#0FFH ;R3=255LCALL DELDJNZ R2,MUSIC4INC DPTRLJMP MUSIC1END0:NOPMOV R2,#0FFH ;歌曲结束,延时1秒后继续MUSIC6:MOV R3,#00HLCALL DELDJNZ R2,MUSIC6LJMP MUSIC0DEL:NOPDEL3:MOV R4,#02HDEL4:NOPDJNZ R4,DEL4NOPDJNZ R3,DEL3RETNOPDAT:DB 18H, 30H, 1CH, 10H DB 20H, 40H, 1CH, 10H DB 18H, 10H, 20H, 10H DB 1CH, 10H, 18H, 40H DB 1CH, 20H, 20H, 20H DB 1CH, 20H, 18H, 20H DB 20H, 80H, 0FFH, 20H DB 30H, 1CH, 10H , 18H DB 20H, 15H, 20H , 1CH DB 20H, 20H, 20H , 26H DB 40H, 20H , 20H , 2BH DB 20H, 26H, 20H , 20H DB 20H, 30H , 80H , 0FFH DB 20H, 20H, 1CH , 10H DB 18H, 10H, 20H , 20H DB 26H, 20H , 2BH , 20H DB 30H, 20H , 2BH , 40H DB 20H, 20H , 1CH , 10HDB 26H, 20H , 2BH, 20H DB 30H, 20H, 2BH , 40H DB 20H, 30H, 1CH , 10H DB 18H, 20H , 15H , 20H DB 1CH, 20H , 20H , 20H DB 26H, 40H, 20H , 20H DB 2BH, 20H, 26H , 20H DB 20H, 20H, 30H , 80H DB 20H, 30H, 1CH , 10H DB 20H, 10H, 1CH , 10H DB 20H, 20H, 26H , 20H DB 2BH, 20H, 30H , 20H DB 2BH, 40H, 20H , 15H DB 1FH, 05H, 20H , 10H DB 1CH, 10H, 20H , 20H DB 26H, 20H, 2BH , 20H DB 30H, 20H, 2BH , 40H DB 20H, 30H, 1CH , 10H DB 18H, 20H , 15H , 20H DB 1CH, 20H , 20H , 20H DB 26H, 40H, 20H , 20H DB 2BH, 20H, 26H , 20H DB 20H, 20H, 30H, 30HDB 18H, 40H, 1CH, 20HDB 20H, 20H, 26H, 40HDB 13H, 60H, 18H , 20HDB 15H, 40H, 13H , 40HDB 18H, 80H, 00H提问人的追问 2010-01-08 08:58原理是什么啊在线等啊我回答人的补充 2010-01-08 15:08一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能象电子琴那样能奏出多种音色的声音。
单片机课程设计生日歌一、课程目标知识目标:1. 让学生理解单片机的基本工作原理,掌握单片机编程的基础知识。
2. 使学生掌握利用单片机实现音乐播放的基本方法,了解音符与频率的关系。
3. 帮助学生掌握单片机I/O口的控制方法,实现LED灯的闪烁。
技能目标:1. 培养学生动手操作单片机的能力,学会编写简单的程序代码。
2. 培养学生分析问题、解决问题的能力,能够将理论知识应用于实际项目中。
3. 提高学生的团队协作能力,学会在项目过程中相互沟通、共同解决问题。
情感态度价值观目标:1. 培养学生对单片机及电子技术的兴趣,激发学习热情。
2. 培养学生的创新精神,敢于尝试新方法,勇于挑战困难。
3. 引导学生认识到科技在生活中的重要作用,增强社会责任感。
课程性质:本课程为实践性较强的课程,以项目为导向,结合理论知识,培养学生的动手操作能力和实际应用能力。
学生特点:学生处于高中阶段,具有一定的物理、数学基础,对电子技术有一定了解,但实践经验不足。
教学要求:结合学生特点,课程设计应注重理论与实践相结合,充分调动学生的积极性,注重培养动手操作能力和团队协作能力。
通过本课程的学习,使学生能够将所学知识应用于实际项目中,提高解决问题的能力。
在教学过程中,注重评估学生的学习成果,确保课程目标的实现。
二、教学内容1. 理论知识:- 单片机原理及结构:介绍单片机的基本组成,如CPU、内存、I/O口等。
- 编程基础:讲解单片机编程的基本语法,如指令、数据类型、函数等。
- 音符与频率:分析音符与频率的关系,介绍如何通过编程实现音乐播放。
2. 实践操作:- 单片机编程软件使用:指导学生使用编程软件,如Keil、Proteus等。
- 生日歌程序编写:根据音符与频率关系,编写生日歌程序代码。
- LED灯控制:实现单片机I/O口控制LED灯闪烁,与生日歌节奏同步。
3. 教学大纲:- 第一周:单片机原理及结构,编程基础学习。
- 第二周:音符与频率关系学习,编程软件使用。
51单片机温度计+计数器(可调时间)+蜂鸣器(生日歌)+花样流水灯6种51单片机课程设计蜂鸣器(生日歌)+温度计+计数器(可调时间)+花样流水灯(6种)#include#include#include#define uchar unsigned char#define uint unsigned int#define led P1 //将P1口定义位8个leduchar a, count, S1num, xqnum, temp, j, tm, key, coun, L, qdq, mb; //定义变量char yue, ri, shi, fen, miao; //定义月日时分秒int nian; //定义年// ==================定义初始化日历uchar code table0[] = "2020-09-4--FRI--";uchar code table1[] = "08:48:00";uchar code xingqi[][3] = { "MON","TUE","WED","THU","FRI","SAT","SUN" };uint led1[]={0x7e,0xbd,0xdb,0xe7,0xff};// ==================定义初始化日历sbit lcdrs=P2^6; //将lcd1602的RS端口(数据/命令选择端)定义到P2.0 sbit lcdrw=P2^7; //将lcd1602的R/W端口(读/写选择端)定义到P2.1 sbit lcden=P2^5; //将lcd1602的E端口(使能端口)定义到P2.2sbit DQ=P3^7;//ds18b20sbit S1=P3^1; //进入设置退出设置sbit S2=P3^2; //+1 或秒表模式sbit S3=P3^3; //-1 或开始秒表计时sbit S0=P3^0; //进入设置退出设置sbit S4=P3^4; //灯模式切换sbit S5=P3^5;sbit beep = P2^2; //定义蜂鸣器uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,1 59, 212,212,106,126,159,169,190,119,119,126,159,142,159,0};uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24, 9,3,12,12,12,12,12,9,3,12,12,12,24,0};//延时unsigned char code str2[16]={" "};uchar data disdata[5];uint value;//温度值温度值uchar flag;//正负标志正负标志void delay1ms(unsigned int ms)//延时1毫秒{unsigned int i,j;for(i=0;i<ms;i++)< bdsfid="117" p=""></ms;i++)<>for(j=0;j<100;j++);}void write_com1(unsigned char com1)//写指令//{ delay1ms(1);lcdrs=0;lcdrw=0;lcden=0;P0=com1;delay1ms(1);lcden=1;delay1ms(1);lcden=0;}void write_dat1(unsigned char dat1)//写数据// { delay1ms(1); lcdrs=1;lcdrw=0;lcden=0;P0=dat1;delay1ms(1);lcden=1;delay1ms(1);lcden=0;}void lcd_init()//初始化设置//{write_com1(0x38);delay1ms(5);write_com1(0x08);delay1ms(5);write_com1(0x01);delay1ms(5);write_com1(0x06);delay1ms(5);write_com1(0x0c);delay1ms(5);}void display(unsigned char *p)//显示{while(*p!='\0'){write_dat1(*p);p++;delay1ms(1);}}init_play()//初始化显示{lcd_init();write_com1(0xc0);display(str2);}void delay_18B20(unsigned int i)//延时1微秒{ while(i--);}void ds1820rst()/*ds1820复位*/{unsigned char x=0;DQ = 1;//DQ复位delay_18B20(4);//延时DQ=0;//DQ拉低delay_18B20(100);//精确延时大于480usDQ=1;//拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{unsigned char i=0;unsigned char dat1 = 0;for (i=8;i>0;i--){DQ = 0; //给脉冲信号dat1>>=1;DQ=1;//给脉冲信号if(DQ)dat1|=0x80;delay_18B20(10);}return(dat1);}void ds1820wr(uchar wdata)/*写数据*/ { unsigned char i=0;for(i=8;i>0;i--){DQ=0;DQ=wdata&0x01;delay_18B20(10);DQ=1;wdata>>=1;}}read_temp()/*读取温度值并转换*/ {uchar a,b; ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/?ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();value=b;value<<=8;value=value|a;if(value<0x0fff)flag=0;else{value=~value+1;flag=1;}value=value*(0.625);//温度值扩大10倍,精确到1位小数return(value);}/************************************************************** *****/ void ds1820disp()//温度值显示{uchar flagdat;disdata[0]=value/1000+0x30;//百位数disdata[1]=value%1000/100+0x30;//十位数disdata[2]=value%100/10+0x30;//个位数disdata[3]=value%10+0x30;//小数位if(flag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}write_com1(0xc8);write_dat1(flagdat);//显示符号位write_com1(0xc9);write_dat1(disdata[0]);//显示百位write_com1(0xca);write_dat1(disdata[1]);//显示十位write_com1(0xcb);write_dat1(disdata[2]);//显示个位write_com1(0xcc);write_dat1(0x2e);//显示小数点write_com1(0xcd);write_dat1(disdata[3]);//显示小数位}void delay(uint t) //@12.000MHz延时函数{uint x, y;for (x = t; x > 0; x--)for (y = 110; y > 0; y--);}void DelayMS(uint x){uchar t;while(x--) for(t=0;t<120;t++);}void PlayMusic(){uint i=0,j,k;while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) { //播放各个音符,SONG_LONG 为拍子长度for(j=0;j<song_long[i]*20;j++)< bdsfid="266" p=""></song_long[i]*20;j++)<>{beep=~beep;//SONG_TONE 延时表决定了每个音符的频率for(k=0;k<="" bdsfid="270" p="">}DelayMS(10);i++;}}//======================液晶void write_com(uchar com) //液晶写指令{lcdrw = 0;lcdrs = 0;P0 = com;delay(2);lcden = 1;delay(2);lcden = 0;}void write_data(uchar dat) //液晶写数据{lcdrw = 0;lcdrs = 1;P0 = dat;delay(2);lcden = 1;delay(2);lcden = 0;}void write_sfm(uchar add, uchar dat) //写时分秒函数{ uchar shi, ge;shi = dat / 10;ge = dat % 10;write_com(0x80 + 0x40 + add);write_data(0x30 + shi);write_data(0x30 + ge);}void write_yr(uchar add, uchar dat) //写月日函数{ uchar shi, ge;shi = dat / 10;ge = dat % 10;write_com(0x80 + add);write_data(0x30 + shi);write_data(0x30 + ge);}void write_nian(uchar add, uint dat) //写年函数{uint qian, bai, shi, ge;qian = dat / 1000;bai = dat % 1000 / 100;shi = dat % 100 / 10;ge = dat % 10;write_com(0x80 + add);write_data(0x30 + qian);write_data(0x30 + bai);write_data(0x30 + shi);write_data(0x30 + ge);}void init_lcd() //液晶初始化{lcden = 0;nian = 2020;yue = 1;ri = 3;shi = 0; //初始shi、fen、miaofen = 0;miao = 0;write_com(0x38); //设置16x2显示,5x7点阵,8位数据口write_com(0x0c); //设置开显示,不显示光标write_com(0x06); //写一个字符后地址指针加1write_com(0x01); //显示清0,数据指针清0}//==================液晶void init() //总初始化函数{init_lcd(); //液晶初始化write_com(0x80); //设置显示初始坐标for (a = 0; a < 14; a++) //显示年月日初始值{write_data(table0[a]);delay(3);}write_com(0x80 + 0x40); //设置显示初始坐标for (a = 0; a < 8; a++) //显示时分秒初始值{write_data(table1[a]);delay(3);}write_nian(0, nian);write_sfm(6, miao); //分别将shi、fen、miao送去液晶显示write_sfm(3, fen);write_sfm(0, shi);qdq=0;mb=0;j=0;L=0;coun=0;count = 0;xqnum = 0;S1num = 0;PT0=1;PT1=0;TH1=(65536-50000)/256;TL1=(65536-50000)%256;TR1=1;ET1=1;led=0xfe;key=0;TMOD = 0x011; //设置定时器0工作模式1 TH0 = (65536-50000) / 256; //定时器装初始值TL0 = (65536-50000) % 256;EA = 1; //开总中断ET0 = 1; //开定时器0中断TR0 = 1; //启动定时器0}//=======================流水灯void t0isr() interrupt 3 //定时器2,用于流水灯{TH1=(65536-50000)/256;TL1=(65536-50000)%256;tm++;if(tm>=9){tm=0;switch(key) //六种样式{case 0:led=_crol_(led,1);break;case 1:led=_cror_(led,1);break;case 2:led=_cror_(led,1);break;case 3:led=_crol_(led,1);break;case 4:if(led==0x00)led=0xff;else led=led*2;break;case 5:led=~led;break;}}}//=======================流水灯//=========================== 独立键盘扫描函数void keyscan(){//————————————————————————————————————————————进入日历时钟设置if(S5 == 0){ read_temp();//读取温度ds1820disp();//显示}if (S0 == 0){ beep=0;PlayMusic(); //播放生日快乐beep=1;}if (S1 == 0){delay(2); //确认定义键被按下if (S1 == 0){while(!S1); //确认按键松开S1num++; //定义键S1按下次数记录if (S1num == 1) //S1按下一次时{TR0 = 0; //关闭定时器write_com(0xc0 + 7); //光标定位到秒位置write_com(0x0f); //光标闪烁}if (S1num == 2) //S1按下两次时{write_com(0xc0 + 4); //光标定位到分位置}if (S1num == 3) //S1按下三次时{write_com(0xc0 + 1); //光标定位到时位置}if (S1num == 4) //S1按下四次时{write_com(0x80 + 13); //光标定位到星期位置} if (S1num == 5) //S1按下五次时{write_com(0x80 + 9); //光标定位到日位置}if (S1num == 6) //S1按下六次时{write_com(0x80 + 6); //光标定位到月位置}if (S1num == 7) //S1按下七次时{write_com(0x80 + 3); //光标定位到年位置}if (S1num == 8) //退出设置,开启中断{S1num = 0;delay(3);TR0 = 1;write_com(0x0c);}}}if (S1num != 0) //只有定义键按下后S2、S3、S4才有效{if (S2 == 0){delay(2); //防抖if (S2 == 0) //确认按键被按下{while (!S2); //释放按键确认if (S1num == 1) //S1按下一次时{miao++; //调整秒加1if (miao == 60) //满60清零miao = 0;write_sfm(6, miao); //每调节一次送液晶显示一次write_com(0x80 + 0x40 + 6); //显示位置重新回到调节处}if (S1num == 2) //S1按下两次时{fen++; //调整分加1if (fen == 60)fen = 0;write_sfm(3, fen);write_com(0x80 + 0x40 + 3);}if (S1num == 3) //S1按下三次时{shi++; //调整时加1if (shi == 24)shi = 0;write_com(0x80 + 0x40); write_sfm(0, shi);}if (S1num == 4) //星期加调整{xqnum++;if (xqnum == 7)xqnum = 0;write_com(0x80 + 0x0b);for (a = 0; a < 3; a++){write_data(xingqi[xqnum][a]); delay(5);}}if (S1num == 5) //日加调整{ri++;if (yue == 2){if (nian % 400 == 0){if (ri == 30)ri = 1;}if (nian % 400 != 0){if (ri == 29)ri = 1;}}else if (yue <= 7){if (yue % 2 == 0 & yue != 2) {if (ri == 31){ ri = 1; }}else if (yue % 2 != 0 & yue != 2) {if (ri == 32){ ri = 1; }}}else if (yue >= 8){if (yue % 2 == 0){if (ri == 32){ ri = 1; }}else if (yue % 2 != 0){if (ri == 31){ ri = 1; }}}write_yr(8, ri);}if (S1num == 6) //月加调整{yue++;if (yue == 13)yue = 1;write_yr(5, yue);}if (S1num == 7) //年加调整{nian++;if (nian == 2030)nian = 2019;write_nian(0, nian);}}}if (S3 == 0){delay(2);if (S3 == 0) //确认按键被按下{while (!S3); //确认按键松开if (S1num == 1){miao--; //调整秒减1if (miao == -1) //减到00后再减重新设置为59 miao = 59;write_sfm(6, miao);write_com(0x80 + 0x40 + 6);}if (S1num == 2){fen--; //调整分减1if (fen == -1)fen = 59;write_sfm(3, fen);write_com(0x80 + 0x40 + 3); }if (S1num == 3){shi--; //调整时减1if (shi == -1)shi = 23;write_sfm(0, shi);write_com(0x80 + 0x40);}if (S1num == 4){xqnum--; //调整星期减一if (xqnum == -1)xqnum = 6;write_com(0x80 + 0x0b);for (a = 0; a < 3; a++){write_data(xingqi[xqnum][a]); delay(5);}}if (S1num == 5) //调整日{ri--;if (yue == 2){if (nian % 400 == 0){if (ri == 0){ ri = 29; }}if (nian % 400 != 0){if (ri == 0){ ri = 28; }}}else if (yue <= 7){if (yue % 2 == 0 & yue != 2) {if (ri == 0){ ri = 30; }}else if (yue % 2 != 0 & yue != 2) {if (ri == 0){ ri = 31; }}}else if (yue >= 8){if (yue % 2 == 0){if (ri == 0){ ri = 31; }}else if (yue % 2 != 0){if (ri == 0){ ri = 30; }}}write_yr(8, ri);}if (S1num == 6) //调整月{yue--;if (yue == 0)yue = 12;write_yr(5, yue);}if (S1num == 7) //调整年{nian--;if (nian == 2030)nian = 2019;write_nian(0, nian);}}}}//————————————————————————————————————-推出日历时钟设置//——————————————————————————————————流水灯设置初值if(S4==0){delay(2);if(S4==0) //确认按键按下{while(!S4);qdq=0; //抢答器重置TR1=1;delay(2);while(S4==0);delay(2);key++;key%=6;if(key==0)led=0xfe;else if(key==1)led=0x7f;else if(key==2)led=0x80;else if(key==3)led=0x01;else if(key==4)led=0xfe;else led=0x55;}}//——————————————————————————————————结束流水灯设置初值}//=========================== 独立键盘扫描函数//=======================定时器0中断服务程序,用于日历时钟、秒表void timer0() interrupt 1{TH0 = (65536-50000) / 256; //重装定时器初始值TL0 = (65536-50000) % 256;count++; //中断次数累加//————————————————————————————————————————————日历时钟if (count == 20) //20次50毫秒即一秒{count = 0;miao++;if (miao == 60) //秒加到60时分进位{miao = 0;fen++;if (fen == 60) //分加到60时时进位{fen = 0;shi++;if (shi == 24) //时加到24时清0{shi = 0;xqnum++;ri++;if (yue == 2) //如果是二月{if (nian % 400 == 0) //闰年判断{if (ri == 30){ri = 1;yue++;write_yr(5, yue);}}if (nian % 400 != 0) //平年判断{if (ri == 29){ri = 1;yue++;write_yr(5, yue);}}}else if (yue <= 7 & yue != 2) //一月到七月{if (yue % 2 == 0) //偶数月(除二月){if (ri == 31){ri = 1;yue++;}}else if (yue % 2 != 0) //奇数月{if (ri == 32){ri = 1;yue++;}}write_yr(5, yue);}else if (yue >= 8) //八月到12月{if (yue % 2 == 0) //偶数月(除二月){if (ri == 32){ri = 1;yue++;if (yue == 13) //如果判断月份为12月,则加一后重新定义月份为1{yue = 1;nian++;write_nian(0, nian);}write_yr(5, yue);}}else if (yue % 2 != 0) //奇数月{if (ri == 31){ri = 1;yue++;write_yr(5, yue);}}}write_yr(8, ri);if (xqnum == 7) //星期写入xqnum = 0;write_com(0x80 + 0x0b); for (a = 0; a < 3; a++) {。
实验三电子音乐设计一、实验内容
1.调试《生日快乐歌》,在实验板上运行程序播放。
2.编写《兰花草》程序,在实验板上运行程序播放。
二.实验设计
1.硬件电路
图3.1 硬件电路原理图
2.程序设计
《生日快乐》程序,参考课件。
《兰花草》程序设计流程图,见图3.2, 3.2. 单片机P3.7输出一定频率信号,经过9012驱动蜂鸣器发声。
三、实验操作
1. 打开KEILuvison3软件,建立工程,设置调试环境,实验板上电;
2. 输入源程序,编译,连接,加载;
3. 运行《生日快乐》歌曲程序,聆听歌曲播放效果;
4.运行《兰花草》歌曲程序,聆听歌曲播放效果。
四、实验报告要求
1.实验名称
2.实验内容
3.实验设计,包括:
(1)硬件电路原理图
(2)程序流程图和源程序
4.实验操作,包括调试程序的方法、过程、出现的问题及解决
5.实验总结
图3.3 T0中断子程序流程图图3.2电子音乐主程序流程图。
;本程序实现蜂鸣器演奏歌曲功能;乐曲名称:生日快乐;///////////////////////////////////////////BUZZER EQU P2.3org 0000h ;主程序起始地址ajmpmain ;跳至主程序org 000bh ;timer0中断起始地址jmp tim0 ;跳至timer0中断子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;org 0030hmain:mov tmod,#01h ;设timer0在MODE1mov ie,#82h ;中断使能start0:mov 30h,#00h ;取简谱码指针next:mov a,30h ;简谱码指针载入Amov dptr,#table ;至table取简谱码movc a,@a+dptrmov r2,a ;取到的简谱码暂存于R2jz end0 ;是否取到00(结束码)?anl a,#0fh ;不是,则取低4位(节拍码)mov r5,a ;将节拍码存入R5mov a,r2 ;将取到的简谱码再载入Aswap a ;高低四位交换anl a,#0fh ;取低四位(音符码)jnz sing ;取到的音符码是否为零?clr tr0 ;是,则不发音jmp d1sing: d ec a ;取到的音符码减1(不含0).mov 22h,a ;存入(22H).rl a ;乘2mov dptr,#table1 ;至table1取相对的高位字节计数值movc a,@a+dptrmov th0,a ;取到的高位字节存入TH0mov 21h,a ;取到的高位字节存入(21H)mov a,22h ;再载入取的的音符码rl a ;乘2inc a ;加1movc a,@a+dptr ;至table1取相对的低位字节计数值mov tl0,a ;取到的高位字节存入TL0mov 20h,a ;取到的高位字节存入(20H)setb tr0 ;启动timer0d1: call delay ;基本单位时间1/4拍187毫秒inc 30h ;取简谱码指针加1jmp next ;取下一个码end0: clr tr0 ;停止timer0jmp start0 ;重复循环;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;time0中断服务子程序用来产生相应的音调脉冲频率。
单片机课程设计生日歌一、教学目标本课程旨在让学生了解和掌握单片机的基本原理和应用,通过制作生日歌项目,培养学生的实际操作能力和创新思维。
具体目标如下:1.知识目标:使学生掌握单片机的基本结构、工作原理和编程方法;了解单片机在实际应用中的重要性。
2.技能目标:培养学生具备单片机的组装、调试和编程能力;学会使用相关软件和实验设备。
3.情感态度价值观目标:培养学生对科技创新的热爱,提高他们的团队协作和沟通能力,增强他们的责任感和使命感。
二、教学内容本课程的教学内容主要包括单片机的基本原理、编程语言、应用实例等。
具体安排如下:1.单片机概述:介绍单片机的定义、发展历程和分类;讲解单片机的基本结构和主要性能指标。
2.单片机编程基础:学习单片机的编程语言,如C语言和汇编语言;掌握单片机的基本指令集和编程技巧。
3.单片机应用实例:分析常见的单片机应用案例,如温度传感器、电机控制等;讲解如何将单片机应用于实际项目中。
4.生日歌项目实践:引导学生分组完成单片机控制的生日歌项目,包括电路设计、编程、调试等环节。
三、教学方法本课程采用多种教学方法,以激发学生的学习兴趣和主动性:1.讲授法:讲解单片机的基本原理、编程方法和应用实例,使学生掌握相关知识。
2.实验法:安排实验环节,让学生亲自动手操作,培养其实际操作能力和创新能力。
3.案例分析法:分析具体的单片机应用案例,让学生了解单片机在实际项目中的应用。
4.讨论法:学生分组讨论,鼓励他们提出问题、分享心得,提高团队协作和沟通能力。
四、教学资源为了支持本课程的教学内容和教学方法,我们将准备以下教学资源:1.教材:选择合适的单片机教材,为学生提供系统性的知识学习。
2.参考书:提供相关的参考书籍,丰富学生的知识体系。
3.多媒体资料:制作课件、视频等多媒体资料,生动形象地展示单片机的原理和应用。
4.实验设备:准备单片机实验板、编程器、实验器件等,为学生提供实践操作的机会。
五、教学评估为了全面、客观地评估学生的学习成果,本课程将采用以下评估方式:1.平时表现:评估学生在课堂上的参与程度、提问回答等情况,以考察其对单片机知识的掌握和运用能力。
;本程序实现蜂鸣器演奏歌曲功能
;乐曲名称:生日快乐
;///////////////////////////////////////////
BUZZER EQU P2.3
org 0000h ;主程序起始地址
ajmpmain ;跳至主程序
org 000bh ;timer0中断起始地址
jmp tim0 ;跳至timer0中断子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0030h
main:
mov tmod,#01h ;设timer0在MODE1
mov ie,#82h ;中断使能
start0:
mov 30h,#00h ;取简谱码指针
next:mov a,30h ;简谱码指针载入A
mov dptr,#table ;至table取简谱码
movc a,@a+dptr
mov r2,a ;取到的简谱码暂存于R2
jz end0 ;是否取到00(结束码)?
anl a,#0fh ;不是,则取低4位(节拍码)
mov r5,a ;将节拍码存入R5
mov a,r2 ;将取到的简谱码再载入A
swap a ;高低四位交换
anl a,#0fh ;取低四位(音符码)
jnz sing ;取到的音符码是否为零?
clr tr0 ;是,则不发音
jmp d1
sing: d ec a ;取到的音符码减1(不含0).
mov 22h,a ;存入(22H).
rl a ;乘2
mov dptr,#table1 ;至table1取相对的高位字节计数值
movc a,@a+dptr
mov th0,a ;取到的高位字节存入TH0
mov 21h,a ;取到的高位字节存入(21H)
mov a,22h ;再载入取的的音符码
rl a ;乘2
inc a ;加1
movc a,@a+dptr ;至table1取相对的低位字节计数值mov tl0,a ;取到的高位字节存入TL0
mov 20h,a ;取到的高位字节存入(20H)
setb tr0 ;启动timer0
d1: call delay ;基本单位时间1/4拍187毫秒
inc 30h ;取简谱码指针加1
jmp next ;取下一个码
end0: clr tr0 ;停止timer0
jmp start0 ;重复循环;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;time0中断服务子程序用来产生相应的音调脉冲频率。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tim0:
push acc ;将A的值暂存于堆栈
push psw ;将psw的值暂存于堆栈
mov tl0,20h ;重设计数值
mov th0,21h
cpl BUZZER ;将蜂鸣器反相
pop psw ;至堆栈取回psw的值
pop acc ;至堆栈取回a的值
reti ;返回主程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
delay: mov r7,#02h ;187毫秒
d2: mov r4,#187
d3: mov r3,#248
djnz r3,$
djnz r4,d3
djnz r7,d2
djnz r5,delay ;决定节拍
ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
table1:
dw 64260,64400,64524,64580
dw 64684,64777,64820,64898
dw 64968,65030,65058,65110
dw 65157,65178,65217
table:
;1
db 82h,01h,81h,94h,84h,0b4h,0a4h,04h,82h,01h,81h,94h,84h,0c4h,0b4h,04h
;2
db 82h,01h,81h,0f4h,0d4h,0b4h,0a4h,94h,0e2h,01h,0e1h,0d4h,0b4h,0c4h,0b4h,04h ;3
db 82h,01h,81h,94h,84h,0b4h,0a4h,04h,82h,01h,81h,94h,84h,0c4h,0b4h,04h
;4
db 82h,01h,81h,0f4h,0d4h,0b4h,0a4h,94h,0e2h,01h,0e1h,0d4h,0b4h,0c4h,0b4h,04h,00 end。