DS1302.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "ds1302.h"
  2. static void DS1302_WriteByte(uint8_t addr,uint8_t data);
  3. static uint8_t DS1302_ReadByte(uint8_t addr);
  4. static void DS1302_Init(void);
  5. static void DS1302_SetTime(uint8_t *writeTime);
  6. static void DS1302_GetTime(DS1302TimeStruct *timeData);
  7. DS1302ClassStruct DS1302Class = {
  8. .Init = DS1302_Init,
  9. .SetTime = DS1302_SetTime,
  10. .GetTime = DS1302_GetTime
  11. };
  12. /*
  13. 初始时间定义{0x20,0x21,0x11,0x13,0x10,0x10,0x00,0x06};
  14. 初始时间2021年11月13号10点10分00秒 星期六
  15. */
  16. uint8_t time_buf[8] = {0x20};//初始时间
  17. uint8_t readtime[8] = {0x20};//当前时间
  18. //DS1302引脚定义,可根据实际情况自行修改端口定义
  19. #define DS1302_CLK_PORT GPIOA
  20. #define DS1302_CLK_CLK RCC_APB2Periph_GPIOA
  21. #define DS1302_CLK_PIN GPIO_Pin_4
  22. #define DS1302_DAT_PORT GPIOA
  23. #define DS1302_DAT_CLK RCC_APB2Periph_GPIOA
  24. #define DS1302_DAT_PIN GPIO_Pin_5
  25. #define DS1302_RST_PORT GPIOA
  26. #define DS1302_RST_CLK RCC_APB2Periph_GPIOA
  27. #define DS1302_RST_PIN GPIO_Pin_6
  28. // Pin0-7设置CRL寄存器 Pin8-15设置CRH寄存器 配置输入输出模式
  29. #define DS1302_DAT_OutPut_Mode() {DS1302_DAT_PORT->CRL &= 0xFF0FFFFF;DS1302_DAT_PORT->CRL |= 0x00300000;}
  30. #define DS1302_DAT_InPut_Mode() {DS1302_DAT_PORT->CRL &= 0xFF0FFFFF;DS1302_DAT_PORT->CRL |= 0x00400000;}
  31. //DS1302引脚输出输入
  32. #define DS1302_DAT_IN() GPIO_ReadInputDataBit(DS1302_DAT_PORT, DS1302_DAT_PIN)
  33. #define DS1302_CLK_0 DS1302_CLK_PORT->BSRR = (uint32_t)DS1302_CLK_PIN<<16 // 置0
  34. #define DS1302_CLK_1 DS1302_CLK_PORT->BSRR = (uint32_t)DS1302_CLK_PIN // 置1
  35. #define DS1302_DAT_0 DS1302_DAT_PORT->BSRR = (uint32_t)DS1302_DAT_PIN<<16 // 置0
  36. #define DS1302_DAT_1 DS1302_DAT_PORT->BSRR = (uint32_t)DS1302_DAT_PIN // 置1
  37. #define DS1302_RST_0 DS1302_RST_PORT->BSRR = (uint32_t)DS1302_RST_PIN<<16 // 置0
  38. #define DS1302_RST_1 DS1302_RST_PORT->BSRR = (uint32_t)DS1302_RST_PIN // 置1
  39. //DS1302地址定义
  40. #define DS1302_SEC_ADDR 0x80 //秒数据地址
  41. #define DS1302_MIN_ADDR 0x82 //分数据地址
  42. #define DS1302_HOUR_ADDR 0x84 //时数据地址
  43. #define DS1302_DAY_ADDR 0x86 //日数据地址
  44. #define DS1302_MONTH_ADDR 0x88 //月数据地址
  45. #define DS1302_WEEK_ADDR 0x8a //星期数据地址
  46. #define DS1302_YEAR_ADDR 0x8c //年数据地址
  47. #define DS1302_CONTROL_ADDR 0x8e //控制数据地址
  48. #define DS1302_CHARGER_ADDR 0x90 //充电功能地址
  49. #define DS1302_CLKBURST_ADDR 0xbe
  50. //向DS1302写入一字节数据
  51. static void DS1302_WriteByte(uint8_t addr,uint8_t data)
  52. {
  53. uint8_t i;
  54. DS1302_RST_0; //禁止数据传输 !!!这条很重要
  55. DS1302_CLK_0; //确保写数据前SCLK为低电平
  56. DS1302_RST_1; //启动DS1302总线
  57. DS1302_DAT_OutPut_Mode();
  58. addr=addr&0xFE; //最低位置零,寄存器0位为0时写,为1时读
  59. for(i=0;i<8;i++) //写入目标地址:addr
  60. {
  61. if (addr&0x01) DS1302_DAT_1;
  62. else DS1302_DAT_0;
  63. DS1302_CLK_1; //时钟上升沿写入数据
  64. DS1302_CLK_0;
  65. addr=addr>>1;
  66. }
  67. for (i=0;i<8;i++) //写入数据:data
  68. {
  69. if(data&0x01) DS1302_DAT_1;
  70. else DS1302_DAT_0;
  71. DS1302_CLK_1; //时钟上升沿写入数据
  72. DS1302_CLK_0;
  73. data = data >> 1;
  74. }
  75. DS1302_CLK_1; // 将时钟电平置于高电平状态 ,处于已知状态
  76. DS1302_RST_0; //停止DS1302总线
  77. }
  78. //从DS1302读出一字节数据
  79. static uint8_t DS1302_ReadByte(uint8_t addr)
  80. {
  81. uint8_t i,temp;
  82. DS1302_RST_0; //这条很重要
  83. DS1302_CLK_0; //先将SCLK置低电平,确保写数居前SCLK被拉低
  84. DS1302_RST_1; //启动DS1302总线
  85. DS1302_DAT_OutPut_Mode();
  86. //写入目标地址:addr
  87. addr=addr|0x01; //最低位置高,寄存器0位为0时写,为1时读
  88. for(i=0;i<8;i++)
  89. {
  90. if (addr&0x01) DS1302_DAT_1;
  91. else DS1302_DAT_0;
  92. DS1302_CLK_1; //写数据
  93. DS1302_CLK_0;
  94. addr = addr >> 1;
  95. }
  96. //从DS1302读出数据:temp
  97. DS1302_DAT_InPut_Mode();
  98. for(i=0;i<8;i++)
  99. {
  100. temp=temp>>1;
  101. if (DS1302_DAT_IN()) temp|=0x80;
  102. else temp&=0x7F;
  103. DS1302_CLK_1;
  104. DS1302_CLK_0;
  105. }
  106. DS1302_CLK_1; //将时钟电平置于已知状态
  107. DS1302_RST_0; //停止DS1302总线
  108. return temp;
  109. }
  110. /**
  111. * @brief DS1302引脚初始化
  112. * @param None
  113. * @retval None
  114. * @note None
  115. */
  116. static void DS1302_Init(void)
  117. {
  118. GPIO_InitTypeDef GPIO_InitStructure;
  119. RCC_APB2PeriphClockCmd(DS1302_CLK_CLK | DS1302_DAT_CLK | DS1302_RST_CLK, ENABLE);
  120. GPIO_InitStructure.GPIO_Pin=DS1302_CLK_PIN;
  121. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  122. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  123. GPIO_Init(DS1302_CLK_PORT,&GPIO_InitStructure);
  124. GPIO_InitStructure.GPIO_Pin=DS1302_RST_PIN;
  125. GPIO_Init(DS1302_RST_PORT,&GPIO_InitStructure);
  126. GPIO_InitStructure.GPIO_Pin=DS1302_DAT_PIN;
  127. GPIO_Init(DS1302_DAT_PORT,&GPIO_InitStructure);
  128. }
  129. /**
  130. * @brief 写入DS1302时间数据,初始化计时初值
  131. * @param None
  132. * @retval None
  133. * @note None
  134. */
  135. static void DS1302_SetTime(uint8_t *writeTime)
  136. {
  137. DS1302_WriteByte(DS1302_CONTROL_ADDR,0x00); //关闭写入
  138. DS1302_WriteByte(DS1302_SEC_ADDR,0x80); //暂停时钟
  139. //DS1302_WriteByte(DS1302_CHARGER_ADDR,0xa9); //涓流充电
  140. DS1302_WriteByte(DS1302_YEAR_ADDR,writeTime[1]); //年
  141. DS1302_WriteByte(DS1302_MONTH_ADDR,writeTime[2]); //月
  142. DS1302_WriteByte(DS1302_DAY_ADDR,writeTime[3]); //日
  143. DS1302_WriteByte(DS1302_HOUR_ADDR,writeTime[4]); //时
  144. DS1302_WriteByte(DS1302_MIN_ADDR,writeTime[5]); //分
  145. DS1302_WriteByte(DS1302_SEC_ADDR,writeTime[6]); //秒
  146. DS1302_WriteByte(DS1302_WEEK_ADDR,writeTime[7]); //周
  147. DS1302_WriteByte(DS1302_CHARGER_ADDR,0xA5);//打开充电功能 选择2K电阻充电方式
  148. DS1302_WriteByte(DS1302_CONTROL_ADDR,0x80);//打开写入
  149. }
  150. /**
  151. * @brief 获取DS1302时间数据
  152. * @param None
  153. * @retval None
  154. * @note None
  155. */
  156. static void DS1302_GetTime(DS1302TimeStruct *timeData)
  157. {
  158. uint8_t readtime[8] = {0x20};//当前时间
  159. readtime[1]=DS1302_ReadByte(DS1302_YEAR_ADDR); //年
  160. readtime[2]=DS1302_ReadByte(DS1302_MONTH_ADDR); //月
  161. readtime[3]=DS1302_ReadByte(DS1302_DAY_ADDR); //日
  162. readtime[4]=DS1302_ReadByte(DS1302_HOUR_ADDR); //时
  163. readtime[5]=DS1302_ReadByte(DS1302_MIN_ADDR); //分
  164. readtime[6]=(DS1302_ReadByte(DS1302_SEC_ADDR))&0x7f; //秒,屏蔽秒的第7位,避免超出59
  165. readtime[7]=DS1302_ReadByte(DS1302_WEEK_ADDR); //周
  166. timeData->year=(readtime[0]>>4)*1000+(readtime[0]&0x0F)*100+(readtime[1]>>4)*10+(readtime[1]&0x0F); //计算年份
  167. timeData->month=(readtime[2]>>4)*10+(readtime[2]&0x0F); //计算月份
  168. timeData->day=(readtime[3]>>4)*10+(readtime[3]&0x0F); //计算日期
  169. timeData->hour=(readtime[4]>>4)*10+(readtime[4]&0x0F); //计算小时
  170. timeData->minute=(readtime[5]>>4)*10+(readtime[5]&0x0F); //计算分钟
  171. timeData->second=(readtime[6]>>4)*10+(readtime[6]&0x0F); //计算秒钟
  172. timeData->week=(readtime[7]&0x0F); //计算星期
  173. #ifdef DEBUG_printf
  174. //printf("read: %d年%d月%d日 %d时%d分%d秒\n", timeData->year, timeData->month, timeData->day, timeData->hour, timeData->minute, timeData->second);
  175. #endif
  176. }