123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include "main.h"
- #define RTC_TX_BUF_SIZE 4
- static uint8_t i2cBufTX[RTC_TX_BUF_SIZE] = {0};
- /**
- * @brief Инициализация RTC
- */
- void RTC_Init(void) {
- /* Clear flags */
- Flag.I2C_TX_End = 0;
- /* Source: Address of the I2C TX buffer. */
- DMA1_Channel3->CMAR = (uint32_t)&i2cBufTX;
- /* Destination: I2C TX data register. */
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- /* Set DMA data transfer length (I2C TX buffer length). */
- DMA1_Channel3->CNDTR = RTC_TX_BUF_SIZE;
- /* Enable DMA channels for I2C */
- DMA1_Channel3->CCR |= DMA_CCR_EN;
- /* Fill buffer with register address and register value */
- i2cBufTX[0] = DS3231_ADDR_CONTROL;
- i2cBufTX[1] = DS3231_1HZ; // set 1 Hz output squware
- i2cBufTX[2] = 0x0; // disable 32 kHz output
- /* Wait for I2C */
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- /*
- LL_I2C_SetSlaveAddr(I2C1, DS3231_I2C_ADDR);
- LL_I2C_SetTransferRequest(I2C1, LL_I2C_REQUEST_WRITE);
- LL_I2C_SetTransferSize(I2C1, 3); // controll addr + 2 bytes of data
- */
- /* Set the device address and number bytes to send. */
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | 3 << I2C_CR2_NBYTES_Pos );
- /* Enable I2C DMA requests. */
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- /* Send a start signal. */
- I2C1->CR2 |= ( I2C_CR2_START );
- /* (DMA is now running.) */
- }
- /**
- * @brief Чтение всех регистров DS3231
- */
- void RTC_ReadAll(rtc_t * data) {
- Flag.I2C_RX_End = 0;
- Flag.I2C_TX_End = 0;
- /* Source: Address of the I2C RX buffer. */
- DMA1_Channel2->CMAR = (uint32_t)data;
- /* Destination: I2C RX data register. */
- DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
- /* Set DMA data transfer length (I2C RX buffer length). */
- DMA1_Channel2->CNDTR = DS3231_SIZE_ALL;
- /* Enable DMA channels for I2C RX */
- DMA1_Channel2->CCR |= DMA_CCR_EN;
- /* wait for i2c */
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- /* send first register address 00h */
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | 1 << I2C_CR2_NBYTES_Pos );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
- I2C1->TXDR = DS3231_ADDR_TIME;
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- /* Reading all */
- /*
- LL_I2C_SetSlaveAddr(I2C1, DS3231_I2C_ADDR);
- LL_I2C_SetTransferRequest(I2C1, LL_I2C_REQUEST_READ);
- LL_I2C_SetTransferSize(I2C1, DS3231_SIZE_ALL);
- */
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | DS3231_SIZE_ALL << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
- I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- }
- /**
- * @brief Запись времени и календаря
- */
- void RTC_WriteTimeCalendar(rtc_t * data) {
- Flag.I2C_TX_End = 0;
- DMA1_Channel3->CMAR = (uint32_t)data;
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- DMA1_Channel3->CNDTR = DS3231_SIZE_TIME + DS3231_SIZE_CALENDAR;
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_TIME + DS3231_SIZE_CALENDAR + 1) << I2C_CR2_NBYTES_Pos );
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
- I2C1->TXDR = DS3231_ADDR_TIME; // send reg addr when START finish
- DMA1_Channel3->CCR |= DMA_CCR_EN; // and launch DMA for data to transfer
- }
- /**
- * @brief Запись времени
- */
- void RTC_WriteTime(rtc_t * data) {
- Flag.I2C_TX_End = 0;
- DMA1_Channel3->CMAR = (uint32_t)data;
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- DMA1_Channel3->CNDTR = DS3231_SIZE_TIME;
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_TIME + 1) << I2C_CR2_NBYTES_Pos );
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
- I2C1->TXDR = DS3231_ADDR_TIME;
- DMA1_Channel3->CCR |= DMA_CCR_EN;
- }
- /**
- * @brief Запись часов
- */
- void RTC_WriteHH(rtc_t * data) {
- Flag.I2C_TX_End = 0; // некому установить этот флаг в 1
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | 2 << I2C_CR2_NBYTES_Pos );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
- I2C1->TXDR = (DS3231_ADDR_TIME + 2);
- while ((I2C1->ISR & I2C_ISR_TXE) == 0) { __NOP(); };
- I2C1->TXDR = data->Hr;
- }
- /**
- * @brief Запись часов и минут
- */
- void RTC_WriteHHMM(rtc_t * data) {
- Flag.I2C_TX_End = 0;
- DMA1_Channel3->CMAR = (uint32_t)&i2cBufTX;
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- DMA1_Channel3->CNDTR = 3; // addr + mm + hh
- DMA1_Channel3->CCR |= DMA_CCR_EN;
- /* Fill buffer with register address and register value */
- i2cBufTX[0] = DS3231_ADDR_TIME + 1; // skip seconds
- i2cBufTX[1] = data->Min;
- i2cBufTX[2] = data->Hr;
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | 3 << I2C_CR2_NBYTES_Pos );
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- }
- /**
- * @brief Запись календаря
- */
- void RTC_WriteCalendar(rtc_t * data) {
- Flag.I2C_TX_End = 0;
- DMA1_Channel3->CMAR = (uint32_t)&(data->WD);
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- DMA1_Channel3->CNDTR = DS3231_SIZE_CALENDAR;
- while ( I2C1->ISR & I2C_ISR_BUSY ) {};
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( DS3231_I2C_ADDR | (DS3231_SIZE_CALENDAR + 1) << I2C_CR2_NBYTES_Pos );
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
- I2C1->TXDR = DS3231_ADDR_CALENDAR;
- DMA1_Channel3->CCR |= DMA_CCR_EN;
- }
- /**
- * @brief Convert BCD value to Binary
- */
- uint8_t bcd2bin(uint8_t bcd)
- {
- return (10 * (bcd >> 4) + (bcd & 0x0f));
- }
- /**
- * @brief Convert Binary value to BCD
- */
- uint8_t bin2bcd(uint8_t bin)
- {
- return (((bin / 10 ) << 4) | (bin % 10));
- }
|