ds1302时钟模块程序

01.#include<reg52.h>        //包含单片机寄存器的头文件

02.#include<intrins.h>       //包含_nop_()的头文件

03.sbit RS=P2^0;            //LCD读写选择位

04.sbit RW=P2^1;    //LCD读写选择位

05.sbit E=P2^2;  //LCD使能端

06.sbit BF=P0^7;        //忙信号

07.sbit SCLK=P1^0;    //1302时钟输出端

08.sbit DATA=P1^1;    //1302数据端

09.sbit RST=P1^2;    //1302复位端

10.unsigned char code digit[]=0123456789;

11./***************************

12.1ms基准延时

13.***************************/

14.void delay1ms(unsigned int n)     

15.{

16.unsigned char i;

17.while(n--)

18.  for(i=0;i<115;i++);

19.}

20./***************************

21.以下是DS1302模块

22.***************************/

23.

24./**************************

25.向1302写一个字节

26.**************************/

27.void Write1302(unsigned char dat)

28.{

29.unsigned char i;

30.

31.SCLK=0;       //确保写数据前SCLK为低电平

32._nop_();

33._nop_(); //给硬件反应时间

34.for(i=0;i<8;i++){

35.  DATA=dat&0x01; //取数据的最低位  低位在前,高位在后

36.  _nop_();

37.  _nop_();  //给硬件反应时间

38.  SCLK=1;  //正跳变写数据

39.  _nop_();

40.  _nop_();  //给硬件反应时间

41.  SCLK=0;  //重新拉低SCLK,形成脉冲

42.  dat>>=1;   //dat右移,为写入下位数据做准备

43.}

44.}

45./**************************

46.根据命令字,向1302写一个字节

47.**************************/

48.

49.void WriteSet1302(unsigned char cmd, unsigned char dat)

50.{

51.  RST=0;          //禁止数据传输   .!!!这条很重要

52.  SCLK=0;      //确保写数据前SCLK为低电平

53.  RST=1;  //开启数据传输       

54.  _nop_();

55.  _nop_();

56.  Write1302(cmd);

57.  Write1302(dat);

58.  SCLK=1;   // 将时钟电平置于高电平状态 ,处于已知状态

59.  RST=0;

60.}

61./**************************

62.向1302读一个字节

63.**************************/

64.

65.unsigned char Read1302()

66.{

67.unsigned char i,dat=0;

68.for(i=0;i<8;i++){

69.  dat>>=1;

70.  if(DATA==1)  //如果读出的数据是1

71.   dat|=0x80;   //将1取出,写在dat的最高位

72.  SCLK=1;      //将SCLK置于高电平,为下降沿读出

73.  _nop_();

74.  _nop_();

75.  SCLK=0;   //拉低SCLK,形成脉冲下降沿

76.}

77.return dat;

78.}

79.

80./**************************

81.根据命令字.向1302读一个字节

82.**************************/

83.

84.unsigned char ReadSet1302(unsigned char cmd)

85.{

86.unsigned char dat;

87.    RST=0;    //这条很重要

88.SCLK=0;   //确保写数居前SCLK被拉低

89.RST=1;    //启动数据传输

90._nop_();

91._nop_();

92.Write1302(cmd);  //写入命令字

93.dat=Read1302();   //读出数据

94.SCLK=1;     //将时钟电平置于已知状态

95.RST=0;      //禁止数据传递

96.return dat;    //将读出的数据返回

97.}

98./**************************

99.初始化1302

100.**************************/

101.

102.void DS1302_Int()

103.{

104.

105.WriteSet1302(0x8E,0x00);                 //根据写状态寄存器命令字,写入不保护指令

106.    WriteSet1302(0x80,((55/10)<<4|(55%10)));   //根据写秒寄存器命令字,写入秒的初始值

107.WriteSet1302(0x82,((59/10)<<4|(59%10)));   //根据写分寄存器命令字,写入分的初始值

108.WriteSet1302(0x84,((23/10)<<4|(23%10))); //根据写小时寄存器命令字,写入小时的初始值

109.WriteSet1302(0x86,((18/10)<<4|(18%10))); //根据写日寄存器命令字,写入日的初始值

110.WriteSet1302(0x88,((6/10)<<4|(6%10))); //根据写月寄存器命令字,写入月的初始值

111.WriteSet1302(0x8c,((9/10)<<4|(9%10)));   //根据写年寄存器命令字,写入年的初始值

112.WriteSet1302(0x90,0xa5);                //打开充电功能 选择2K电阻充电方式

113.WriteSet1302(0x8E,0x80);              //根据写状态寄存器命令字,写入保护指令

114.}

115.

116.

117.

118.

119./***************************

120.以下是液晶模块

121.***************************/

122.

123./***************************

124.忙信号检测

125.***************************/

126.

127.bit BusyTest()

128.{

129.bit result;

130.RS=0;   //根据规定,RS为低电平,RW为高电平时,可以读状态

131.RW=1;

132.E=1;

133._nop_();

134._nop_();

135.result=BF;     //将忙碌标志电平赋给result

136.E=0;     //将E恢复低电平

137._nop_();

138._nop_();

139.return result;

140.

141.}

142.

143./***************************

144.将模式设置指令或显示地址送入LCD

145.***************************/

146.

147.void WriteInstruction(unsigned char dictate)

148.{

149.while(BusyTest()==1);     //如果忙就等待

150.RS=0;      //根据规定,RS和R/W同时为低电平时,可以写入指令

151.RW=0;

152.E=0;       //E置低电平(写指令时,E为高脉冲,

153.                           // 就是让E从0到1发生正跳变,所以应先置0

154._nop_();

155._nop_();

156.P0=dictate;

157._nop_();

158._nop_();

159._nop_();

160._nop_();

161.E=1;     //E置高电平

162._nop_();

163._nop_();

164._nop_();

165._nop_();

166.E=0;       //当E由高电平跳变成低电平时,液晶模块开始执行命令

167.}

168.

169.

170./***************************

171.设定字符显示位置

172.***************************/

173.

174.void WriteAddress(unsigned char x)

175.{

176.     WriteInstruction(x|0x80); //显示位置的确定方法规定为80H+地址码x

177.}

178./***************************

179.向LCD写数据

180.***************************/

181.

182.void WriteData(unsigned char dat)

183.{

184.while(BusyTest()==1);    //如果忙就等待

185.RS=1;        //RS为高电平,RW为低电平时,可以写入数据

186.RW=0;

187.E=0;        //E置低电平(写指令时,E为高脉冲,

188.                     // 就是让E从0到1发生正跳变,所以应先置0

189._nop_();

190._nop_();

191.P0=dat;     //将数据送入P0口,即将数据写入液晶模块

192._nop_();

193._nop_();

194._nop_();

195._nop_();

196.E=1;       //E置高电平

197._nop_();

198._nop_();

199._nop_();

200._nop_();

201.E=0;   //当E由高电平跳变成低电平时,液晶模块开始执行命令

202.}

203.

204.

205./***************************

206.初始化LCD

207.***************************/

208.

209.void LCD_Int()

210.{

211.delay1ms(15);      //延时15ms,首次写指令时应给LCD一段较长的反应时间

212.WriteInstruction(0x38);     //显示模式设置:16×2显示,5×7点阵,8位数据接口

213.delay1ms(5);

214.WriteInstruction(0x38);

215.delay1ms(5);

216.WriteInstruction(0x38);

217.delay1ms(5);     //连续三次,确保初始化成功

218.WriteInstruction(0x0c);  //显示模式设置:显示开,无光标,光标不闪烁

219.delay1ms(5);

220.WriteInstruction(0x06);    //显示模式设置:光标右移,字符不移

221.delay1ms(5);

222.WriteInstruction(0x01);     //清屏幕指令,将以前的显示内容清除

223.delay1ms(5);

224.}

225.

226.

227./***************************

228.以下是1302的显示程序

229.***************************/

230.

231.void DisplaySecond(unsigned char x)

232.{

233.unsigned char i,j;   //i,j分别储存十位和个位

234.    i=x/10;

235.j=x%10;

236.WriteAddress(0x49);

237.WriteData(digit[i]);

238.WriteData(digit[j]);

239.delay1ms(15);

240.}

241.

242.void DisplayMinute(unsigned char x)

243.{

244.unsigned char i,j;

245.    i=x/10;

246.j=x%10;

247.WriteAddress(0x46);

248.WriteData(digit[i]);

249.WriteData(digit[j]);

250.delay1ms(15);

251.}

252.

253.void DisplayHour(unsigned char x)

254.{

255.unsigned char i,j;

256.    i=x/10;

257.j=x%10;

258.WriteAddress(0x43);

259.WriteData(digit[i]);

260.WriteData(digit[j]);

261.delay1ms(15);

262.}

263.

264.void DisplayDay(unsigned char x)

265.{

266.unsigned char i,j;

267.    i=x/10;

268.j=x%10;

269.WriteAddress(0x0c);

270.WriteData(digit[i]);

271.WriteData(digit[j]);

272.delay1ms(15);

273.}

274.

275.void DisplayMonth(unsigned char x)

276.{

277.unsigned char i,j;

278.    i=x/10;

279.j=x%10;

280.WriteAddress(0x09);

281.WriteData(digit[i]);

282.WriteData(digit[j]);

283.delay1ms(15);

284.}

285.

286.void DisplayYear(unsigned char x)

287.{

288.unsigned char i,j;

289.    i=x/10;

290.j=x%10;

291.WriteAddress(0x06);

292.WriteData(digit[i]);

293.WriteData(digit[j]);

294.delay1ms(15);

295.}

296.

297./*******************************

298.主函数

299.*******************************/

300.

301.void main()

302.{

303.unsigned char second,minute,hour,day,month,year;     //分别储存苗、分、小时,日,月,年

304.unsigned char ReadValue;        //储存从1302读取的数据

305.LCD_Int();     //将液晶初始化

306.WriteAddress(0x01);   //写Date的显示地址,将在第1行第2列开始显示

307.WriteData('D');

308.WriteData('a');

309.WriteData('t');

310.WriteData('e');

311.WriteData(':');

312.WriteAddress(0x08);

313.WriteData('-');

314.WriteAddress(0x0b);

315.WriteData('-');

316.WriteAddress(0x45);

317.WriteData(':');

318.WriteAddress(0x48);

319.WriteData(':');

320.DS1302_Int();            //将1302初始化

321.while(1){

322.  ReadValue = ReadSet1302(0x81);   //从秒寄存器读数据

323.        second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//将读出数据转化

324.     DisplaySecond(second);          //显示秒

325.     ReadValue = ReadSet1302(0x83);  //从分寄存器读

326.        minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化

327.     DisplayMinute(minute);        //显示分

328.        ReadValue = ReadSet1302(0x85);  //从分寄存器读

329.        hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化

330.     DisplayHour(hour);              //显示小时

331.        ReadValue = ReadSet1302(0x87);  //从分寄存器读

332.        day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化

333.     DisplayDay(day);                //显示日

334.     ReadValue = ReadSet1302(0x89);  //从分寄存器读

335.        month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化

336.     DisplayMonth(month);            //显示月

337.     ReadValue = ReadSet1302(0x8d);  //从分寄存器读

338.        year=((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F); //将读出数据转化

339.     DisplayYear(year);              //显示年

340.}

341.}