DS1302的STM32F103c8t6驱动程序(附代码亲测可用)
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时钟模块程序(稳定并且有详细代码注释)