选用单片机芯片:51单片机 AT89S52
函数功能:串口通信下位机程序,用来读取DS1302时钟和DS18B20温度数据,并发给上位机用于显示。
注意:代码里有DS1302调时和两种工作方式的代码,可根据需要更改,满足自己需求。(现在是:掉电后时钟继续走,每次上电都初始化时间)。
C#上位机程序见下个博客。
/*******************************************************************
函数功能:串口通信下位机程序,用来读取DS1302时钟和DS18B20温度数据,
并发给上位机用于显示。
作者:Crazy Wind
日期:2020.12.11
version:1.0.0
日期:2020.12.01
version:1.1.0
*增加了液晶显示模块代码
********************************************************************/
#include "reg52.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
/*****************************************************
函数功能:ms延时
******************************************************/
void delayms(uint ms)
{
uchar i,j;
for(i=0;i<ms;i++)
{
for(j=115;j>0;j--);
}
}
/*****************************************************
函数功能:微秒延时
入口参数:n
*****************************************************/
void delayus(uchar n)
{
uchar i;
for(i=0;i<n;i++);
}
/************************************************************************/
/*****************************DS1302操作程序*****************************/
/************************************************************************/
sbit SCLK=P1^0; //位定义1302芯片的接口,时钟输出端口定义在P1.0引脚
sbit DATA=P1^1; //位定义1302芯片的接口,数据输出端定义在P1.1引脚
sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P1.2引脚
uchar sec=0,min=13,hour=18,day=1,month=12,year=20,week=2; //定义时间
/*****************************************************
函数功能:向1302写一个字节数据
入口参数:dat
*****************************************************/
void Write1302(uchar dat)
{
uchar j;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delayus(2); //稍微等待,使硬件做好准备
for(j=0;j<8;j++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302 低位在前,高位在后
delayus(2); //稍微等待,使硬件做好准备
SCLK=1; //!!上升沿!!写入数据
delayus(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
/*****************************************************
函数功能:向1302写命令和一个字节数据
入口参数:Cmd:命令 dat:数据
*****************************************************/
void WriteSet1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delayus(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于高电平状态
RST=0; //禁止数据传递
}
/*****************************************************
函数功能:从1302读一个字节数据
*****************************************************/
uchar Read1302(void)
{
uchar i,dat;
delayus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1;
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delayus(2); //稍微等待
SCLK=0; //!!下降沿!!读出数据
delayus(2); //稍微等待
}
return dat; //将读出的数据返回
}
/*****************************************************
函数功能:向1302写命令和从1302读一个字节数据
入口参数:Cmd:命令
*****************************************************/
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
/*****************************************************
函数功能:初始化DS1302
*****************************************************/
void Init_DS1302(void)
{
/*******掉电后时钟继续走,只初始化一次时间*******/
/*
uchar flag;
flag=ReadSet1302(0x81); //读秒寄存器,81H
if(flag&0x80) //读出CH,判断时钟芯片是否关闭(CH=0时时钟开始运行)
{
WriteSet1302(0x8E,0x00); //写寄存器命令,WP写入不保护指令(WP=0,允许写操作)
WriteSet1302(0x80,((sec/10)<<4|(sec%10))); //写秒寄存器命令,写入秒的初始值
WriteSet1302(0x82,((min/10)<<4|(min%10))); //写分寄存器命令,写入分的初始值
WriteSet1302(0x84,((hour/10)<<4|(hour%10))); //写时寄存器命令,写入时的初始值
WriteSet1302(0x86,((day/10)<<4|(day%10))); //写日寄存器命令,写入日的初始值
WriteSet1302(0x88,((month/10)<<4|(month%10)));//写月寄存器命令,写入月的初始值
WriteSet1302(0x8c,((year/10)<<4|(year%10))); //写年寄存器命令,写入年的初始值
WriteSet1302(0x8a,(week%10)); //写星期寄存器命令,写入星期的初始值
WriteSet1302(0x90,0xa5); //打开充电功能 选择2K电阻充电方式
WriteSet1302(0x8E,0x80); //写寄存器命令,写入保护指令(WP=1,禁止写操作)
}
*/
/*******掉电后时钟继续走,每次上电都初始化时间*******/
WriteSet1302(0x8E,0x00); //写寄存器命令,WP写入不保护指令(WP=0,允许写操作)
WriteSet1302(0x80,((sec/10)<<4|(sec%10))); //写秒寄存器命令,写入秒的初始值
WriteSet1302(0x82,((min/10)<<4|(min%10))); //写分寄存器命令,写入分的初始值
WriteSet1302(0x84,((hour/10)<<4|(hour%10))); //写时寄存器命令,写入时的初始值
WriteSet1302(0x86,((day/10)<<4|(day%10))); //写日寄存器命令,写入日的初始值
WriteSet1302(0x88,((month/10)<<4|(month%10))); //写月寄存器命令,写入月的初始值
WriteSet1302(0x8c,((year/10