c程序:
|
文件: |
51+ds1302+key(存在小故障).rar |
大小: |
29KB |
下载: |
下载 | |
原理图:
pcb图:
|
文件: |
万年历pcb.pdf |
大小: |
17KB |
下载: |
下载 | |
pcb工程文件:
|
文件: |
51+ds1302+key(存在小故障).rar |
大小: |
29KB |
下载: |
下载 | |
//注:第一次下载的时候不注释setRtc(),第二次下载的时候注释掉它。
-----------------------------------------------------------------------------------程序修正版:
可以显示时间和温度,在P1^1口接18b20,工程如下:
|
文件: |
bishe.rar |
大小: |
1342KB |
下载: |
下载 | |
---------------------------------------------------------------------------------
ds1302驱动
#include
#include
sbit SCK=P3^6;
sbit SDA=P3^4;
sbit RST=P3^5;
/*复位脚*/
#define RST_CLR RST=0/*电平置低*/
#define RST_SET RST=1/*电平置高*/
/*双向数据*/
#define IO_CLR SDA=0/*电平置低*/
#define IO_SET SDA=1/*电平置高*/
#define IO_R SDA/*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0/*时钟信号*/
#define SCK_SET SCK=1/*电平置高*/
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //控制数据地址
#define ds1302_charger_add 0x90
#define ds1302_clkburst_add 0xbe
unsigned char time_buf1[8] = {20,9,3,13,18,51,00,6};//空年月日时分秒周
unsigned char time_buf[8] ;//空年月日时分秒周
/*向DS1302写入一字节数据*/
void ds1302_write_byte(unsigned char addr, unsigned char d) {
unsigned char i;
RST_SET; /*启动DS1302总线*/
/*写入目标地址:addr*/
addr = addr & 0xFE;/*最低位置零*/
for (i = 0; i < 8; i ++) {
if (addr & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
/*写入数据:d*/
for (i = 0; i < 8; i ++) {
if (d & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
d = d >> 1;
}
RST_CLR; /*停止DS1302总线*/
}
/*从DS1302读出一字节数据*/
unsigned char ds1302_read_byte(unsigned char addr) {
unsigned char i;
unsigned char temp;
RST_SET; /*启动DS1302总线*/
/*写入目标地址:addr*/
addr = addr | 0x01;/*最低位置高*/
for (i = 0; i < 8; i ++) {
if (addr & 0x01) {
IO_SET;
}
else {
IO_CLR;
}
SCK_SET;
SCK_CLR;
addr = addr >> 1;
}
/*输出数据:temp*/
for (i = 0; i < 8; i ++) {
temp = temp >> 1;
if (IO_R) {
temp |= 0x80;
}
else {
temp &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
RST_CLR; /*停止DS1302总线*/
return temp;
}
/*向DS302写入时钟数据*/
void ds1302_write_time(void) {
unsigned char i,tmp;
for(i=0;i<8;i++){ //BCD处理
tmp=time_buf1[i]/10;
time_buf[i]=time_buf1[i]%10;
time_buf[i]=time_buf[i]+tmp*16;
}
ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
ds1302_write_byte(ds1302_sec_add,0x80); //暂停
ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电
ds1302_write_byte(ds1302_year_add,time_buf[1]); //年
ds1302_write_byte(ds1302_month_add,time_buf[2]); //月
ds1302_write_byte(ds1302_date_add,time_buf[3]); //日
ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时
ds1302_write_byte(ds1302_min_add,time_buf[5]); //分
ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒
ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
}
/*从DS302读出时钟数据*/
void ds1302_read_time(void) {
unsigned char i,tmp;
time_buf[1]=ds1302_read_byte(ds1302_year_add); //年
time_buf[2]=ds1302_read_byte(ds1302_month_add); //月
time_buf[3]=ds1302_read_byte(ds1302_date_add); //日
time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时
time_buf[5]=ds1302_read_byte(ds1302_min_add); //分
time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒
time_buf[7]=ds1302_read_byte(ds1302_day_add); //周
for(i=0;i<8;i++){ //BCD处理
tmp=time_buf[i]/16;
time_buf1[i]=time_buf[i]%16;
time_buf1[i]=time_buf1[i]+tmp*10;
}
}
/*DS302初始化函数*/
void ds1302_init(void) {
RST_CLR; /*RST脚置低*/
SCK_CLR; /*SCK脚置低*/
}
-----------------------------------------------------------------------------------
18b20驱动:
#include
#include
sbit DQ=P1^1;
unsigned char tempL=0; //临时变量低位
unsigned char tempH=0; //临时变量高位
float temperature; //温度值
/****************************************************************************
函数功能:延时子程序
入口参数:k
出口参数:
****************************************************************************/
void delay(unsigned int k)
{
unsigned int n;
n=0;
while(n < k)
{n++;}
return;
}
/****************************************************************************
函数功能:数码管扫描延时子程序
入口参数:
出口参数:
****************************************************************************/
void delay1(void)
{
int k;
for(k=0;k<400;k++);
}
/****************************************************************************
函数功能:DS18B20初始化子程序
入口参数:
出口参数:
****************************************************************************/
Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay(8); //延时
DQ=0; //发送复位脉冲
delay(85); //延时(>480ms)
DQ=1; //拉高数据线
delay(14); //等待(15~60ms)
}
/****************************************************************************
函数功能:向DS18B20读一字节数据
入口参数:
出口参数:dat
****************************************************************************/
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat=0;
for (i=8;i>0;i--)
{
DQ=1;
delay(1);
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
/****************************************************************************
函数功能:向DS18B20写一字节数据
入口参数:dat
出口参数:
****************************************************************************/
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
/****************************************************************************
函数功能:向DS18B20读温度值
入口参数:
出口参数:temperature
****************************************************************************/
float ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
delay(125); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
//温度转换,把高低位做相应的运算转化为实际温度
temperature=((tempH*256)+tempL)*0.0625;
delay(200);
return(temperature);
}
-----------------------------------------------------------------------------------
1602驱动:
#include
#include
#include
sbit RS = P2^7;//Pin4
sbit RW = P2^6; //Pin5
sbit E = P2^5;//Pin6
#define Data P0 //数据端口
unsigned char TempData[8];
unsigned char SecondLine[]=" ";
unsigned char FirstLine[] =" ";
/******************************************************************/
/* 函数声明 */
/******************************************************************/
void DelayUs(unsigned char us)//delay us
{
unsigned char uscnt;
uscnt=us>>1;/* Crystal frequency in 12MHz*/
while(--uscnt);
}
/******************************************************************/
void DelayMs(unsigned char ms)//delay Ms
{
while(--ms)
{
DelayUs(250);
DelayUs(250);
DelayUs(250);
DelayUs(250);
}
}
void WriteCommand(unsigned char c)
{
DelayMs(5);//short delay before operation
E=0;
RS=0;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
}
/****************************************************************/
void WriteData(unsigned char c)
{
DelayMs(5); //short delay before operation
E=0;
RS=1;
RW=0;
_nop_();
E=1;
Data=c;
E=0;
RS=0;
}
/*********************************************************************/
void ShowChar(unsigned char pos,unsigned char c)
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0; //是第二行则命令代码高4位为0xc
else
p=pos+0x80; //是第二行则命令代码高4位为0x8
WriteCommand (p);//write command
WriteData (c); //write data
}
/*************************************************************************/
void ShowString (unsigned char line,char *ptr)
{
unsigned char l,i;
l=line<<4;
for (i=0;i<16;i++)
ShowChar (l++,*(ptr+i));//循环显示16个字符
}
/*********************************************************************/
void InitLcd()
{
DelayMs(15);
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x38); //display mode
WriteCommand(0x06); //显示光标移动位置
WriteCommand(0x0c); //显示开及光标设置
WriteCommand(0x01); //显示清屏
}
void dist(int x)
{
SecondLine[11]='0'+x/100;
SecondLine[12]='0'+x%100/10;
SecondLine[13]='0'+x%10;
ShowString(1,SecondLine);
}
/////////////////////////////////////////////////////////////////
void disp(int x)
{
//年-月-日 ^周^
FirstLine[0]='2';
FirstLine[1]='0';
FirstLine[2]='0'+TempData[1]/10;
FirstLine[3]='0'+TempData[1]%10;
FirstLine[4]='-';
FirstLine[5]='0'+TempData[2]/10;
FirstLine[6]='0'+TempData[2]%10;
FirstLine[7]='-';
FirstLine[8]='0'+TempData[3]/10;
FirstLine[9]='0'+TempData[3]%10;
FirstLine[15]='0'+TempData[7]%10;
SecondLine[0]='0'+TempData[4]/10;
SecondLine[1]='0'+TempData[4]%10;
SecondLine[2]=':';
SecondLine[3]='0'+TempData[5]/10;
SecondLine[4]='0'+TempData[5]%10;
SecondLine[5]=':';
SecondLine[6]='0'+TempData[6]/10;
SecondLine[7]='0'+TempData[6]%10;
if(x>100)
{
SecondLine[11]='0'+x/100;
SecondLine[12]='0'+x%100/10;
SecondLine[13]='.';
SecondLine[14]='0'+x%10;
SecondLine[15]='C';
}
else if(x>10)
{
SecondLine[11]='0'+x/100;
SecondLine[12]='.';
SecondLine[13]='0'+x%100/10;
SecondLine[14]='0'+x%10;
SecondLine[15]='C';
}
else
{
SecondLine[11]='0'+x/100;
SecondLine[12]='0'+x%100/10;
SecondLine[13]='0'+x%10;
SecondLine[15]='C';
}
ShowString(0,FirstLine);
//时:分:秒
ShowString(1,SecondLine);
}
-----------------------------------------------------------------------------------
主函数:
#include
#include"ds1302.h"
#include"LCD1602.h"
#include "ds18b20.h"
sbit LACTCH1=P2^0;//锁存端口定义
sbit LACTCH2=P2^3;
bit SetFlag; //更新时间标志位
unsigned char time_buf2[16];
void UART_Init(void)
{
// SCON = 0x50; /* SCON: 模式 1, 8-bit UART, 使能接收 */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
TH1 = 0xFD; /* TH1: reload value for 9600 baud @ 11.0592MHz */
TR1 = 1; /* TR1: timer 1 run */
//EA = 1; /*打开总中断*/
//ES = 1; /*打开串口中断*/
}
int get_temp()
{
temperature=ReadTemperature();
return (int)(temperature*10);
}
main()
{
unsigned char i;
UART_Init();
P0=0; //取显示数据,屏蔽数码管显示
LACTCH1=1; //锁存
LACTCH1=0;
P0=0; //取段码
LACTCH2=1; // 锁存
LACTCH2=0;
ds1302_init(); /*DS302初始化函数*/
//ds1302_write_time();
InitLcd(); //初始化LCD
Init_DS18B20();
DelayMs(15); //延时用于稳定功能
while(1)
{
ds1302_read_time();//读取时钟信息
//dist(get_temp());
disp(get_temp()); //液晶显示时间信息
//dist(123);
//delay(1000);
for(i=1;i<8;i++)
TempData[i]=time_buf1[i];
//disp(); //液晶显示时间信息
//KeyPro();
/*
if(SetFlag) //如果接收到串口信息则更新时钟
{
for(i=0;i<8;i++)
{
time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];//数据整合,如2个数 1和5整合成15
}
ds1302_write_time();
SetFlag=0; //时钟信息更新后标志位清零
}
*/
}
}
/******************************************************************/
/* 串口中断程序 */
/******************************************************************/
void UART_SER (void) interrupt 4 //串行中断服务程序
{
unsigned char Temp; //定义临时变量
unsigned char i;
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
Temp=SBUF; //读入缓冲区的值
time_buf2[i]=Temp&0x0F;
i++;
if(i==16) //连续接收16个字符信息
{
i=0;
SetFlag=1; //接收完成标志位置1
}
SBUF=Temp; //把接收到的值再发回电脑端
//P1=Temp&0x0F; //调试时候显示
}
if(TI) //如果是发送标志位,清零
TI=0;
}