怎么在KEIL51中编译通不过啊,一直有两处警告啊....... 以下是程序 //多功能时钟, 精确到小数0.01秒, 即10ms //功能: 时钟, 秒表, 温度计 /**//* S5键为功能选择键, 上电默认使用时钟功能 功能顺序为: 时钟, 温度计, 秒表 mode = 1. 时钟(每次掉电后都要重新设置时间) 1)当选中时钟功能时, 具体按键功能如下: 2)可设置时分秒, 时利用发光二极管显示, 分秒用数码管显示 3)时钟: 采用定时器0计时, 工作方式1 mode = 2. 时钟设置模式 当选中时钟设置模式 S2为位选, S3为增加选中位的值 S4确定更改, S5放弃更改, 进入秒表模式 mode = 3. 秒表 1)当选中秒表功能时, 具体按键功能如下: S2为开始/暂停, S3为清零 2)采用定时器1计时, 工作方式1 mode = 4. 温度计 1)利用DS18B20检测环境温度; 2)最小温度值为0.01℃, 可表示温度范围: -55℃~+125℃ */ #include <reg52.H> #include <intrins.H> #include <math.h> //0-F数码管的编码(共阴极) unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-9数码管的编码(共阴极), 带小数点 unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef}; sbit wela = P2^7; //数码管位选 sbit dula = P2^6; //数码管段选 sbit ds = P2^2; 10:21 2007-10-7unsigned char th, tl, mode = 1; //mode存放功能模式, 默认在模式1 时钟 10:21 2007-10-7unsigned char clockPosition = 0; //时钟设置模式下, 光标所在的位置; 默认在0 10:21 2007-10-7unsigned char clockTmp = 0; //用于时钟模式下临时计数 bit clockTmpBit = 0; //用于时钟模式下临时标志位 //秒4字节, 分2字节, 时1字节 unsigned char datas[] = {0, 0, 0, 0, 0, 0, 0};//保存计时器数据 unsigned char clockDatas[] = {0, 0, 0, 0, 0, 0, 0};//保存时钟数据 unsigned char * values = clockDatas; //根据mode选择适当的数据数组指针 int tempValue; //存放温度值 unsigned char tempCount = 0; //用于记录显示了多少次温度值, 用于定时 sbit S2 = P3^4; //键S2, 作开始/暂停 sbit S3 = P3^5; //键S3, 清零 sbit S4 = P3^6; //键S4 sbit S5 = P3^7; //键S5 unsigned char tmpDatas[] = {0, 0, 0, 0, 0, 0, 0}; //存放临时设置值 unsigned char icount; //延时函数, 对于11.0592MHz时钟, 例i=5,则大概延时5ms. void delay(unsigned int i) { unsigned int j; while(i--) { for(j = 0; j < 125; j++); } } /**//***********************温度计模式******************************/ //初始化DS18B20 //让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动 void dsInit() { //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us unsigned int i; ds = 0; i = 100; //拉低约800us, 符合协议要求的480us以上 while(i>0) i--; ds = 1; //产生一个上升沿, 进入等待应答状态 i = 4; while(i>0) i--; } void dsWait() { unsigned int i; while(ds); while(~ds); //检测到应答脉冲 i = 4; while(i > 0) i--; } //向DS18B20读取一位数据 //读一位, 让DS18B20一小周期低电平, 然后两小周期高电平, //之后DS18B20则会输出持续一段时间的一位数据 bit readBit() { unsigned int i; bit b; ds = 0; i++; //延时约8us, 符合协议要求至少保持1us ds = 1; i++; i++; //延时约16us, 符合协议要求的至少延时15us以上 b = ds; i = 8; while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求 return b; }
//读取一字节数据, 通过调用readBit()来实现 unsigned char readByte() { unsigned int i; unsigned char j, dat; dat = 0; for(i=0; i<8; i++) { j = readBit(); //最先读出的是最低位数据 dat = (j << 7) | (dat >> 1); } return dat; }
//向DS18B20写入一字节数据 void writeByte(unsigned char dat) { unsigned int i; unsigned char j; bit b; for(j = 0; j < 8; j++) { b = dat & 0x01; dat >>= 1; //写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1 if(b) { ds = 0; i++; i++; //拉低约16us, 符号要求15~60us内 ds = 1; i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求 } else //写"0", 将DQ拉低60us~120us { ds = 0; i = 8; while(i>0) i--; //拉低约64us, 符号要求 ds = 1; i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了 } } }
//向DS18B20发送温度转换命令 void sendChangeCmd() { dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化 dsWait(); //等待DS18B20应答 delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号 writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0x44); //写入温度转换命令字 Convert T }
//向DS18B20发送读取数据命令 void sendReadCmd() { dsInit(); dsWait(); delay(1); writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0xbe); //写入读取数据令字 Read Scratchpad }
//获取当前温度值 void getTempValue() { unsigned int tmpvalue; float t; unsigned char low, high; sendReadCmd(); //连续读取两个字节数据 low = readByte(); high = readByte(); //将高低两个字节合成一个整形变量 //计算机中对于负数是利用补码来表示的 //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value tmpvalue = high; tmpvalue <<= 8; tmpvalue |= low; tempValue = tmpvalue; //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度 t = tempValue * 0.0625; //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入 //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度 //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度 tempValue = t * 100 + (tempValue > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5 }
//显示当前温度值, 精确到小数点后一位 //若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码 void displayTemp() { unsigned char i; unsigned int tmp = abs(tempValue); tmpDatas[0] = tmp / 10000; tmpDatas[1] = tmp % 10000 / 1000; tmpDatas[2] = tmp % 1000 / 100; tmpDatas[3] = tmp % 100 / 10; tmpDatas[4] = tmp % 10; if(tempValue < 0) { //关位选, 去除对上一位的影响 P0 = 0xff; wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; //段选 P0 = 0x40; //显示"-"号 dula = 1; //打开锁存, 给它一个下降沿量 dula = 0;
//位选 P0 = 0xfe; wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; delay(1); } for(i = 0; i != 5; i++) { //关位选, 去除对上一位的影响 P0 = 0xff; wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; //段选 if(i != 2) { P0 = table[tmpDatas]]; //显示数字 } else { P0 = tableWidthDot[tmpDatas]]; //显示带小数点数字 } dula = 1; //打开锁存, 给它一个下降沿量 dula = 0;
//位选 P0 = _crol_(0xfd, i); //选择第(i + 1) 个数码管 wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; delay(1); } tempCount++; if(tempCount==100) { tempCount = 0; getTempValue(); sendChangeCmd(); } }
//显示时钟和秒表的结果 void display() { unsigned char i; if(mode == 4) //显示温度 { displayTemp(); } else { //显示时间 for(i = 0; i < 6; i++) { //关位选, 去除对上一位的影响 P0 = 0xff; wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; //段选 if(i == 2 || i == 4) { P0 = tableWidthDot[values]; //显示带小数点数字, 作为分秒, 秒与毫秒的分隔 } else { P0 = table[values]; //显示数字 } if(mode == 2 && i == clockPosition) //时钟设置模式下, 光标所在位置, 闪烁 { clockTmp++; if(clockTmp == 20) { clockTmpBit = ~clockTmpBit; clockTmp = 0; } if(clockTmpBit) P0 = 0x00; } dula = 1; //打开锁存, 给它一个下降沿量 dula = 0; //位选 P0 = _cror_(0xdf, i); //选择第(i + 1) 个数码管 wela = 1; //打开锁存, 给它一个下降沿量 wela = 0; delay(1); } if(mode == 2 && 6 == clockPosition) //时钟设置模式下, 光标所在位置, 闪烁 { clockTmp++; if(clockTmp == 20) { clockTmpBit = ~clockTmpBit; clockTmp = 0; } if(clockTmpBit) { if(values[6] == 0) { P1 = 0x0f; } else { P1 = ~values[6]; } } else { P1 = 0xff; } } else { P1 = ~values[6]; } } }
//检测功能模式键是否被按下 void checkModeKey() { if(!S5) { delay(7); if(!S5) { mode++; switch(mode) { case 2: //定时器0是不会关闭的, 即使在设置模式下 for(icount = 0; icount < 7; icount++) { tmpDatas[icount] = clockDatas[icount]; //将设置之前的值暂存到临时数组 } values = tmpDatas; break; case 3: //秒表模式 values = datas; break; case 4: //温度计模式 //启动温度转换 sendChangeCmd(); getTempValue(); break; default: values = clockDatas; mode = 1; TR0 = 1; } while(!S5) //等待释放键 { display(); } } } }
//选中位数值增1, 用于时钟模式的设置状态下 void add() { values[clockPosition]++; switch(clockPosition) { case 3: case 5: if(values[clockPosition] > 5) values[clockPosition] = 0; break; case 6: if(values[clockPosition] > 23) values[clockPosition] = 0; break; default: if(values[clockPosition] > 9) values[clockPosition] = 0; } }
//检测是否有键按下, 并执行相应功能 void checkKey() { checkModeKey(); switch(mode) { case 2: if(!S2) //左移光标位 { delay(7); if(!S2) { clockPosition++; if(clockPosition > 6) { clockPosition = 0; } } } else if(!S3) //选中位增1 { delay(7); if(!S3) { add(); } } else if(!S4) //选中确定更改 { delay(7); if(!S4) { for(icount = 0; icount < 7; icount++) { clockDatas[icount] = tmpDatas[icount]; //将设置的值存到clockDatas[] } values = clockDatas; mode = 1; //将模式变成时钟模式 } } break; case 3: if(!S2) { delay(7); //延时大约10ms, 去抖动 if(!S2) //开始/暂停键按下 { TR1 = ~TR1; } } else if(!S3) { delay(7); //延时大约10ms, 去抖动 if(!S3) //清零键按下 { TR1 = 0; TH1 = th; TL1 = tl; for(icount = 0; icount < 7; icount++) { datas[icount] = 0; } } } break; } //等待键被释放 while(!S2 || !S3 || !S4) { display(); // 等待期间要显示 } }
void main() { delay(1); th = 0xdb;//(65536 - 10000/1.085) / 256; //定时10ms tl = 0xff;//(65536 - 10000/1.085) - th * 256; TH1 = TH0 = th; //初始化定时器1, 0 TL1 = TL0 = tl; EA = 1; //开中断 ET1 = ET0 = 1; //允许定时器1, 0 中断请求 TMOD = 0x11; //定时器1, 0 都工作方式1 TR1 = 0; TR0 = 1; //开始显示时间 while(1) { checkKey(); //检测是否就键按下 display(); //显示计时值 } }
//定时器0中断响应函数, 用于时钟计时 void time0() interrupt 1 { TH0 = th; //重置计数值 TL0 = tl;
clockDatas[0]++; //0.01秒 if(clockDatas[0] == 10) { clockDatas[0] = 0; clockDatas[1]++; //0.1秒 if(clockDatas[1] == 10) { clockDatas[1] = 0; clockDatas[2]++; //秒 if(clockDatas[2] == 10) { clockDatas[2] = 0; clockDatas[3]++; //10秒 if(clockDatas[3] == 6) { clockDatas[3] = 0; clockDatas[4]++; //分 if(clockDatas[4] == 10) { clockDatas[4] = 0; clockDatas[5]++; //10分 if(clockDatas[5] == 6) { clockDatas[5] = 0; clockDatas[6]++; //时 if(clockDatas[6] == 24) { clockDatas[6] = 0; } } } } } } } }
//定时器1中断响应函数, 用于秒表计时 void time1() interrupt 3 { TH1 = th; //重置计数值 TL1 = tl;
datas[0]++; //0.01秒 if(datas[0] == 10) { datas[0] = 0; datas[1]++; //0.1秒 if(datas[1] == 10) { datas[1] = 0; datas[2]++; //秒 if(datas[2] == 10) { datas[2] = 0; datas[3]++; //10秒 if(datas[3] == 6) { datas[3] = 0; datas[4]++; //分 if(datas[4] == 10) { datas[4] = 0; datas[5]++; //10分 if(datas[5] == 6) { datas[5] = 0; datas[6]++; //时 if(datas[6] == 24) { datas[6] = 0; } } } } } } } }
|