HW_PIC32.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. inline void _waitForIdleBus() { while (I2C1CON & 0x1f) {} }
  2. void DS3231::begin()
  3. {
  4. if ((_sda_pin == SDA) and (_scl_pin == SCL))
  5. {
  6. uint32_t tpgd;
  7. _use_hw = true;
  8. pinMode(SDA, OUTPUT);
  9. digitalWrite(SDA, HIGH);
  10. IFS0CLR = 0xE0000000; // Clear Interrupt Flag
  11. IEC0CLR = 0xE0000000; // Disable Interrupt
  12. I2C1CONCLR = (1 << _I2CCON_ON); // Disable I2C interface
  13. tpgd = ((F_CPU / 8) * 104) / 125000000;
  14. I2C1BRG = (F_CPU / (2 * TWI_FREQ) - tpgd) - 2; // Set I2C Speed
  15. I2C1ADD = DS3231_ADDR; // Set I2C device address
  16. I2C1CONSET = (1 << _I2CCON_ON) | (1 << _I2CCON_STREN); // Enable I2C Interface
  17. }
  18. else
  19. {
  20. _use_hw = false;
  21. pinMode(_scl_pin, OUTPUT);
  22. }
  23. }
  24. void DS3231::_burstRead()
  25. {
  26. if (_use_hw)
  27. {
  28. _waitForIdleBus(); // Wait for I2C bus to be Idle before starting
  29. I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
  30. if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
  31. while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
  32. I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
  33. while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
  34. {
  35. I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
  36. I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
  37. }
  38. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  39. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  40. I2C1TRN = 0; // Send the register address
  41. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  42. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  43. _waitForIdleBus(); // Wait for I2C bus to be Idle before starting
  44. I2C1CONSET = (1 << _I2CCON_RSEN); // Send start condition
  45. if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
  46. while (I2C1CON & (1 << _I2CCON_RSEN)) {} // Wait for start condition to finish
  47. I2C1TRN = (DS3231_ADDR<<1) | 1; // Send device Read address
  48. while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
  49. {
  50. I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
  51. I2C1TRN = (DS3231_ADDR<<1) | 1; // Retry send device Read address
  52. }
  53. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  54. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  55. byte dummy = I2C1RCV; // Clear _I2CSTAT_RBF (Receive Buffer Full)
  56. for (int i=0; i<7; i++)
  57. {
  58. _waitForIdleBus(); // Wait for I2C bus to be Idle before continuing
  59. I2C1CONSET = (1 << _I2CCON_RCEN); // Set RCEN to start receive
  60. while (I2C1CON & (1 << _I2CCON_RCEN)) {} // Wait for Receive operation to finish
  61. while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {} // Wait for Receive Buffer Full
  62. _burstArray[i] = I2C1RCV; // Read data
  63. if (i == 6)
  64. I2C1CONSET = (1 << _I2CCON_ACKDT); // Prepare to send NACK
  65. else
  66. I2C1CONCLR = (1 << _I2CCON_ACKDT); // Prepare to send ACK
  67. I2C1CONSET = (1 << _I2CCON_ACKEN); // Send ACK/NACK
  68. while (I2C1CON & (1 << _I2CCON_ACKEN)) {} // Wait for ACK/NACK send to finish
  69. }
  70. I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
  71. while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
  72. }
  73. else
  74. {
  75. _sendStart(DS3231_ADDR_W);
  76. _waitForAck();
  77. _writeByte(0);
  78. _waitForAck();
  79. _sendStart(DS3231_ADDR_R);
  80. _waitForAck();
  81. for (int i=0; i<7; i++)
  82. {
  83. _burstArray[i] = _readByte();
  84. if (i<6)
  85. _sendAck();
  86. else
  87. _sendNack();
  88. }
  89. _sendStop();
  90. }
  91. }
  92. uint8_t DS3231::_readRegister(uint8_t reg)
  93. {
  94. uint8_t readValue=0;
  95. if (_use_hw)
  96. {
  97. _waitForIdleBus(); // Wait for I2C bus to be Idle before starting
  98. I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
  99. if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
  100. while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
  101. I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
  102. while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
  103. {
  104. I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
  105. I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
  106. }
  107. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  108. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  109. I2C1TRN = reg; // Send the register address
  110. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  111. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  112. _waitForIdleBus(); // Wait for I2C bus to be Idle before starting
  113. I2C1CONSET = (1 << _I2CCON_RSEN); // Send start condition
  114. if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
  115. while (I2C1CON & (1 << _I2CCON_RSEN)) {} // Wait for start condition to finish
  116. I2C1TRN = (DS3231_ADDR<<1) | 1; // Send device Read address
  117. while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
  118. {
  119. I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
  120. I2C1TRN = (DS3231_ADDR<<1) | 1; // Retry send device Read address
  121. }
  122. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  123. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  124. byte dummy = I2C1RCV; // Clear _I2CSTAT_RBF (Receive Buffer Full)
  125. _waitForIdleBus(); // Wait for I2C bus to be Idle before continuing
  126. I2C1CONSET = (1 << _I2CCON_RCEN); // Set RCEN to start receive
  127. while (I2C1CON & (1 << _I2CCON_RCEN)) {} // Wait for Receive operation to finish
  128. while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {} // Wait for Receive Buffer Full
  129. readValue = I2C1RCV; // Read data
  130. I2C1CONSET = (1 << _I2CCON_ACKDT); // Prepare to send NACK
  131. I2C1CONSET = (1 << _I2CCON_ACKEN); // Send NACK
  132. while (I2C1CON & (1 << _I2CCON_ACKEN)) {} // Wait for NACK send to finish
  133. I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
  134. while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
  135. }
  136. else
  137. {
  138. _sendStart(DS3231_ADDR_W);
  139. _waitForAck();
  140. _writeByte(reg);
  141. _waitForAck();
  142. _sendStart(DS3231_ADDR_R);
  143. _waitForAck();
  144. readValue = _readByte();
  145. _sendNack();
  146. _sendStop();
  147. }
  148. return readValue;
  149. }
  150. void DS3231::_writeRegister(uint8_t reg, uint8_t value)
  151. {
  152. if (_use_hw)
  153. {
  154. _waitForIdleBus(); // Wait for I2C bus to be Idle before starting
  155. I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
  156. if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
  157. while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
  158. I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
  159. while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
  160. {
  161. I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
  162. I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
  163. }
  164. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  165. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  166. I2C1TRN = reg; // Send the 1st data byte
  167. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  168. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  169. I2C1TRN = value; // Send the 2nd data byte
  170. while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
  171. while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
  172. I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
  173. while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
  174. }
  175. else
  176. {
  177. _sendStart(DS3231_ADDR_W);
  178. _waitForAck();
  179. _writeByte(reg);
  180. _waitForAck();
  181. _writeByte(value);
  182. _waitForAck();
  183. _sendStop();
  184. }
  185. }