温度传感器与蜂鸣器的使用

实时显示温度与时间,并设置闹钟,播放音乐

 

                                                   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 }

 

posted @ 2020-07-23 16:25  何时悠长假期  Views(480)  Comments(0Edit  收藏  举报