ds1302驱动+18b20+1602
dsb18b20
对于市面上的大多数51单片机开发板来说。
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds1302是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述。
下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/****************************************************************************** * Function: static void v_DS1302Write_f( uint8 Content ) ** Description:向DS1302写一个字节的内容** Parameter:uint8 Content : 要写的字节** *******************************************************************************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/******************************************************************************* Function: static uint8 v_DS1302Read_f( void ) ** Description: 从DS1302当前设定的地址读取一个字节的内容** Parameter: ** Return: 返回读出来的值(uint8) *******************************************************************************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{ReadValue &= 0x7f ;}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/****************************************************************************** * Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: *******************************************************************************/ void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/****************************************************************************** * Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) *******************************************************************************/ uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;ReadValue = v_DS1302Read_f() ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/****************************************************************************** * Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) ** Parameter: ** ** Return: *******************************************************************************/ void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/****************************************************************************** * Function: void v_ClockUpdata_f( void ) ** Description:读取时间数据,并保存在结构体CurrentTime中** Parameter: ** ** Return: *******************************************************************************/ void v_ClockUpdata_f( void ){CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
DS1302 DS18B20 LCD1602经典万年历 高低温报警
/*********************************************//* Filename :万年历** Describe : 时间星期日期温度高低温报警** Designer :潜力狼** Date :2012-07-16/*********************************************/#include<reg52.h>#include<intrins.h>/**********************************************//************ 接口定义如下***************//**********************************************/sbit SCK = P1^7; //时钟sbit SDA = P2^3; //数据sbit RST = P1^3; //DS1302复位(片选)sbit E=P1^2;//1602使能引脚sbit RW=P2^1;//1602读写引脚sbit RS=P2^0;//1602数据/命令选择引脚#define uchar unsigned char#define uint unsigned int#define DS1302_W_ADDR 0xBE#define DS1302_R_ADDR 0xBF#define jump_ROM 0xCC //DS18B20#define start 0x44 //DS18B20#define read_EEROM 0xBE //DS18B20sbit DQ = P1^4;unsigned char TMPH_DS18B20,TMPL_DS18B20;/****************************************************/uchar num,m,n;uchar time1[7]={0x50,0x59,0x23,0x31,0x12,0x07,0x12};//秒分时日月周年10-08-15 23:59:50 ****注意没有code 才可以做指针变量(地址)//uchar time1[7]={50,59,23,31,12,07,12};//此种十进制表示需要转换成BCD码才能写入DS1302 ,而且这样表达,在液晶上显示困难char code table[] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//液晶显示0~9数字的LCD字型码值(ASCII码)void delay(uint z){while(z--);}void delay_1ms(uchar z){uint i,j;for(i=0;i<z;i++)for(j=0;j<128;j++);}void write_DS1302_byte(uchar dat) {uchar i;//RST=1;for(i=0;i<8;i++){SDA=dat&0x01;SCK=1;dat>>=1;SCK=0;}}uchar read_DS1302_byte(void) {uchar i,temp=0;for(i=0;i<8;i++){temp>>=1;if(SDA)temp|=0x80;SCK=1;SCK=0;}return temp;}void reset_DS1302(){RST=0;SCK=0;RST=1;}void clear_DS1302_WP(){reset_DS1302();RST=1; //?write_DS1302_byte(0x8e);write_DS1302_byte(0);SDA=0; //?RST=0; // ?}void set_DS1302_WP(){reset_DS1302();RST=1;write_DS1302_byte(0x8e);write_DS1302_byte(0x80);SDA=0;RST=0;}void set_time(uchar *timedata){uchar i;//,temp;/* for(i=0;i<7;i++) //时钟显示的7个数BCD码转换{temp=timedata[i]/10;timedata[i]=timedata[i]%10;timedata[i]=temp*16+timedata[i];} */clear_DS1302_WP();reset_DS1302();write_DS1302_byte(DS1302_W_ADDR);//写入写地址指令for(i=0;i<7;i++){write_DS1302_byte(timedata[i]);delay(10);}write_DS1302_byte(0); //??????SDA=0;RST=0;set_DS1302_WP();}void read_time(uchar *timedata){uchar i;clear_DS1302_WP();reset_DS1302();write_DS1302_byte(DS1302_R_ADDR);for(i=0;i<7;i++){timedata[i]=read_DS1302_byte();delay(10);}SDA=0;RST=1;set_DS1302_WP();}/****************************************//*LCD1602 函数体*//****************************************///uchar code table[]="Time: ";//uchar code table1[]="Data:20";uchar code week[]="MonTueWenThuFriSatSun";void write_LCD1602_cmd(uchar del) // 写入命令函数{RS=0;//RS=0时,一个高脉冲读取命令RW=0;E=0; //可以省略不写delay_1ms(5);P0=del;delay_1ms(5);E=1; //E从0到1再跳变到0,即一个高脉冲delay_1ms(5);E=0;}void write_LCD1602_data(uchar del) //写入数据函数{RS=1; //RS=1时,一个高脉冲读取数据RW=0;E=0;delay_1ms(5);P0=del;delay_1ms(5);E=1;//E从0到1再跳变到0,即一个高脉delay_1ms(5);E=0;}void LCD1602_init(){write_LCD1602_cmd(0x38);write_LCD1602_cmd(0x0e);write_LCD1602_cmd(0x06);//wcmd(0x80); //命令数据0x80是让液晶从第一位开始显示}/********************************************************/ /* 温度传感器DS18B20 对温度的采集*//********************************************************/ uchar Reset_DS18B20(void){uchar deceive_ready;DQ = 0;delay(29);DQ = 1;delay(3);deceive_ready = DQ;delay(25);return(deceive_ready);}uchar read_DS18B20_bit(void){uchar i;DQ = 0;DQ = 1;for(i=0; i<3; i++);return(DQ);}void write_DS18B20_bit(uchar bitval){DQ=0;if(bitval==1)DQ=1;delay(5);DQ=1;}uchar read_DS18B20_byte(void){uchar i,m,receive_data;m = 1;receive_data = 0;for(i=0; i<8; i++){if(read_DS18B20_bit()){receive_data = receive_data + (m << i);}delay(6);}return(receive_data);}void write_DS18B20_byte(uchar val){uchar i,temp;for(i=0; i<8; i++){temp = val >> i;temp = temp & 0x01;write_DS18B20_bit(temp);delay(5);}}void main(){uint temp;//DS18B20LCD1602_init();set_time(&time1);while(1){Reset_DS18B20();write_DS18B20_byte(jump_ROM);write_DS18B20_byte(start);Reset_DS18B20();write_DS18B20_byte(jump_ROM);write_DS18B20_byte(read_EEROM);TMPL_DS18B20 = read_DS18B20_byte();TMPH_DS18B20 = read_DS18B20_byte();temp = TMPL_DS18B20/16 + TMPH_DS18B20*16;m = table[temp/10%10];n = table[temp%10];/* if(temp>32|temp<20) //蜂鸣器报警!!!{Bell=0;delay_1ms(200);Bell=1;} */read_time(&time1);write_LCD1602_cmd(0x80);write_LCD1602_data(' ');write_LCD1602_data(time1[2]/16+48); //时write_LCD1602_data(time1[2]%16+48);write_LCD1602_data(':');write_LCD1602_data(time1[1]/16+48); // 分write_LCD1602_data(time1[1]%16+48);write_LCD1602_data(':');write_LCD1602_data(time1[0]%16+48);write_LCD1602_data(' ');write_LCD1602_cmd(0x80+12); //英文缩写星期switch(time1[5]%16) //{case 1:write_LCD1602_data(week[0]);write_LCD1602_data(week[1]);write_LCD1602_data(week[2]);break;case 2:write_LCD1602_data(week[3]);write_LCD1602_data(week[4]);write_LCD1602_data(week[5]);break;case 3:write_LCD1602_data(week[6]);write_LCD1602_data(week[7]);write_LCD1602_data(week[8]);break;case 4:write_LCD1602_data(week[9]);write_LCD1602_data(week[10]);write_LCD1602_data(week[11]);break;case 5:write_LCD1602_data(week[12]);write_LCD1602_data(week[13]);write_LCD1602_data(week[14]);break;case 6:write_LCD1602_data(week[15]);write_LCD1602_data(week[16]);write_LCD1602_data(week[17]);break;case 7:write_LCD1602_data(week[18]);write_LCD1602_data(week[19]);write_LCD1602_data(week[20]);break;}write_LCD1602_cmd(0x80+0x40);write_LCD1602_data(2+48); //显示2write_LCD1602_data(0+48); //显示0write_LCD1602_data(time1[6]/16+48); //显示12年write_LCD1602_data(time1[6]%16+48);write_LCD1602_data('-');write_LCD1602_data(time1[4]/16+48); //月write_LCD1602_data(time1[4]%16+48);write_LCD1602_data('-');write_LCD1602_data(time1[3]%16+48);write_LCD1602_data(' ');write_LCD1602_data(m); //温度write_LCD1602_data(n);//write_LCD1602_data(temp/10%10+48);//直接转换为LCD字型码(ASCII码)显示温度//write_LCD1602_data(temp%10+48);write_LCD1602_data(0xdf);write_LCD1602_data('C');}}。
以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计的电子钟
实验目的:1、能够以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计一款电子钟2、熟悉DS1302芯片的工作过程3、熟悉CD1602芯片的工作过程4、可以进行必要的扩展,如用第三DS18B20新品进行温度采集和显示5、熟悉掌握51的c程序的编写6、掌握用Proteus进行系统设计仿真验证实验仪器、仪表目录1、DS1302实时时钟芯片1片2、LCD1602液晶显示屏1个,3、80C52芯片1片5、DS18B20芯片一片6、晶振、电容、电阻、开关各若干等7、proteus仿真软件8、Keil C51、PC机实验设计任务以DS1302实时时钟芯片和液晶显示屏LCD1602为基础设计一个电子钟,要求:时间和日期可调整,按键采用3个按键;至少在Proteus上调试通过。
扩展:闹钟和重要日期提醒功能(增加蜂鸣器),闹铃音乐功能实验步骤1、打开Keil软件,新建一个工程文件,选择好芯片,并记得在“Options for Target 1”的Output 选项中,将Create HEX Fil选项勾起来。
2、将编写的程序保存成“.C”的形式3、编译保存好的C文件,并根据提示修改程序中的错误,直到编译成功为止4、打开proteus软件,画出实验电路图5、在89C52中,载入原来已生成的HEX文档6、按下运行键,对Proteus进行软件仿真,观察运行结果原理、结果及分析一、设计方案原理与设计特点分析电子钟总的设计模块:各个模块电路原理分析:1、DS1302时钟采集模块:1.1电路原理图:1.2 DS1302分析:首先DS1302是DALLAS公司推出的涓流充电时钟芯片。
内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。
GND 为地。
51单片机实现基于DS1302_1602_18B20的多功能电子时钟_带测温功能
#include<reg51.h>#define uchar unsigned char#define uint unsigned int/*------------------寄存器地址定义------------*/#define WRITE_SECOND 0x80#define WRITE_MINUTE 0x82#define WRITE_HOUR 0x84#define WRITE_DAY 0x86#define WRITE_MONTH 0x88#define WRITE_YEAR 0x8C#define WRITE_PROTECT 0x8E#define WRITE_WEEK 0x8A#define WRITE_CURRENT 0x90#define READ_SECOND 0x81#define READ_MINUTE 0x83#define READ_HOUR 0x85#define READ_DAY 0x87#define READ_MONTH 0x89#define READ_WEEK 0x8B#define READ_YEAR 0x8Dsbit RST=P3^5; //DS1302片选sbit DIO=P3^4; //DS1302数据信号sbit SCLK=P3^6; //DS1302时钟信号sbit ACC7=ACC^7;sbit ACC0=ACC^0;unsigned char count;sbit beep=P1^4;void INITIAL_1302();unsigned char READ_1302(unsigned char addr);void WRITE_1302(unsigned char addr,unsigned char date); sbit LCD_E=P2^7; //液晶使能端sbit LCD_RS=P2^6; //液晶数据命令选择端sbit LCD_RW=P2^5; //液晶读写选择端sbit key0=P3^2; //功能键sbit key1=P3^3; //增大键sbit key2=P3^4; //减小键sbit DQ=P3^7; //18b20温度输入输出端char hour,minute,second,week,day,month,year,tem; unsigned char num,flag;unsigned char str1[]=" 20 - - ";unsigned char str2[]=" : : C";void delay(unsigned char z);void LCD_WRITE_COM(unsigned char com);void LCD_WRITE_DA TA(unsigned char date);void LCD_WRITE_SFM(unsigned char addr,unsigned char date);void LCD_WRITE_NYR(unsigned char addr,unsigned char date);void LCD_WRITE_WEEK(unsigned char week);void LCD_INITIAL();void LCD_WRITE_TEMP(uchar addr,uchar temp);void keyscan();void INITIAL_TEMER0();uchar TMPH ,TMPL;void w1602c(uchar com);void w1602d(uchar data01);void delay2(uint ms);void delay3(uint us);uchar resert(void);uchar read_byte();void write_byte(uchar val);uint get_temp();void display();void delay3(uint us); //18b20uchar resert(void); //18b20uchar read_byte(); //18b20void write_byte(uchar val); //18b20uint get_temp(); //18b20void main(){LCD_INITIAL(); //液晶初始化INITIAL_1302(); //DS1302初始化INITIAL_TEMER0(); //定时器初始化while(1){keyscan(); //按键扫描if(flag==0) //当标志位为0,允许读取DS1302数据,将数据送入液晶显示{second=READ_1302(0x81);LCD_WRITE_SFM(10,second);minute=READ_1302(0x83);LCD_WRITE_SFM(7,minute);hour=READ_1302(0x85);LCD_WRITE_SFM(4,hour);week=READ_1302(0x8b);LCD_WRITE_WEEK(week);day=READ_1302(0x87);LCD_WRITE_NYR(9,day);month=READ_1302(0x89);LCD_WRITE_NYR(6,month);year=READ_1302(0x8d);LCD_WRITE_NYR(3,year);tem=get_temp();LCD_WRITE_TEMP(13,tem);}}}/**********************1602BU份******************************************************/void delay(unsigned char z) //1602de延时函数{unsigned char x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void LCD_WRITE_COM(unsigned char com){LCD_RS=0;LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}void LCD_WRITE_DA TA(unsigned char date){LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}void LCD_WRITE_SFM(unsigned char addr,unsigned char date) {unsigned char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_NYR(unsigned char addr,unsigned char date) {char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_WEEK(unsigned char week){LCD_WRITE_COM(0x80+12);switch(week){case 1: LCD_WRITE_DA TA('M');delay(5);LCD_WRITE_DATA('O');delay(5);;LCD_WRITE_DATA('N');break;case 2: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('E');break;case 3: LCD_WRITE_DA TA('W');delay(5);LCD_WRITE_DATA('E');delay(5);LCD_WRITE_DATA('D');break;case 4: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('H');delay(5);LCD_WRITE_DATA('U');break;case 5: LCD_WRITE_DA TA('F');delay(5);LCD_WRITE_DATA('R');delay(5);LCD_WRITE_DATA('I');break;case 6: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('A');delay(5);LCD_WRITE_DATA('T');break;case 7: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('N');break;}}void LCD_WRITE_TEMP(uchar addr,uchar temp){char shi,ge;shi=temp/10;ge=temp%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_INITIAL(){unsigned char i;LCD_WRITE_COM(0x38);LCD_WRITE_COM(0x0c);LCD_WRITE_COM(0x06); //经本人试验证明1602初始化不清屏也可实现LCD_WRITE_COM(0x80);for(i=0;i<16;i++){LCD_WRITE_DATA(str1[i]);delay(5);}LCD_WRITE_COM(0x80+0x40);//液晶第二行显示for(i=0;i<16;i++){LCD_WRITE_DATA(str2[i]);delay(5);}}/***************************1302部分***************************************************/void WRITE_1302(unsigned char addr,unsigned char date) {unsigned char i;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){SCLK=0;ACC=date;DIO=ACC0;date>>=1;SCLK=1;}RST=0;}unsigned char READ_1302(unsigned char addr){unsigned char i,date1,date2;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){ACC7=DIO;SCLK=1;ACC>>=1;SCLK=0;}RST=0;date1=ACC;date2=date1/16;date1=date1%16;date1=date1+date2*10;return(date1) ;}void INITIAL_1302(){WRITE_1302(WRITE_SECOND,READ_1302(READ_SECOND)&0x7f); //启动DS1302}/**************************键盘扫描部分***************************************************/void keyscan(){if(key0==0)//确认功能键按下{delay(20);if(key0==0)//去抖{while(!key0);//释放num++;switch(num){case 1: flag=1; //修改时间,禁止从DS1302读数据TR0=0; //定时器关LCD_WRITE_COM(0x0f); //光标开始闪烁LCD_WRITE_COM(0x80+3);//第一次按下,光标定位到年位置break;case 2: LCD_WRITE_COM(0x80+6);//第二次按下,光标定位到月位置break;case 3: LCD_WRITE_COM(0x80+9);//第三次按下,光标定位到日位置break;case 4: LCD_WRITE_COM(0x80+12);//第四次按下,光标定位到星期位置break;case 5: LCD_WRITE_COM(0x80+0x40+4);//第五次按下,光标定位到时位置break;case 6: LCD_WRITE_COM(0x80+0x40+7);//第六次按下,光标定位到分位置break;case 7: LCD_WRITE_COM(0x80+0x40+10);//第七次按下,光标定位到秒位置break;case 8: num=0;//第八次按下,记录清零LCD_WRITE_COM(0x0c);//不显示光标WRITE_1302(WRITE_PROTECT,0x00); //允许写操作WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302WRITE_1302(WRITE_PROTECT,0x80); //开写保护flag=0; //时间修改完毕,允许液晶从DS1302读数据TR0=1;break;}}}if(num!=0){if(key1==0)//确认增大键按下{delay(20);if(key1==0)//增大键确实按下{while(!key1);switch(num){case 1: year++;//调节年if(year==100)year=0;LCD_WRITE_NYR(3,year);//将调节后的年送入液晶显示LCD_WRITE_COM(0x80+3);//光标回到指定处break;case 2: month++;//调节月if(month==13)month=0;LCD_WRITE_NYR(6,month);//将调节后的月送入液晶显示LCD_WRITE_COM(0x80+6);//光标回到指定处break;case 3: day++;//调节日if(day==32)day=0;LCD_WRITE_NYR(9,day);//将调节后的日送入液晶显示LCD_WRITE_COM(0x80+9);//光标回到指定处break;case 4: week++;if(week==8)week=0;LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示LCD_WRITE_COM(0x80+12);//光标回到指定处break;case 5: hour++;if(hour==24)hour=0;LCD_WRITE_SFM(4,hour);//将调节后的小时送入液晶显示LCD_WRITE_COM(0x80+0x40+4);//光标回到指定处break;case 6: minute++;if(minute==60)minute=0;LCD_WRITE_SFM(7,minute);//将调节后的分送入液晶显示LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处break;case 7: second++;if(second==60)second=0;LCD_WRITE_SFM(10,second);//将调节后的秒送入液晶显示LCD_WRITE_COM(0x80+0x40+10);//光标回到指定处break;default:break;}}}if(key2==0)//确认减小键按下{delay(20);if(key2==0)//减小键确实按下{while(!key2);switch(num){case 1: year--;//调节年if(year==-1)year=99;LCD_WRITE_NYR(3,year);LCD_WRITE_COM(0x80+3);break;case 2: month--;//调节月if(month==-1)month=12;LCD_WRITE_NYR(6,month);LCD_WRITE_COM(0x80+6);break;case 3: day--;//调节日if(day==-1)day=31;LCD_WRITE_NYR(9,day);LCD_WRITE_COM(0x80+9);break;case 4: week--;//调节星期if(week==0)week=7;LCD_WRITE_WEEK(week);LCD_WRITE_COM(0x80+12);break;case 5: hour--;//调节时if(hour==-1)hour=23;LCD_WRITE_SFM(4,hour);LCD_WRITE_COM(0x80+0x40+4);break;case 6: minute--;//调节分if(minute==-1)minute=59;LCD_WRITE_SFM(7,minute);LCD_WRITE_COM(0x80+0x40+7);break;case 7: second--;//调节秒if(second==-1)second=59;LCD_WRITE_SFM(10,second);LCD_WRITE_COM(0x80+0x40+10);break;default:break;}}}}}/*******************************蜂鸣器部分******************************************//*-----------定时器0初始化-------------------------*/void INITIAL_TEMER0(){TMOD=0x01;TH0=(65536-20000)/256;TL0=(65536-20000)%256; //晶振频率12MHZ 定时20ms作右TR0=1;EA=1;ET0=1;}/*-------------------------------------------*/void timer0()interrupt 1{TH0=(65536-20000)/256;TL0=(65536-20000)%256; //重装count++;if(count==50) //1秒到{count=0;beep=0; //蜂鸣器响delay(5);beep=1; //蜂鸣器灭}if(tem>=30){beep=0;}}/*****************************18b20部分*********************************************888*/void delay3(uint us){uint s;for(s=0;s<us;s++);}uchar resert(void){uchar ready;DQ=0;delay3(32) ;DQ=1;delay3(3);ready=DQ;delay3(25);return ready;}uchar read_byte(){uchar i,j;uchar value=0;for(i=0;i<8;i++){DQ=0;DQ=1;for(j=0;j<3;j++);if(DQ){value|=0x01<<i;}delay3(6) ;}return value;}void write_byte(uchar val) {uchar i,temp;for(i=0;i<8;i++){temp=val>>i;temp=temp&0x01;DQ=0;if(temp==1)DQ=1;delay3(5);DQ=1;}DQ=1;}uint get_temp(){float f_temp;uint temp;P2=0x00;resert();delay3(50);write_byte(0xcc);write_byte(0x44);resert();write_byte(0xcc);write_byte(0xbe);TMPL = read_byte();TMPH = read_byte();temp = TMPH;temp <<= 8;TMPL=TMPL&0xf0;temp = temp | TMPL;f_temp=temp*0.0625;temp=f_temp;return temp;}。
89C51+LCD1602+DS1302+DS18B20多功能电子钟综合
实验二十三LCD1602+DS1302+DS18B20多功能电子钟综合实验一.实验目的:做一个可以显示温度的多功能电子钟。
二.实验电路图:键盘接线图LCD1602接线图华南理工大学无线电爱好者协会F D R 工作室Ds1302和ds18b20接线图三、硬件接线图:1602及18b20的连接华南理工大学无线电爱好者协会F D R 工作室蜂鸣器连接按键及ds1302连接四、实验原理:华南理工大学无线电爱好者协会F D R 工作室前面我们做了那么多的实验,好像都只是不实用的东西。
现在这个就实用了,LCD1602+DS1302+DS18B20多功能电子钟综合实验 。
DS1302的精度可达到一天只差一秒,(当然在常温下,其精度取决于你的晶振的精度。
)而DS18B20的测温精度是0.0625度。
所以整个系统的精度还是很高的。
我们还要什么功能呢?可以显示时间和温度了,那时间慢了,怎么办?所以要键盘啦,可以修改时间。
还要什么功能呢?闹钟,可以通过键盘来设定闹钟。
闹钟的声音通过蜂鸣器发出来。
那么这个系统就完善了。
当然可以用蜂鸣器发出音乐来,这里我就不加这个进去了,让你们来加吧。
下面我就先介绍一下这个系统的用法了。
首先,显示屏(LCD1602)上要显示时间温度,第一行显示:DAT :日期 星期,第二行显示:时间 温度。
其次,我们可以修改时间,包括修改闹钟的时间:按下0修改秒,按下1修改分,按下2修改时,按下3修改日,按下4修改月份,按下5修改星期,按下6修改年份,按下7修改闹钟的时间。
进入修改界面后,键15是确定键,键14是取消键,键13是推出键,键13是闹钟的功能取消(如果想再开闹钟的话,重新修改闹钟时间就行了)。
修改界面中,第一行是提示修改什么,第二行显示你要修改的内容的当前数据和你键入的数据。
闹钟响了之后按下按键8-15中的任意一个就可以使闹钟停止闹铃了.五、源程序: #include <reg52.h> #include <intrins.h> #define MSB 0x80 //读忙位 #define HIGH 1 #define LOW 0//*****************************************#define DATA_MODE 0x28 //LCD 模式设置,0x28位四位数据线模式#define OPEN_SCREEN 0x0C //打开LCD 显示 #define DISPLAY_ADDRESS 0x80 //写地址指令#define CLEARSCREEN LCD_en_com(0x01) //清屏//***********//LCD1602的接线//***************************** #define LCDIO P0 //LCD1602的高四位接在P0口的高四位sbit LCD1602_RS=P0^0; //RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
51单片机课程设计(DS1302时钟、18B20温度计)
摘要:该设计实现了24小时制的时间显示及设定、年月日星期的显示及设定、闹钟的设定、温度的检测及显示等功能。
设计共分为四大部分,分别是控制部分、时钟部分、温度检测部分和人机交互部分。
以单片机(AT89C51)组成的最小系统为整个设计的控制核心,单片机通过对时钟芯片(DS1302)的控制完成时钟的功能,通过对温度传感器(18B20)的控制完成温度检测的功能,最后通过对数码管、蜂鸣器及按键的控制完成时间和温度的显示以及调整时间、设定闹钟等功能。
关键词:电子钟;温度计;单片机目录摘要: (1)第一章设计任务 (3)第二章电路设计 (3)2.1电路方案的比较 (3)2.2根据设计绘制框图及原理图 (5)第三章工作原理 (7)3.1 单片机的工作原理 (7)3.2 DS18B20的工作原理 (8)3.3DS1302的工作原理 (10)3.4数码管的工作原理 (12)第四章调试与验证 (12)4.1程序调试 (12)4.2仿真验证 (15)参考文献 (15)附录 (16)附录一使用说明 (16)附录二元件清单 (16)附录三 pcb版图 (17)附录四程序清单 (18)第一章设计任务1、基本要求(1)能够实现时间的正确显示,并且可以对表进行调整。
(2)能够实现年月日及星期的显示,并且可以对日期进行调整。
(3)能够实现对温度的及时检测,并且可以正确显示。
(4)用protel99se绘制设计的原理图,并生成PCB图。
(5)用protues实现对设计的仿真。
2、提高要求(1)能够实现闹铃的设定。
(2)为了使显示画面更美观,信息量更大,尝试使用液晶显示器(1602或12864)对时间和温度进行显示。
(3)将硬件实物做出来。
第二章电路设计2.1电路方案的比较1、时钟电路的设计方案一:时钟电路可由555定时器组成,通过555定时器构成1Hz脉冲发生电路(如图2-1),然后将脉冲机输入单片机,经单片机计算生成时钟。
脉冲信号从555的3号引脚输出,通过电阻和电容可以得到不同频率的脉冲。
玩转DS1302和DS18B20
对于市面上的大多数51单片机开发板来说。
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds130 2是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述。
下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS 1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/****************************************************************************** * Function: static void v_DS1302Write_f( uint8 Content ) * * Description:向DS1302写一个字节的内容** Parameter:uint8 Content : 要写的字节** *******************************************************************************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/****************************************************************************** * Function: static uint8 v_DS1302Read_f( void ) ** Description: 从DS1302当前设定的地址读取一个字节的内容* * Parameter: ** Return: 返回读出来的值(uint8) *******************************************************************************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{ReadValue &= 0x7f ;}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/******************************************************************************* Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: * ******************************************************************************/void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/******************************************************************************* Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) *******************************************************************************/uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;ReadValue = v_DS1302Read_f() ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/******************************************************************************* Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) * * Parameter:** ** Return: *******************************************************************************/void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/******************************************************************************* Function: void v_ClockUpdata_f( void ) ** Description:读取时间数据,并保存在结构体CurrentTime中** Parameter:** ** Return:*******************************************************************************/void v_ClockUpdata_f( void ){CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
基于51单片机ds1302和ds18b20芯片设计的电子日历
用DS1302时钟芯片、AT89C51单片机、温度传感器DS18B20、LCD 液晶1602设计的电子日历,proteus仿真及C程序.#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7;//ds18b20与单片机连接口uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志unsigned char code digit[10]={""}; //定义字符数组显示数字sbit DATA=P3^6; //位定义1302芯片的接口,数据输出端定义在P1.1引脚sbit RST=P3^4; //位定义1302芯片的接口,复位端口定义在P1.1引脚sbit SCLK=P3^5; //位定义1302芯片的接口,时钟输出端口定义在P1.1引脚//液晶引脚定义sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7;/*****************************************************函数功能:延时若干微秒入口参数:n***************************************************/void delaynus(unsigned char n){unsigned char i;for(i=0;i<n;i++);}void Write1302(unsigned char dat){unsigned char i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备delaynus(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++){DATA=dat&0x01; //取出dat的第0位数据写入1302 delaynus(2); //稍微等待,使硬件做好准备SCLK=1;delaynus(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1;}}/*****************************************************函数功能:根据命令字,向1302写一个字节数据入口参数:Cmd,储存命令字;dat,储存待写的数据***************************************************/void WriteSet1302(unsigned char Cmd,unsigned char dat){RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delaynus(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}unsigned char Read1302(void){unsigned char i,dat;delaynus(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据{dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delaynus(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delaynus(2); //稍微等待}return dat; //将读出的数据返回//dat已经是一位一位的存在单}// 片集中unsigned char ReadSet1302(unsigned char Cmd){unsigned char dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1;RST=0;return dat;}void Init_DS1302(void){WriteSet1302(0x8E,0x00);WriteSet1302(0x80,((0/10)<<4|(0%10)));WriteSet1302(0x82,((0/10)<<4|(0%10)));WriteSet1302(0x84,((12/10)<<4|(12%10)));WriteSet1302(0x86,((16/10)<<4|(16%10)));WriteSet1302(0x88,((11/10)<<4|(11%10)));WriteSet1302(0x8c,((8/10)<<4|(8%10)));}/***************************************************** 函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/ void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/***************************************************** 函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}bit BusyTest(void){bit result;RS=0;RW=1;E=1;_nop_();_nop_();_nop_();_nop_();result=BF;E=0;return result;}void WriteInstruction (unsigned char dictate) {while(BusyTest()==1);RS=0;RW=0;E=0;_nop_();_nop_();P0=dictate;_nop_();_nop_();_nop_();_nop_();E=1;_nop_();_nop_();_nop_();_nop_();E=0;}/void WriteAddress(unsigned char x) {WriteInstruction(x|0x80);}void WriteData(unsigned char y) {while(BusyTest()==1);RS=1;RW=0;E=0;P0=y;_nop_();_nop_();_nop_();_nop_();E=1;_nop_();_nop_();_nop_();_nop_();E=0;}void LcdInitiate(void){delaynms(15);WriteInstruction(0x38); delaynms(5);WriteInstruction(0x38); delaynms(5);WriteInstruction(0x38); delaynms(5);WriteInstruction(0x0c); delaynms(5);WriteInstruction(0x06); delaynms(5);WriteInstruction(0x01); delaynms(5);}void DisplaySecond(unsigned char x) {unsigned char i,j;i=x/10;//取十位j=x%10;//取个位WriteAddress(0x49);WriteData(digit[i]);WriteData(digit[j]);delaynms(50);void DisplayMinute(unsigned char x){unsigned char i,j;i=x/10;//取十位j=x%10;//取个位WriteAddress(0x46);WriteData(digit[i]);WriteData(digit[j]);delaynms(50); //延时1ms给硬件一点反应时间}void DisplayHour(unsigned char x){unsigned char i,j; //j,k,l分别储存温度的百位、十位和个位i=x/10;j=x%10;WriteAddress(0x43);WriteData(digit[i]);WriteData(digit[j]);delaynms(50);}void delay_18B20(unsigned int i)//延时1微秒while(i--);}void ds1820rst()/*ds1820复位*/ {unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0;delay_18B20(100);DQ = 1;delay_18B20(40);}uchar ds1820rd()/*读数据*/ {unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/ {unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp(){uchar a,b;ds1820rst();ds1820wr(0xcc);ds1820wr(0x44);ds1820rst();ds1820wr(0xcc);ds1820wr(0xbe);a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{ tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);return(tvalue);}void ds1820disp(){ uchar flagdat;disdata[0]=tvalue/1000+0x30;disdata[1]=tvalue%1000/100+0x30;disdata[2]=tvalue%100/10+0x30;disdata[3]=tvalue%10+0x30;if(tflag==0)flagdat=0x20;elseflagdat=0x2d;if(disdata[0]==0x30){disdata[0]=0x20;if(disdata[1]==0x30){disdata[1]=0x20;}}WriteAddress (0x80);WriteData (flagdat);WriteAddress (0x81);WriteData (disdata[0]);WriteAddress (0x82);WriteData (disdata[1]);WriteAddress (0x83);WriteData (disdata[2]);WriteAddress (0x84);WriteData (0x2e);WriteAddress (0x85);WriteData (disdata[3]);}/*结束*/void main(void){unsigned char second,minute,hour; //分别储存苗、分、小时,unsigned char ReadValue; //储存从1302读取的数据LcdInitiate(); //将液晶初始化WriteAddress(0x45); //写小时与分钟分隔符的显示地址,显示在第2行第6列WriteData(':'); //将字符常量写入LCDWriteAddress(0x48); //写分钟与秒分隔符的显示地址,显示在第2行第9列WriteData(':'); //将字符常量写入LCDInit_DS1302(); //将1302初始化while(1){read_temp();//读取温度ds1820disp();//显示ReadValue = ReadSet1302(0x81); //从秒寄存器读数据second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);DisplaySecond(second); //显示秒ReadValue = ReadSet1302(0x83); //从分寄存器读minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化DisplayMinute(minute); //显示分ReadValue = ReadSet1302(0x85); //从分寄存器读hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化DisplayHour(hour); //显示小时}}。
基于51单片机ds1302和ds18b20芯片方案设计书的电子日历
用DS1302时钟芯片、A T89C51单片机、温度传感器DS18B20、LCD液晶1602设计的电子日历,proteus仿真及C程序.#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7。
//ds18b20与单片机连接口uchar data disdata[5]。
uint tvalue。
//温度值uchar tflag。
//温度正负标志unsigned char code digit[10]={"0123456789"}。
//定义字符数组显示数字sbit DA TA=P3^6。
//位定义1302芯片的接口,数据输出端定义在P1.1引脚sbit RST=P3^4。
//位定义1302芯片的接口,复位端口定义在P1.1引脚sbit SCLK=P3^5。
//位定义1302芯片的接口,时钟输出端口定义在P1.1引脚//液晶引脚定义sbit RS=P2^0。
//寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1。
//读写选择位,将RW位定义为P2.1引脚sbit E=P2^2。
//使能信号位,将E位定义为P2.2引脚sbit BF=P0^7。
/*****************************************************函数功能:延时若干微秒***************************************************/void delaynus(unsigned char n){unsigned char i。
for(i=0。
i<n。
i++)。
}void Write1302(unsigned char dat){unsigned char i。
[整理]1602液晶DS1302时钟芯片DS18B20温度传感器
看看我做的万年历,1602液晶+DS1302时钟芯片+DS18B20温度传感器
文章发表于:2007-09-21 16:26。
有兴趣的朋友可以看看这个作品最好的地方是在proteus仿真软件里通过了,这个仿真软件什么都有,对学单片机的人来说是最好的,你什么元件都不用买,写好代码可以就可以仿真了,做出来的效果跟硬件一样,极力推荐大家使用这个仿真软件,我使用这个软件有2年了,我打算在我的小组里写一套教程,一步步上手学会仿真,51单片机爱好者,欢迎加入我创建的小组,以后大家可以一起交流,多提一些意见,有什么好的作品和思想都可以一起交流。
实物图:
实物图:
proteus仿真图:
硬件实物还加入了一个无线遥控模块,可以无线的修改时间内容。
如果你已经安装好proteus了,直接打开那个绿色的文件,就可以直接运行了。
效果跟实物图一样的。
源程序就用KEIL打开。
源程序压缩包:。
DS1302+DS18B20+LCD1602单片机c语言驱动程序案例
程有华老师MCS51系列单片机教学(C语言)源代码——“DS1302+DS18B20+LCD1602”实验【文档构成】第一部分:Proteus仿真原理图第三部分:Keil C程序源代码(可copy使用)(程有华单片机培训工作室制作)第一部分:Proteus仿真原理图第2 页/ 共16 页第二部分:Keil C程序源代码(可copy使用)#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit p20=P2^0;sbit p21=P2^1;sbit p22=P2^2;sbit p23=P2^3;sbit p24=P2^4;sbit p25=P2^5;sbit LCDRS = P2^7;sbit LCDE = P2^6;sbit SCLK = P1^0;sbit IO = P1^1;sbit REST = P1^2;sbit p34 = P3^4;sbit p17 = P1^7;sbit DQ = P1^6;float n;bit sanyear; bit sanmonth; bit sanday; bit sanweek;bit sanhour; bit sanmin; bit sansec;bit san;ucharseccs=0X55,mincs=0X59,hourcs=0X22,daycs=0X09,monthcs=0X10,yearcs=0X07,weekcs=0X01; uchar sec,min,hour,day,month,year,week;uchar key=0xaa;uchar rl=0; uint qq,time,yy;uint TEMPL,TEMPH,aa,bb;uchar code zimo[]={0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00, // 三0x00,0x1F,0x15,0x15,0x1B,0x11,0x1F,0x00, // 四0x00,0x1E,0x08,0x1E,0x0A,0x0A,0x1F,0x00, // 五0x00,0x04,0x00,0x1F,0x0A,0x11,0x00,0x00, // 六0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02, // 年0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00, // 月0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00, // 日0x04,0x0E,0x1C,0x1F,0x1C,0x0E,0x04,0x00};uchar code lcdadd[]={0x86,0x8a,0x8e,0xc8,0xcb,0xce,0x82};uchar code sz[]={"0123456789"};void keyer(void)p20=1;p21=0;if(!p22) { while(!p22);key=0x01; }if(!p23) { while(!p23);key=0x02; }if(!p24) { while(!p24);key=0x03; }if(!p25) { while(!p25);key=0x04; }p20=0;p21=1;if(!p22) {while(!p22); key=0x05; }if(!p23) { while(!p23);key=0x06; }if(!p24) { while(!p24);key=0x07; }if(!p25) { while(!p25);key=0x08; }} /**************盼键*************/ void into0init(void){TMOD = 0X01;TH0 = 15536/256;TL0 = 5536%256;IE = 0X82;TR0 = 1;} /************ INTO0 INITIALIZTION ***/ void into0deal(void) interrupt 1{TH0 = (65536-50000)/256;TL0 = (65536-50000)%256;time=time+1;if(time==8){time=0;san=!san;}}void delayus(uchar n){while(--n);} /************ US DELAY *************/ void delay(uint m){uint i,j;for(i=0;i<m;i++)for(j=0;j<125;j++);} /************ MS DELAY ************/ void LCD_WC(uchar i){LCDRS = 0;LCDE = 1;P0 = i;delay(5);delay(1);} /************ LCD WTIRE COMMAND ****/ void LCD_WD(uchar i){LCDRS=1;LCDE=1;P0=i;delay(5);LCDE=0;delay(2);} /*********** LCD WTIRE DATA *******/ void LCD_WB(void){uchar i;LCD_WC(0x40);for(i=0;i<64;i++)LCD_WD(zimo[i]);} /************ LCD WTIRE WORD ******/ void LCD_CS(void){LCD_WC(0x01);LCD_WC(0x02);LCD_WC(0x06);LCD_WC(0x0C);LCD_WC(0x14);LCD_WC(0x38);delay(10);LCD_WB();} /************ LCD INITIALIZTION **/ bit DS18b20_CS(void){bit dp;DQ=0;delayus(237);DQ=1;delayus(27);dp=DQ;delayus(237);return(dp);} /*********** DS18b20 INITIALIZTION */ void wbit(bit bp){DQ=0;delayus(3);if(bp)DQ=bp;delayus(20);DQ=1;} /*********** DS18b20 WRITE BIT *****/ void wbyte(uchar m){uchar i;for(i=0;i<8;i++){wbit(m&0x01);m=m>>1;}} /*********** DS18b20 WRITE BYTE ***/ bit rbit(void){bit bp;DQ=0;delayus(3);DQ=1;if(DQ)bp=1;else bp=0;delayus(20);return(bp);} /*********** DS18b20 READ BIT *****/ uchar rbyte(void){uchar i,m=0;for(i=0;i<8;i++){m=m>>1;if(rbit())m=m|0x80;}return(m);} /*********** DS18b20 READ BYTE ****/ void STARTUPDS18b20(void){while(DS18b20_CS());wbyte(0xcc);wbyte(0x44);// delay(750);for (yy=0;yy<10;yy++){keyer();if(key!=0xaa)break;}} /*********** STARTUP DS18b20 ******/ void READTEMP(void){STARTUPDS18b20();while(DS18b20_CS());// delay(1);wbyte(0xcc);wbyte(0xbe);TEMPL=rbyte();TEMPH=rbyte();n=(TEMPL+TEMPH*256)*0.0625;n=n*100;} /*********** READ TEMP IN DS18b20 */ void DISPDS18b20(void){uint m;READTEMP();LCD_WC(0x0c0);m=(uint)n;LCD_WD(sz[m/1000]);aa=sz[m/1000];m=m%1000;LCD_WD(sz[m/100]);bb=sz[m/100];m=m%100;LCD_WD('.');LCD_WD(sz[m/10]);m=m%10;LCD_WD(sz[m]);LCD_WD('C');if((aa>=sz[2])&&(bb>=sz[5])){p17=!p17;}if((aa>=sz[2])&&(bb==sz[5]))p17=0;if((aa<=sz[2])&&(bb<sz[4]))p17=1;} /* DS18b20 TEMP DEAL WITH AND RENOVATE */ uchar DS1302read(uchar address){uint b,c,e;e = address;SCLK = 0; REST = 0; REST = 1;for (b=0;b<8;b++){SCLK = 0;IO = (bit)(e & 0x01);SCLK = 1;e = e >> 1;}for (b=0;b<8;b++){SCLK = 0;c = c >> 1;if(IO)c=c|0x80;SCLK = 1;}REST = 0;SCLK = 1;return (c);}void DS1302wirte(uchar address,uchar dataes){uint a,adddat;SCLK = 0; REST = 0; REST = 1;adddat = address;for(a=0;a<8;a++){SCLK = 0;IO = (bit)(adddat & 0x01); //adddat & 0x01;////ddress&0x01);SCLK = 1;adddat = adddat >> 1;}adddat = dataes;for(a=0;a<8;a++){SCLK = 0;IO = (bit)(adddat & 0x01); //adddat & 0x01;//dataes&0x01;SCLK = 1;adddat = adddat >> 1;}REST = 0;}void DS1302readrealtime(void){sec = DS1302read(0x81);min = DS1302read(0x83);hour = DS1302read(0x85);day = DS1302read(0x87);month= DS1302read(0x89);year = DS1302read(0x8d);week = DS1302read(0x8b);}void DS1302init (void){DS1302wirte(0x8e,0x00);DS1302wirte(0x90,0xa9);DS1302wirte(0x80,seccs);DS1302wirte(0x82,mincs);DS1302wirte(0x84,hourcs);DS1302wirte(0x86,daycs);DS1302wirte(0x88,monthcs);DS1302wirte(0x8a,weekcs);DS1302wirte(0x8c,yearcs);}void OnlyMeSee (void){seccs = sec; mincs = min; hourcs = hour; weekcs = week;daycs = day; monthcs = month; yearcs = year;}void realtimedisplay(void){LCD_WC(0x80);LCD_WD('2');LCD_WD('0');if(sanyear==0){LCD_WD(sz[year/16]);LCD_WD(sz[year%16]);}else{LCD_WD(' ');LCD_WD(' ');}LCD_WC(0x84);LCD_WD(4);LCD_WD(' ');if(sanmonth==0){LCD_WD(sz[month/16]);LCD_WD(sz[month%16]);}else{LCD_WD(' ');LCD_WD(' ');}LCD_WC(0x88);LCD_WD(5);LCD_WD(' ');if(sanday==0){LCD_WD(sz[day/16]);LCD_WD(sz[day%16]);}else{LCD_WD(' ');LCD_WD(' ');}LCD_WC(0x8C);LCD_WD(6);LCD_WD('<');if(sanweek==0){if (1==week%16)LCD_WD('-');if (2==week%16)LCD_WD('=');if (3==week%16)LCD_WD(0);if (4==week%16)LCD_WD(1);if (5==week%16)LCD_WD(2);if (6==week%16)LCD_WD(3);if (7==week%16)LCD_WD(6);}else{LCD_WD(' ');}LCD_WD('>');LCD_WC(0xc8);if(sanhour==0){LCD_WD(sz[hour/16]);LCD_WD(sz[hour%16]);}else{LCD_WD(' ');LCD_WD(' ');}LCD_WC(0xca);LCD_WD(':');if(sanmin==0){LCD_WD(sz[min/16]);LCD_WD(sz[min%16]);}else{LCD_WD(' ');LCD_WD(' ');}LCD_WC(0xcd);LCD_WD(':');if(sansec==0){LCD_WD(sz[sec/16]);LCD_WD(sz[sec%16]);}else{LCD_WD(' ');LCD_WD(' ');}}void OnlyMeSee1(void){EA=0;sanyear=0;sanmonth=0;sanday=0;sanweek=0;sanhour=0;sanmin=0;sansec=0;}void keywith (void){keyer();if(key==0x08){key=0xaa;EA=1;while(1){loop: realtimedisplay();if(rl==0){sanyear = san;sanmonth=0;sanday=0;sanweek=0;sanhour=0;sanmin=0;sansec=0; }if(rl==1){sanmonth= san;sanyear=0;sanday=0;sanweek=0;sanhour=0;sanmin=0;sansec=0; }if(rl==2){sanday = san;sanyear=0;sanmonth=0;sanweek=0;sanhour=0;sanmin=0;sansec=0; }if(rl==3){sanweek = san;sanyear=0;sanmonth=0;sanday=0;sanhour=0;sanmin=0;sansec=0; }if(rl==4){sanhour = san;sanyear=0;sanmonth=0;sanday=0;sanweek=0;sanmin=0;sansec=0; }if(rl==5){sanmin = san;sanyear=0;sanmonth=0;sanday=0;sanweek=0;sanhour=0;sansec=0; }if(rl==6){sansec = san;sanyear=0;sanmonth=0;sanday=0;sanweek=0;sanhour=0;sanmin=0; }keyer();if(key==0x08){break;}if(key==0x03){OnlyMeSee();DS1302init();break;}if(key==0x05){key=0xaa;rl=rl-1;if(rl==255)rl=6;goto loop;}if(key==0x07){key=0xaa;rl=rl+1;if(rl==7)rl=0;goto loop;}if(key==0x02){ key=0xaa;switch(rl){case 0: {LCD_WC(0x82); year=year+0x01;switch(year){case 0x0a :year=0x10; break;case 0x1a :year=0x20; break;case 0x2a :year=0x30; break;case 0x31 :year=0x00; break;}LCD_WD(sz[year/16]);LCD_WD(sz[year%16]);LCD_WC(0x82);goto loop;case 1: {LCD_WC(0x86);month = month+0x01;switch(month){case 0x0a :month=0x10; break;case 0x13 :month=0x01; break;}LCD_WD(sz[month/16]);LCD_WD(sz[month%16]);LCD_WC(0x86);goto loop;}case 2: {LCD_WC(0x8a);day = day+0x01;switch(day){case 0x0a :day=0x10; break;case 0x1a :day=0x20; break;case 0x2a :day=0x30; break;case 0x32 :day=0x01; break;}LCD_WD(sz[day/16]);LCD_WD(sz[day%16]);LCD_WC(0x8a);goto loop;}case 3: {LCD_WC(0x8e);week = week+1;if(week==8){week=1;if (1==week%16)LCD_WD('-');LCD_WC(0x8e);goto loop;}if (1==week%16)LCD_WD('-');if (2==week%16)LCD_WD('=');if (3==week%16)LCD_WD(0);if (4==week%16)LCD_WD(1);if (5==week%16)LCD_WD(2);if (6==week%16)LCD_WD(3);if (7==week%16)LCD_WD(6);LCD_WC(0x8e);goto loop;}LCD_WC(0xc8);hour = hour+0x01;switch(hour){case 0x0a :hour=0x10; break;case 0x1a :hour=0x20; break;case 0x24 :hour=0x00; break;}LCD_WD(sz[hour/16]);LCD_WD(sz[hour%16]);LCD_WC(0xc8);goto loop;}case 5: {LCD_WC(0xcb); min = min+0x01;switch(min){case 0x0a :min=0x10; break;case 0x1a :min=0x20; break;case 0x2a :min=0x30; break;case 0x3a :min=0x40; break;case 0x4a :min=0x50; break;case 0x5a :min=0x00; break;}LCD_WD(sz[min/16]);LCD_WD(sz[min%16]);LCD_WC(0xcb);goto loop;}case 6: {LCD_WC(0xce);sec = sec+0x01;switch(sec){case 0x0a :sec=0x10; break;case 0x1a :sec=0x20; break;case 0x2a :sec=0x30; break;case 0x3a :sec=0x40; break;case 0x4a :sec=0x50; break;case 0x5a :sec=0x00; break;}LCD_WD(sz[sec/16]);LCD_WD(sz[sec%16]);LCD_WC(0xce);goto loop;}}}if(key==0x06){ key=0xaa;switch(rl){case 0: {LCD_WC(0x82); year=year-0x01;switch(year){case 0xff :year=0x30; break;case 0x2f :year=0x29; break;case 0x1f :year=0x19; break;case 0x0f :year=0x09; break;}LCD_WD(sz[year/16]);LCD_WD(sz[year%16]);LCD_WC(0x82);goto loop;}case 1: {LCD_WC(0x86);month = month-0x01;switch(month){case 0x00 :month=0x12; break;case 0x0f :month=0x09; break;}LCD_WD(sz[month/16]);LCD_WD(sz[month%16]);LCD_WC(0x86);goto loop;}case 2: {LCD_WC(0x8a);day = day-0x01;switch(day){case 0x00 :day=0x31; break;case 0x2f :day=0x29; break;case 0x1f :day=0x19; break;case 0x0f :day=0x09; break;}LCD_WD(sz[day/16]);LCD_WD(sz[day%16]);LCD_WC(0x8a);goto loop;}case 3: {LCD_WC(0x8e);week = week-1;switch(week){}if (1==week%16)LCD_WD('-');if (2==week%16)LCD_WD('=');if (3==week%16)LCD_WD(0);if (4==week%16)LCD_WD(1);if (5==week%16)LCD_WD(2);if (6==week%16)LCD_WD(3);if (7==week%16)LCD_WD(6);LCD_WC(0x8e);goto loop;}case 4: {LCD_WC(0xc8);hour = hour-0x01;switch(hour){case 0xff :hour=0x23; break;case 0x1f :hour=0x19; break;case 0x0f :hour=0x09; break;}LCD_WD(sz[hour/16]);LCD_WD(sz[hour%16]);LCD_WC(0xc8);goto loop;}case 5: {LCD_WC(0xcb); min = min-0x01;switch(min){case 0xff :min=0x59; break;case 0x4f :min=0x49; break;case 0x3f :min=0x39; break;case 0x2f :min=0x29; break;case 0x1f :min=0x19; break;case 0x0f :min=0x09; break;}LCD_WD(sz[min/16]);LCD_WD(sz[min%16]);LCD_WC(0xcb);goto loop;}case 6: {LCD_WC(0xce);sec = sec-0x01;switch(sec){case 0xff :sec=0x59; break;case 0x4f :sec=0x49; break;case 0x2f :sec=0x29; break;case 0x1f :sec=0x19; break;case 0x0f :sec=0x09; break;}LCD_WD(sz[sec/16]);LCD_WD(sz[sec%16]);LCD_WC(0xce);goto loop;}}}}}key=0xaa;OnlyMeSee1();rl=0;}void main(void){into0init(); EA=0;DS18b20_CS(); LCD_CS(); DS1302init();while(1){DS1302readrealtime();realtimedisplay();DISPDS18b20();keywith();}}。
DS1302和DS18B20综合运用
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds1302是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/******************************************************************************* Function: static void v_DS1302Write_f( uint8 Content ) ** Description:向DS1302写一个字节的内容** Parameter:uint8 Content : 要写的字节** *******************************************************************************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/****************************************************************************** * Function: static uint8 v_DS1302Read_f( void ) ** Description: 从DS1302当前设定的地址读取一个字节的内容** Parameter: ** Return: 返回读出来的值(uint8) *******************************************************************************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/******************************************************************************* Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: *******************************************************************************/void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/******************************************************************************* Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) *******************************************************************************/uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/******************************************************************************* Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) ** Parameter: ** ** Return: *******************************************************************************/void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/******************************************************************************* Function: void v_ClockUpdata_f( void ) ** Description:读取时间数据,并保存在结构体CurrentTime中** Parameter: ** ** Return: *******************************************************************************/void v_ClockUpdata_f( void ){CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
51单片机的18B20、1302和LCM1602液晶显示温度与万年历显控制
摘要本设计以数字集成电路技术为基础,单片机技术为核心。
软件设计采用模块化结构,C语言编程。
系统通过LCD显示数据,可以显示日期(年、月、日、时、分、秒)以及温度。
在内容安排上首先描述系统硬件工作原理,着重介绍了各硬件接口技术和各个接口模块的功能;其次,详细的阐述了程序的各个模块和实现过程。
前言电子时钟是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。
数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表。
钟表的数字化给人们生产生活带来了极大的方便,在此基础上完成的电子时钟精度高,功能易于扩展。
可扩展成为诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等电路。
所有这些,都是以钟表数字化为基础的。
因此,研究数字时钟及扩大其应用有着非常现实的意义。
本设计就是数字时钟简单的扩展应用。
1.1设计目标:利用单片机技术,以及模拟电子技术和数字电子技术的理论知识,设计实现MCS-51单片机对LCM1602液晶输出显示控制的这一基本要求。
1.2设计要求:本设计利用DS1302;DS18B20;LCD1602实现以下功能:(1) 显示日期功能(年、月、日、时、分、秒以及星期)(2) 可通过按键切换年、月、日及时、分、秒的显示状态(3) 可随时调校年、月、日或时、分、秒(4) 可每次增减一进行时间调节(5) 可动态完整显示年份,实现真正的万年历显示(6) 可显示温度2 设计方案2.1 控制器硬件控制电路主要用了AT89C52芯片处理器、LCD显示器等。
根据各自芯片的功能互相连接成电子万年历的控制电路。
软件控制程序主要有主控程序、电子万年历的时间控制程序、时间显示及星期显示和温度采集程序等组成。
主控程序中对整个程序进行控制,进行了初始化程序及计数器、还有键盘功能程序、以及显示程序等工作,时间控制程序是电子万年历中比较重要的部分。
DS1302+18B20万年历1602显示1的程序
DS1302+18B20万年历1602显⽰1的程序/* 该程序实现了⽤单⽚机来控制时钟芯⽚DS1302进⾏万年历的显⽰。
这个代码相对来说很复杂,注释⽐较多,⼤家可以仔细分析。
程序运⾏,⾸先设置时间。
按S19,进⾏某⼀位的设置,会看到某⼀位上⾯会闪烁。
按S20,数值加1.按S21,数值减1.设置完后,时间会进⾏运⾏。
另外,1602上也会有时间显⽰的。
*/#include#include"DS18B20_3.H"#define uint unsigned int#define uchar unsigned charuchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;//flag⽤于读取头⽂件中的温度值,和显⽰温度值#define yh 0x80 //LCD第⼀⾏的初始位置,因为LCD1602字符地址⾸位D7恒定为1(100000000=80)#define er 0x80+0x40 //LCD第⼆⾏初始位置(因为第⼆⾏第⼀个字符位置地址是0x40)//液晶屏的与C51之间的引脚连接定义(显⽰数据线接C51的P0⼝)sbit rs=P2^5;sbit rw=P2^6; //如果硬件上rw接地,就不⽤写这句和后⾯的rw=0了sbit en=P2^7;sbit SCLK = P1^6; //实时时钟时钟线引脚sbit IO = P3^5; //实时时钟数据线引脚sbit RST = P1^7; //实时时钟复位线引脚sbit ACC0=ACC^0;sbit ACC7=ACC^7;sbit key1=P3^2; //设置键sbit key2=P3^3; //加键sbit key3=P3^4; //减键uchar code tab1[]={"20 - - "}; //年显⽰的固定字符uchar code tab2[]={": : "};//时间显⽰的固定字符void delay(uint xms)//延时函数,有参函数{uint x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}//在这个程序中,液晶写⼊有关函数会在DS1302的函数中调⽤,所以液晶程序要放在前⾯write_1602com(uchar com)//液晶写⼊指令函数{rs=0;//数据/指令选择置为指令rw=0; //读写选择置为写P0=com;//送⼊数据delay(1);en=1;//拉⾼使能端,为制造有效的下降沿做准备delay(1);en=0;//en由⾼变低,产⽣下降沿,液晶执⾏命令}write_1602dat(uchar dat)//液晶写⼊数据函数{rs=1;//数据/指令选择置为数据rw=0; //读写选择置为写P0=dat;//送⼊数据delay(1);en=1; //en置⾼电平,为制造下降沿做准备delay(1);en=0; //en由⾼变低,产⽣下降沿,液晶执⾏命令}lcd_init()//液晶初始化函数{write_1602com(0x38);//设置液晶⼯作模式,意思:16*2⾏显⽰,5*7点阵,8位数据write_1602com(0x0c);//开显⽰不显⽰光标write_1602com(0x06);//整屏不移动,光标⾃动右移write_1602com(0x01);//清显⽰write_1602com(yh+1);//⽇历显⽰固定符号从第⼀⾏第1个位置之后开始显⽰for(a=0;a<14;a++){write_1602dat(tab1[a]);//向液晶屏写⽇历显⽰的固定符号部分//delay(3);}write_1602com(er+2);//时间显⽰固定符号写⼊位置,从第2个位置后开始显⽰for(a=0;a<8;a++) {write_1602dat(tab2[a]);//写显⽰时间固定符号,两个冒号//delay(3);}}//DS1302有关⼦函数void write_byte(uchar dat)//写⼀个字节{ACC=dat;RST=1;for(a=8;a>0;a--){IO=ACC0;SCLK=0;SCLK=1;ACC=ACC>>1;}}uchar read_byte()//读⼀个字节{RST=1;for(a=8;a>0;a--){ACC7=IO;SCLK=1; //下降沿读数据SCLK=0;ACC=ACC>>1;}return (ACC);}void write_1302(uchar add,uchar dat)//向1302芯⽚写函数,指定写⼊地址,数据RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;}uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址{uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);}uchar BCD_Decimal(uchar bcd)//BCD码转⼗进制函数,输⼊BCD,返回⼗进制{ uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}void ds1302_init() //1302芯⽚初始化⼦函数(2012-07-20,12:00:00,week4){RST=0;SCLK=0;write_1302(0x8e,0x00); //允许写,禁⽌写保护write_1302(0x8e,0x80); //打开写保护}//温度显⽰⼦函数void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显⽰位置{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得⼗位数字write_1602com(er+add); //er是头⽂件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显⽰码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显⽰码write_1602dat(0xdf); //显⽰温度的⼩圆圈符号,0xdf是液晶屏字符库的该符号地址码write_1602dat(0x43); //显⽰"C"符号,0x43是液晶屏字符库⾥⼤写C的地址码}//时分秒显⽰⼦函数void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显⽰位置加、现⽰数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得⼗位数字write_1602com(er+add);//er是头⽂件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显⽰码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显⽰码}//年⽉⽇显⽰⼦函数void write_nyr(uchar add,uchar dat)//向LCD写年⽉⽇,有显⽰位置加数、显⽰数据,两个参数{uchar gw,sw;gw=dat%10; //取得个位数字sw=dat/10; //取得⼗位数字write_1602com(yh+add); //设定显⽰位置为第⼀个位置+addwrite_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显⽰码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显⽰码}//写星期函数void write_week(uchar week){write_1602com(yh+0x0c);//星期字符的显⽰位置switch(week){case 1:write_1602dat('M');//星期数为1时,显⽰write_1602dat('O');write_1602dat('N');break;case 2:write_1602dat('T');//星期数据为2时显⽰write_1602dat('U');write_1602dat('E');break;case 3:write_1602dat('W');//星期数据为3时显⽰write_1602dat('E');write_1602dat('D');break;case 4:write_1602dat('T');//星期数据为4是显⽰write_1602dat('H');write_1602dat('U');break;case 5:write_1602dat('F');//星期数据为5时显⽰write_1602dat('R');write_1602dat('I');break;case 6:write_1602dat('S');//星期数据为6时显⽰write_1602dat('T');write_1602dat('A');break;case 7:write_1602dat('S');//星期数据为7时显⽰write_1602dat('U');write_1602dat('N');break;}}//键盘函数void keyscan(){if(key1==0)//key1为功能键(设置键){delay(9);//延时,⽤于消抖动if(key1==0)//延时后再次确认按键按下{while(!key1);key1n++;key1n=1;//设置按键共有秒、分、时、星期、⽇、⽉、年、返回,8个功能循环switch(key1n){case 1: TR0=0;//关闭定时器write_1602com(er+0x09);//设置按键按动⼀次,秒位置显⽰光标write_1602com(0x0f); //设置光标为闪烁temp=(miao)/10*16+(miao)%10;//秒数据写⼊DS1302write_1302(0x8e,0x00);write_1302(0x80,0x80|temp);//miaowrite_1302(0x8e,0x80);break;case 2: write_1602com(er+6);//按2次fen位置显⽰光标break;case 3: write_1602com(er+3);//按动3次,shibreak;case 4: write_1602com(yh+0x0e);//按动4次,weekbreak;case 5: write_1602com(yh+0x0a);//按动5次,ribreak;case 6: write_1602com(yh+0x07);//按动6次,yuebreak;case 7: write_1602com(yh+0x04);//按动7次,nianbreak;case 8:write_1602com(0x0c);//按动到第8次,设置光标不闪烁TR0=1;//打开定时器temp=(miao)/10*16+(miao)%10;write_1302(0x8e,0x00);write_1302(0x80,0x00|temp);//miao数据写⼊DS1302write_1302(0x8e,0x80);break;}}}if(key1n!=0)//当key1按下以下。
ds1302和ds18b20最详细的资料
ds1302和ds18b20最详细的资料对于市面上的大多数51单片机开发板来说。
ds1302和ds18b20应该是比较常见的两种外围芯片。
ds1302是具有SPI总线接口的时钟芯片。
ds18b20则是具有单总线接口的数字温度传感器。
下面让我们分别来认识并学会应用这两种芯片。
首先依旧是看DS1302的datasheet中的相关介绍。
上面是它的一些基本的应用介绍。
下面是它的引脚的描述。
下面是DS1302的时钟寄存器。
我们要读取的时间数据就是从下面这些数据寄存器中读取出来的。
当我们要想调整时间时,可以把时间数据写入到相应的寄存器中就可以了。
这是DS1302内部的31个RAM寄存器。
在某些应用场合我们可以应用到。
如我们想要做一个带定时功能的闹钟。
则可以把闹钟的时间写入到31个RAM寄存器中的任意几个。
当单片机掉电时,只要我们的DS1302的备用电池还能工作,那么保存在其中的闹钟数据就不会丢失~~由于对于这些器件的操作基本上按照数据手册上面提供的时序图和相关命令字来进行操作就可以了。
因此在我们应用这些器件的时候一定要对照着手册上面的要求来进行操作。
如果觉得还不够放心的话。
可以到网上下载一些参考程序。
对着手册看别人的程序,看别人的思路是怎么样的。
DS1302和单片机的连接很简单。
只需一根复位线,一根时钟线,一根数据线即可。
同时它本身还需要接一个32.768KHz的晶振来提供时钟源。
对于晶振的两端可以分别接一个6PF左右的电容以提高晶振的精确度。
同时可以在第8脚接上一个3.6V的可充电的电池。
当系统正常工作时可以对电池进行涓流充电。
当系统掉电时,DS1302由这个电池提供的能量继续工作。
下面让我们来驱动它。
sbit io_DS1302_RST = P2^0 ;sbit io_DS1302_IO = P2^1 ;sbit io_DS1302_SCLK = P2^2 ;//-------------------------------------常数宏---------------------------------//#define DS1302_SECOND_WRITE 0x80 //写时钟芯片的寄存器位置#define DS1302_MINUTE_WRITE 0x82#define DS1302_HOUR_WRITE 0x84#define DS1302_WEEK_WRITE 0x8A#define DS1302_DAY_WRITE 0x86#define DS1302_MONTH_WRITE 0x88#define DS1302_YEAR_WRITE 0x8C#define DS1302_SECOND_READ 0x81 //读时钟芯片的寄存器位置#define DS1302_MINUTE_READ 0x83#define DS1302_HOUR_READ 0x85#define DS1302_WEEK_READ 0x8B#define DS1302_DAY_READ 0x87#define DS1302_MONTH_READ 0x89#define DS1302_YEAR_READ 0x8D//-----------------------------------操作宏----------------------------------//#define DS1302_SCLK_HIGH io_DS1302_SCLK = 1 ;#define DS1302_SCLK_LOW io_DS1302_SCLK = 0 ;#define DS1302_IO_HIGH io_DS1302_IO = 1 ;#define DS1302_IO_LOW io_DS1302_IO = 0 ;#define DS1302_IO_READ io_DS1302_IO#define DS1302_RST_HIGH io_DS1302_RST = 1 ;#define DS1302_RST_LOW io_DS1302_RST = 0 ;/******************************************************* 保存时间数据的结构体*******************************************************/struct{uint8 Second ;uint8 Minute ;uint8 Hour ;uint8 Day ;uint8 Week ;uint8 Month ;uint8 Year ;}CurrentTime ;/************************************************************** **************** * Function: static void v_DS1302Write_f( uint8 Content ) ** Description:向DS1302写一个字节的内容** Parameter:uint8 Content : 要写的字节** **************************************************************** ***************/static void v_DS1302Write_f( uint8 Content ){uint8 i ;for( i = 8 ; i > 0 ; i-- ){if( Content & 0x01 ){DS1302_IO_HIGH}else{DS1302_IO_LOW}Content >>= 1 ;DS1302_SCLK_HIGHDS1302_SCLK_LOW}}/************************************************************** **************** * Function: static uint8 v_DS1302Read_f( void ) * * Description: 从DS1302当前设定的地址读取一个字节的内容* * Parameter: ** Return: 返回读出来的值(uint8) **************************************************************** ***************/ static uint8 v_DS1302Read_f( void ){uint8 i, ReadValue ;DS1302_IO_HIGHfor( i = 8 ; i > 0 ; i-- ){ReadValue >>= 1 ;if( DS1302_IO_READ ){ReadValue |= 0x80 ;}else{ReadValue &= 0x7f ;}DS1302_SCLK_HIGHDS1302_SCLK_LOW}return ReadValue ;}/************************************************************** **************** * Function: void v_DS1302WriteByte_f( uint8 Address, uint8 Content ) ** Description: 从DS1302指定的地址写入一个字节的内容** Parameter: Address: 要写入数据的地址** Content: 写入数据的具体值** Return: **************************************************************** ***************/ void v_DS1302WriteByte_f( uint8 Address, uint8 Content ){DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;v_DS1302Write_f( Content ) ;DS1302_RST_LOWDS1302_SCLK_HIGH}/************************************************************** **************** * Function: uint8 v_DS1302ReadByte_f( uint8 Address ) ** Description:从DS1302指定的地址读出一个字节的内容** Parameter:Address: 要读出数据的地址** ** Return: 指定地址读出的值(uint8) **************************************************************** ***************/ uint8 v_DS1302ReadByte_f( uint8 Address ){uint8 ReadValue ;DS1302_RST_LOWDS1302_SCLK_LOWDS1302_RST_HIGHv_DS1302Write_f( Address ) ;ReadValue = v_DS1302Read_f() ;DS1302_RST_LOWDS1302_SCLK_HIGHreturn ReadValue ;}/************************************************************** ***************** Function: void v_ClockInit_f( void ) ** Description:初始化写入DS1302时钟寄存器的值(主程序中只需调用一次即可) ** Parameter: ** ** Return: **************************************************************** ***************/ void v_ClockInit_f( void ){if( v_DS1302ReadByte_f( 0xc1) != 0xf0 ){v_DS1302WriteByte_f( 0x8e, 0x00 ) ; //允许写操作v_DS1302WriteByte_f( DS1302_YEAR_WRITE, 0x08 ) ; //年v_DS1302WriteByte_f( DS1302_WEEK_WRITE, 0x04 ) ; //星期v_DS1302WriteByte_f( DS1302_MONTH_WRITE, 0x12 ) ; //月v_DS1302WriteByte_f( DS1302_DAY_WRITE, 0x11 ) ; //日v_DS1302WriteByte_f( DS1302_HOUR_WRITE, 0x13 ) ; //小时v_DS1302WriteByte_f( DS1302_MINUTE_WRITE, 0x06 ) ; //分钟v_DS1302WriteByte_f( DS1302_SECOND_WRITE, 0x40 ) ; //秒v_DS1302WriteByte_f( 0x90, 0xa5 ) ; //充电v_DS1302WriteByte_f( 0xc0, 0xf0 ) ; //判断是否初始化一次标识写入v_DS1302WriteByte_f( 0x8e, 0x80 ) ; //禁止写操作}}/************************************************************** **************** * Function: void v_ClockUpdata_f( void ) * * Description:读取时间数据,并保存在结构体CurrentTime中** Parameter: ** ** Return: **************************************************************** ***************/ void v_ClockUpdata_f( void ){CurrentTime.Second = v_DS1302ReadByte_f( DS1302_SECOND_READ ) ;CurrentTime.Minute = v_DS1302ReadByte_f( DS1302_MINUTE_READ ) ;CurrentTime.Hour = v_DS1302ReadByte_f( DS1302_HOUR_READ ) ;CurrentTime.Day = v_DS1302ReadByte_f( DS1302_DAY_READ ) ;CurrentTime.Month = v_DS1302ReadByte_f( DS1302_MONTH_READ ) ;CurrentTime.Week = v_DS1302ReadByte_f( DS1302_WEEK_READ ) ;CurrentTime.Year = v_DS1302ReadByte_f( DS1302_YEAR_READ ) ;}有了上面的这些函数我们就可以对DS1302进行操作了。
51+DS1302+DS18B20+LCD1602-显示时间-温度-可调时
1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电.当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:振荡源,外接32.768kHz晶振。
3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平.只有在SCLK为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向).5)SCLK为时钟输入端。
2、DS1302的控制字节DS1302 的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见数据手册。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM 相关的寄存器等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
* 修改说明 :
******************************************************************************************/
void main(void)
void Disp_line2(void); //显示屏幕第二行
void id_case1_key();
//*********** DS1302 时间显示定义部分
sbit T_CLK = P3^5;
sbit T_IO = P3^6;
sbit T_RST = P3^7;
sbit ACC0=ACC^0;
id_case1_key();
break;
case 7://秒
min=0;
sec=1;
Disp_line1();
Disp_line2();
void Delay5Ms(void);
void Delay400Ms(void);
uchar code week[]={"Week."};
/******************************************************************************************
//初始化后设置为:04年12月2日星期4 0点0分0秒
uchar inittime[7]={0x00,0x00,0x00,0x02,0x12,0x04,0x04};
// 秒 分钟 小时 日 月 年 星期
//***** 18B20温度显示定义部分
id_case1_key();
break;
case 6://分钟
hour=0;
min=1;
Disp_line1();
Disp_line2();
硬件连接:
---------------------------------------------------------------
|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.2 |
|DB1-----P0.1 | DB5-----P0.5 | RS-------P2.1 |
TL0=(65535-50000)%256;
EA=1;
TR0=1;
ET0=1;
W1302(0x90,0xa5);//打开充电二级管 一个二级管串联一个2K电阻
W1302(0x8e,0x80);//写保护,禁止写操作
adjust_res(0x1f); //调整18B20的分辨率 0x1f:0.5; 0x3f:0.25; 0x5f:0.125
break;
case 2://月
year=0;
mon=1;
Disp_line1();
Disp_line2();
id_case1_key();
* 函数名称 :
* 功能描述 :
* 参数 : 参数名称: 输入/输出? 类型 描述
*
* 返回值 :
* 作者 :
* 创建日期 :2006-12-19
* 全局变量 :
* 全局静态变量:
* 局部静态变量:
*----------------------------------------修改历史------------------------------------------
/******************************************************************************
文件名 :ds1302clock.c
CPU: AT89S52 主频:11.0592M
液晶型号: 生产厂家:1602
{
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
Delay5Ms(); //延时片刻(可不要)
mychar(); //显示自定义字符
TMOD=0x01;
TH0=(65535-50000)/256;
id_case1_key();
break;
case 5://小时
weekk=0;
hour=1;
Disp_line1();
Disp_line2();
}
if (key3==0) // 设置和选择项目键
{
Delay5Ms();
if(key3==0)
{
id++;
if(id>7)
id=0;
sbit DQ = P1^4; //18B20 接P07口
typedef unsigned char byte;
typedef unsigned int word;
Read_Temperature(char,char);
void mychar(void);
void adjust_res(char res); //res 分别等于 0x1f, 0x3f, 0x5f 温度读数分辨率分别对应
break;
case 1://年
year=1;
Disp_line1();
Disp_line2();
id_case1_key();
// 0.5, 0.25, 0.125
//******* 1602LCD驱动 **********************************************************
void WriteDataLCM(uchar WDLCM);
sbit key1 = P1^5;
sbit key2 = P1^6;
sbit key3 = P1^7;
sbit key4 = P3^2;
uchar id,timecount;
bit flag,sflag; //flag是时钟冒号闪烁标志,sflag是温度负号显示标志
void Disp_line1(void); //显示屏幕第一行
id_case1_key();
break;
}
}
}
/******************************************************************************************
* 函数名称 :
* 功能描述 :中断入口,冒号闪烁
* 参数 : 参数名称: 输入/输出? 类型 描述
*
* 返回值 :
* 作者 :
* 创建日期 :2006-12-19
* 全局变量 :
* 全局静态变量:
void WriteCommandLCM(uchar WCLCM,BuysC);
uchar ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void DisplayListChar(uchar X, uchar Y, uchar code *DData);
******************************************************************************/
#include <reg52.h>
#include <string.h>
#include <intrins.h>
#define uchar unsigned char
break;
case 3://日
mon=0;
day=1;
Disp_line1();
Disp_line2();
id_case1_key();
|DB2-----P0.2 | DB6-----P0.6 | E -------P2.5 |
|DB3-----P0.3 | DB7-----P0.7 | Vo接1k电阻到地
---------------------------------------------------------------
}
while(key3==0);
}
switch(id)
{
case 0:
sline2();
while(1)
{
if ((key1|key2)==0) //初始化
{
Delay5Ms();
if ((key1|key2)==0)
Set1302(inittime);
void W1302(uchar, uchar); // 向DS1302写入一个字节
uchar R1302(uchar); // 从DS1302读出一个字节
void Set1302(uchar * ); // 设置时间
bit sec,min,hour,year,mon,day,weekk; //闪烁标志位
sbit ACC7=ACC^7;
void Set(uchar,uchar); //根据选择调整相应项目
void RTInputByte(uchar); /* 输入 1Byte */
uchar RTOutputByte(void); /* 输出 1Byte */
break;
case 4://星期
day=0;
weekk=1;
Disp_line1();