2020-09-27 15:27:37
使用的DS1302模塊:


DS1302是美國DALLAS公司推出的一種高性能、低功耗的實時時鍾芯片,附加31字節靜態RAM,采用三線接口與CPU進行同步通信,並可采用突發方式一次傳送多個字節的時鍾信號和RAM數據。實時時鍾可提供秒、分、時、日、星期、月和年,一個月小與31天時可以自動調整,且具有閏年補償功能。工作電壓寬達2.5~5.5V。采用雙電源供電(主電源和備用電源),可設置備用電源充電方式,提供了對后背電源進行涓細電流充電的能力。DS1302的外部引腳分配如下圖所示。DS1302用於數據記錄,特別是對某些具有特殊意義的數據點的記錄上,能實現數據與出現該數據的時間同時記錄,因此廣泛應用於測量系統中。


DS1302的一條指令一個字節8位,其中第七位(即最高位)是固定1,這一位如果是0的話,那寫進去是無效的。第六位是選擇RAM還是CLOCK的,我前邊說過,我們這里主要講CLOCK時鍾的使用,它的RAM功能我們不用,所以如果選擇CLOCK功能,第六位是0,如果要用RAM,那第六位就是1。從第五到第一位,決定了寄存器的5位地址,而第零位是讀寫位,如果要寫,這一位就是0,如果要讀,這一位就是1,如圖15-9所示。
DS1302時鍾的寄存器,其中8個和時鍾有關的,5位地址分別是00000一直到00111這8個地址,還有一個寄存器的地址是01000,這是涓流充電所用的寄存器,我們這里不講。在DS1302的數據手冊里的地址,直接把第七位、第六位和第零位值給出來了,所以指令就成了80H、81H那些了,最低位是1,那么表示讀,最低位是0表示寫,如圖15-10所示。
寄存器一:最高位CH是一個時鍾停止標志位。如果我們的時鍾電路有備用電源部分,上電后,我們要先檢測一下這一位,如果這一位是0,那說明我們的時鍾在系統掉電后,由於備用電源的供給,時鍾是持續正常運行的;如果這一位是1,那么說明我們的時鍾在系統掉電后,時鍾部分不工作了。若我們的Vcc1懸空或者是電池沒電了,當我們下次重新上電時,讀取這一位,那這一位就是1,我們可以通過這一位判斷時鍾在單片機系統掉電后是否持續運行。剩下的7位高3位是秒的十位,低4位是秒的個位,這里注意再提一次,DS1302內部是BCD碼,而秒的十位最大是5,所以3個二進制位就夠了。
寄存器二:bit7沒意義,剩下的7位高3位是分鍾的十位,低4位是分鍾的個位。
寄存器三:bit7是1的話代表是12小時制,是0的話代表是24小時制,bit6固定是0,bit5在12小時制下0代表的是上午,1代表的是下午,在24小時制下和bit4一起代表了小時的十位,低4位代表的是小時的個位。
寄存器四:高2位固定是0,bit5和bit4是日期的十位,低4位是日期的個位。
寄存器五:高3位固定是0,bit4是月的十位,低4位是月的個位。
寄存器六:高5位固定是0,低3位代表了星期。
寄存器七:高4位代表了年的十位,低4位代表了年的個位。這里特別注意,這里的00到99年指的是2000年到2099年。
寄存器八:bit7是一個保護位,如果這一位是1,那么是禁止給任何其他的寄存器或者那31個字節的RAM寫數據的。因此在寫數據之前,這一位必須先寫成0。
寄存器二:bit7沒意義,剩下的7位高3位是分鍾的十位,低4位是分鍾的個位。
寄存器三:bit7是1的話代表是12小時制,是0的話代表是24小時制,bit6固定是0,bit5在12小時制下0代表的是上午,1代表的是下午,在24小時制下和bit4一起代表了小時的十位,低4位代表的是小時的個位。
寄存器四:高2位固定是0,bit5和bit4是日期的十位,低4位是日期的個位。
寄存器五:高3位固定是0,bit4是月的十位,低4位是月的個位。
寄存器六:高5位固定是0,低3位代表了星期。
寄存器七:高4位代表了年的十位,低4位代表了年的個位。這里特別注意,這里的00到99年指的是2000年到2099年。
寄存器八:bit7是一個保護位,如果這一位是1,那么是禁止給任何其他的寄存器或者那31個字節的RAM寫數據的。因此在寫數據之前,這一位必須先寫成0。
可用代碼:
DS1302.c:
1 #include"DS1302.h" 2 3 /***************************************** 4 * 函數名:void DS1302_GPIOInit(void) 5 * 描述 : DS1302 GPIO配置 6 * 輸入 : 7 * 輸出 :無 8 * 調用 : 9 CLK---PB5, 10 IO--->PB6, 11 RES--->PB7, 12 *************************************/ 13 void DS1302_GPIOInit(void) 14 { 15 GPIO_InitTypeDef GPIO_InitStructre; 16 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); /*open GPIO clock*/ 17 GPIO_InitStructre.GPIO_Pin= GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; 18 GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz; 19 GPIO_InitStructre.GPIO_Mode=GPIO_Mode_Out_PP; 20 GPIO_Init(DS1302_PORT, &GPIO_InitStructre); 21 } 22 /***************************************** 23 * 函數名:void DS1302_IO_GPIO(void) 24 * 描述 : DS1302 之 IO GPIO 輸入輸出配置 25 * 輸入 :FLAG標志位 26 * 輸出 :無 27 * 調用 :OUT:表示輸出,IN:表示輸入 28 FLAG: 29 *************************************/ 30 void DS1302_IO_GPIO(uchar FLAG) 31 { 32 GPIO_InitTypeDef GPIO_InitStructre; 33 //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); /*open GPIO clock*/ 34 /**********配置數據IO端口 輸出 **********/ 35 if(FLAG==0x01) 36 { 37 GPIO_InitStructre.GPIO_Pin= GPIO_Pin_6;//配置IO_GPIO 38 GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz; 39 GPIO_InitStructre.GPIO_Mode=GPIO_Mode_Out_PP; 40 GPIO_Init(DS1302_PORT, &GPIO_InitStructre); 41 } 42 /**********配置數據IO端口 輸入**********/ 43 else if(FLAG==0x00) 44 { 45 GPIO_InitStructre.GPIO_Pin= GPIO_Pin_6;//配置IO_GPIO 46 GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz; 47 GPIO_InitStructre.GPIO_Mode=GPIO_Mode_IPU; //配置上拉輸入 48 GPIO_Init(DS1302_PORT, &GPIO_InitStructre); 49 } 50 } 51 /***************************************** 52 * 函數名:void DS1302_delay(u8 dd) 53 * 描述 :簡單延時 54 * 輸入 : 55 * 輸出 :無 56 * 調用 : 57 *************************************/ 58 void DS1302_delay(u8 dd) 59 { 60 u8 i; 61 for(;dd>0;dd--) 62 for(i=110;i>0;i--); 63 } 64 65 /***************************************** 66 * 函數名:void DS1302_Write(uchar add,uchar dat) 67 * 描述 :DS1302寫指令和數據 68 * 輸入 :add:發送地址,dat:所在數據 69 * 輸出 :無 70 * 調用 : 71 *************************************/ 72 void DS1302_Write(uchar add,uchar dat) 73 { 74 uchar i,temp1,temp2; 75 temp1=add; 76 temp2=dat; 77 RES_Set_1;//RET=1; 78 //發送地址 79 for(i=0;i<8;i++) 80 { 81 if(temp1&0x01) 82 {IO_Set_1; } //IO=1; 83 else 84 { IO_Reset_0;} //IO=0; 85 temp1=temp1>>1; 86 CLK_Set_1; //CLK=1; 87 DS1302_delay(2); 88 CLK_Reset_0; //CLK=0; 89 } 90 91 //發送數據 92 for(i=0;i<8;i++) 93 { 94 /*IO=(temp2>>i)&0x01;這一句代替下面屏蔽的內容 */ 95 if(temp2&0x01) 96 {IO_Set_1; } //IO=1; 97 else 98 { IO_Reset_0;} //IO=0; 99 temp2=temp2>>1; 100 CLK_Set_1; //CLK=1; 101 DS1302_delay(2); 102 CLK_Reset_0; //CLK=0; 103 } 104 RES_Reset_0;// RET=0; 105 } 106 107 108 109 110 /***************************************** 111 * 函數名:uchar DS1302_Read(uchar add) 112 * 描述 :DS1302讀數據 113 * 輸入 :add:發送所在地址 114 * 輸出 : 115 * 調用 : 116 *************************************/ 117 uchar DS1302_Read(uchar add) 118 { 119 uchar i,suf,temp,mm,nn,value; 120 temp=add; 121 RES_Set_1;//RET=1; 122 //寫地址 123 for(i=0;i<8;i++) 124 { 125 if(temp&0x01) 126 {IO_Set_1; } //IO=1; 127 else 128 { IO_Reset_0;} //IO=0; 129 temp=temp>>1; 130 CLK_Set_1; //CLK=1; 131 DS1302_delay(2); 132 CLK_Reset_0; //CLK=0; 133 } 134 //讀數據 135 136 DS1302_IO_GPIO(IN);//配置IO為輸入 137 for(i=0;i<8;i++) 138 { 139 suf=suf>>1;//讀數據變量 140 if(IO_Read) //IO=1 141 { 142 suf=suf|0x80; 143 } 144 else //IO=0 145 { 146 suf=suf&0x7f; 147 } 148 149 CLK_Set_1; //CLK=1; 150 DS1302_delay(2); 151 CLK_Reset_0; //CLK=0; 152 } 153 RES_Reset_0; // RET=0; 154 155 DS1302_IO_GPIO(OUT);//配置IO為輸出,恢復正常狀態 156 //數據處理轉化十進制 157 mm=suf/16; 158 nn=suf%16; 159 value=mm*10+nn; 160 return value; 161 } 162 /***************************************** 163 * 函數名:void DS1302_SetTime(uchar *ad) 164 * 描述 :DS1302 寫入設置時間 165 * 輸入 :add:發送所在地址 166 * 輸出 : 167 * 調用 : 168 *************************************/ 169 void DS1302_SetTime(uchar *ad) 170 { 171 DS1302_Write(0x8e,0x00); //WP=0 允許數據寫入DS1302 172 /**********以下對時分秒的初始化*************/ 173 DS1302_Write(ds1302_sec_addr,ad[5]); //秒 174 DS1302_Write(ds1302_min_addr,ad[4]); //分 175 DS1302_Write(ds1302_hour_addr,ad[3]); //時 176 /**********以下對年月日的初始化*************/ 177 DS1302_Write(ds1302_day_addr,ad[2]); 178 DS1302_Write(ds1302_month_addr,ad[1]); 179 DS1302_Write(ds1302_year_addr,ad[0]); 180 181 DS1302_Write(0x8e,0x80); //0x8e控制字節地址,bit7=WP WP=1 禁止數據寫入DS1302 182 } 183 184 185 /***************************************** 186 * 函數名: void DS1302_OFF(void) 187 * 描述 :DS1302時間禁止走時 188 * 輸入 : 189 * 輸出 : 190 * 調用 : 191 *************************************/ 192 void DS1302_OFF(void) 193 { 194 uchar temp; 195 temp=DS1302_Read(0x81);//讀取表地址時間 196 DS1302_Write(0x8e,0x00);//WP=0 允許數據寫入DS1302 197 temp=temp|(1<<7); 198 DS1302_Write(0x80,temp);//WP=1 禁止數據寫入DS1302 199 200 } 201 /***************************************** 202 * 函數名: void DS1302_ON(void) 203 * 描述 :DS1302時間開始運行,走時 204 * 輸入 : 205 * 輸出 : 206 * 調用 : 207 *************************************/ 208 void DS1302_ON(void) 209 { 210 uchar temp; 211 temp=DS1302_Read(0x81); 212 DS1302_Write(0x8e,0x00);//WP=0 允許數據寫入DS1302 213 temp=temp|(0<<7); 214 DS1302_Write(0x80,temp);//WP=0 允許數據寫入DS1302 215 216 } 217 218 219 220 221 222 223 /***************************************** 224 * 函數名:void DS1302_init(uchar *time) 225 * 描述 : DS1302初始化 226 * 輸入 :無 227 * 輸出 :無 228 * 調用 : 229 *************************************/ 230 void DS1302_init(uchar *time) 231 { 232 DS1302_GPIOInit();//GPIO初始化配置 233 DS1302_delay(2); 234 RES_Reset_0; //RET=0; 235 CLK_Reset_0;// CLK=0; 236 //下面是對DS1302啟動電池,不掉電 設置時間 237 DS1302_Write(0x8e,0x00);//WP=0 允許數據寫入DS1302 238 DS1302_Write(0x90,0xA7);//充電(1個二極管+8K電阻) 239 DS1302_Write(0x8E,0X80);//開啟保護 WP=1 240 if(DS1302_Read(0X81)&0X80)//查詢DS302時鍾是否啟動,如果時鍾停止走動:啟動時鍾+初始化時鍾 241 { 242 DS1302_SetTime(time);//設置設置初始時鍾 243 } 244 //否則跳過 245 246 } 247 /***************************************** 248 * 函數名:void DS1302_Readtime(void) 249 * 描述 : DS1302時間讀出 250 * 輸入 :無 251 * 輸出 :無 252 * 調用 : 253 *************************************/ 254 void DS1302_Readtime(void) 255 { 256 label2[0]=DS1302_Read( 0x8D)/10; //年:十位 257 label2[1]=DS1302_Read( 0x8D)%10; //年:個位 258 label2[2]='/'; 259 label2[3]=DS1302_Read( 0x89)/10; //月 : 260 label2[4]=DS1302_Read( 0x89)%10; //月 : 261 label2[5]='/'; 262 label2[6]=DS1302_Read( 0x87)/10; //日 263 label2[7]=DS1302_Read( 0x87)%10; //日 264 label2[8]=DS1302_Read( 0x85)/10; //時 265 label2[9]=DS1302_Read( 0x85)%10; //時 266 label2[10]=':'; 267 label2[11]=DS1302_Read( 0x83)/10; //讀分 268 label2[12]=DS1302_Read( 0x83)%10; //讀分 269 label2[13]=':'; 270 label2[14]=DS1302_Read( 0x81)/10; //讀秒 271 label2[15]=DS1302_Read( 0x81)%10; //讀秒 272 }
DS1302.h:
1 #ifndef __DS1302_H__ 2 #define __DS1302_H__ 3 #include <stm32f10x.h> 4 #define uchar unsigned char 5 #define uint unsigned int 6 /***DS1302時鍾芯片****************************/ 7 //CLK--->PB5 8 //IO---->PB6 9 //RES--->PB7 10 /****************************/ 11 12 #define OUT 0x01 13 #define IN 0x00 14 extern uchar label2[16];//時間存放數組 15 //extern uchar Settime[6]={0x17,0x04,0x18,0x16,0x57,0x30}; //設置時間函數 16 #define DS1302_PORT GPIOB 17 18 #define CLK_Reset_0 GPIOB->BRR=GPIO_Pin_5 19 #define CLK_Set_1 GPIOB->BSRR=GPIO_Pin_5 20 21 #define IO_Reset_0 GPIOB->BRR=GPIO_Pin_6 22 #define IO_Set_1 GPIOB->BSRR=GPIO_Pin_6 23 24 #define RES_Reset_0 GPIOB->BRR=GPIO_Pin_7 25 #define RES_Set_1 GPIOB->BSRR=GPIO_Pin_7 26 27 #define IO_Read GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6) 28 /*************************/ 29 #define Time_24_Hour 0x00 //24小時制 30 #define Time_Start 0x00 //開始走時 31 //DS1302寄存器操作指令定義時間地址 32 #define ds1302_sec_addr 0x80 //秒 33 #define ds1302_min_addr 0x82 //分 34 #define ds1302_hour_addr 0x84 //時 35 #define ds1302_day_addr 0x86 //日 36 #define ds1302_month_addr 0x88 //月 37 #define ds1302_year_addr 0x8c //年 38 /********************/ 39 void DS1302_GPIOInit(void); 40 void DS1302_IO_GPIO(uchar FLAG);//配置IO的方向 41 void DS1302_delay(u8 dd); 42 void DS1302_Write(uchar add,uchar dat); 43 uchar DS1302_Read(uchar add); 44 void DS1302_SetTime(uchar *ad); 45 void DS1302_OFF(void); 46 void DS1302_ON(void); 47 void DS1302_init(uchar *time); 48 void DS1302_Readtime(void); 49 50 51 52 #endif
main.c:
1 #include "stm32f10x.h" 2 #include "led.h" 3 #include "key.h" 4 #include "usart1.h" 5 #include "delay.h" 6 #include "DS1302.h" 7 8 #define AHB_INPUT 72 9 10 unsigned char uart1_buf[11]={0}; 11 volatile u32 time; // ms 計時變量 12 13 u16 t=0,mode=0,flag=0; 14 u8 label2[16]; //時間存放數組顯示格式 15 u8 Settime[6]={0x20,0x09,0x16,0x20,0x59,0x50}; // 初始時間設置: 年 月 日 時 分 秒 16 17 int main(void) 18 { 19 int tt = 0; 20 21 SystemInit(); // 配置系統時鍾為72M 22 delay_init(); 23 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置完中斷向量表以后才能初始化其他東西 24 uart_init(9600); 25 26 TIM2_NVIC_Configuration(); // TIM2 定時配置 27 TIM2_Configuration(); 28 START_TIME; // TIM2 開始計時 29 30 DS1302_init(Settime); //時間初始化 31 DS1302_SetTime(Settime); //設置初始時間 32 33 34 while(1) 35 { 36 tt++; 37 if(tt>=3200000) 38 { 39 tt = 0; 40 DS1302_Readtime(); 41 printf("%lld,",num); 42 printf("20"); 43 printf("%d",label2[0]); 44 printf("%d",label2[1]); 45 printf("%c",label2[2]); 46 printf("%d",label2[3]); 47 printf("%d",label2[4]); 48 printf("%c",label2[5]); 49 printf("%d",label2[6]); 50 printf("%d, ",label2[7]); 51 52 printf("%d",label2[8]); 53 printf("%d",label2[9]); 54 printf("%c",label2[10]); 55 printf("%d",label2[11]); 56 printf("%d",label2[12]); 57 printf("%c",label2[13]); 58 printf("%d",label2[14]); 59 printf("%d, ",label2[15]); 60 printf("%.2f, %.2f ",PM25,PM10); 61 printf("%c",0x0d); 62 printf("%c",0x0a); 63 } 64 65 } 66 }
參考:
STM32之DS1302時鍾模塊程序(穩定並且有詳細代碼注釋)
