ds3231.c 6.3 KB

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