MSP430:实时时钟-DS1302
2017-11-03 来源:eefocus
1 /*
2 * DS1302.h
3 *
4 * Created on: 2013-11-27
5 * Author: Allen
6 */
7
8 #ifndef DS1302_H_
9 #define DS1302_H_
10
11 #include
12 #include 'MyType.h'
13
14 //时间结构体
15 typedef struct
16 {
17 uchar year; //00-99,前面自己加入20,比如读出13为2013
18 uchar month;
19 uchar date;
20 uchar hour;
21 uchar min;
22 uchar sec;
23 uchar week;
24 }_calendar_obj;
25
26 extern _calendar_obj calendar; //日历结构体
27
28 #define delay_time 0
29 //DS1302地址定义
30 #define ds1302_sec_add 0x80 //秒数据地址
31 #define ds1302_min_add 0x82 //分数据地址
32 #define ds1302_hr_add 0x84 //时数据地址
33 #define ds1302_date_add 0x86 //日数据地址
34 #define ds1302_month_add 0x88 //月数据地址
35 #define ds1302_day_add 0x8a //星期数据地址
36 #define ds1302_year_add 0x8c //年数据地址
37 #define ds1302_control_add 0x8e //控制数据地址
38 #define ds1302_charger_add 0x90
39 #define ds1302_clkburst_add 0xbe
40
41 //SCLK:P2.3
42 #define SCLK_DIR (P2DIR)
43 #define SCLK_OUT (P2OUT)
44 #define SCLK_REN (P2REN)
45 #define SCLK_PIN (BIT3)
46
47 #define SCLK_UP (Set_Bit(SCLK_REN,SCLK_PIN))
48 #define SCLK_DirOut (Set_Bit(SCLK_DIR,SCLK_PIN))
49 #define SCLK_H (Set_Bit(SCLK_OUT,SCLK_PIN))
50 #define SCLK_L (Clr_Bit(SCLK_OUT,SCLK_PIN))
51
52
53 //DS_SDA:P2.4
54 #define IO_DIR (P2DIR)
55 #define IO_OUT (P2OUT)
56 #define IO_IN (P2IN)
57 #define IO_REN (P2REN)
58 #define IO_PIN (BIT4)
59
60 #define IO_UP (Set_Bit(IO_REN,IO_PIN))
61 #define IO_DirOut (Set_Bit(IO_DIR,IO_PIN))
62 #define IO_H (Set_Bit(IO_OUT,IO_PIN))
63 #define IO_L (Clr_Bit(IO_OUT,IO_PIN))
64
65
66 #define IO_DirIn (Clr_Bit(IO_DIR,IO_PIN))
67 #define IO_Data (Get_Bit(IO_IN,IO_PIN))
68
69 //RST:P2.5
70 #define RST_DIR (P2DIR)
71 #define RST_OUT (P2OUT)
72 #define RST_IN (P2IN)
73 #define RST_REN (P2REN)
74 #define RST_PIN (BIT5)
75
76 #define RST_UP (Set_Bit(RST_REN,RST_PIN))
77 #define RST_DirOut (Set_Bit(RST_DIR,RST_PIN))
78 #define RST_H (Set_Bit(RST_OUT,RST_PIN))
79 #define RST_L (Clr_Bit(RST_OUT,RST_PIN))
80
81
82 void DS1302_Init(void);
83 static void delay_us( unsigned int k );
84 void ds1302_write_byte(uchar addr, uchar data);
85 uchar ds1302_read_byte(uchar addr);
86 void ds1302_write_time(uchar year,uchar month,uchar day,uchar hour,uchar min,uchar sec,uchar week);
87 void ds1302_read_time(void);
88 void ds1302_sendtime_uart(void);
89
90 #endif
1 /*
2 * DS1302.c
3 *
4 * Created on: 2013-11-29
5 * Author: Allen
6 */
7
8 #include 'DS1302.h'
9 #include
10 #include 'uart.h'
11
12 _calendar_obj calendar;
13
14 void DS1302_Init(void)
15 {
16 SCLK_DirOut;
17 RST_DirOut;
18 IO_DirOut;
19 SCLK_L;
20 RST_L;
21 delay_us(10);
22 SCLK_H;
23 }
24
25
26 static void delay_us( unsigned int k )
27 {
28 while(k--)
29 _nop();
30
31 }
32
33 //向DS1302写入一字节数据
34 void ds1302_write_byte(uchar addr, uchar data)
35 {
36 uchar i;
37 IO_DirOut;
38 RST_H; //启动DS1302总线
39 //写入目标地址:addr
40 addr = addr & 0xFE; //最低位置零,寄存器0位为0时写,为1时读
41 for (i = 0; i < 8; i ++) {
42 if (addr & 0x01) {
43 IO_H;
44 }
45 else {
46 IO_L;
47 }
48 SCLK_H; //产生时钟
49 delay_us(delay_time);
50 SCLK_L;
51 delay_us(delay_time);
52 addr = addr >> 1;
53 }
54 //写入数据:d
55 for (i = 0; i < 8; i ++) {
56 if (data & 0x01) {
57 IO_H;
58 }
59 else {
60 IO_L;
61 }
62 SCLK_H; //产生时钟
63 delay_us(delay_time);
64 SCLK_L;
65 delay_us(delay_time);
66 data = data >> 1;
67 }
68 RST_L; //停止DS1302总线
69 }
70
71 //从DS1302读出一字节数据
72 uchar ds1302_read_byte(uchar addr)
73 {
74
75 uchar i,temp;
76 RST_H; //启动DS1302总线
77 //写入目标地址:addr
78 addr = addr | 0x01; //最低位置高,寄存器0位为0时写,为1时读
79 IO_DirOut;
80 for (i = 0; i < 8; i ++)
81 {
82 if (addr & 0x01)
83 {
84 IO_H;
85 }
86 else
87 {
88 IO_L;
89 }
90 SCLK_H; //产生时钟
91 delay_us(delay_time);
92 SCLK_L;
93 delay_us(delay_time);
94 addr = addr >> 1;
95 }
96 //输出数据:temp
97 IO_DirIn;
98 for (i = 0; i < 8; i ++)
99 {
100 temp = temp >> 1;
101 if (IO_Data)
102 // if( P2IN & BIT4)
103 {
104 temp |= 0x80;
105 }
106 else
107 {
108 temp &= 0x7F;
109 }
110 SCLK_H; //产生时钟
111 delay_us(delay_time);
112 SCLK_L;
113 delay_us(delay_time);
114 }
115 RST_L; //停止DS1302总线
116 return temp;
117 }
118
119 //向DS302写入时钟数据
120 void ds1302_write_time(uchar year,uchar month,uchar day,uchar hour,uchar min,uchar sec,uchar week)
121 {
122 uchar temp=0;
123 ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
124 ds1302_write_byte(ds1302_sec_add,0x80); //暂停时钟
125 //ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电
126
127 temp=(year/10<<4)|(year%10&0x0F);
128 ds1302_write_byte(ds1302_year_add,119); //年
129
130 temp=(month/10<<4)|(month%10&0x0F);
131 ds1302_write_byte(ds1302_month_add,temp); //月
132
133 temp=(day/10<<4)|(day%10&0x0F);
134 ds1302_write_byte(ds1302_date_add,temp); //日
135
136 temp=((hour/10<<4)|(hour%10&0x0F))&0x3F;
137 ds1302_write_byte(ds1302_hr_add,temp); //时
138
139 temp=(min/10<<4)|(min%10&0x0F);
140 ds1302_write_byte(ds1302_min_add,temp); //分
141
142 temp=(sec/10<<4)|(sec%10&0x0F);
143 temp=temp&0x7f;
144 ds1302_write_byte(ds1302_sec_add,temp); //秒
145
146 temp=week;
147 ds1302_write_byte(ds1302_day_add,temp); //周
148
149 ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
150 }
151
152 //从DS302读出时钟数据
153 void ds1302_read_time(void)
154 {
155 uchar temp=0;
156
157 temp=ds1302_read_byte(ds1302_year_add);//年
158 calendar.year=(temp>>4)*10+temp&0x0F; //年
159
160 temp=ds1302_read_byte(ds1302_month_add);//月
161 calendar.month=(temp>>4)*10+temp&0x0F; //月
162
163 temp=ds1302_read_byte(ds1302_date_add);//日
164 calendar.date=((temp&0x70)>>4)*10 + (temp&0x0F); //日
165
166 temp=ds1302_read_byte(ds1302_hr_add);//时
167 calendar.hour=((temp&0x70)>>4)*10 + (temp&0x0F);
168
169 temp=ds1302_read_byte(ds1302_min_add); //分
170 calendar.min=((temp&0x70)>>4)*10 + (temp&0x0F); //分
171
172 temp=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59,此位控制时钟是否开启
173 calendar.sec=((temp&0x70)>>4)*10 + (temp&0x0F);//秒,屏蔽秒的第7位,避免超出59
174
175 temp=ds1302_read_byte(ds1302_day_add); //周
176 calendar.week=(temp>>4)*10+temp&0x0F; //周
177 }
178
179 void ds1302_sendtime_uart(void)
180 {
181
182 uart_send_ch(calendar.year/10+'0');
183 uart_send_ch(calendar.year%10+'0');
184 uart_send_ch('-');
185 uart_send_ch(calendar.month/10+'0');
186 uart_send_ch(calendar.month%10+'0');
187 uart_send_ch('-');
188 uart_send_ch(calendar.date/10+'0');
189 uart_send_ch(calendar.date%10+'0');
190 uart_send_ch(' ');
191
192 uart_send_ch(calendar.hour/10+'0');
193 uart_send_ch(calendar.hour%10+'0');
194 uart_send_ch(':');
195 uart_send_ch(calendar.min/10+'0');
196 uart_send_ch(calendar.min%10+'0');
197 uart_send_ch(':');
198 uart_send_ch(calendar.sec/10+'0');
199 uart_send_ch(calendar.sec%10+'0');
200
201 uart_send_ch(' ');
202 uart_send_ch(calendar.week/10+'0');
203 uart_send_ch(calendar.week%10+'0');
204
205 uart_send_ch('\n');
206 }
运行很简单:
main:
DS1302_Init();
ds1302_write_time(13,12,1,20,33,23,7);
ds1302_read_time();
ds1302_sendtime_uart();
注意:年份不需要20,只写后面两位,范围00-99,所以年份范围是2000-2099
如果需要读出时间:
ds1302_read_time();
ds1302_sendtime_uart();
还是很好操作的,两个电源pin角,电池以及外接直流。
至于寄存器,时钟,细看SPEC吧
这里采取24小时制式。