diff --git a/demo/i2c/ds3231/ds3231.c b/demo/i2c/ds3231/ds3231.c new file mode 100755 index 0000000..f2e1f62 --- /dev/null +++ b/demo/i2c/ds3231/ds3231.c @@ -0,0 +1,101 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "ds3231.h" +#include "string.h" + + +uint8_t DS3231_Write(uint8_t reg, uint8_t dat) +{ + return I2C_Write(DS3231_I2C_ADDR, reg, &dat, 1); +} + +uint8_t DS3231_MultipleRead(uint8_t reg, uint8_t *buf, uint8_t len) +{ + return I2C_Read(DS3231_I2C_ADDR, reg, buf, len); +} + +uint8_t DS3231_Hex2Bcd(uint8_t hex) +{ + uint8_t i, j, k; + + i = hex / 10; /* get tens place */ + j = hex % 10; /* get ones place */ + k = j + (i << 4); /* set bcd */ + return k; /* return bcd */ +} + +uint8_t DS3231_Bcd2Hex(uint8_t val) +{ + uint8_t temp; + + temp = val & 0x0F; /* get ones place */ + val = (val >> 4) & 0x0F; /* get tens place */ + val = val * 10; /* set tens place */ + temp = temp + val; /* get hex */ + return temp; /* return hex */ +} + +uint8_t DS3231_Init(void) +{ + uint8_t res; + uint8_t prev; + + res = DS3231_MultipleRead(DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple_read */ + if (res != HAL_OK) /* check result */ + { + return res; + } + prev &= ~(1 << 7); /* clear config */ + res = DS3231_Write(DS3231_REG_STATUS, prev); /* write status */ + if (res != HAL_OK) /* check result */ + { + return res; + } + return HAL_OK; +} + +uint8_t DS3231_ReadAll(uint8_t *buf) +{ + return DS3231_MultipleRead(DS3231_REG_SECOND, buf, 19); +} + +uint8_t DS3231_GetTime(DS3231_Time_t *t) +{ + uint8_t res; + uint8_t buf[7]; + memset(buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */ + res = DS3231_MultipleRead(DS3231_REG_SECOND, (uint8_t *)buf, 7); /* multiple_read */ + if (res != HAL_OK) /* check result */ + { + return res; /* return error */ + } + t->year = DS3231_Bcd2Hex(buf[6]) + 1990 + ((buf[5] >> 7) & 0x01) * 100; /* get year */ + t->month = DS3231_Bcd2Hex(buf[5]&0x1F); /* get month */ + t->week = DS3231_Bcd2Hex(buf[3]); /* get week */ + t->date = DS3231_Bcd2Hex(buf[4]); /* get date */ + t->am_pm = (DS3231_AmPm_t)((buf[2] >> 5) & 0x01); /* get am pm */ + t->format = (DS3231_HourFormat_t)((buf[2] >> 6) & 0x01); /* get format */ + if (t->format == DS3231_FORMAT_12H) /* if 12H */ + { + t->hour = DS3231_Bcd2Hex(buf[2] & 0x1F); /* get hour */ + } + else + { + t->hour = DS3231_Bcd2Hex(buf[2] & 0x3F); /* get hour */ + } + t->minute = DS3231_Bcd2Hex(buf[1]); /* get minute */ + t->second = DS3231_Bcd2Hex(buf[0]); /* get second */ + return HAL_OK; /* success return 0 */ +} diff --git a/demo/i2c/ds3231/ds3231.h b/demo/i2c/ds3231/ds3231.h new file mode 100755 index 0000000..008c170 --- /dev/null +++ b/demo/i2c/ds3231/ds3231.h @@ -0,0 +1,130 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __FW_DS3231_H__ +#define __FW_DS3231_H__ + + +#include "fw_hal.h" + +#define DS3231_I2C_ADDR 0xD0 /**< iic device address */ + +#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_BOOL_FALSE = 0x00, /**< disable function */ + DS3231_BOOL_TRUE = 0x01, /**< enable function */ +} DS3231_Bool_t; + +typedef enum +{ + DS3231_ALARM_1 = 0x00, /**< alarm 1 */ + DS3231_ALARM_2 = 0x01, /**< alarm 2 */ +} DS3231_Alarm_t; + +typedef enum +{ + DS3231_AM = 0x00, /**< am */ + DS3231_PM = 0x01, /**< pm */ +} DS3231_AmPm_t; + +typedef enum +{ + DS3231_PIN_SQUARE_WAVE = 0x00, /**< square wave pin */ + DS3231_PIN_INTERRUPT = 0x01, /**< interrupt pin */ +} DS3231_PinType_t; + +typedef enum +{ + DS3231_FORMAT_12H = 0x01, /**< 12h format */ + DS3231_FORMAT_24H = 0x00, /**< 24h format */ +} DS3231_HourFormat_t; + +typedef enum +{ + DS3231_STATUS_ALARM_2 = (1 << 1), /**< alarm 2 status */ + DS3231_STATUS_ALARM_1 = (1 << 0), /**< alarm 1 status */ +} DS3231_AlarmStatus_t; + +typedef enum +{ + DS3231_ALARM1_MODE_ONCE_A_SECOND = 0x0F, /**< interrupt once a second */ + DS3231_ALARM1_MODE_SECOND_MATCH = 0x0E, /**< interrupt second match */ + DS3231_ALARM1_MODE_MINUTE_SECOND_MATCH = 0x0C, /**< interrupt minute second match */ + DS3231_ALARM1_MODE_HOUR_MINUTE_SECOND_MATCH = 0x08, /**< interrupt hour minute second match */ + DS3231_ALARM1_MODE_DATE_HOUR_MINUTE_SECOND_MATCH = 0x00, /**< interrupt date hour minute second match */ + DS3231_ALARM1_MODE_WEEK_HOUR_MINUTE_SECOND_MATCH = 0x10, /**< interrupt week hour minute second match */ +} DS3231_Alarm1Mode_t; + +typedef enum +{ + DS3231_ALARM2_MODE_ONCE_A_MINUTE = 0x07, /**< interrupt once a minute */ + DS3231_ALARM2_MODE_MINUTE_MATCH = 0x06, /**< interrupt minute match */ + DS3231_ALARM2_MODE_HOUR_MINUTE_MATCH = 0x04, /**< interrupt hour minute match */ + DS3231_ALARM2_MODE_DATE_HOUR_MINUTE_MATCH = 0x00, /**< interrupt data hour minute match */ + DS3231_ALARM2_MODE_WEEK_HOUR_MINUTE_MATCH = 0x10, /**< interrupt week hour minute match */ +} DS3231_Alarm2Mode_t; + +typedef struct ds3231_time_s +{ + uint16_t year; /**< year */ + uint8_t month; /**< month */ + uint8_t week; /**< week */ + uint8_t date; /**< date */ + uint8_t hour; /**< hour */ + uint8_t minute; /**< minute */ + uint8_t second; /**< second */ + DS3231_HourFormat_t format; /**< hour format */ + DS3231_AmPm_t am_pm; /**< am pm */ +} DS3231_Time_t; + +typedef struct ds3231_handle_s +{ + uint8_t (*iic_init)(void); /**< point to a iic_init function address */ + uint8_t (*iic_deinit)(void); /**< point to a iic_deinit function address */ + uint8_t (*iic_write)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a iic_write function address */ + uint8_t (*iic_read)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a iic_read function address */ + void (*debug_print)(const char *const fmt, ...); /**< point to a debug_print function address */ + void (*receive_callback)(uint8_t type); /**< point to a receive_callback function address */ + void (*delay_ms)(uint32_t ms); /**< point to a delay_ms function address */ + uint8_t inited; /**< inited flag */ +} ds3231_handle_t; + + +uint8_t DS3231_Init(void); +uint8_t DS3231_GetTime(DS3231_Time_t *t); +uint8_t DS3231_ReadAll(uint8_t *buf); + + +#endif diff --git a/demo/i2c/ds3231/ds3231_stc8h3k.c b/demo/i2c/ds3231/ds3231_stc8h3k.c new file mode 100644 index 0000000..b00d625 --- /dev/null +++ b/demo/i2c/ds3231/ds3231_stc8h3k.c @@ -0,0 +1,81 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*** + * Demo: ZS-042, DS3231 I2C RTC/TCXO/Crystal + * Board: STC8H3K32 + * + * P32 -> SCL + * P33 -> SDA + * GND -> GND + * 3.3V -> VCC + */ + +#include "fw_hal.h" +#include "ds3231.h" + +void I2C_Init(void) +{ + // Master mode + I2C_SetWorkMode(I2C_WorkMode_Master); + /** + * I2C clock = FOSC / 2 / (__prescaler__ * 2 + 4) + */ + I2C_SetClockPrescaler(0x3F); + // Switch alternative port + I2C_SetPort(I2C_AlterPort_P32_P33); + // Start I2C + I2C_SetEnabled(HAL_State_ON); +} + +void GPIO_Init(void) +{ + // SDA + GPIO_P3_SetMode(GPIO_Pin_3, GPIO_Mode_InOut_QBD); + // SCL + GPIO_P3_SetMode(GPIO_Pin_2, GPIO_Mode_Output_PP); +} + +int main(void) +{ + DS3231_Time_t t; + uint8_t i, buf[19]; + + SYS_SetClock(); + // UART1 configuration: baud 115200 with Timer2, 1T mode, no interrupt + UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200); + + GPIO_Init(); + I2C_Init(); + DS3231_Init(); + + while(1) + { + DS3231_GetTime(&t); + UART1_TxHex(t.year >> 8); + UART1_TxHex(t.year & 0xFF); + UART1_TxChar('-'); + UART1_TxHex(t.month); + UART1_TxChar('-'); + UART1_TxHex(t.date); + UART1_TxChar(' '); + UART1_TxHex(t.hour); + UART1_TxChar(':'); + UART1_TxHex(t.minute); + UART1_TxChar(':'); + UART1_TxHex(t.second); + UART1_TxString("\r\n"); + SYS_Delay(1000); + } +} diff --git a/demo/i2c/mpu6050/main.c b/demo/i2c/mpu6050/main.c index f5e0023..0907eaf 100644 --- a/demo/i2c/mpu6050/main.c +++ b/demo/i2c/mpu6050/main.c @@ -30,7 +30,7 @@ void I2C_Init(void) // Master mode I2C_SetWorkMode(I2C_WorkMode_Master); /** - * I2C clock = SYSCLK / 2 / (__prescaler__ * 2 + 4) + * I2C clock = FOSC / 2 / (__prescaler__ * 2 + 4) * MPU6050 works with i2c clock up to 400KHz * * 44.2368 / 2 / (26 * 2 + 4) = 0.39 MHz diff --git a/demo/i2c/ssd1306/ssd1306_stc8h3k.c b/demo/i2c/ssd1306/ssd1306_stc8h3k.c index 84d2d77..2d59be2 100644 --- a/demo/i2c/ssd1306/ssd1306_stc8h3k.c +++ b/demo/i2c/ssd1306/ssd1306_stc8h3k.c @@ -13,7 +13,7 @@ // limitations under the License. /*** - * Demo: SSD1306 12864 OLED + * Demo: SSD1306/SSD1315 12864 OLED * Board: STC8H3K32 * * P32 -> SCL @@ -30,7 +30,7 @@ void I2C_Init(void) // Master mode I2C_SetWorkMode(I2C_WorkMode_Master); /** - * I2C clock = SYSCLK / 2 / (__prescaler__ * 2 + 4) + * I2C clock = FOSC / 2 / (__prescaler__ * 2 + 4) * SSD1306 works with i2c clock up to 1.3 MHz, beyond this value, display may fail. */ I2C_SetClockPrescaler(0x10);