1. 程式人生 > 實用技巧 >溫度感測器與蜂鳴器的使用

溫度感測器與蜂鳴器的使用

實時顯示溫度與時間,並設定鬧鐘,播放音樂

proteus模擬圖

  1 #include <AT89X51.H> 
  2 #include <intrins.h>
  3 #include <string.h>
  4 #define uint unsigned int
  5 #define uchar unsigned char
  6 
  7 sbit IO = P1^0;
  8 sbit SCLK = P1^1;
  9 sbit RST = P1^2;         //pdf中的CE即是RST
10 sbit RS = P2^0; 11 sbit RW = P2^1; 12 sbit EN = P2^2; 13 sbit beep = P1^3; 14 sbit k1 = P3^0; 15 sbit k2 = P3^1; 16 sbit k3 = P3^2; 17 sbit k4 = P3^5; 18 sbit LED = P2^7; 19 sbit DQ = P3^3; 20 21 uchar LCD_DQY_BUFFER1[30]={"DATE 00-00-00 00:00:00 00.0C"}; // buffer緩衝器 年 13個字元 22
uchar LCD_DQY_BUFFER2[]={"CLOCK 00:00:00 "}; //時間 23 uchar DateTime[7]; 24 25 uchar n=0, h=23,m=19,s=0,R=0; 26 uchar table[]={"0123456789"}; 27 uchar ClockTime[7]; 28 29 uint dian; 30 uchar A; 31 uchar temp[6]={10,10,10,10,10,10}; 32 33 /*音樂部分*/ 34 uchar timeh,timel;//用於存放定時器的高8位和低8位 35 uchar code jianpu[]={//
定義<<送別>>簡譜 每一個值第一位對應簡譜的音調,第二位對應拍的長短 36 0x54,0x32,0x52,0x88,0x64,0x84,0x58,0x54,0x12,0x22,0x34,0x22,0x12,0x28,0x00,0x00, 37 0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,0x54,0x22,0x32,0x46,0x92,0x18,0x00,0x00, 38 0x64,0x84,0x88,0x74,0x62,0x72,0x88,0x62,0x72,0x82,0x62,0x62,0x52,0x32,0x12,0x28,0x00,0x00, 39 0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,0x54,0x22,0x32,0x46,0x92,0x18,0x00,0x00, 40 0x54,0x32,0x52,0x88,0x64,0x84,0x58,0x54,0x12,0x22,0x34,0x22,0x12,0x28,0x00,0x00, 41 0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,0x54,0x22,0x32,0x46,0x92,0x18,0x00,0x00 42 }; 43 //適合12M的晶振定時器初值表,高低8位分開 44 uchar code chuzhi[]= 45 { 46 0xFF,0xFF, //佔位 47 0xFC,0x43, //中音1-7 48 0xFC,0xad, 49 0xFD,0x0a, 50 0xFD,0x34, 51 0xFD,0x82, 52 0xFD,0xc8, 53 0xFE,0x06, 54 0xFE,0x21, //高音1 55 0xFC,0x0C //低音7 56 }; 57 void timer0() interrupt 1 //定時器0(T0)中斷服務程式 58 { 59 TH0=timeh; //將timeh賦給計時器的高8位 60 TL0=timel; //將timel賦給計時器的低8位 61 beep=~beep; //定時器每次到時將蜂鳴器反相 62 } 63 64 void delay(uchar z) //延時125MS,設為1個十六分音符,1/4拍 65 { uint y; 66 for(z;z>0;z--) 67 for(y=15615;y>0;y--); 68 } 69 70 void delay1(uchar z) //延時0.5MS 71 { uchar y; 72 for(z;z>0;z--) 73 for(y=243;y>0;y--); 74 } 75 76 void music() 77 { 78 uchar temp; //存放簡譜陣列中的每一個音符的臨時變數 79 uchar i=0; 80 uchar jp; //jp用於取出temp中的高8位和低8位 81 IT0=1; //INT0 82 TMOD=0x01; //設定定時器T0工作於方式1 83 IE=0x82; //允許T0中斷 84 85 86 while(R==1) 87 { 88 temp=jianpu[i]; 89 if(temp==0xff) 90 break; 91 jp=temp/16; //取數的高4位,音訊數值 92 93 if(jp!=0) 94 { 95 timeh=chuzhi[jp*2]; //構造定時器初值高8位 96 timel=chuzhi[jp*2+1]; //構造定時器初值低8位 97 TR0=1; //開定時器 98 } 99 else 100 { 101 TR0=0; //關定時器 102 beep=1; //關蜂鳴器 103 } 104 delay(temp%16); //取數的低4位,節拍(音符總時延) 105 TR0=0; //唱完一個音停5MS 106 beep=1; 107 delay1(10); 108 i++; 109 110 if(k4==0) //鬧鐘的控制鍵 111 { 112 R=0; 113 m=m+5; 114 } 115 } 116 } 117 118 /*1602部分*/ 119 void DelayMS(uint ms) // 1 120 { 121 uchar i; 122 while(ms--) 123 { 124 for(i=0;i<120;i++); 125 } 126 } 127 128 void Write_A_Byte_TO_DQ1302(uchar x) // 2 DQ1302寫 129 { 130 uchar i; 131 for(i=0;i<8;i++) 132 { 133 IO=x&0x01;SCLK=1;SCLK=0;x>>=1; //假設x=5,那麼x的二進位制為0101,x>>1表示x右移1位,即把最右邊一位的1刪掉,變為010,此時x=2 134 } // 135 } 136 137 uchar Get_A_Byte_FROM_DQ1302() // 3 DQ1302取 138 { 139 uchar i,b=0x00; 140 for(i=0;i<8;i++) 141 { 142 b |= _crol_((uchar)IO,i); //左移 // 143 SCLK=1;SCLK=0; 144 } 145 return b/16*10+b%16; //取完8個位,轉為十六進位制 146 } 147 148 uchar Read_Data(uchar addr) // 4 DQ1302讀取 149 { 150 uchar dat; 151 RST = 0;SCLK=0;RST=1; 152 Write_A_Byte_TO_DQ1302(addr); 153 dat = Get_A_Byte_FROM_DQ1302(); 154 SCLK=1;RST=0; 155 return dat; 156 } 157 158 void GetTime() // 5 獲得DateTime[i]陣列 159 { 160 uchar i,addr = 0x81; //位址0x81為讀秒,每次進2,直到0x8D讀年 161 for(i=0;i<7;i++) 162 { 163 DateTime[i]=Read_Data(addr);addr+=2; //將dat放進陣列中 164 } 165 } 166 167 uchar Read_LCD_State() // 6 1602 168 { 169 uchar state; 170 RS=0;RW=1;EN=1;DelayMS(1); 171 state=P0; 172 EN = 0;DelayMS(1); 173 return state; 174 } 175 176 void LCD_Busy_Wait() // 7 177 { 178 while((Read_LCD_State()&0x80)==0x80); //當最高位為1時,延時5秒 179 DelayMS(5); 180 } 181 182 void Write_LCD_Data(uchar dat) // 8 183 { 184 LCD_Busy_Wait(); 185 RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0; //dat為 186 } 187 188 void Write_LCD_Command(uchar cmd) // 9 command命令 控制 189 { 190 LCD_Busy_Wait(); 191 RS=0;RW=0;EN=0;P0=cmd;EN=1;DelayMS(1);EN=0; //cmd為地址 192 } 193 194 void Init_LCD() // 10 初始化 195 { 196 Write_LCD_Command(0x38); //顯示16*2顯示,5*7點陣,8位資料介面 197 DelayMS(1); 198 Write_LCD_Command(0x01); //顯示清零,資料指標清零 199 DelayMS(1); 200 Write_LCD_Command(0x06); //寫一個字元後地址指標加一 201 DelayMS(1); 202 Write_LCD_Command(0x0c); //設定開顯示,不顯示游標 203 DelayMS(1); 204 } 205 206 void Set_LCD_POS(uchar p) // 11 207 { 208 Write_LCD_Command(p|0x80); // 209 } 210 211 void Display_LCD_String(uchar p,uchar *s) //12 在LCD顯示 Display_LCD_String(0x00,LCD_DQY_BUFFER1); 212 { 213 uchar i; 214 Set_LCD_POS(p); //p為液晶屏地址0x00 215 for(i=0;i<25;i++) 216 { 217 Write_LCD_Data(s[i+n]); 218 DelayMS(1); 219 } 220 n++; DelayMS(500); 221 if(n>16) 222 n=0; 223 } 224 225 void Display_LCD_String2(uchar p,uchar *s) //12 在LCD顯示 Display_LCD_String(0x00,LCD_DQY_BUFFER1); 226 { 227 uchar i; 228 Set_LCD_POS(p); //p為液晶屏地址0x00 229 for(i=0;i<16;i++) 230 { 231 Write_LCD_Data(s[i]); 232 DelayMS(1); 233 } 234 } 235 236 void Format_DateTime(uchar d,uchar *a) // 13 Format_DateTime(DateTime[6],LCD_DQY_BUFFER1+5); 237 { 238 a[0]=d/10+'0'; //0’的ASCII值為48 加‘0’,是為了將前面的數字(1,2···)轉換為ASCII碼的值 239 a[1]=d%10+'0'; 240 } 241 242 void Format_DateTime2(uchar d,uchar *a) // 13 243 { 244 a[0]=d+'0'; 245 } 246 247 /*鍵盤掃描和設定鬧鐘時間*/ 248 void keyscan() 249 { 250 if(k1==0) 251 { 252 DelayMS(100); 253 if(k1==0) // 254 { 255 h++; 256 if(h>=24) 257 { h=0; } 258 while(!k1); //等待按鍵釋放 259 } 260 } 261 262 if(k2==0) // 263 { 264 m=m+1; 265 if(m>=60) 266 m=0; 267 while(!k2); 268 } 269 if(k3==0) // 270 { 271 s=s+1; 272 if(s>=60) 273 s=0; 274 while(!k3); 275 } 276 if(k4==0) //控制鍵 277 { 278 R=0; 279 } 280 } 281 282 void GetClockTime() 283 { 284 ClockTime[0] = h/10; 285 ClockTime[1] = h%10; 286 ClockTime[2] = m/10; 287 ClockTime[3] = m%10; 288 ClockTime[4] = s/10; 289 ClockTime[5] = s%10; 290 } 291 292 /*DQ18B20部分 */ 293 void init_tempr()//DQ18B20初始化 294 { 295 uchar n; 296 DQ=1; 297 DelayMS(8); 298 DQ=0; 299 DelayMS(80); //500us 300 DQ=1; 301 DelayMS(8); 302 n=DQ; 303 DelayMS(4); 304 } 305 void write_byte(uchar dat) 306 { 307 uchar i; 308 for(i=0;i<8;i++) 309 { 310 DQ=0; 311 DQ=dat&0x01; 312 DelayMS(4); 313 DQ=1; 314 dat>>=1; 315 } 316 DelayMS(4); 317 } 318 uchar read_byte(void) 319 { 320 uchar i,value; 321 for(i=0;i<8;i++) 322 { 323 DQ=0; 324 value>>=1; 325 DQ=1; 326 if(DQ) 327 value|=0x80; 328 DelayMS(4); 329 } 330 return value; 331 } 332 uchar readtempr(void) 333 { 334 uint temp, a,b; 335 init_tempr(); 336 write_byte(0xcc); 337 write_byte(0x44); 338 DelayMS(300); 339 init_tempr(); 340 write_byte(0xcc); 341 write_byte(0xbe); 342 DelayMS(300); 343 a=read_byte(); 344 b=read_byte(); 345 346 temp=b; 347 temp<<=4; 348 temp+=(a&0xf0)>>4; 349 dian=(a&0x0f)*10*6/10; // 小數位轉化 350 return temp; 351 } 352 353 void dis_deal() 354 { 355 temp[0]=A/10; 356 temp[1]= A%10; 357 temp[2]=dian/10 ; 358 temp[3]=dian%10 ; 359 } 360 361 /*主函式*/ 362 void main() 363 { 364 SCON = 0X40; // 序列口的工作模式選擇 365 TMOD = 0X20; // 定時器0方式2 366 PCON = 0X00; // 波特率倍數 367 TH1 = 0XFD; 368 TL1 = 0XFD; 369 TI = 0; 370 TR1 = 1; 371 372 TCON=0x05; 373 PX1=1; 374 PT0=0; 375 EX1=1; 376 Init_LCD(); 377 while(1) 378 { 379 GetTime(); 380 Format_DateTime(DateTime[6],LCD_DQY_BUFFER1+5); // 381 Format_DateTime(DateTime[4],LCD_DQY_BUFFER1+8); // 382 Format_DateTime(DateTime[3],LCD_DQY_BUFFER1+11); // 383 Format_DateTime(DateTime[2],LCD_DQY_BUFFER1+14); // 384 Format_DateTime(DateTime[1],LCD_DQY_BUFFER1+17); // 385 Format_DateTime(DateTime[0],LCD_DQY_BUFFER1+20); // 386 Display_LCD_String(0x00,LCD_DQY_BUFFER1); 387 388 A=readtempr(); 389 dis_deal(); 390 Format_DateTime2(temp[0],LCD_DQY_BUFFER1+23); // 391 Format_DateTime2(temp[1],LCD_DQY_BUFFER1+24); // 392 Format_DateTime2(temp[2],LCD_DQY_BUFFER1+26); // 393 394 keyscan(); 395 GetClockTime(); 396 Format_DateTime2(ClockTime[0],LCD_DQY_BUFFER2+6); 397 Format_DateTime2(ClockTime[1],LCD_DQY_BUFFER2+7); 398 Format_DateTime2(ClockTime[2],LCD_DQY_BUFFER2+9); 399 Format_DateTime2(ClockTime[3],LCD_DQY_BUFFER2+10); 400 Format_DateTime2(ClockTime[4],LCD_DQY_BUFFER2+12); 401 Format_DateTime2(ClockTime[5],LCD_DQY_BUFFER2+13); 402 Display_LCD_String2(0x40,LCD_DQY_BUFFER2); 403 404 if( DateTime[2] == h && DateTime[1] == m) 405 { 406 R=1; music(); 407 } 408 else 409 { 410 R=0; 411 } 412 413 } 414 }