#include "stc15.h"#include intrins.h //添加nop函数的头文件#include stdio.h //sprintf函数#include ds1302.h //sprintf函数#include onewire.h //sprintf函数//定时器1定时1ms 测试DS 1302,测试温度模块读取是不是正常
#include "stc15.h"#include <intrins.h> //添加nop函数的头文件#include <stdio.h> //sprintf函数#include <ds1302.h> //sprintf函数#include <onewire.h> //sprintf函数//定时器1定时1ms 测试DS 1302,测试温度模块读取是不是正常#define FOSC 11059200L#define T1MS (65536-FOSC/1000) //1T模式//#define T1MS (65536-FOSC/12/1000) //12T模式#define LED 4 #define ULN 5 #define COM 6 #define ABC 7 typedef unsigned char u8;typedef unsigned int u16;typedef unsigned long u32;u8 LEDbuf=0xFF; //LED缓冲u8 ULNbuf=0x00; //ULN2003缓冲u8 SMGbuf[8]; //数码管8位,缓冲u8 SMGtemp[20]; //数码管暂时变量,20个字节最多u32 t1mscnt=0;u16 LEDdly=0;u16 ULNdly=0;u16 SMGABCdly=0; //数码管刷新数据u16 SMGdly=0;//数码管显示延时u16 KEYdly=0;u16 ReadDly =0;float wendu=0; //温度float wenduset=23;char page=0; //页面char pagexx=0;char ctrlmode=0;//控制模式,=0温度控制,=1,时间控制u8 zhengdianflag=0;u16 zhengdiantime=0;/************* 本地常量声明 **************/u8 code t_display[]={ //标准字库// 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,//black - H J K L N o P U t G Q r M y 0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e, 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码//函数声明void Delay1ms(); //@11.0592MHzvoid delayms(u16 xms);void sel573(u8 x);//选择哪个一个通道void closeall();void LEDctrl();void ULNctrl();void LEDout();void ULNout();//字库是共阴数码管字库,在stcISP中复制过来。void SMGconv();//将字符串和字库对比,转换到打印区void SMGdisp();void KeyRead();void ReadData();void SMGnow();//测试DS1302程序,测试温度程序void main(){ u8 i=0; //关闭所有的外设 closeall(); //读取一次温度,跳过85度的数据 wendu = read18b20(); delayms(800);//跳过85度的显示数据 AUXR |= 0x40; //定时器1为1T模式 TMOD = 0x00; //设置定时器为模式0(16位自动重装载) TL1 = T1MS; //初始化计时值 TH1 = T1MS >> 8; TR1 = 1; //定时器1开始计时 ET1 = 1; //使能定时器0中断 EA = 1; second = 50; minute = 59; hour =5; set1302(); //设置时间 wendu = read18b20(); //这里读取一次,覆盖之前的85度 while(1) { if(LEDdly>100) { LEDdly=0; LEDctrl(); } if(ULNdly>100) { ULNdly=0; ULNctrl(); } if(ReadDly>500) { ReadDly=0; ReadData(); } if(SMGABCdly>300) { SMGABCdly =0; SMGnow(); } KeyRead(); }}/* Timer1 interrupt routine */void tm1_isr() interrupt 3 using 1{ t1mscnt++; LEDdly++; ULNdly++; ReadDly++; SMGABCdly++; SMGdly++; SMGdisp();//1ms刷新一次 if(zhengdianflag==1) { zhengdiantime++; if(zhengdiantime>=5000) { zhengdiantime=0; //时间清0 zhengdianflag=0; //标记等于0 } }// }void Delay1ms() //@11.0592MHz{ unsigned char i, j; _nop_(); _nop_(); _nop_(); i = 11; j = 190; do { while (--j); } while (--i);}void delayms(u16 xms){ u16 i; for(i=0;i<xms;i++) { Delay1ms(); }}void sel573(u8 x)//选择哪个一个通道{ switch(x) { case 0: P2=P2&0x1F;break; case LED: P2=P2&0x1F|0x80;break;//0x80--a0--c0--e0 case ULN: P2=P2&0x1F|0xA0;break; case COM: P2=P2&0x1F|0xC0;break; case ABC: P2=P2&0x1F|0xE0;break; }}void closeall(){ //关闭LED,蜂鸣器,数码管等; sel573(LED);LEDbuf=0x00;P0=~LEDbuf;sel573(0); //注意,这里取反了LEDbuf,再输出, //因为原理图是低电平点亮,和我们1点亮的常识不太符合 sel573(ULN);ULNbuf=0x00;P0=ULNbuf;sel573(0); //注意ULN2003是反相芯片,0---1,关闭继电器和蜂鸣器 sel573(COM);P0=0x00;sel573(0); //共阳数码管,我们让等于0,不亮 sel573(ABC);P0=0xFF;sel573(0);}void LEDout(){ sel573(LED);P0=~LEDbuf;sel573(0); }void LEDctrl(){ if(zhengdianflag==1) { LEDbuf = LEDbuf | 0x01 ;//L1点亮,P00=0; 00000001 } else if(zhengdianflag==0) { LEDbuf = LEDbuf& (~0x01) ;//L1ximie,P00=0; 0000 0001 } //控制模式 if(ctrlmode==0) //温度控制模式,L2点亮 { LEDbuf = LEDbuf | 0x02 ;//L2点亮,P00=0; 1111 1101 } else if(ctrlmode==1) { LEDbuf = LEDbuf & (~0x02) ;//L2熄灭,P00=0; 0000 0010 } //判断P04是不是等于1,L10点亮 //ULNbuf>>4 0001 0000 if((ULNbuf>>4)&0x01 ==1) //吸合状态 { //L3间隔100ms闪烁 将0000 0100,P03异或1,其他异或0 LEDbuf = LEDbuf ^ 0x04 ;//L3点亮,P00=0; 0000 0100 } else //放开状态 if((ULNbuf>>4)&0x01 ==0) { LEDbuf = LEDbuf &(~0x04) ;//L3熄灭,P00=0;0000 0100 } //输出数据 LEDout();}void ULNout(){ sel573(ULN);P0=ULNbuf;sel573(0);}void ULNctrl(){ if(ctrlmode==0) //温度控制模式 { if(wendu>=wenduset) //继电器P04,让P04=1,闭合 { ULNbuf = ULNbuf |0x10; //0001 0000 } else if(wendu<wenduset) //继电器P04,让P04=0, 松开 { ULNbuf = ULNbuf & (~0x10); //1110 1111 } } else if(ctrlmode==1) //时间控制模式 { //如果是整点的话 if(zhengdianflag==1) { ULNbuf = ULNbuf |0x10; //0001 0000 } else if(zhengdianflag==0) { ULNbuf = ULNbuf & (~0x10); //1110 1111 } } //输出数据 ULNout();}//字库是共阴数码管字库,在stcISP中复制过来。void SMGconv()//将字符串和字库对比,转换到打印区{ //对比一下,放到字库中,注意有个小数点 u8 i,j,temp; while(SMGtemp[i]!=0x00) { switch(SMGtemp[i]) { case '0':temp =0x3F;break; case '1':temp =0x06;break; case '2':temp =0x5B;break; case '3':temp =0x4F;break; case '4':temp =0x66;break; case '5':temp =0x6D;break; case '6':temp =0x7D;break; case '7':temp =0x07;break; case '8':temp =0x7F;break; case '9':temp =0x6F;break; //剩下的字符,看实际需要 case '-':temp =0x40;break; case 'U':temp =0x3E;break; //********** 其他,熄灭 default : temp =0x00;break; } //判断下一个是不是小数点,是的话 //把最高位点亮,i=i+2,跳过小数点 if(SMGtemp[i+1]=='.') { temp =temp |0x80; i=i+2; } else i=i+1; SMGbuf[j]= temp; j=j+1; }}void SMGdisp(){ static u8 i=0; //消隐鬼影 sel573(COM);P0=0x00;sel573(0); //共阳数码管,我们让等于0,不亮 sel573(ABC);P0=0xFF;sel573(0); //显示数据 sel573(COM);P0=T_COM[i];sel573(0); //共阳数码管,我们让等于0,不亮 sel573(ABC);P0=~SMGbuf[i];sel573(0);//注意取反,注意这里是SMGbuf i=i+1; if(i>=8)i=0;}void KeyRead(){//****************************** S17 S13 S9 S5 //****************************** P30=1;P31=1;P32=0;P33=1; P34=1;P35=1;P42=1;P44=1; if(P34==0) //*******************************S17 { delayms(10); if(P34==0) { if(page==2) //参数设置界面 { wenduset=wenduset-1; //每次减1度,最小是10度 if(wenduset<10)wenduset=99; } } while(P34==0)//等待松开 { if(page==1) { pagexx=1; //按下的话,就是显示分秒 read1302();//500ms读取一次时间 SMGnow(); delayms(1); } } pagexx=0;//关闭回到,时,分 } else if(P35==0) //*******************************S13 { delayms(10); //切换工作控制模式 if(P35==0) { if(ctrlmode==0)ctrlmode=1; else if(ctrlmode==1)ctrlmode=0; } while(P35==0);//等待松开 }//****************************** S16 S12 S8 S4 //****************************** P30=1;P31=1;P32=1;P33=0; P34=1;P35=1;P42=1;P44=1; if(P34==0) { delayms(10); if(P34==0) // &*********************************S16 { if(page==2) //参数设置界面 { wenduset=wenduset+1; //每次加一读,最大是99度 if(wenduset>100)wenduset=10; } } while(P34==0);//等待松开 } else if(P35==0) //************************S12 //**********切换页面 { delayms(10); if(P35==0) { if(page==0)page=1; else if(page==1)page=2; else if(page==2)page=0; } while(P35==0);//等待松开 } //******************************}void ReadData(){ read1302();//500ms读取一次时间 if(minute==0 && second ==0 ) { //整点 zhengdianflag=1; } wendu = read18b20();//500ms读取一次 }void SMGnow(){ if(page==0) //温度显示界面 { //U1xxx23.5 sprintf(SMGtemp,"U1 %4.1f",wendu); //测试时间显示 } else if(page==1) { //U2x23-25 if(pagexx==0) { sprintf(SMGtemp,"U2 %02d-%02d",(int)hour,(int)minute); //测试时间显示 } else if(pagexx==1) { sprintf(SMGtemp,"U2 %02d-%02d",(int)minute,(int)second); //测试时间显示 } } else if(page==2) { //U3xxxx23 sprintf(SMGtemp,"U3xxxx%2d",(int)wenduset); //测试时间显示 } SMGconv(); }
DS1302.h
#ifndef __DS1302_H#define __DS1302_Hextern unsigned char second;extern unsigned char minute;extern unsigned char hour;void Write_Ds1302(unsigned char temp);void Write_Ds1302_Byte( unsigned char address,unsigned char dat );unsigned char Read_Ds1302_Byte( unsigned char address );void init1302();//初始化1302的时间,注意BCD码//设置时间和读取时间void set1302();void read1302();#endif
DS1302.c
/* 程序说明: DS1302驱动程序 软件环境: Keil uVision 4.10 硬件环境: CT107单片机综合实训平台 8051,12MHz 日 期: 2011-8-9*/#include <stc15.h>#include <intrins.h> #include <ds1302.h>unsigned char second;unsigned char minute;unsigned char hour;sbit SCK=P1^7; sbit SDA=P2^3; sbit RST = P1^3; // DS1302复位 void Write_Ds1302(unsigned char temp) { unsigned char i; for (i=0;i<8;i++) { SCK=0; SDA=temp&0x01; temp>>=1; SCK=1; }} void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) { RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST=0; }unsigned char Read_Ds1302_Byte ( unsigned char address ){ unsigned char i,temp=0x00; RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302(address); for (i=0;i<8;i++) { SCK=0; temp>>=1; if(SDA) temp|=0x80; SCK=1; } RST=0; _nop_(); SCK=0; _nop_(); SCK=1; _nop_(); SDA=0; _nop_(); SDA=1; _nop_(); return (temp); }void init1302()//初始化1302的时间,注意BCD码{ //关闭写保护 Write_Ds1302_Byte(0x8E,0x00); //写数据 Write_Ds1302_Byte(0x80,0x50); // 秒 50秒 Write_Ds1302_Byte(0x82,0x20); //分 20分 Write_Ds1302_Byte(0x84,0x10); //时 10点 //打开写保护 Write_Ds1302_Byte(0x8E,0x80); }//设置时间和读取时间void set1302(){ unsigned char miaotemp; unsigned char fentemp; unsigned char shitemp; //将十进制数据,改造成BCD码。参照STCISP软件 miaotemp= ((second / 10) << 4) + (second % 10); fentemp = ((minute / 10) << 4) + (minute % 10); shitemp= ((hour / 10) << 4) + (hour % 10); //关闭写保护 Write_Ds1302_Byte(0x8E,0x00); //写数据 Write_Ds1302_Byte(0x80,miaotemp); // 秒 50秒 Write_Ds1302_Byte(0x82,fentemp); //分 20分 Write_Ds1302_Byte(0x84,shitemp); //时 10点 //打开写保护 Write_Ds1302_Byte(0x8E,0x80); }void read1302(){ unsigned char miaotemp; unsigned char fentemp; unsigned char shitemp; //关闭写保护 Write_Ds1302_Byte(0x8E,0x00); //数据 miaotemp=Read_Ds1302_Byte(0x81); // 秒 50秒 fentemp=Read_Ds1302_Byte(0x83); //分 20分 shitemp= Read_Ds1302_Byte(0x85); //时 10点 //打开写保护 Write_Ds1302_Byte(0x8E,0x80); second = ((miaotemp >> 4) & 0x07) * 10 + (miaotemp& 0x0f); minute = ((fentemp >> 4) & 0x07) * 10 + (fentemp & 0x0f); hour = ((shitemp >> 4) & 0x03) * 10 + (shitemp& 0x0f);}
onewire.h
#ifndef __ONEWIRE_H#define __ONEWIRE_Hunsigned char rd_temperature(void); //; ;float read18b20();#endif
onewire.c
/* 程序说明: 单总线驱动程序 软件环境: Keil uVision 4.10 硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机 日 期: 2011-8-9*/#include "stc15.h"#include "onewire.h"sbit DQ = P1^4; //单总线接口//单总线延时函数void Delay_OneWire(unsigned int t) //STC89C52RC{ t=t*10; while(t--);}//通过单总线向DS18B20写一个字节void Write_DS18B20(unsigned char dat){ unsigned char i; for(i=0;i<8;i++) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5);}//从DS18B20读取一个字节unsigned char Read_DS18B20(void){ unsigned char i; unsigned char dat; for(i=0;i<8;i++) { DQ = 0; dat >>= 1; DQ = 1; if(DQ) { dat |= 0x80; } Delay_OneWire(5); } return dat;}//DS18B20设备初始化bit init_ds18b20(void){ bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0; Delay_OneWire(80); DQ = 1; Delay_OneWire(10); initflag = DQ; Delay_OneWire(5); return initflag;}//背下来 ,忘记了顺序的话,float read18b20(){ unsigned char high,low; unsigned int temp; float xx; init_ds18b20(); Write_DS18B20(0xCC); //跳过ROM Write_DS18B20(0x44); //开始转换 Delay_OneWire(100); init_ds18b20(); Write_DS18B20(0xCC); //跳过ROM Write_DS18B20(0xBE); //读取数据 Delay_OneWire(100); low= Read_DS18B20(); //先低 high= Read_DS18B20(); //后高 //与0x0F,是将高四位清0,因为只有12位精度 //左移八位,然后或,合并 temp = ((high &0x0F)<<8) | low ; xx=temp*0.0625;//转换得到实际的温度 return xx;}