1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
| /\* 功能:数码管时钟显示。 (1)8位数码管显示设定的时间与日期。 (2)通过按键切换时间与日期的显示。 \*/
#include <reg52.h>
sbit LE_DUAN = P2^0; //定义573锁存使能端口 数码管段锁存 sbit LE_WEI = P2^1; //定义573锁存使能端口 数码管位锁存 #define SEGPORT P0 //定义数码管连接端口
sbit SCK = P1^6; // DS1302时钟线 sbit SDA = P1^7; // DS1302数据线 sbit RST = P1^5; // DS1302复位线
//DS1302 复位重定义 #define RST\_CLR RST=0 //电平置低 #define RST\_SET RST=1 //电平置高
//DS1302 数据 #define SDA\_CLR SDA=0 //电平置低 #define SDA\_SET SDA=1 //电平置高 #define SDA\_RD SDA //电平读取
//DS1302 时钟 #define SCK\_CLR SCK=0 //时钟信号 #define SCK\_SET SCK=1 //电平置高
#define DS1302\_SEC 0x80 //秒数据地址 #define DS1302\_MIN 0x82 //分数据地址 #define DS1302\_HOUR 0x84 //时数据地址 #define DS1302\_DATE 0x86 //日数据地址 #define DS1302\_MON 0x88 //月数据地址 #define DS1302\_DAY 0x8a //星期数据地址 #define DS1302\_YEAR 0x8c //年数据地址 #define DS1302\_CTRL 0x8e //控制数据地址 #define DS1302\_CHARGE 0x90 //涓流充电
bit ReadRTC_Flag; //读DS1302标志。1为读 0为不读。 unsigned char TimeMode; //日期与时间切换标志。
unsigned char time_buf1[8] = {40,21,11,6,17,30,50,7}; // -年月日时分秒周 2021-11-6 10:59:50 7周 unsigned char time_buf[8] ; // -年月日时分秒周 unsigned char TempData[8] ;
unsigned char code Seg_Wei[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管的位码,低电平有效。 unsigned char code Seg_Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //共阴数码管显示段码值 0~9,-
void DS1302\_Init(void); void DS1302\_Write\_Byte(unsigned char addr, unsigned char d); unsigned char DS1302\_Read\_Byte(unsigned char addr) ; void DS1302\_Read\_Time(void); void DS1302\_Write\_Time(void);
void Seg\_Disp(unsigned char FirstBit,unsigned char Num); void InitTIMER0(void);//inital timer0 void Delay\_1ms(unsigned int i); unsigned char GetKey(void);
void main(void) { unsigned char Key; InitTIMER0(); DS1302\_Init(); DS1302\_Write\_Time(); P2=0xff; //51默认为输入 while(1) { Key = GetKey(); if(Key&0x01) { TimeMode = ~TimeMode; //有按键后,模式取反,改变当前显示模式 } if(ReadRTC_Flag==1) { ReadRTC_Flag=0; DS1302\_Read\_Time(); if(TimeMode) { TempData[0]=Seg_Duan[time_buf1[1]/10]; //年 数据的转换, TempData[1]=Seg_Duan[time_buf1[1]%10]; //因我们采用数码管0~9的显示,将数据分开 TempData[2]=0x40; //加入"-" TempData[3]=Seg_Duan[time_buf1[2]/10]; //月 TempData[4]=Seg_Duan[time_buf1[2]%10]; TempData[5]=0x40; TempData[6]=Seg_Duan[time_buf1[3]/10]; //日 TempData[7]=Seg_Duan[time_buf1[3]%10]; } else { TempData[0]=Seg_Duan[time_buf1[4]/10]; //时 数据的转换, TempData[1]=Seg_Duan[time_buf1[4]%10]; //因我们采用数码管0~9的显示,将数据分开 TempData[2]=0x40; //加入"-" TempData[3]=Seg_Duan[time_buf1[5]/10]; //分 TempData[4]=Seg_Duan[time_buf1[5]%10]; TempData[5]=0x40; TempData[6]=Seg_Duan[time_buf1[6]/10]; //秒 TempData[7]=Seg_Duan[time_buf1[6]%10]; } } } }
/\*------------------------------------------------ DS1302初始化 ------------------------------------------------\*/ void DS1302\_Init(void) { RST_CLR; //RST脚置低 SCK_CLR; //SCK脚置低 DS1302\_Write\_Byte(DS1302_SEC,0x00); }
/\*------------------------------------------------ 向DS1302写入一字节数据 ------------------------------------------------\*/ void DS1302\_Write\_Byte(unsigned char addr, unsigned char dat) { unsigned char i; RST_SET; addr = addr & 0xFE; //写地址 最低位为W写,低电平 for (i = 0; i < 8; i++) { if (addr & 0x01) { SDA_SET; } else { SDA_CLR; } SCK_SET; SCK_CLR; addr = addr >> 1; } //写入数据:dat for (i = 0; i < 8; i ++) { if (dat & 0x01) { SDA_SET; } else { SDA_CLR; } SCK_SET; SCK_CLR; dat = dat >> 1; } RST_CLR; //停止DS1302总线 }
/\*------------------------------------------------ 从DS1302读出一字节数据 ------------------------------------------------\*/
unsigned char DS1302\_Read\_Byte(unsigned char addr) { unsigned char i; unsigned char temp; RST_SET; addr = addr | 0x01; //最低RD,有效为高电平 for (i = 0; i < 8; i ++) { if (addr & 0x01) { SDA_SET; } else { SDA_CLR; } SCK_SET; SCK_CLR; addr = addr >> 1; } //输出数据:temp for (i = 0; i < 8; i ++) { temp = temp >> 1; if (SDA_RD) { temp |= 0x80; } else { temp &= 0x7F; } SCK_SET; SCK_CLR; } SDA_CLR;//将读1个字节函数最后加上I/O=0即可消除85显示 RST_CLR; //停止DS1302总线 return temp; }
/\*------------------------------------------------ 从DS1302读出时钟数据 ------------------------------------------------\*/ void DS1302\_Read\_Time(void) { unsigned char i,tmp; time_buf[1]=DS1302\_Read\_Byte(DS1302_YEAR); //年 time_buf[2]=DS1302\_Read\_Byte(DS1302_MON); //月 time_buf[3]=DS1302\_Read\_Byte(DS1302_DATE); //日 time_buf[4]=DS1302\_Read\_Byte(DS1302_HOUR); //时 time_buf[5]=DS1302\_Read\_Byte(DS1302_MIN); //分 time_buf[6]=(DS1302\_Read\_Byte(DS1302_SEC))&0x7F;//秒 time_buf[7]=DS1302\_Read\_Byte(DS1302_DAY); //周
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; } }
/\*------------------------------------------------ 向DS1302写入时钟数据 ------------------------------------------------\*/ 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_CTRL,0x00); //关闭写保护 DS1302\_Write\_Byte(DS1302_SEC,0x80); //暂停 //DS1302\_Write\_Byte(DS1302\_CHARGE,0xa9); //涓流充电 DS1302\_Write\_Byte(DS1302_YEAR,time_buf[1]); //年 DS1302\_Write\_Byte(DS1302_MON,time_buf[2]); //月 DS1302\_Write\_Byte(DS1302_DATE,time_buf[3]); //日 DS1302\_Write\_Byte(DS1302_HOUR,time_buf[4]); //时 DS1302\_Write\_Byte(DS1302_MIN,time_buf[5]); //分 DS1302\_Write\_Byte(DS1302_SEC,time_buf[6]); //秒 DS1302\_Write\_Byte(DS1302_DAY,time_buf[7]); //周 DS1302\_Write\_Byte(DS1302_CTRL,0x80); //打开写保护 }
/\*------------------------------------------------ 数码管显示, pos为起始位 ------------------------------------------------\*/ void Seg\_Disp(unsigned char pos,unsigned char Num) { static unsigned char i=0;
SEGPORT=0; //清空数据,防止有交替重影 LE_DUAN=1; //段锁存 LE_DUAN=0;
SEGPORT=Seg_Wei[i+pos]; //取位码 LE_WEI=1; //位锁存 LE_WEI=0;
SEGPORT=TempData[i]; //取显示数据,段码 LE_DUAN=1; //段锁存 LE_DUAN=0; i++; if(i==Num) i=0; }
/\*------------------------------------------------ Timer0 初始化,开中断,2ms定时 ------------------------------------------------\*/ void InitTIMER0(void) { TMOD|=0x01; //定时器设置 16位 TH0=(65536-2000)/256; //定时时间 2ms TL0=(65536-2000)%256; EA=1; ET0=1; TR0=1; }
/\*------------------------------------------------ 简单延时程序:约1ms ------------------------------------------------\*/ void delay\_1ms(unsigned int i) { unsigned char j; while(i--) for(j=0;j<125; j++); }
/\*------------------------------------------------ 按键扫描 这里按键接在 P2.2 ------------------------------------------------\*/ unsigned char GetKey(void) { unsigned char KeyTemp,CheckValue,Key=0x00; CheckValue = P2&0x04; if(CheckValue==0x04) return 0x00; delay\_1ms(10); KeyTemp = P2&0x04; if(KeyTemp == CheckValue) return 0x00; if(!(CheckValue&0x04)) Key = 0x01; return Key; }
void tim0\_isr(void) interrupt 1//中断,用于数码管扫描 { static unsigned char num; TH0=(65536-2000)/256; //重新赋值 2ms TL0=(65536-2000)%256;
Seg\_Disp(0,8); num++;
if(num==50) //大致100ms { num=0; ReadRTC_Flag=1; //读标志位置1 } }
|