请求高手帮忙(懂单片机的)
(单片机)设计一种适用于家庭的多功能数字钟,要求能显示小时、分;时间显示有两种方式,12小时制和24小时制;能够随时对当前时间进行调整;能够随时输入闹铃时间,闹铃时间到发出闹铃提醒信号;能够显示当前温度;走时准确,使用方便。
[解决办法]
基于DS18B20的数字温度计设计
#include "DigThermo.h"
/* 延时t毫秒 */
void delay(uint t)
{
uint i;
while(t--)
{
/* 对于11.0592M时钟,约延时1ms */
for (i=0;i<125;i++)
{}
}
}
/* 产生复位脉冲初始化DS18B20 */
void TxReset(void)
{
uint i;
DQ = 0;
/* 拉低约900us */
i = 100;
while (i>0)i--;
DQ = 1;// 产生上升沿
i = 4;
while (i>0)i--;
}
/* 等待应答脉冲 */
void RxWait(void)
{
uint i;
while(DQ);
while(~DQ);// 检测到应答脉冲
i = 4;
while (i>0)i--;
}
/* 读取数据的一位,满足读时隙要求 */
bit RdBit(void)
{
uint i;
bit b;
DQ = 0;
i++;
DQ = 1;
i++;i++;// 延时15us以上,读时隙下降沿后15us,DS18B20输出数据才有效
b = DQ;
i = 8;
while(i>0) i--;
return (b);
}
/* 读取数据的一个字节 */
uchar RdByte(void)
{
uchar i,j,b;
b = 0;
for (i=1;i<=8;i++)
{
j = RdBit();
b = (j<<7)|(b>>1);
}
return(b);
}
/* 写数据的一个字节,满足写1和写0的时隙要求 */
void WrByte(uchar b)
{
uint i;
uchar j;
bit btmp;
for(j=1;j<=8;j++)
{
btmp = b&0x01;
b = b>>1;// 取下一位(由低位向高位)
if (btmp)
{
/* 写1 */
DQ = 0;
i++;i++;// 延时,使得15us以内拉高
DQ = 1;
i = 8;
while(i>0) i--;// 整个写1时隙不低于60us
}
else
{
/* 写0 */
DQ = 0;
i = 8;
while(i>0) i--;// 保持低在60us到120us之间
DQ = 1;
i++;
i++;
}
}
}
/* 启动温度转换 */
void convert(void)
{
TxReset();// 产生复位脉冲,初始化DS18B20
RxWait();// 等待DS18B20给出应答脉冲
delay(1);// 延时
WrByte(0xcc);// skip rom 命令
WrByte(0x44);// convert T 命令
}
/* 读取温度值 */
void RdTemp(void)
{
TxReset();// 产生复位脉冲,初始化DS18B20
RxWait();// 等待DS18B20给出应答脉冲
delay(1);// 延时
WrByte(0xcc);// skip rom 命令
WrByte(0xbe);// read scratchpad 命令
tplsb = RdByte();// 温度值低位字节(其中低4位为二进制的“小数”部分)
tpmsb = RdByte();// 高位值高位字节(其中高5位为符号位)
}
/* 主程序,读取的温度值最终存放在tplsb和tpmsb变量中。
tplsb其中低4位为二进制的“小数”部分;tpmsb其中高
5位为符号位。真正通过数码管输出时,需要进行到十进
制有符号实数(包括小数部分)的转换。 */
void main(void)
{
do
{
delay(1);// 延时1ms
convert();// 启动温度转换,需要750ms
delay(1000);// 延时1s
RdTemp();// 读取温度
}
while(1);
}
基于DS12C887的实时日历时钟显示系统设计
#include "CalendarClk.h"
/* 从串行口获取数据函数,数据包括:year1,month1,dayofweek1,
dayofmonth1,hour1,min1。如果获取到正确数据则返回1,否则返回0 */
uchar getdata()
{
// 略去
}
/* 设置日历和时钟函数 */
void settime()
{
REG_B = REG_B|0x80;// SET=1,芯片DS12C887处于设置状态
MIN = min1;
HOUR = hour1;
DAYOFWEEK = dayofweek1;
DAYOFMONTH = dayofmonth1;
MONTH = month1;
YEAR = year1;
REG_B = REG_B&0x7f; // SET=0,芯片DS12C887恢复正常数据更新状态
}
/* 获取日历时钟函数 */
void gettime()
{
while (REG_A&0x80==0x00)// 直到UIP=0时,才能读取日历时钟信息{
{
min2 = MIN ;
hour2 = HOUR;
dayofweek2 = DAYOFWEEK;
dayofmonth2 = DAYOFMONTH;
month2 = MONTH;
year2 = YEAR;
}
}
/* 13位数码管显示年、月、日、星期、时、分 */
void display()
{
// 略去
}
/* 串口初始化函数 */
void init_serial()
{
TMOD = 0x20;// 定时器T1使用工作方式2
TH1 = 250;
TL1 = 250;
TR1 = 1;// 开始计时
PCON = 0x80;// SMOD = 1
SCON = 0x50;// 工作方式1,波特率9600kbit/s,允许接收
}
void main(void)
{
uchar setflag;
init_serial();
/* 设置DV2、DV1、DV0为010,打开芯片DS12C877内部晶振 */
REG_A = REG_A&0xaf;// DV2=DV0=0
REG_A = REG_A|0x20;// DV1=0
REG_B = REG_B&0x7b;// SET=0,时间数据正常更新;DM=0,二进制数据模式
REG_B = REG_B|0x02;// 寄存器B的24/12位置1,24小时时间模式
while (1)
{
setflag = getdata();// 通过查询方式获取串口数据
/* 如果获取到正确数据,则设置时间 */
if (setflag==0x01)
settime();
/* 调用获取日历时钟函数 */
gettime();
/* 13位数码管显示日历、星期和时间信息 */
display();
}
}
拿去看看改改差不多了吧···