一、功能實現:
二、代碼內容:
主函數.c
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"sbit Buzzer=P2^5;#define SPEED 500
//原先默認一個四分音符延遲500ms#define P 0 //休止
#define L1 1 //低音1
#define L1_ 2 //低音1升半音
#define L2 3
#define L2_ 4
#define L3 5
#define L4 6
#define L4_ 7
#define L5 8
#define L5_ 9
#define L6 10
#define L6_ 11
#define L7 12
#define M1 13
#define M1_ 14
#define M2 15
#define M2_ 16
#define M3 17
#define M4 18
#define M4_ 19
#define M5 20
#define M5_ 21
#define M6 22
#define M6_ 23
#define M7 24
#define H1 25
#define H1_ 26
#define H2 27
#define H2_ 28
#define H3 29
#define H4 30
#define H4_ 31
#define H5 32
#define H5_ 33
#define H6 34
#define H6_ 35
#define H7 36unsigned int FreqTable[]={0,//第零位是休止符63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,//12低音64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,//12中音65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283 //12高音};//Music[]數組中每行第一個為音調,第二個為延續時間
//以16分音符為1,8分音符為2,4分音符為4,2分音符為8,全音符為16//RAM只有512字節,不夠存儲
//ROM有8K(FLASH),使用ROM,Music前要加code,但是此時性質變為只可讀取,不可修改unsigned char code Music[]=
{ //音符,時值,//line1M1,2+1,M1,1,L6,2,M1,2,M3,2,M2,2+2,M1,2,M3,2,M3,2,L5,2,L7,2,L6,4,M1,2,L7,2,L6,2,L6,2,M1,2,M2,2,M3,2,L5,2+2+1,M5,1,//Line2L5,2,L5,2,L3,2,M5,2,M3,4,M3,2,M2,2,L6,4,M1,2,M3,2,M2,2+4,M1,2,M3,2,M3,2,L5,2,L7,2,L6,4,M1,2,L7,2,L6,2,L6,2,M3,2,M3,2,M1,2,M2,2,P,2,M1,2,//Line3M3,2,M3,2,M2,2,M3,2,L6,4+4,P,4,M3,2,M5,2,M6,4,M3,2,M6,2,M5,4,P,2,M5,2,M6,2,M5,2,M3,2,M2,2,M3,4,M3,2,M2,2,M1,2,L6,2,M1,2,M3,2,M2,4,P,2,M3,2,//Line4M5,2,M5,2,M5,2,M1,2,M2,4,M3,2,M5,2,M6,4,M3,2,M6,2,M5,4,P,2,M5,2,M6,2,M5,2,M5,2,M6,2,M3,4,M3,2,M2,2,M1,2,L6,2,M1,2,M2,2,M3,2,L5,2,L5,2,L3,2,//Line5L5,4,L5,2,L7,2,L6,4+4,0xFF //終止標志
};unsigned char FreqSelect,MusicSelect=0;void main()
{Timer0_Init();while(1){ if(Music[MusicSelect]!=0xFF){FreqSelect=Music[MusicSelect];MusicSelect++;//原先默認一個四分音符延遲500ms,此程序由于四分音符延長時間為4部分,則一部分的延長時間為125msDelay(SPEED/4*Music[MusicSelect]);MusicSelect++; TR0=0;//停止計時Delay(5);TR0=1;//開始計時 }else{TR0=0;while(1);}}}void Timer0_Routine() interrupt 1
{ if(FreqTable[FreqSelect]!=0){TL0 = FreqTable[FreqSelect]%256;TH0 = FreqTable[FreqSelect]/256; Buzzer=!Buzzer; }}
定時器.c
#include <REGX52.H>
/*** @brief 定時器0初始化,1毫秒@11.0592MHz* @param 無* @param 無* @retval 無*///由軟件生成的定時器計算,注意每次要重新配置參數
void Timer0_Init(void)
{//AUXR &= 0x7F; //(89C52因為版本老沒有這個寄存器)定時器時鐘12T模式TMOD &= 0xF0; //設置定時器模式TMOD |= 0x01; //設置定時器模式TL0 = 0x66; //設置定時初始值TH0 = 0xFC; //設置定時初始值TF0 = 0; //清除TF0標志TR0 = 1; //定時器0開始計時//(補上)ET0=1;//允許中斷EA=1;//允許總中斷PT0=0;//中斷優先級為0
}/*
void Timer0_Init()//定時器+中斷系統的初始化函數
{//原理圖在開發手冊P190//TMOD=0x01; //0000 0001 from 開發手冊P189-定時器工作模式//TMOD是不可位尋址只能整體賦值 TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位保持不變/*假設TMOD為1010 00111010 0011 & 1111 0000 = 1010 0000TMOD=TMOD&0xF低四位清零,高四位保持不變TMOD=TMOD|0x01;//把TMOD的最低位改為1,高四位保持不變1010 0000 | 0000 0001 =1010 0001最低位改為1,高四位保持不變TF0=0; //from 開發手冊P188-定時器控制-中斷//TCOM是可位尋址可以對其中的每一位單獨賦值,TF0就是其中一位TR0=1; //from 開發手冊P188-定時器控制-開始計數0~65535每隔一微秒計數加一總共定時時間位65535微秒如果賦初始值為64535,距離計數器計數器溢出差值1000所以計時時間為1毫秒P190原理圖TH0=64535/256;TL0=64535%256;16進制存儲在兩個寄存器,分高低位如果以10進制為例子
123存儲在兩個寄存器內
123/100=1(高位)
123%100=23(低位)//下面是中斷系統的初始化,是老一代51單片機,現在單片機可以向下兼容的。ET0=1;EA=1;PT0=0;}
*//*初始化后如何在主代碼中使用定時器T0的功能,定時器T0的中斷號為1舉個例子void Timer0_Routine() interrupt 1
{ static unsigned int T0Count;//退出此程序后不刷新數據,保留數據,稱為局內的靜態數據TL0 = 0x66;TH0 = 0xFC; //計時器溢出默認為0,下一次中斷會變成65倍的時間//將其設定為T0Count++;if(T0Count>=500){T0Count=0;}}
*/
定時器.h
#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0_Init(void);#endif
Delay.c
void Delay(unsigned int xms)
{unsigned char data i, j;while(xms--){i = 2;j = 199;do{while (--j);} while (--i);}
}
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (創作不易,主函數在主頁下載資源內)
? ? ? ? ? ? ? ? ? ? ? ? ?【免費】51單片機:蜂鳴器播放音樂(盜將行).zip資源-CSDN文庫
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 謝謝大家!
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 小白一枚,請多指教! ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FROM 明月清風mls