51單片機定時器LCD顯示加音樂
單片機源程序如下:
- #include<reg51.h> //調用51單片機的頭文件
- #define uchar unsigned char
- #define uint unsigned int
- //---------------------------------------
- //1602液晶相關I/O設置
- //sbit E=P2^3; //1602液晶的E腳接在P2.3口上
- //sbit RW=P2^4; //1602液晶的RW腳接在P2.4口上
- //sbit RS=P2^5; //1602液晶的RS腳接在P2.5口上
- sbit E=P2^7; //1602液晶的E腳接在P2.3口上
- sbit RW=P2^5; //1602液晶的RW腳接在P2.4口上
- sbit RS=P2^6; //1602液晶的RS腳接在P2.5口上
- sbit Busy=P0^7;
- //按鍵相關I/O設置
- sbit key1=P3^0;
- sbit key2=P3^1;
- sbit key3=P3^2;
- //sbit beep = P1^3;
- sbit beep = P1^5;
- uchar code word1[]={" TIME STOP "};
- uchar code word2[]={" TIME SET! "};
- uchar code word3[]={" TIME START "};
- //---------------------------------------
- unsigned char i;
- unsigned char menu;
- signed int Time_bai,Time_ge;
- bit Adjust;
- //---------------------------------------
- //1602液晶寄存器設置
- unsigned int DISbuf_ge,DISbuf_bai; //設置16位的unsigend int型寄存器用來暫存1602要顯示的內容
- //---------------------------------------
- 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 Display();
- void DelayMS(uint ms)
- {
- uchar t;
- while(ms--)
- {
- 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;
- if(Adjust==1)
- break;
-
- //SONG_TONE 延時表決定了每個音符的頻率
-
- for(k=0;k<SONG_TONE[i]/3;k++);
-
- }
-
- DelayMS(70);
- i++;
-
- }
- }
- void led()
- {
- P2 = P2 << 1; //第一次循環,led1亮,其他都不亮
- if(P2 == 0x00) //全部移出
- P2 = 0x01;
- }
- //---------------------------------------
- //名稱:1602液晶用延時函數
- //---------------------------------------
- void Delay1602(unsigned int t)
- {
- unsigned int k; //定義一個16位寄存器用來做延時用
- for(k=0;k<t;k++); //延時
- }
- //---------------------------------------
- //名稱:1602液晶忙檢測函數
- //---------------------------------------
- void LCD1602_busy(void)
- {
- Busy=1; //將P0.7置1,為讀狀態做準備
- RS=0; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
- RW=1; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
- E=1; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入
- while(Busy==1); //由P0.7讀入1,表示1602液晶忙,需要等待
- E=0; //讀完以后,恢復E的電平
- }
- //---------------------------------------
- //名稱:1600寫命令函數
- //適用:給力者GL9單片機開發學習系統
- //公司:寧波芯動電子有限公司
- //網址:www.MovingChip.com
- //日期:20120914
- //---------------------------------------
- void LCD1602_Write_com(unsigned char combuf)
- {
- RS=0; //選擇指令寄存器
- RW=0; //選擇寫狀態
- P0=combuf; //將命令字通過P0口送至DB
- E=1; //E高電平將命令字寫入1602液晶
- E=0; //寫完以后,恢復E的電平
- }
- //---------------------------------------
- //名稱:1602寫命令函數(帶忙檢測)
- //---------------------------------------
- void LCD1602_Write_com_busy(unsigned char combuf)
- {
- LCD1602_busy(); //調用忙檢測函數
- LCD1602_Write_com(combuf); //調用忙檢測函數
- }
- //---------------------------------------
- //名稱:1602寫數據函數(帶忙檢測)
- //---------------------------------------
- void LCD1602_Write_data_busy(unsigned char databuf)
- {
- LCD1602_busy(); //調用忙檢測函數
- RS=1; //選擇數據寄存器
- RW=0; //選擇寫狀態
- P0=databuf; //將命令字通過P0口送至DB
- E=1; //E高電平將命令字寫入1602液晶
- E=0; //寫完以后,恢復E的電平
- }
- //---------------------------------------
- //名稱:1602液晶顯示地址寫函數
- //適用:給力者GL9單片機開發學習系統
- //公司:寧波芯動電子有限公司
- //網址:www.MovingChip.com
- //日期:20120914
- //---------------------------------------
- void LCD1602_Write_address(unsigned char x,unsigned char y)
- {
- x&=0x0f; //列地址限制在0-15間
- y&=0x01; //行地址限制在0-1間
- if(y==0) //如果是第一行
- LCD1602_Write_com_busy(x|0x80); //將列地址寫入
- else //如果是第二行
- LCD1602_Write_com_busy((x+0x40)|0x80); //將列地址寫入
- }
- //---------------------------------------
- //名稱:1602液晶初始化函數
- //---------------------------------------
- void LCD1602_init(void)
- {
- Delay1602(1500); //調用延時函數
- LCD1602_Write_com(0x38); //8位數據總線,兩行顯示模式,5*7點陣顯示
- Delay1602(500); //調用延時函數
- LCD1602_Write_com(0x38); //8位數據總線,兩行顯示模式,5*7點陣顯示
- Delay1602(500); //調用延時函數
- LCD1602_Write_com(0x38); //8位數據總線,兩行顯示模式,5*7點陣顯示
- LCD1602_Write_com_busy(0x38); //8位數據總線,兩行顯示模式,5*7點陣顯示
- LCD1602_Write_com_busy(0x08); //顯示功能關,無光標
- LCD1602_Write_com_busy(0x01); //清屏
- //LCD1602_Write_com_busy(0x06); //寫入新的數據后,光標右移,顯示屏不移動
- LCD1602_Write_com_busy(0x0C); //顯示功能開,無光標
- }
- //---------------------------------------
- //名稱:1602液晶指定地址顯示函數
- //---------------------------------------
- void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf)
- {
- LCD1602_Write_address(x,y); //先將地址信息寫入
- LCD1602_Write_data_busy(buf); //再寫入要顯示的數據
- }
- //---------------------------------------
- //名稱:1602液晶將字符輸出到液晶顯示
- //---------------------------------------
- void Print(unsigned char x,unsigned char y,unsigned char *str)
- {
- LCD1602_Write_address(x,y);
- while(*str!='\0')
- {
- LCD1602_Write_data_busy(*str);
- str++;
- }
- }
- //---------------------------------------
- //名稱:Delay10ms延時10毫秒函數
- //---------------------------------------
- void Delay10ms(void) //誤差 0us
- {
- unsigned char a,b,c;
- for(c=1;c>0;c--)
- for(b=38;b>0;b--)
- for(a=130;a>0;a--);
- }
- void keyscan()
- {
- if(key1==0) //檢測按鍵K1是否按下
- {
- Delay10ms(); //消除抖動
- while(key1==0);
- menu++;
- if(menu==3)
- menu=1;
- Adjust=1;
- }
- if(menu==1)
- {
- Print(0,0,word2);
- DISbuf_bai=0;
- DISbuf_ge=0;
- LCD1602_Disp(2,1,DISbuf_bai/1000+'0'); //在第1行的第1列顯示千位
- LCD1602_Disp(3,1,(DISbuf_bai%1000)/100+'0'); //在第1行的第2列顯示百位
- LCD1602_Disp(4,1,':');
- LCD1602_Disp(5,1,(DISbuf_ge%100)/10+'0'); //在第1行的第3列顯示十位
- LCD1602_Disp(6,1,DISbuf_ge%10+'0'); //在第1行的第4列顯示個位
- if(key2==0) //檢測按鍵K1是否按下
- {
- Delay10ms(); //消除抖動
- while(key2==0);
- Time_ge++;
- if(Time_ge>59)
- {
- Time_ge=0;
- Time_bai++;
- }
- }
- if(key3==0) //檢測按鍵K1是否按下
- {
- Delay10ms(); //消除抖動
- while(key3==0);
- Time_ge--;
- if(Time_ge<0)
- {
- Time_ge=59;
- Time_bai--;
- }
-
- }
- }
- if(menu==2)
- {
- if(key2==0) //檢測按鍵K1是否按下
- {
- Delay10ms(); //消除抖動
- while(key2==0);
- Print(0,0,word3);
- Adjust=0;
- }
- if(key3==0) //檢測按鍵K1是否按下
- {
- Delay10ms(); //消除抖動
- while(key3==0);
- Print(0,0,word1);
- Adjust=1;
-
- }
- if(Adjust==0)
- {
- Print(0,0,word3);
- }
- else
- {
- Print(0,0,word1);
- }
- }
- LCD1602_Disp(9,1,Time_bai/10+'0'); //在第1行的第1列顯示千位
- LCD1602_Disp(10,1,Time_bai%10+'0'); //在第1行的第2列顯示百位
- LCD1602_Disp(11,1,':');
- LCD1602_Disp(12,1,Time_ge/10+'0'); //在第1行的第3列顯示十位
- LCD1602_Disp(13,1,Time_ge%10+'0'); //在第1行的第4列顯示個位
- }
- void Display()
- {
- LCD1602_Disp(2,1,DISbuf_bai/10+'0'); //在第1行的第1列顯示千位
- LCD1602_Disp(3,1,DISbuf_bai%10+'0'); //在第1行的第2列顯示百位
- LCD1602_Disp(4,1,':');
- LCD1602_Disp(5,1,DISbuf_ge/10+'0'); //在第1行的第3列顯示十位
- LCD1602_Disp(6,1,DISbuf_ge%10+'0'); //在第1行的第4列顯示個位
- if(DISbuf_ge==Time_ge && DISbuf_bai==Time_bai)
- Adjust=1;
- }
- //---------------------------------------
- //名稱: 主函數
- //---------------------------------------
- void main(void) //主函數,單片機開機后就是從這個函數開始運行
- {
- LCD1602_init(); //調用1602液晶初始化函數
- //***定時器Timer0初始化***
- TMOD&=0xF0; //將TMOD的低4位定時器0控制部分清零
- TMOD|=0x01; //設置定時器0為方式1
- TL0=0xFF; //設置定時器0初值低8位
- TH0=0x4B; //設置定時器0初值高8位
- TR0=1; //啟動定時器0
- ET0=1; //Timer0中斷允許
- //**********************
- //***開全局中斷設置****
- //定時器Timer0設置了中斷允許,此處要開全局中斷
- EA=1; //開全局中斷
- //*********************
- menu=2;
- Adjust=1;
- Time_bai=1;
- Time_ge=0;
- DISbuf_bai=0;
- DISbuf_ge=0;
- Print(0,0,word1);
- LCD1602_Disp(2,1,DISbuf_bai/10+'0'); //在第1行的第1列顯示千位
- LCD1602_Disp(3,1,DISbuf_bai%10+'0'); //在第1行的第2列顯示百位
- LCD1602_Disp(4,1,':');
- LCD1602_Disp(5,1,DISbuf_ge/10+'0'); //在第1行的第3列顯示十位
- LCD1602_Disp(6,1,DISbuf_ge%10+'0'); //在第1行的第4列顯示個位
- beep=1;
- P0 = 0x01;
- while(1) //死循環,單片機初始化后,將一直運行這個死循環
- {
-
- if(Adjust==0) //非調節模式下顯示時間和控制燈
- {
- Display();
- PlayMusic(); //播放生日快樂
- //DelayMS(500); //播放完后暫停一段時間
- }
- else
- {
- beep = 1;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
Project8.zip
(53.13 KB, 下載次數: 25)
2017-9-5 17:55 上傳
點擊文件名下載附件
51單片機定時器LCD顯示加音樂
|