主要元件
89c52单片机
ds1302实时时钟程序
24c02
18b20
pcf8574
lcd1602
不知道为什么使用i2c光标不清晰
下面制作出来的实物图:
单片机源程序如下:
- #include"mcu.h"
- #include"ds1302.c"
- #include"pcf8574lcd.h"
- #include"24c02.h"
- sbit a0 = ACC^0;
- sbit a1 = ACC^1;
- sbit a2 = ACC^2;
- sbit a3 = ACC^3;
- sbit a4 = ACC^4;
- sbit a5 = ACC^5;
- sbit a6 = ACC^6;
- sbit a7 = ACC^7;
- sbit SCLK = P1^2; //时钟
- sbit IO = P1^3; //数据
- sbit RST = P1^4; //复位
- sbit DQ = P0^0 ; //18B20接口
- sbit sp = P3^4 ; //蜂鸣器
- sbit sb = P0^6 ; //继电器电源
- //输出
- sbit sb0 = P2^0 ;
- sbit sb1 = P2^1 ;
- sbit sb2 = P2^2 ;
- sbit sb3 = P2^3 ;
- //按键
- sbit MODE = P2^7 ; //模式键
- sbit INC = P2^6 ; //增加键
- sbit DEC = P2^5 ; //减少键
- sbit OK = P2^4 ; //OK键 定时开关键
-
- volatile uint8 data timedata[7] ; //时间值
- volatile uint8 data display_buffer1[16]; //显示缓冲区1
- volatile uint8 data display_buffer2[16]; //显示缓冲区2
- volatile uint8 data temdata[5] ; //存放温度值
- volatile uint16 data tdat ; //温度值变量
- volatile uint8 data tflag ; //温度正负值标志
- volatile int self_pos = 0 ;//菜单箭头标志变量
- volatile int OK_VALUE = 0 ; //OK键键值变量
- volatile bit bdata DIS_ON = 1 ; //显示开关 1 == on 0 == off
- volatile bit bdata SCAN_ON = 0 ; //按键扫描开关位,由定时器每20MS刷新
- volatile data MODE_ON = 0 ; //模式键按下后显示菜单
- volatile data INC_VALUE = 0 ;
- volatile data DEC_VALUE = 0 ;
- volatile bit bdata ALARM_VALUE = 0 ;//闹钟标志位
- volatile bit bdata ALARM_ON = 1 ; //闹钟响时关闭标志位
- volatile int data read_1 = 1,read_2 = 1,read_3 = 1,read_4 = 1;
-
- /****************************************************************
- 延时函数
- *****************************************************************/
- void delay_ms(uint16 count) // 延时时间count*1ms
- { uint16 i;
- for(;count>0;count--)
- {
- for(i=0;i<110;i++)
- {
- nop;
- }
- }
- }
- /**********************************************************
- 蜂鸣器
- ************************************************************/
- void speakers(uint8 speak_count)
- {
- for(;speak_count>0;speak_count--)
- {
- sp = 0 ;
- delay_ms(15) ;
- sp = 1 ;
-
- }
- }
- //底层驱动函数(输入)
- void DS1302_input(uint8 inputdata)
- {
- ACC = inputdata ;
- IO = a0 ; SCLK = 1 ; SCLK = 0 ;
- IO = a1 ; SCLK = 1 ; SCLK = 0 ;
- IO = a2 ; SCLK = 1 ; SCLK = 0 ;
- IO = a3 ; SCLK = 1 ; SCLK = 0 ;
- IO = a4 ; SCLK = 1 ; SCLK = 0 ;
- IO = a5 ; SCLK = 1 ; SCLK = 0 ;
- IO = a6 ; SCLK = 1 ; SCLK = 0 ;
- IO = a7 ; SCLK = 1 ; SCLK = 0 ;
- }
- //底层驱动函数(输出)控制位的第七位必须为1
- uint8 DS1302_output(void)
- {
- IO = 1 ;
- a0 = IO ;
- SCLK = 1 ; SCLK =0 ; a1 = IO ;
- SCLK = 1 ; SCLK =0 ; a2 = IO ;
- SCLK = 1 ; SCLK =0 ; a3 = IO ;
- SCLK = 1 ; SCLK =0 ; a4 = IO ;
- SCLK = 1 ; SCLK =0 ; a5 = IO ;
- SCLK = 1 ; SCLK =0 ; a6 = IO ;
- SCLK = 1 ; SCLK =0 ; a7 = IO ;
- return(ACC);
- }
- //底层驱动函数(指定地址写一个字节的数据)
- void DS1302_write_byte(uint8 cmd , uint8 dat)
- {
- SCLK = 0 ;
- RST = 0 ;
- RST = 1 ;
- DS1302_input(cmd) ;
- DS1302_input(dat) ;
- RST = 0 ;
- SCLK = 1 ;
- }
- //底层驱动函数(指定地址读取一字节的数据)
- uint8 DS1302_read_byte(int cmd)
- {
- uint8 receivedata = 0 ;
- SCLK = 0 ;
- RST = 0 ;
- RST = 1 ;
- DS1302_input(cmd) ;
- receivedata = DS1302_output() ;
- RST = 0 ;
- SCLK = 1 ;
- return(receivedata) ;
- }
- //1302的初始数据
- void DS1302_init()
- {
- if(DS1302_read_byte(0xef) != 0xf0) //检测初始化标志数据不为f0则初始化1302
- {
- DS1302_write_byte(0x8e,0x00) ;//允许写操作
- DS1302_write_byte(0xee,0xf0) ; //初始化标志
- DS1302_write_byte(0x8c,0x18) ;//年
- DS1302_write_byte(0x8a,0x01) ;//星期
- DS1302_write_byte(0x88,0x01) ;//月
- DS1302_write_byte(0x86,0x01) ;//日
- DS1302_write_byte(0x84,0x12) ;//时
- DS1302_write_byte(0x82,0x00) ;//分
- DS1302_write_byte(0x80,0x00) ;//秒
- DS1302_write_byte(0x90,0xa5) ;//充电
- DS1302_write_byte(0x8e,0x80) ;//禁止写操作
- }
- }
- /********************************************************
- 读取时间数据并放在timedata[]中
- *********************************************************/
- void DS1302_read_time()
- {
- timedata[0] = DS1302_read_byte(0x8d) ; //年
- timedata[1] = DS1302_read_byte(0x89) ; //月
- timedata[2] = DS1302_read_byte(0x87) ; //日
- timedata[3] = DS1302_read_byte(0x85) ; //时
- timedata[4] = DS1302_read_byte(0x83) ; //分
- timedata[5] = DS1302_read_byte(0x81) ; //秒
- timedata[6] = DS1302_read_byte(0x8b) ; //星期
- }
- /***********************************************************
- DS18B20函数
- *************************************************************/
- void delay_18b20(int16 sum) //短暂延时
- {
- while(sum--);
- }
- void rst_18b20() //18B20复位
- { //uchar flag;
- DQ=1;
- delay_18b20(8);
- DQ=0;
- delay_18b20(80);
- DQ=1;
- delay_18b20(13);
- //flag=DQ;
- //return(flag);
- // delay_18b20(20);
- }
- void wr_18b20(int dat) //写一个字节的数据
- {
- uint8 i=8;
- for(;i>0;i--)
- {
- DQ=0;
- DQ=dat&0x01;
- delay_18b20(5);
- DQ=1;
- dat>>=1;
- }
- }
- uint8 rd_18b20() //读一个字节的内容
- {
- uint8 dat=0,i=8;
- for(;i>0;i--)
- {
- DQ=0;
- dat>>=1;
- DQ=1;
- if(DQ)
- dat|=0x80;
- delay_18b20(4);
- }
- return(dat);
- }
- uint16 rd_temperature() //读取温度值
- {
- uint8 a=0,b=0;
- uint16 t=0;
- float tt=0;
- rst_18b20(); //复位
- wr_18b20(0xcc); //跳过ROM
- wr_18b20(0x44); //启动温度转换
- rst_18b20(); //再次对18B20操作时,需要重新复位一次
- wr_18b20(0xcc); //跳过ROM
- wr_18b20(0xbe); //读取内部RAM的内容
- a=rd_18b20(); //读温度值低位(内部RAM的第0个字节)
- b=rd_18b20(); //读温度值高位(内部RAM的第1个字节)
- t=b;
- t<<=8; //温度值的高8位放在t的高8位
- t=t|a; //温度值的低8位放在t的低8位
- if(t<0x0fff) //判断温度值得正负值
- tflag=0; //tflag=0温度值为正
- else
- {
- t=~t+1; //温度值为负,负值以补码形式存放,这里要将其还原成原码
- tflag=1; //tflag=1温度值为负
- }
- tt=t*0.0625;
- t = tt*100 ;
- return(t);
-
- }
- //***********************************************//
- void tem_conv() //温度转换
- {
- uint8 flagdat ;//定义温度值符号
- if(tflag==0)
- temdata[4]=flagdat=0x20;//温度为正不显示负号
- else
- temdata[4]=flagdat=0x2d;//负温度显示负号
- temdata[0]=tdat/1000+0x30;//温度十位
- temdata[1]=tdat%1000/100+0x30;//温度个位
- temdata[2]=tdat%100/10+0x30;//小数十位
- temdata[3]=tdat%10+0x30;//小数百位
- /*if(temdata[0]==0x30)
- {temdata[0]=0x20;//?????0,???
- if(temdata[1]==0x30)
- {
- temdata[1]=0x20;//?????0,???0????
- }
- }*/
-
- }
-
- /**************************************************************
- 更新显示缓冲区
- ***************************************************************/
- void updata_buffer(void)
- {
- //显示日期
- display_buffer1[0] = '2' ;
- display_buffer1[1] = '0' ;
- display_buffer1[2] = timedata[0]/16+0x30 ; //年
- display_buffer1[3] = timedata[0]%16+0x30 ;
- display_buffer1[4] = 0 ;
- display_buffer1[5] = timedata[1]/16+0x30 ; //月
- display_buffer1[6] = timedata[1]%16+0x30 ;
- display_buffer1[7] = 0 ;
- display_buffer1[8] = timedata[2]/16+0x30 ; //日
- display_buffer1[9] = timedata[2]%16+0x30 ;
- display_buffer1[10] = ' ' ;
- display_buffer1[11] = ' ' ;
- display_buffer1[12] = ' ' ;
- switch(timedata[6]%16) //显示星期
- { case 1 : {display_buffer1[13] = '1' ;
- }break ;
- case 2 : {display_buffer1[13] = '2' ;
- }break ;
- case 3 : {display_buffer1[13] = '3' ;
- }break ;
- case 4 : {display_buffer1[13] = '4' ;
- }break ;
- case 5 : {display_buffer1[13] = '5' ;
- }break ;
- case 6 : {display_buffer1[13] = '6' ;
- }break ;
- case 7 : {display_buffer1[13] = '7' ;
- }break ;
- default : break; }
- display_buffer1[14] = ' ' ;
- if(ALARM_VALUE == 1)
- display_buffer1[15] = 1 ; //按下ok键显示定时标志
- else
- if(ALARM_VALUE == 0)
- display_buffer1[15] = 3 ;
-
- //当前时间值
- display_buffer2[0] = timedata[3]/16+0x30; //时
- display_buffer2[1] = timedata[3]%16+0x30;
- display_buffer2[2] = ':' ;
- display_buffer2[3] = timedata[4]/16+0x30 ; //分
- display_buffer2[4] = timedata[4]%16+0x30 ;
- display_buffer2[5] = ':' ;
- display_buffer2[6] = timedata[5]/16+0x30 ; //秒
- display_buffer2[7] = timedata[5]%16+0x30 ;
-
- //温度值
- display_buffer2[8] = ' ' ;
- display_buffer2[9] = temdata[4] ; //负号
- display_buffer2[10] = temdata[0] ; //温度十位
- display_buffer2[11] = temdata[1] ; //温度个位
- display_buffer2[12] = '.' ;
- display_buffer2[13] = temdata[2] ; //小数十位
- display_buffer2[14] = temdata[3] ; //小数百位
- display_buffer2[15] = 'C' ;
- }
- /******************************************************************
- 显示缓冲区内容
- *******************************************************************/
- void display_buffer(void)
- {
- uint8 i ;
- send_command(0x80) ; //显示第一行
- for(i=0;i<16;i++)
- send_data(display_buffer1[i]);
- send_command(0xc0) ; //显示第二行
- for(i=0;i<16;i++)
- send_data(display_buffer2[i]);
- }
- /*****************************************************************
- 按键扫描函数
- ******************************************************************/
- void key_scan(void)
- {
- if(MODE == 0)
- {
- delay_ms(10) ;
- while(!MODE) ;
- speakers(5) ;
- DIS_ON = 0 ;
- MODE_ON ++ ;
- if(MODE_ON == 1 && OK_VALUE == 0)
- send_command(0x01);
- if(MODE_ON == 2 && OK_VALUE == 0)
- {
- MODE_ON = 0 ;
- DIS_ON = 1 ;
- self_pos = 0 ;
- }
- }
-
- if(INC == 0 && MODE_ON == 1 && OK_VALUE == 0)
- {
- delay_ms(10) ;
- while(!INC) ;
- speakers(5) ;
- send_command(0x01) ;
- self_pos++ ;
- if(self_pos > 4)
- self_pos = 0 ;
- }
- if(DEC == 0 && MODE_ON == 1 && OK_VALUE == 0)
- {
- delay_ms(10) ;
- while(!DEC) ;
- speakers(5) ;
- send_command(0x01) ;
- self_pos++ ;
- if(self_pos > 4)
- self_pos = 0 ;
- }
- if(DEC == 0 )
- {
- delay_ms(10) ;
- while(!DEC) ;
- speakers(5) ;
- DEC_VALUE++;
- }
- if(INC == 0)
- {
- delay_ms(10) ;
- while(!INC) ;
- speakers(5) ;
- INC_VALUE++;
- }
- if(OK == 0 && MODE_ON != 0)
- {
- delay_ms(10) ;
- while(!OK) ;
- speakers(5) ;
- send_command(0x01) ;
- OK_VALUE++;
- INC_VALUE = 0 ;
- DEC_VALUE = 0 ;
- }
- if(OK == 0 && MODE_ON == 0)
- {
- delay_ms(10) ;
- while(!OK) ;
- speakers(5) ;
- ALARM_ON = 1 ;
- if(ALARM_VALUE == 1)
- ALARM_VALUE = 0 ;
- else
- ALARM_VALUE = 1 ;
- }
- }
- /*******************************************************************
- 按键菜单人机交互函数(第一级)
- ********************************************************************/
- void menu_display_1()
- {
- if(MODE_ON == 1 && OK_VALUE == 0)
- {
- switch(self_pos)
- {
- case 0 : {
- LCD1602_write_string(1,1,"Time ") ;
- LCD1602_write_string(1,0," Timing1 ") ;
- }break ;
- case 1 : {
- LCD1602_write_string(1,1," Time ") ;
- LCD1602_write_string(1,0,"Timing1 ") ;
- }break ;
- case 2 : {
- LCD1602_write_string(1,1," Timing1 ") ;
- LCD1602_write_string(1,0,"Timing2") ;
- }break ;
- case 3 : {
- LCD1602_write_string(1,1," Timing2 ") ;
- LCD1602_write_string(1,0,"Timing3") ;
- }break ;
- case 4 : {
- LCD1602_write_string(1,1," Timing3 ") ;
- LCD1602_write_string(1,0,"Timing4") ;
- }break ;
- default : break ;
- }
- }
- }
- /*******************************************************************
- 按键菜单人机交互函数(第二级)
- ********************************************************************/
- void menu_display_2(void)
- {
- uint8 i ,j;
- if(MODE_ON != 0 && OK_VALUE != 0)
- {
- send_command(0x0f) ;
- if(self_pos == 0 )
- {
-
- send_command(0x81) ;
- for(i=0;i<15;i++)
-
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
8574and1602ti.rar
(92.21 KB, 下载次数: 98)
|