bit write=0; //写24C02的标志; sbit sda=P2^0; sbit scl=P2^1; void delay0() { ;; } void start() //开始信号 { sda=1; delay0(); scl=1; delay0(); sda=0; delay0(); } void stop() //停止 { sda=0; delay0(); scl=1; delay0(); sda=1; delay0(); } void respons() //应答 { uchar i; scl=1; delay0(); while((sda==1)&&(i<250))i++; scl=0; delay0(); } void init_24c02()//IIC初始化函数 { sda=1; delay0(); scl=1; delay0(); } void write_byte(uchar date)//写一个字节函数 { uchar i,temp; temp=date; for(i=0;i<8;i++) { temp=temp<<1; scl=0; delay0(); sda=CY; delay0(); scl=1; delay0(); } scl=0; delay0(); sda=1; delay0(); } uchar read_byte()//读一个字节函数 { uchar i,k; scl=0; delay0(); sda=1; delay0(); for(i=0;i<8;i++) { scl=1; delay0(); k=(k<<1)|sda; scl=0; delay0(); } return k; } void write_add(uchar address,uchar date)//指定地址写一个字节 { start(); write_byte(0xa0); respons(); write_byte(address); respons(); write_byte(date); respons(); stop(); } char read_add(uchar address)//指定地址读一个字节 { uchar date; start(); write_byte(0xa0); respons(); write_byte(address); respons(); start(); write_byte(0xa1); respons(); date=read_byte(); stop(); return date; }
#include<reg52.h> #include<define.h> void delay(uint z)//延时函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void di() //蜂鸣器报警声音 { beep=0; delay(100); beep=1; } void write_com(uchar com) {//写液晶命令函数 rs=0; lcden=0; P0=com; delay(3); lcden=1; delay(3); lcden=0; } void write_date(uchar date) {//写液晶数据函数 rs=1; lcden=0; P0=date; delay(3); lcden=1; delay(3); lcden=0; } void init() {//初始化函数 uchar num; EA=1;//打开总中断 EX1=1;//开外部中断1 IT1=1;//设置负跳变沿触发中断 flag1=0;//变量初始化 t0_num=0; s1num=0; week=1; dula=0;//关闭数码管显示 wela=0; lcden=0; rd=0; /*以下几行在首次设置DS12C887时使用,以后不必再写入 write_ds(0x0A,0x20);//打开振荡器 write_ds(0x0B,0x26);//设置24小时模式,数据二进制格式 //开启闹铃中断 set_time();//设置上电默认时间 -----------------------------------------------------*/ write_com(0x38);//1602液晶初始化 write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); for(num=0;num<15;num++)//写入液晶固定部分显示 { write_date(table[num]); delay(1); } write_com(0x80+0x40); for(num=0;num<11;num++) { write_date(table1[num]); delay(1); } } void write_sfm(uchar add,char date) {//1602液晶刷新时分秒函数4为时,7为分,10为秒 char shi,ge; shi=date/10; ge=date%10; write_com(0x80+0x40+add); write_date(0x30+shi); write_date(0x30+ge); } void write_nyr(uchar add,char date) {//1602液晶刷新年月日函数3为年,6为分,9为秒 char shi,ge; shi=date/10; ge=date%10; write_com(0x80+add); write_date(0x30+shi); write_date(0x30+ge); } void write_week(char we) {//写液晶星期显示函数 write_com(0x80+12); switch(we) { case 1: write_date('M');delay(5); write_date('O');delay(5); write_date('N'); break; case 2: write_date('T');delay(5); write_date('U');delay(5); write_date('E'); break; case 3: write_date('W');delay(5); write_date('E');delay(5); write_date('D'); break; case 4: write_date('T');delay(5); write_date('H');delay(5); write_date('U'); break; case 5: write_date('F');delay(5); write_date('R');delay(5); write_date('I'); break; case 6: write_date('S');delay(5); write_date('A');delay(5); write_date('T'); break; case 7: write_date('S');delay(5); write_date('U');delay(5); write_date('N'); break; } } void keyscan() { if(flag_ri==1) {//这里用来取消闹钟报警,任一键取消报警 if((s1==0)||(s2==0)||(s3==0)||(s4==0)) { delay(5); if((s1==0)||(s2==0)||(s3==0)||(s4==0)) { while(!(s1&&s2&&s3&&s4)); di(); flag_ri=0;//清除报警标志 } } } if(s1==0)//检测S1 { delay(5); if(s1==0) { s1num++;//记录按下次数 if(flag1==1) if(s1num==4) s1num=1; flag=1; while(!s1);di(); switch(s1num) {//光标闪烁点定位 case 1: write_com(0x80+0x40+10); write_com(0x0f); break; case 2: write_com(0x80+0x40+7); break; case 3: write_com(0x80+0x40+4); break; case 4: write_com(0x80+12); break; case 5: write_com(0x80+9); break; case 6: write_com(0x80+6); break; case 7: write_com(0x80+3); break; case 8: s1num=0; write_com(0x0c); flag=0; write_ds(0,miao); write_ds(2,fen); write_ds(4,shi); write_ds(6,week); write_ds(7,day); write_ds(8,month); write_ds(9,year); break; } } } if(s1num!=0)//只有当S1按下后,才检测S2和S3 { if(s2==0) { delay(1); if(s2==0) { while(!s2);di(); switch(s1num) {//根据功能键次数调节相应数值 case 1: miao++; if(miao==60) miao=0; write_sfm(10,miao); write_com(0x80+0x40+10); break; case 2: fen++; if(fen==60) fen=0; write_sfm(7,fen); write_com(0x80+0x40+7); break; case 3: shi++; if(shi==24) shi=0; write_sfm(4,shi); write_com(0x80+0x40+4); break; case 4: week++; if(week==8) week=1; write_week(week); write_com(0x80+12); break; case 5: day++; if(day==32) day=1; write_nyr(9,day); write_com(0x80+9); break; case 6: month++; if(month==13) month=1; write_nyr(6,month); write_com(0x80+6); break; case 7: year++; if(year==100) year=0; write_nyr(3,year); write_com(0x80+3); break; } } } if(s3==0) { delay(1); if(s3==0) { while(!s3);di(); switch(s1num) {//根据功能键次数调节相应数值 case 1: miao--; if(miao==-1) miao=59; write_sfm(10,miao); write_com(0x80+0x40+10); break; case 2: fen--; if(fen==-1) fen=59; write_sfm(7,fen); write_com(0x80+0x40+7); break; case 3: shi--; if(shi==-1) shi=23; write_sfm(4,shi); write_com(0x80+0x40+4); break; case 4: week--; if(week==0) week=7; write_week(week); write_com(0x80+12); break; case 5: day--; if(day==0) day=31; write_nyr(9,day); write_com(0x80+9); break; case 6: month--; if(month==0) month=12; write_nyr(6,month); write_com(0x80+6); break; case 7: year--; if(year==-1) year=99; write_nyr(3,year); write_com(0x80+3); break; } } } } if(s4==0)//检测S4 { delay(5); if(s4==0) { flag1=~flag1; while(!s4);di(); if(flag1==0) {//退出闹钟设置时保存数值 flag=0; write_com(0x80+0x40); write_date(' '); write_date(' '); write_com(0x0c); write_ds(1,miao); write_ds(3,fen); write_ds(5,shi); } else {//进入闹钟设置 read_alarm();//读取原始数据 miao=amiao;//重新赋值用以按键调节 fen=afen; shi=ashi; write_com(0x80+0x40); write_date('R');//显示标志 write_date('i'); write_com(0x80+0x40+3); write_sfm(4,ashi);//送液晶显示闹钟时间 write_sfm(7,afen); write_sfm(10,amiao); } } } } void write_ds(uchar add,uchar date) {//写12C887函数 dscs=0; dsas=1; dsds=1; dsrw=1; P0=add;//先写地址 dsas=0; dsrw=0; P0=date;//再写数据 dsrw=1; dsas=1; dscs=1; } uchar read_ds(uchar add) {//读12C887函数 uchar ds_date; dsas=1; dsds=1; dsrw=1; dscs=0; P0=add;//先写地址 dsas=0; dsds=0; P0=0xff; ds_date=P0;//再读数据 dsds=1; dsas=1; dscs=1; return ds_date; } /*---首次操作12C887时给予寄存器初始化--- void set_time() {//首次上电初始化时间函数 write_ds(0,0); write_ds(1,0); write_ds(2,0); write_ds(3,0); write_ds(4,0); write_ds(5,0); write_ds(6,0); write_ds(7,0); write_ds(8,0); write_ds(9,0); } ----------------------------------------*/ void read_alarm() {//读取12C887闹钟值 amiao=read_ds(1); afen=read_ds(3); ashi=read_ds(5); } void main()//主函数 { init();//调用初始化函数 while(1) { keyscan();//按键扫描 if(flag_ri==1)//当闹钟中断时进入这里 { di(); delay(100); di(); delay(500); } if(flag==0&&flag1==0)//正常工作时进入这里 { keyscan();//按键扫描 year=read_ds(9);//读取12C887数据 month=read_ds(8); day=read_ds(7); week=read_ds(6); shi=read_ds(4); fen=read_ds(2); miao=read_ds(0); write_sfm(10,miao);//送液晶显示 write_sfm(7,fen); write_sfm(4,shi); write_week(week); write_nyr(3,year); write_nyr(6,month); write_nyr(9,day); } } } void exter() interrupt 2//外部中断1服务程序 { uchar c; //进入中断表示闹钟时间到, flag_ri=1; //设置标志位,用以大程序中报警提示 c=read_ds(0x0c);//读取12C887的C寄存器表示响应了中断 }
#include <reg52.h> #include <stdio.h> #define uchar unsigned char #define uint unsigned int sbit ds=P2^2; //温度传感器信号线 sbit dula=P2^6; //数码管段选线 sbit wela=P2^7; //数码管位选线 sbit beep=P2^3; //蜂鸣器 uint temp; float f_temp; uint warn_l1=260; uint warn_l2=250; uint warn_h1=300; uint warn_h2=320; sbit led0=P1^0; sbit led1=P1^1; sbit led2=P1^2; sbit led3=P1^3; unsigned char code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0xbf,0x86, 0xdb,0xcf,0xe6,0xed, 0xfd,0x87,0xff,0xef}; //不带小数点的编码 void delay(uint z)//延时函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void dsreset(void) //18B20复位,初始化函数 { uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--; } bit tempreadbit(void) //读1位函数 { uint i; bit dat; ds=0;i++; //i++ 起延时作用 ds=1;i++;i++; dat=ds; i=8;while(i>0)i--; return (dat); } uchar tempread(void) //读1个字节 { uchar i,j,dat; dat=0; for(i=1;i<=8;i++) { j=tempreadbit(); dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里 } return(dat); } void tempwritebyte(uchar dat) //向18B20写一个字节数据 { uint i; uchar j; bit testb; for(j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if(testb) //写 1 { ds=0; i++;i++; ds=1; i=8;while(i>0)i--; } else { ds=0; //写 0 i=8;while(i>0)i--; ds=1; i++;i++; } } } void tempchange(void) //DS18B20 开始获取温度并转换 { dsreset(); delay(1); tempwritebyte(0xcc); // 写跳过读ROM指令 tempwritebyte(0x44); // 写温度转换指令 } uint get_temp() //读取寄存器中存储的温度数据 { uchar a,b; dsreset(); delay(1); tempwritebyte(0xcc); tempwritebyte(0xbe); a=tempread(); //读低8位 b=tempread(); //读高8位 temp=b; temp<<=8; //两个字节组合为1个字 temp=temp|a; f_temp=temp*0.0625; //温度在寄存器中为12位 分辨率位0.0625° temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入 f_temp=f_temp+0.05; return temp; //temp是整型 } ////////////////////显示程序////////////////////////// void display(uchar num,uchar dat) { uchar i; dula=0; P0=table[dat]; dula=1; dula=0; wela=0; i=0XFF; i=i&(~((0X01)<<(num))); P0=i; wela=1; wela=0; delay(1); } void dis_temp(uint t) { uchar i; i=t/100; display(0,i); i=t%100/10; display(1,i+10); i=t%100%10; display(2,i); } ////////////////////////////////////////////// void warn(uint s,uchar led) //蜂鸣器报警声音 ,s控制音调 { uchar i;i=s; dula=0; wela=0; beep=0; P1=~(led); while(i--) { dis_temp(get_temp()); } beep=1; P1=0XFF; i=s; while(i--) { dis_temp(get_temp()); } } void deal(uint t) { uchar i; if((t>warn_l2)&&(t<=warn_l1)) //大于25度小于27度 { warn(40,0x01); } else if(t<=warn_l2) //小于25度 { warn(10,0x03); } else if((t<warn_h2)&&(t>=warn_h1)) //小于32度大于30度 { warn(40,0x04); } else if(t>=warn_h2) //大于32度 { warn(10,0x0c); } else { i=40; while(i--) { dis_temp(get_temp()); } } } void init_com(void) { TMOD = 0x20; PCON = 0x00; SCON = 0x50; TH1 = 0xFd; TL1 = 0xFd; TR1 = 1; } void comm(char *parr) { do { SBUF = *parr++; //发送数据 while(!TI); //等待发送完成标志为1 TI =0; //标志清零 }while(*parr); //保持循环直到字符为'\0' } void main() { uchar buff[4],i; dula=0; wela=0; init_com(); while(1) { tempchange(); for(i=10;i>0;i--) { dis_temp(get_temp());} deal(temp); sprintf(buff,"%f",f_temp); for(i=10;i>0;i--) { dis_temp(get_temp());} comm(buff); for(i=10;i>0;i--) { dis_temp(get_temp());} } }
/* extern void SectorErase(uint sector_addr); // 扇区擦除 extern uchar byte_read(uint byte_addr); // byte读 extern void byte_write(uint byte_addr, uchar original_data); // byte写 extern uchar byte_write_verify(uint byte_addr, uchar original_data);// byte写并校验 extern uchar ArrayWrite(uint begin_addr, uint len, uchar code *array); // byte数组写并校验 extern void ArrayRead(uint begin_addr, uchar len); // 读出, 保存在Ttotal[]中 */ #define RdCommand 0x01 #define PrgCommand 0x02 #define EraseCommand 0x03 #define Error 1 #define Ok 0 #define WaitTime 0x01 #define PerSector 512 /* ================ 打开 ISP,IAP 功能 ================= */ void ISP_IAP_enable(void) { EA = 0; /* 关中断 */ ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */ ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */ ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */ } /* =============== 关闭 ISP,IAP 功能 ================== */ void ISP_IAP_disable(void) { ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */ ISP_TRIG = 0x00; EA = 1; /* 开中断 */ } /* ================ 公用的触发代码 ==================== */ void ISPgoon(void) { ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */ ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */ ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */ _nop_(); } /* ==================== 字节读 ======================== */ unsigned char byte_read(unsigned int byte_addr) { ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 地址赋值 */ ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */ ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭ISP,IAP功能 */ return (ISP_DATA); /* 返回读到的数据 */ } /* ================== 扇区擦除 ======================== */ void sectorerase(unsigned int sector_addr) { unsigned int iSectorAddr; iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */ ISP_ADDRH = (unsigned char)(iSectorAddr >> 8); ISP_ADDRL = 0x00; ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */ ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭ISP,IAP功能 */ } /* ==================== 字节写 ======================== */ void byte_write(unsigned int byte_addr, unsigned char original_data) { ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */ ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff); ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */ ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */ ISP_DATA = original_data; /* 写入数据准备 */ ISPgoon(); /* 触发执行 */ ISP_IAP_disable(); /* 关闭IAP功能 */ } void write_eep(float eep_data,uint add) { uchar fcdh,fcdl; fcdh=(uint)(eep_data*100)/256; fcdl=(uint)(eep_data*100)%256; byte_write(add,fcdh);//写入浮充电电压高8位 byte_write(add+1,fcdl);//写入浮充电电压低8位 } float read_eep(uint add) { float date_re; uchar dateh,datel; dateh=byte_read(add); datel=byte_read(add+1); date_re=(dateh*256+datel)/100.0; return date_re; }
12T单片机
DS18B20
#include<reg52.h> #include<stdio.h> #define uchar unsigned char #define uint unsigned int void delay(uint xms); sbit ds=P0^1; //DS18B20 uint temp; //整型温度数据 float f_temp; //浮点型温度数据 void delayms(unsigned char x) { unsigned char i, j; for(i = x; i; --i) for(j = 110; j; --j); } void initSCI(void) { SM0 = 0; /*Step 1 : 确定串口通信方式*/ SM1 = 1; TMOD = 0x20; /*step 2: 根据串口通信方式 确定是否设置波特率*/ TH1 = 0xfd; TL1 = 0xfd; TR1 = 1; /*step 3 :启动*/ REN = 1; EA = 1; /*step 4: 是否启用中断函数*/ ES = 1; delayms(100); } void putChar (unsigned char chr)//发送一个字符 { SBUF = chr; while(!TI); delayms(3); TI=0; delayms(3); } void print(int x) { unsigned char t; while(x) { t = x % 10; putChar(t + '0'); x /= 10; } } void putStr(char *s) { while(*s) { putChar(*s++); } } void dsreset(void)//DS18b20初始化 { uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--; } bit tempreadbit()//读一位数据 { uint i;bit dat; ds=0;i++; ds=1;i++;i++; dat=ds; i=8; while(i>0)i--; return(dat); } uchar tempread(void)//读一个字节数据 { uchar i,j,dat;dat=0; for(i=1;i<=8;i++) { j=tempreadbit(); dat=(j<<7)|(dat>>1); } return(dat); } void tempwritebyte(uchar dat) { uint i; uchar j; bit testb; for(j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if(testb) { ds=0; i++;i++; ds=1; i=8;while(i>0)i--; } else { ds=0; i=8;while(i>0)i--; ds=1; i++;i++; } } } /*温度转换*/void tempchange(void) { dsreset(); delay(1); tempwritebyte(0xcc);//跳过读ROM tempwritebyte(0x44);//温度转换指令 } /*读取寄存器中存储温度的数据*/ uint get_temp() { uchar a,b; dsreset(); delay(1); tempwritebyte(0xcc); tempwritebyte(0xbe); a=tempread(); b=tempread(); temp=b; temp<<=8;temp=temp|a; f_temp=temp*0.0625; temp=f_temp*10+0.5; f_temp=f_temp+0.5; return temp; } unsigned char buff[5]; void main() { uint i; initSCI(); while(1) { tempchange(); for(i=10;i>0;i--) { get_temp(); delay(200); putStr("\r\nTemp = "); sprintf(buff,"%f",f_temp); //sprintf(buff,"%f",1.342342345); putStr(buff); } } } void delay(uint xms) // 延时函数 { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); }
1T 单片机 DS18B20
#include<reg52.h> #include<stdio.h> #include<intrins.h> typedef unsigned char BYTE; #define uchar unsigned char #define uint unsigned int void delay(uint xms); sbit DQ = P1^2; //DS18B20的数据口位P3.3 BYTE TPH; //存放温度值的高字节 BYTE TPL; uint temp; //整型温度数据 float f_temp; //浮点型温度数据 void delayms(unsigned char x) { unsigned char i, j; for(i = x; i; --i) for(j = 110; j; --j); } void initSCI(void) { SM0 = 0; /*Step 1 : 确定串口通信方式*/ SM1 = 1; TMOD = 0x20; /*step 2: 根据串口通信方式 确定是否设置波特率*/ TH1 = 0xfd; TL1 = 0xfd; TR1 = 1; /*step 3 :启动*/ REN = 1; EA = 1; /*step 4: 是否启用中断函数*/ ES = 1; delayms(100); } void putChar (unsigned char chr)//发送一个字符 { SBUF = chr; while(!TI); delayms(3); TI=0; delayms(3); } void putStr(char *s) { while(*s) { putChar(*s++); } } void DelayXus(BYTE n) { while (n--) { _nop_(); _nop_(); } } /************************************** 复位DS18B20,并检测设备是否存在 **************************************/ void DS18B20_Reset() { CY = 1; while (CY) { DQ = 0; //送出低电平复位信号 DelayXus(240); //延时至少480us DelayXus(240); DQ = 1; //释放数据线 DelayXus(60); //等待60us CY = DQ; //检测存在脉冲 DelayXus(240); //等待设备释放数据线 DelayXus(180); } } /************************************** 从DS18B20读1字节数据 **************************************/ BYTE DS18B20_ReadByte() { BYTE i; BYTE dat = 0; for (i=0; i<8; i++) //8位计数器 { dat >>= 1; DQ = 0; //开始时间片 DelayXus(1); //延时等待 DQ = 1; //准备接收 DelayXus(1); //接收延时 if (DQ) dat |= 0x80; //读取数据 DelayXus(60); //等待时间片结束 } return dat; } /************************************** 向DS18B20写1字节数据 **************************************/ void DS18B20_WriteByte(BYTE dat) { char i; for (i=0; i<8; i++) //8位计数器 { DQ = 0; //开始时间片 DelayXus(1); //延时等待 dat >>= 1; //送出数据 DQ = CY; DelayXus(60); //等待时间片结束 DQ = 1; //恢复数据线 DelayXus(1); //恢复延时 } } uint DS18B20_GetTemp() { DS18B20_Reset(); //设备复位 DS18B20_WriteByte(0xCC); //跳过ROM命令 DS18B20_WriteByte(0x44); //开始转换命令 while (!DQ); //等待转换完成 DS18B20_Reset(); //设备复位 DS18B20_WriteByte(0xCC); //跳过ROM命令 DS18B20_WriteByte(0xBE); //读暂存存储器命令 TPL = DS18B20_ReadByte(); //读温度低字节 TPH = DS18B20_ReadByte(); //读温度高字节 temp = TPH; temp <<= 8; temp = temp | TPL; f_temp = temp * 0.0625; temp = f_temp * 10 + 0.5; f_temp = f_temp + 0.5; return temp; } unsigned char buff[5]; void main() { uint i; initSCI(); while(1) { for(i=10;i>0;i--) { DS18B20_GetTemp(); delay(200); putStr("\r\nTemp = "); sprintf(buff,"%f",f_temp); putStr(buff); } } } void delay(uint xms) // 延时函数 { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); }