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.}