在蓝桥杯单片机中ds1302和ds18b20作为两个常考的模块其基础的应用十分重要。
这种写法适合c语言基础较为薄弱的同学。前面为讲解,后面为例程代码。
先看ds18b20
首先,通过官方给出的驱动,我们首先需要将#include <reg52.h>的头文件换成蓝桥杯单片机的
#include <STC15F2K60S2.H>的头文件,由于蓝桥杯单片机的运行环境是51的12倍,故我们需要将单总线延时函数扩大12倍。
![](https://img-blog.csdnimg.cn/img_convert/a5bfb69d074ca6820c58257b700ff185.png)
改为
![](https://img-blog.csdnimg.cn/img_convert/914b8d848fbe8d234a9bb56e824ceea1.png)
由于蓝桥杯单片机上只有一个ds18b20,通过手册,如图
![](https://img-blog.csdnimg.cn/img_convert/eca2783fef9a42adcdd1dcf090bffa84.png)
我们可以知道温度转换的过程,可以将温度转化的函数补充完整。
![](https://img-blog.csdnimg.cn/img_convert/d15691997ed5ef06352e977c7a907181.png)
此时读出的温度是十六进制数,我们需要将其转化为十进制数方便显示。
DS18B20的分辨率为0.0625。读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625。
保留两位小数---*0.0625
保留一位小数---*0.625
保留整数---*6.25
2.时钟(ds1302)
通过官方给出的驱动,我们首先需要将#include <reg52.h>的头文件换成蓝桥杯单片机的
#include <STC15F2K60S2.H>的头文件.
通过ds1302的手册
![](https://img-blog.csdnimg.cn/img_convert/c068db5448a851b2ffb2a2d930f87edd.png)
首先补充时钟读取函数
![](https://img-blog.csdnimg.cn/img_convert/fdc773bb52858b894470fa7ba1faa2ae.png)
通过for循环不断对时分秒年月日星期去读取。
补充时钟设置函数
除了正常操作以外设置时钟时还需要先关闭写保护
![](https://img-blog.csdnimg.cn/img_convert/51f70e9f81ae4c39fd7d395e85079bd2.png)
ds1302的使用
首先需要在主函数中定义一个数组存储当前的时间
![](https://img-blog.csdnimg.cn/img_convert/5f593a79348081a01f5b24dd15b06d91.png)
因为ds1302中时间是以二进制的形式存在的,所以数组里的时间也是以二进制的形式存在的。
然后在主函数中调用设置时钟函数,将数组中的时间存入ds1302中,完成时钟的初始化。
![](https://img-blog.csdnimg.cn/img_convert/c5a9789253b72af15c278ef5da4c039b.png)
最后调用读取函数,读取ds1302中的时间,并将其转化为十进制,在数码管上显示。
![](https://img-blog.csdnimg.cn/img_convert/4855048373cac3ed972a529b038bfa68.png)
下面是具体的应用,通过读取·ds18b20,ds1302,完成温度,时分秒,年月日的界面显示,并且界面3秒自动切换。
main.c
#include <STC15F2K60S2.H>
#include <intrins.h>
/*************头文件的调用***********************/
#include "ds1302.h"
#include "onewire.h"
#define uc unsigned char
#define ui unsigned int
/****************时间时间的存放***********/
uc tac[7]={0x50,0x35,0x11,0x16,0x03,0x04,0x23};
/***********打开所需要的通道*********/
#define COM(X) {P0 = X; P2 = (P2 & 0x1F | 0xC0); P2 &= 0x1F;}
#define SEG(X) {P0 = X; P2 = (P2 & 0x1F | 0xE0); P2 &= 0x1F;}
#define BUZ(X) {P0 = X; P2 = (P2 & 0x1F | 0xA0); P2 &= 0x1F;}
#define LED(X) {P0 = X; P2 = (P2 & 0x1F | 0x80); P2 &= 0x1F;}
/***********数码管显示数组********************/
uc code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc6,0x8e,0x8C,0xC1,0x86,0xbf,0x88};//0-9,C,F,P,U,E,-
//10-C
//11-F
//12-P
//13-U
//14-E
//15--
/*************界面切换时的变量***********/
xdata uc k;
xdata ui count;
/**************延时函数*************/
void Delay100us() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 39;
do
{
while (--j);
} while (--i);
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*************数码管显示函数******************/
void OutputSMG(uc gqb,uc yxl)
{
uc i;
for(i=0;i<8;i++)
{
SEG(0xff);
COM(0x01<<gqb);
SEG(yxl);
Delay100us();
}
COM(0x00);
SEG(0x00);
}
/*******************时分秒显示函数**********/
void smg_SFM()
{
uc F,S,M;
readtime(tac);
S=(tac[2]>>4)*10+(tac[2]&0X0F);//十六进制转十进制
F=(tac[1]>>4)*10+(tac[1]&0X0F);//十六进制转十进制
M=(tac[0]>>4)*10+(tac[0]&0X0F);//十六进制转十进制
OutputSMG(0,tab[S/10]);
OutputSMG(1,tab[S%10]);
OutputSMG(2,tab[15]);//-
OutputSMG(3,tab[F/10]);
OutputSMG(4,tab[F%10]);
OutputSMG(5,tab[15]);//-
OutputSMG(6,tab[M/10]);
OutputSMG(7,tab[M%10]);
}
/*******************年月日显示函数**********/
void smg_RYN()
{
uc R,Y,N;
readtime(tac);
R=(tac[3]>>4)*10+(tac[3]&0X0F);
Y=(tac[4]>>4)*10+(tac[4]&0X0F);
N=(tac[6]>>4)*10+(tac[6]&0X0F);
OutputSMG(0,tab[N/10]);
OutputSMG(1,tab[N%10]);
OutputSMG(2,tab[15]);//-
OutputSMG(3,tab[Y/10]);
OutputSMG(4,tab[Y%10]);
OutputSMG(5,tab[15]);//-
OutputSMG(6,tab[R/10]);
OutputSMG(7,tab[R%10]);
}
/*******************温度显示函数**********/
void smg_wd()
{
ui temp;
temp=rd_temperature();
temp=temp*0.625;
OutputSMG(5,tab[temp/100]);
OutputSMG(6,(tab[temp/10%10]&0x7f));
OutputSMG(7,tab[temp%10]);
}
/*******************定时器2函数用于界面切换**********/
void Timer2Init(void) //500微秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x90; //设置定时初值
T2H = 0xE8; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2|=0X04;
EA=1;
}
void tim2()interrupt 12
{
count++;
if(count==4000)
{
count=0;
k++;
if(k>2)
{k=0;}
}
}
/************用于消除温度开机时的85显示*************/
void ds18b20_xxx()
{
Delay750ms();
rd_temperature();
}
/*******主函数********/
void main()
{
LED(0XFF);
BUZ(0X00);
ds18b20_xxx();
savetime(tac);
Timer2Init();
while(1)
{
switch(k)//界面切换
{
case 0:smg_RYN();break;//年月日
case 1:smg_wd();break;//温度
case 2:smg_SFM();break;//时分秒
}
}
}
ds18b20.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //扩大12倍
{
unsigned int i;
while(t--)
{for(i=0;i<12;i++);}
}
//通过单总线向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;
}
unsigned int rd_temperature(void)//自己补的温度读取函数
{
unsigned int H,L;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(80);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
L=Read_DS18B20();
H=Read_DS18B20();
return (H<<8)+L;
}
ds18b20.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include <STC15F2K60S2.H>//改成15的头文件
#include <intrins.h>
unsigned int rd_temperature(void);
#endif
ds1302.c
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <STC15F2K60S2.H>
#include <intrins.h>
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 readtime(unsigned char *time)
{
unsigned char i=0;
unsigned char dat=0x81;
for (i=0;i<7;i++)
{
*(time+i)=Read_Ds1302_Byte (dat); //i对应的是偏移量
dat=dat+2;
}
}
void savetime(unsigned char *Time)
{
unsigned char i=0;
unsigned char dat=0x80;
Write_Ds1302_Byte(0x8e,0x00);//禁止写保护
for (i=0;i<7;i++)
{
Write_Ds1302_Byte( dat, *(Time+i) );
dat=dat+2;
}
Write_Ds1302_Byte(0x8e,0x80);//启用写保护
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
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 readtime(unsigned char *time);
void savetime(unsigned char *Time);
#endif
如果对你有所帮助,还请点赞哦!
![](https://img-blog.csdnimg.cn/img_convert/586b6288c0cb1eacf71c4df36acd7bce.png)
谢谢大家