一、题目要求
二、代码操作
2.1 main.c
#include <STC15F2K60S2.h> #include <intrins.h> #include "ds1302.h" sbit DQ=P1^4; #define uchar unsigned char #define uint unsigned int uchar code SMG_duanma[19] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x88,0x80,0xc6,0xc0,0x86,0x8e, 0xbf,0x7f,0XFF};//分别是0-9(对应下标),A-F,“-”,“.”,“灭” //分别是“0.-9.” uchar code SMG_Dot_AC[10] = {0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10}; uchar Write_DS1302_adrr[7] = {0X80, 0X82, 0X84, 0X86, 0X88, 0X8A, 0X8C}; uchar Read_DS1302_adrr[7] = {0X81, 0X83, 0X85, 0X87, 0X89, 0X8B, 0X8D}; uchar shijian[7] = {0X50, 0X59, 0X23, 0X18, 0X04, 0X06, 0X20}; //秒、分、时、日、月、周、年 //是否让提示符1、2闪烁 uchar Flashing = -1; //是否到10个温度数据 bit Save_Temp_FULL = -1; //L1灯检查 uchar L1_Check = 1; //中断检查是否可以读取温度 bit Check_T_s = 0; //温度数组计数 uchar count = 0; //存储温度数组 uchar Save_Temp[10] = {0}; //定时器5ms计数 uchar T_5ms = 0; //采集间隔时间位置 uchar T_Interval_i = 0; //采集间隔时间数组 uchar T_Interval_s[4]= {1, 5, 30, 60}; //数码管初始化 uchar yi=18; uchar er=18; uchar san=18; uchar si=18; uchar wu=18; uchar liu=18; uchar qi=18; uchar ba=18; //系统初始化 void Initsys(); //配置HC138 void SelectHC138(uchar channel); //在pos位码上,显示value段码 void DisplaySMG_Bit(uchar pos, uchar value); //数码管8位码显示 void SMG_Display(); //数码管的延时 void Delay_one_ms_SMG(); //按键消抖延时 void Delay_five_ms_Key(); void Init_DS1302(); void Read_DS1302(); //*************************** //获取温度 uchar temget(); //延时500微秒 void Delay500us(); //延时100微秒 void Delay100us(); //温度初始化 void dsinit(); void write(uchar dat); uchar read(); void Delays(uint b); //*************************** void Timer0Init(void); //5毫秒@11.0592MHz //参数设置界面下,独立按键扫描 uchar Setting_Alone_Key(); //参数设置界面 void Setting_Display_Mode(); //时钟显示界面 void Chock_Display_Mode(); //温度采集显示界面 void GetTemp_Display_Mode(); //温度采集_按键扫描 uchar GetTemp_Alone_Key(); void main() { Init_DS1302(); Initsys(); Timer0Init(); while(1) { yi = 18; er = 18; san = 18; EA = 0; Setting_Display_Mode(); Chock_Display_Mode(); GetTemp_Display_Mode(); } } //温度采集显示界面 void GetTemp_Display_Mode() { uchar temp = 0; while(1) { uchar i; yi = 16;er = 0; san = 0;si = 18; wu = 18; liu = 16; qi = Save_Temp[0] / 10; ba = Save_Temp[0] % 10; SMG_Display(); temp = GetTemp_Alone_Key(); if(temp == 1) { L1_Check = -1; Flashing = -1; SelectHC138(4); P0 = 0XFF; for(i = 0; i < 10; i++) { san = i; qi = Save_Temp[i] / 10; ba = Save_Temp[i] % 10; SMG_Display(); Delays(200); } temp = GetTemp_Alone_Key(); while(1) { SMG_Display(); temp = GetTemp_Alone_Key(); if(temp == 2) { break; } } if(temp == 2) { break; } } } } void Delays(uint b) { while(b--) { SMG_Display(); } } //温度采集_按键扫描 uchar GetTemp_Alone_Key() { if(P31 == 0) { Delay_five_ms_Key(); if(P31 == 0) { return 1; } while(!P31) { SMG_Display(); } } //S7按键 else if(P30 == 0) { Delay_five_ms_Key(); if(P30 == 0) { return 2; } while(!P30); } return 3; } //时钟显示界面 void Chock_Display_Mode() { EA = 1; Flashing = 0; Init_DS1302(); while(1) { if(Check_T_s == 1) { Save_Temp[count] = temget(); count++; Check_T_s = 0; if(count == 10) { count = 0; Save_Temp_FULL = 1; break; } } Read_DS1302(); yi = shijian[2] / 16; er = shijian[2] % 16; si = shijian[1] / 16; wu = shijian[1] % 16; qi = shijian[0] / 16; ba = shijian[0] % 16; SMG_Display(); } } //参数设置界面 void Setting_Display_Mode() { uchar check = -2; Save_Temp_FULL = 0; T_Interval_i = 0; while(1) { liu = 16; check = Setting_Alone_Key(); qi = T_Interval_s[T_Interval_i] / 10; ba = T_Interval_s[T_Interval_i] % 10; if(check == 0) { break; } SMG_Display(); } liu = 18; } //参数设置界面下,独立按键扫描 uchar Setting_Alone_Key() { uchar i = -1; //S5按键 if(P32 == 0) { Delay_five_ms_Key(); if(P32 == 0) { while(1) { return 0; } } while(!P32) { SMG_Display(); } } //S4按键 else if(P33 == 0) { Delay_five_ms_Key(); if(P33 == 0) { T_Interval_i++; if(T_Interval_i == 4) { T_Interval_i = 0; } i = 1; } while(!P33) { SMG_Display(); } } return i; } //按键消抖延时 void Delay_five_ms_Key() { uint i,j; for(i = 0; i < 5; i++) for(j = 845; j > 0; j--); } //配置HC138 void SelectHC138(uchar channel) { switch(channel) { case 4: //LED P2 = (P2 & 0X1F) | 0X80; break; case 5: //蜂鸣器和继电器 P2 = (P2 & 0X1F) | 0Xa0; break; case 6: //位码 P2 = (P2 & 0X1F) | 0Xc0; break; case 7: //段码 P2 = (P2 & 0X1F) | 0Xe0; break; case 0: //锁住所有寄存器 P2 = (P2 & 0X1F) | 0X00; break; } } //系统初始化 void Initsys() { SelectHC138(5); P0 = 0X00;//关闭蜂鸣器和继电器 SelectHC138(4); P0 = 0XFF;//关闭LED SelectHC138(6); P0 = 0XFF; //选择所有数码管 SelectHC138(7); P0 = 0XFF; //关闭所有数码管 } //在pos位码上,显示value段码 void DisplaySMG_Bit(uchar pos, uchar value) { SelectHC138(6); P0 = 0X01 << pos; SelectHC138(7); P0 = value; } //数码管8位码显示 void SMG_Display() { DisplaySMG_Bit(0, SMG_duanma[yi]); Delay_one_ms_SMG(); DisplaySMG_Bit(1, SMG_duanma[er]); Delay_one_ms_SMG(); DisplaySMG_Bit(2, SMG_duanma[san]); Delay_one_ms_SMG(); DisplaySMG_Bit(3, SMG_duanma[si]); Delay_one_ms_SMG(); DisplaySMG_Bit(4, SMG_duanma[wu]); Delay_one_ms_SMG(); DisplaySMG_Bit(5, SMG_duanma[liu]); Delay_one_ms_SMG(); DisplaySMG_Bit(6, SMG_duanma[qi]); Delay_one_ms_SMG(); DisplaySMG_Bit(7, SMG_duanma[ba]); Delay_one_ms_SMG(); } //数码管的延时 void Delay_one_ms_SMG() { uint j; for(j = 845; j > 0; j--); } //*****************中断********************* void Timer0Init(void) //5毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x00; //设置定时初值 TH0 = 0x28; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1; } void ServiceTimer0() interrupt 1 using 1 { static uchar T_s = 0; T_5ms++; if(T_5ms == 200) { if((T_s == T_Interval_s[T_Interval_i]) && (Save_Temp_FULL == 0)) { Check_T_s = 1; T_s = 0; } if(Flashing == 0) { Flashing = 1; san = 18; liu = 18; if(Save_Temp_FULL == 1 && L1_Check == 1) { P0 = 0XFF; SelectHC138(4); P00 = 0; } } else if(Flashing == 1) { Flashing = 0; san = 16; liu = 16; if(Save_Temp_FULL == 1 && L1_Check == 1) { P0 = 0XFF; SelectHC138(4); P00 = 1; } } T_5ms = 0; T_s++; } } //******************DS1302****************** //时间初始化 void Init_DS1302() { uchar i; Write_Ds1302(0X81, 0X00); for(i = 0; i < 7; i++) { Write_Ds1302(Write_DS1302_adrr[i], shijian[i]); } } //读出时间 void Read_DS1302() { uchar i; for(i = 0; i < 7; i++) { shijian[i] = Read_Ds1302(Read_DS1302_adrr[i]); } } //********************温度****************** uchar temget() { unsigned char di8,gao8,temp; dsinit(); write(0xcc); write(0x44); Delay500us(); Delay500us(); dsinit(); write(0xcc); write(0xbe); di8=read(); gao8=read(); temp=gao8<<4; temp=temp|(di8>>4); return temp; } uchar read() { uchar i; uchar dat; for(i=0;i<8;i++) { DQ=0; _nop_(); //1 dat>>=1; DQ=1; if(DQ==1) { dat|=0x80; } Delay100us(); } return dat; } void write(uchar dat) { uchar i; for(i=0;i<8;i++) {DQ=0; DQ=dat&0x01; Delay100us(); DQ=1; dat>>=1; }} void dsinit() { DQ=0; Delay500us(); DQ=1; Delay500us(); } void Delay100us() { unsigned char i, j; _nop_(); _nop_(); i = 2; j = 15; do { while (--j); } while (--i); } void Delay500us() { unsigned char i,j; _nop_(); _nop_(); i=6; j=93; do { while(j--); }while(i--); }
2.2 ds1302.c
#include <reg52.h> #include <intrins.h> sbit SCK=P1^7; sbit SDA=P2^3; sbit RST = P1^3; // DS1302复位 void Write_Ds1302_Byte(unsigned char temp) { unsigned char i; for (i=0;i<8;i++) { SCK=0; SDA=temp&0x01; temp>>=1; SCK=1; } } void Write_Ds1302( unsigned char address,unsigned char dat ) { RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302_Byte(address); Write_Ds1302_Byte(dat); RST=0; } unsigned char Read_Ds1302 ( unsigned char address ) { unsigned char i,temp=0x00; RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302_Byte(address); for (i=0;i<8;i++) { SCK=0; temp>>=1; if(SDA) temp|=0x80; SCK=1; } RST=0; _nop_(); RST=0; SCK=0; _nop_(); SCK=1; _nop_(); SDA=0; _nop_(); SDA=1; _nop_(); return (temp); }
三、一些心得
1.bit型慎用
2.按键最好return出来,出来后再做处理
3.大程序,在最后写延时时,写短一点,因为可能还有其他程序在运行,拖慢时间
4.DS1302用16进制写入,16进制读出,转换时用/16和%16