ds3231.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "main.h"
  2. #define RTC_TX_BUF_SIZE 4
  3. static uint8_t i2cBufTX[RTC_TX_BUF_SIZE] = {0};
  4. /**
  5. * @brief Инициализация RTC
  6. */
  7. void RTC_Init(void) {
  8. /* Clear flags */
  9. Flag.I2C_TX_End = 0;
  10. /* Source: Address of the I2C TX buffer. */
  11. DMA1_Channel3->CMAR = (uint32_t)&i2cBufTX;
  12. /* Destination: I2C TX data register. */
  13. DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
  14. /* Set DMA data transfer length (I2C TX buffer length). */
  15. DMA1_Channel3->CNDTR = 3; // hardcode / magic number
  16. /* Enable DMA channels for I2C */
  17. DMA1_Channel3->CCR |= DMA_CCR_EN;
  18. /* Fill buffer with register address and register value */
  19. i2cBufTX[0] = DS3231_ADDR_CONTROL;
  20. i2cBufTX[1] = DS3231_1HZ; // set 1 Hz output squware
  21. i2cBufTX[2] = 0x0; // disable 32 kHz output
  22. /* Wait for I2C */
  23. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  24. /* Set the device address and number bytes to send. */
  25. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  26. I2C1->CR2 |= ( DS3231_I2C_ADDR | 3 << I2C_CR2_NBYTES_Pos );
  27. /* Enable I2C DMA requests. */
  28. I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
  29. /* Send a start signal. */
  30. I2C1->CR2 |= ( I2C_CR2_START );
  31. /* (DMA is now running.) */
  32. }
  33. /**
  34. * @brief Чтение всех регистров DS3231
  35. */
  36. void RTC_ReadAll(rtc_t * data) {
  37. Flag.I2C_RX_End = 0;
  38. Flag.I2C_TX_End = 0;
  39. /* Source: Address of the I2C RX buffer. */
  40. DMA1_Channel2->CMAR = (uint32_t)data;
  41. /* Destination: I2C RX data register. */
  42. DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
  43. /* Set DMA data transfer length (I2C RX buffer length). */
  44. DMA1_Channel2->CNDTR = DS3231_SIZE_ALL;
  45. /* Enable DMA channels for I2C RX */
  46. DMA1_Channel2->CCR |= DMA_CCR_EN;
  47. /* wait for i2c */
  48. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  49. /* send first register address 00h */
  50. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  51. I2C1->CR2 |= ( DS3231_I2C_ADDR | 1 << I2C_CR2_NBYTES_Pos );
  52. I2C1->CR2 |= ( I2C_CR2_START );
  53. while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
  54. I2C1->TXDR = DS3231_ADDR_TIME;
  55. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  56. /* Reading all */
  57. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  58. I2C1->CR2 |= ( DS3231_I2C_ADDR | DS3231_SIZE_ALL << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
  59. I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
  60. I2C1->CR2 |= ( I2C_CR2_START );
  61. }
  62. /**
  63. * @brief Запись времени и календаря
  64. */
  65. void RTC_WriteTimeCalendar(rtc_t * data) {
  66. Flag.I2C_TX_End = 0;
  67. DMA1_Channel3->CCR &= ~DMA_CCR_EN;
  68. DMA1_Channel3->CMAR = (uint32_t)data;
  69. DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
  70. DMA1_Channel3->CNDTR = DS3231_SIZE_TIME + DS3231_SIZE_CALENDAR;
  71. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  72. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  73. I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_TIME + DS3231_SIZE_CALENDAR + 1) << I2C_CR2_NBYTES_Pos );
  74. I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
  75. I2C1->CR2 |= ( I2C_CR2_START );
  76. while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
  77. I2C1->TXDR = DS3231_ADDR_TIME; // send reg addr when START finish
  78. DMA1_Channel3->CCR |= DMA_CCR_EN; // and launch DMA for data to transfer
  79. }
  80. /**
  81. * @brief Запись времени
  82. */
  83. void RTC_WriteTime(rtc_t * data) {
  84. Flag.I2C_TX_End = 0;
  85. DMA1_Channel3->CMAR = (uint32_t)data;
  86. DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
  87. DMA1_Channel3->CNDTR = DS3231_SIZE_TIME;
  88. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  89. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  90. I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_TIME + 1) << I2C_CR2_NBYTES_Pos );
  91. I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
  92. I2C1->CR2 |= ( I2C_CR2_START );
  93. while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
  94. I2C1->TXDR = DS3231_ADDR_TIME;
  95. DMA1_Channel3->CCR |= DMA_CCR_EN;
  96. }
  97. /**
  98. * @brief Запись часов
  99. */
  100. void RTC_WriteHH(rtc_t * data) {
  101. Flag.I2C_TX_End = 0; // некому установить этот флаг в 1
  102. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  103. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  104. I2C1->CR2 |= ( DS3231_I2C_ADDR | 2 << I2C_CR2_NBYTES_Pos );
  105. I2C1->CR2 |= ( I2C_CR2_START );
  106. while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
  107. I2C1->TXDR = (DS3231_ADDR_TIME + 2);
  108. while ((I2C1->ISR & I2C_ISR_TXE) == 0) { __NOP(); };
  109. I2C1->TXDR = data->Hr;
  110. }
  111. /**
  112. * @brief Запись часов и минут
  113. */
  114. void RTC_WriteHHMM(rtc_t * data) {
  115. Flag.I2C_TX_End = 0;
  116. DMA1_Channel3->CMAR = (uint32_t)&i2cBufTX;
  117. DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
  118. DMA1_Channel3->CNDTR = 3; // addr + mm + hh
  119. DMA1_Channel3->CCR |= DMA_CCR_EN;
  120. /* Fill buffer with register address and register value */
  121. i2cBufTX[0] = DS3231_ADDR_TIME + 1; // skip seconds
  122. i2cBufTX[1] = data->Min;
  123. i2cBufTX[2] = data->Hr;
  124. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  125. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  126. I2C1->CR2 |= ( DS3231_I2C_ADDR | 3 << I2C_CR2_NBYTES_Pos );
  127. I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
  128. I2C1->CR2 |= ( I2C_CR2_START );
  129. }
  130. /**
  131. * @brief Запись календаря
  132. */
  133. void RTC_WriteCalendar(rtc_t * data) {
  134. Flag.I2C_TX_End = 0;
  135. DMA1_Channel3->CMAR = (uint32_t)&(data->WD);
  136. DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
  137. DMA1_Channel3->CNDTR = DS3231_SIZE_CALENDAR;
  138. while ( I2C1->ISR & I2C_ISR_BUSY ) {};
  139. I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
  140. I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_CALENDAR + 1) << I2C_CR2_NBYTES_Pos );
  141. I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
  142. I2C1->CR2 |= ( I2C_CR2_START );
  143. while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
  144. I2C1->TXDR = DS3231_ADDR_CALENDAR;
  145. DMA1_Channel3->CCR |= DMA_CCR_EN;
  146. }
  147. /**
  148. * @brief Convert BCD value to Binary
  149. */
  150. uint8_t bcd2bin(uint8_t bcd)
  151. {
  152. return (10 * (bcd >> 4) + (bcd & 0x0f));
  153. }
  154. /**
  155. * @brief Convert Binary value to BCD
  156. */
  157. uint8_t bin2bcd(uint8_t bin)
  158. {
  159. return (((bin / 10 ) << 4) | (bin % 10));
  160. }