From d1220b2f582ee21e5668be778520ded04260e50a Mon Sep 17 00:00:00 2001 From: IOsetting Date: Tue, 24 Jan 2023 21:03:41 +0800 Subject: [PATCH] feat: ll i2c ds3231 example --- Examples/LL/I2C/DS3231_RealTimeClock/main.c | 264 ++++++++++++++++++ Examples/LL/I2C/DS3231_RealTimeClock/main.h | 27 ++ .../LL/I2C/DS3231_RealTimeClock/py32f0xx_it.c | 40 +++ .../LL/I2C/DS3231_RealTimeClock/py32f0xx_it.h | 19 ++ 4 files changed, 350 insertions(+) create mode 100644 Examples/LL/I2C/DS3231_RealTimeClock/main.c create mode 100644 Examples/LL/I2C/DS3231_RealTimeClock/main.h create mode 100644 Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.c create mode 100644 Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.h diff --git a/Examples/LL/I2C/DS3231_RealTimeClock/main.c b/Examples/LL/I2C/DS3231_RealTimeClock/main.c new file mode 100644 index 0000000..37e50a3 --- /dev/null +++ b/Examples/LL/I2C/DS3231_RealTimeClock/main.c @@ -0,0 +1,264 @@ +/*** + * Demo: I2C - DS3231 Real Time Clock + * + * PY32 + * PF1 SCL + * PF0 SDA + */ +#include +#include "main.h" +#include "py32f0xx_bsp_printf.h" + + +#define MASTER_ADDRESS 0xA0 +#define DS3231_ADDRESS 0xD0 + +#define I2C_STATE_READY 0 +#define I2C_STATE_BUSY_TX 1 +#define I2C_STATE_BUSY_RX 2 + +#define DS3231_REG_SECOND 0x00 /**< second register */ +#define DS3231_REG_MINUTE 0x01 /**< minute register */ +#define DS3231_REG_HOUR 0x02 /**< hour register */ +#define DS3231_REG_WEEK 0x03 /**< week register */ +#define DS3231_REG_DATE 0x04 /**< date register */ +#define DS3231_REG_MONTH 0x05 /**< month register */ +#define DS3231_REG_YEAR 0x06 /**< year register */ +#define DS3231_REG_ALARM1_SECOND 0x07 /**< alarm1 second register */ +#define DS3231_REG_ALARM1_MINUTE 0x08 /**< alarm1 minute register */ +#define DS3231_REG_ALARM1_HOUR 0x09 /**< alarm1 hour register */ +#define DS3231_REG_ALARM1_WEEK 0x0A /**< alarm1 week register */ +#define DS3231_REG_ALARM2_MINUTE 0x0B /**< alarm2 minute register */ +#define DS3231_REG_ALARM2_HOUR 0x0C /**< alarm2 hour register */ +#define DS3231_REG_ALARM2_WEEK 0x0D /**< alarm2 week register */ +#define DS3231_REG_CONTROL 0x0E /**< control register */ +#define DS3231_REG_STATUS 0x0F /**< status register */ +#define DS3231_REG_XTAL 0x10 /**< xtal register */ +#define DS3231_REG_TEMPERATUREH 0x11 /**< temperature high register */ +#define DS3231_REG_TEMPERATUREL 0x12 /**< temperature low register */ + +typedef enum +{ + DS3231_FORMAT_12H = 0x01, /**< 12h format */ + DS3231_FORMAT_24H = 0x00, /**< 24h format */ +} DS3231_HourFormat_t; + +uint8_t buff[7]; + +__IO uint32_t i2cState = I2C_STATE_READY; + +static void APP_SystemClockConfig(void); +static void APP_I2CConfig(void); +void APP_I2C_Transmit(uint8_t devAddress, uint8_t memAddress, uint8_t *pData, uint16_t size); +uint8_t APP_I2C_Receive(uint16_t devAddress, uint16_t memAddress, uint8_t *buf, uint16_t size); + +uint8_t DS3231_Hex2Bcd(uint8_t hex) +{ + return (hex % 10) + ((hex / 10) << 4); +} + +uint8_t DS3231_Bcd2Hex(uint8_t bcd) +{ + return (bcd >> 4) * 10 + (bcd & 0x0F); +} + +uint8_t DS3231_GetStatus(void) +{ + APP_I2C_Receive(DS3231_ADDRESS, DS3231_REG_STATUS, buff, 1); + return buff[0]; +} + +void DS3231_GetTime(uint8_t *t) +{ + APP_I2C_Receive(DS3231_ADDRESS, DS3231_REG_SECOND, buff, 7); + t[0] = 19 + ((buff[5] >> 7) & 0x01); // century + t[1] = DS3231_Bcd2Hex(buff[6]); // year + t[2] = DS3231_Bcd2Hex(buff[5] & 0x1F); // month + t[3] = DS3231_Bcd2Hex(buff[3]); // week + t[4] = DS3231_Bcd2Hex(buff[4]); // date + t[8] = (buff[2] >> 6) & 0x01; // 12h/24h + t[9] = (buff[2] >> 5) & 0x01; // am/pm + if (t[8] == DS3231_FORMAT_12H) + { + t[5] = DS3231_Bcd2Hex(buff[2] & 0x1F); // hour + } + else + { + t[5] = DS3231_Bcd2Hex(buff[2] & 0x3F); // hour + } + t[6] = DS3231_Bcd2Hex(buff[1]); // minute + t[7] = DS3231_Bcd2Hex(buff[0]); // second +} + +int main(void) +{ + uint8_t time[10]; + + APP_SystemClockConfig(); + + BSP_USART_Config(115200); + printf("I2C Demo: DS3231 Real Time Clock\r\nClock: %ld\r\n", SystemCoreClock); + + APP_I2CConfig(); + + time[0] = DS3231_GetStatus(); + printf("Status: %d\r\n", time[0]); + + while(1) + { + DS3231_GetTime(time); + printf("%02d%02d-%02d-%02d %02d:%02d:%02d %d-%d\r\n", + time[0], time[1], time[2], time[4], time[5], time[6], time[7], time[8], time[9]); + LL_mDelay(1000); + } +} + +static void APP_I2CConfig(void) +{ + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOF); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); + + // PF1 SCL + GPIO_InitStruct.Pin = LL_GPIO_PIN_1; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_12; + LL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + // PF0 SDA + GPIO_InitStruct.Pin = LL_GPIO_PIN_0; + GPIO_InitStruct.Alternate = LL_GPIO_AF_12; + LL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1); + + LL_I2C_InitTypeDef I2C_InitStruct; + /* + * Clock speed: + * - standard = 100khz + * - fast = 400khz + */ + I2C_InitStruct.ClockSpeed = LL_I2C_MAX_SPEED_FAST; + I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_16_9; + I2C_InitStruct.OwnAddress1 = MASTER_ADDRESS; + I2C_InitStruct.TypeAcknowledge = LL_I2C_NACK; + LL_I2C_Init(I2C1, &I2C_InitStruct); +} + +void APP_I2C_Transmit(uint8_t devAddress, uint8_t memAddress, uint8_t *pData, uint16_t size) +{ + while (i2cState == I2C_STATE_BUSY_TX); + LL_I2C_DisableBitPOS(I2C1); + + i2cState = I2C_STATE_BUSY_TX; + /* Start */ + LL_I2C_GenerateStartCondition(I2C1); + while (LL_I2C_IsActiveFlag_SB(I2C1) != 1); + /* Send slave address */ + LL_I2C_TransmitData8(I2C1, (devAddress & (uint8_t)(~0x01))); + while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1); + LL_I2C_ClearFlag_ADDR(I2C1); + + /* Send memory address */ + while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1); + LL_I2C_TransmitData8(I2C1, memAddress); + while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1); + + /* Transfer data */ + while (size > 0) + { + while (LL_I2C_IsActiveFlag_TXE(I2C1) != 1); + LL_I2C_TransmitData8(I2C1, *pData++); + size--; + + if ((LL_I2C_IsActiveFlag_BTF(I2C1) == 1) && (size != 0U)) + { + LL_I2C_TransmitData8(I2C1, *pData++); + size--; + } + + while (LL_I2C_IsActiveFlag_BTF(I2C1) != 1); + } + + /* Stop */ + LL_I2C_GenerateStopCondition(I2C1); + i2cState = I2C_STATE_READY; +} + +uint8_t APP_I2C_Receive(uint16_t devAddress, uint16_t memAddress, uint8_t *buf, uint16_t size) +{ + uint8_t temp = 0; + + i2cState = I2C_STATE_BUSY_RX; + /* Turn on ACK */ + LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK); + /* Start */ + LL_I2C_GenerateStartCondition(I2C1); + /* Wait the status of Start Bit */ + while(LL_I2C_IsActiveFlag_SB(I2C1) != 1); + + /* Send slave address */ + LL_I2C_TransmitData8(I2C1, (devAddress & (uint8_t)(~0x01))); + /* Wait the status of Address sent (master mode) */ + while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1); + /* Clear Address Matched flag */ + LL_I2C_ClearFlag_ADDR(I2C1); + + /* Send memory address */ + LL_I2C_TransmitData8(I2C1, (uint8_t)(memAddress & 0x00FF)); + while (LL_I2C_IsActiveFlag_BTF(I2C1) != 1); + + /* Start */ + LL_I2C_GenerateStartCondition(I2C1); + while(LL_I2C_IsActiveFlag_SB(I2C1) != 1); + + /* Send slave address(read) */ + LL_I2C_TransmitData8(I2C1, (devAddress | 0x1)); + while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1); + LL_I2C_ClearFlag_ADDR(I2C1); + + while (size--) + { + while(LL_I2C_IsActiveFlag_RXNE(I2C1) != 1); + *buf++ = LL_I2C_ReceiveData8(I2C1); + } + LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK); + LL_I2C_GenerateStopCondition(I2C1); + + i2cState = I2C_STATE_READY; + return temp; +} + +static void APP_SystemClockConfig(void) +{ + LL_UTILS_ClkInitTypeDef UTILS_ClkInitStruct; + + LL_RCC_HSI_Enable(); + /* Change this value to adjust frequency */ + LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz + 15); + while (LL_RCC_HSI_IsReady() != 1); + + UTILS_ClkInitStruct.AHBCLKDivider = LL_RCC_SYSCLK_DIV_1; + UTILS_ClkInitStruct.APB1CLKDivider = LL_RCC_APB1_DIV_1; + LL_PLL_ConfigSystemClock_HSI(&UTILS_ClkInitStruct); + + /* Re-init frequency of SysTick source, reload = freq/ticks = 48000000/1000 = 48000 */ + LL_InitTick(48000000, 1000U); +} + +void APP_ErrorHandler(void) +{ + while (1); +} + +#ifdef USE_FULL_ASSERT +void assert_failed(uint8_t *file, uint32_t line) +{ + while (1); +} +#endif /* USE_FULL_ASSERT */ diff --git a/Examples/LL/I2C/DS3231_RealTimeClock/main.h b/Examples/LL/I2C/DS3231_RealTimeClock/main.h new file mode 100644 index 0000000..6e3c2ea --- /dev/null +++ b/Examples/LL/I2C/DS3231_RealTimeClock/main.h @@ -0,0 +1,27 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "py32f0xx_ll_bus.h" +#include "py32f0xx_ll_cortex.h" +#include "py32f0xx_ll_dma.h" +#include "py32f0xx_ll_exti.h" +#include "py32f0xx_ll_gpio.h" +#include "py32f0xx_ll_pwr.h" +#include "py32f0xx_ll_rcc.h" +#include "py32f0xx_ll_i2c.h" +#include "py32f0xx_ll_system.h" +#include "py32f0xx_ll_tim.h" +#include "py32f0xx_ll_utils.h" + + +void APP_ErrorHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.c b/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.c new file mode 100644 index 0000000..3a10d14 --- /dev/null +++ b/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.c @@ -0,0 +1,40 @@ +#include "main.h" +#include "py32f0xx_it.h" + +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + while (1) + { + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ +} diff --git a/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.h b/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.h new file mode 100644 index 0000000..76b3dad --- /dev/null +++ b/Examples/LL/I2C/DS3231_RealTimeClock/py32f0xx_it.h @@ -0,0 +1,19 @@ +#ifndef __PY32F0XX_IT_H +#define __PY32F0XX_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +void NMI_Handler(void); +void HardFault_Handler(void); +void SVC_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* __PY32F0XX_IT_H */