-
Notifications
You must be signed in to change notification settings - Fork 5.4k
增加外部RTC驱动,使用DS1307模块演示 #11458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
wenzhi346
wants to merge
6
commits into
RT-Thread:master
Choose a base branch
from
wenzhi346:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+735
−0
Open
增加外部RTC驱动,使用DS1307模块演示 #11458
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| /** | ||
| * @file drv_rtc.c | ||
| * @brief RT-Thread RTC device driver (通用外接RTC芯片框架) | ||
| * | ||
| * 支持通过 rtconfig.h 中的宏定义选择 RTC 芯片: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| * BSP_USING_DS1307 - DS1307 (I2C addr 0x68, 5V) | ||
| * BSP_USING_PCF8563 - PCF8563 (I2C addr 0x51, 3.3V) | ||
| * | ||
| * 添加新芯片: 在下方加 #elif 分支,实现 init/get_time/set_time 即可 | ||
| * | ||
| * 引脚: GP34(SDA), GP35(SCL) | ||
| */ | ||
|
|
||
| #include <rtthread.h> | ||
| #include <rtdevice.h> | ||
| #include <time.h> | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
|
|
||
| /* ========== RTC 芯片选择 ========== */ | ||
| #if defined(BSP_USING_DS1307) | ||
| # include "ds1307.h" | ||
| # define RTC_INIT() ds1307_init() | ||
| # define RTC_GET_TIME(t) ds1307_get_time(t) | ||
| # define RTC_SET_TIME(t) ds1307_set_time(t) | ||
| # define RTC_CHIP_NAME "DS1307" | ||
|
|
||
| #elif defined(BSP_USING_PCF8563) | ||
| # include "pcf8563.h" | ||
| # define RTC_INIT() pcf8563_init() | ||
| # define RTC_GET_TIME(t) pcf8563_get_time(t) | ||
| # define RTC_SET_TIME(t) pcf8563_set_time(t) | ||
| # define RTC_CHIP_NAME "PCF8563" | ||
|
|
||
| #else | ||
| # error "RTC chip not selected! Define BSP_USING_DS1307 or BSP_USING_PCF8563 in rtconfig.h" | ||
| #endif | ||
|
|
||
| static struct rt_device g_rtc_dev; | ||
|
|
||
| static rt_err_t ns800_rtc_init(struct rt_device *dev) | ||
| { | ||
| rt_err_t result = RTC_INIT(); | ||
| if (result != RT_EOK) { | ||
| rt_kprintf("RTC: %s init failed!\n", RTC_CHIP_NAME); | ||
| return result; | ||
| } | ||
| rt_kprintf("RTC: %s init success!\n", RTC_CHIP_NAME); | ||
| return RT_EOK; | ||
| } | ||
|
|
||
| static rt_err_t ns800_rtc_open(struct rt_device *dev, rt_uint16_t oflag) | ||
| { | ||
| return RT_EOK; | ||
| } | ||
|
|
||
| static rt_err_t ns800_rtc_close(struct rt_device *dev) | ||
| { | ||
| return RT_EOK; | ||
| } | ||
|
|
||
| static rt_err_t ns800_rtc_control(struct rt_device *dev, int cmd, void *args) | ||
| { | ||
| rt_err_t result = RT_EOK; | ||
| struct tm time_struct; | ||
| time_t *time = (time_t *)args; | ||
|
|
||
| switch (cmd) { | ||
| case RT_DEVICE_CTRL_RTC_GET_TIME: | ||
| result = RTC_GET_TIME(&time_struct); | ||
| if (result == RT_EOK) { | ||
| *time = mktime(&time_struct); | ||
| } | ||
| break; | ||
|
|
||
| case RT_DEVICE_CTRL_RTC_SET_TIME: | ||
| result = RTC_SET_TIME(localtime(time)); | ||
| break; | ||
|
|
||
| default: | ||
| result = -RT_ENOSYS; | ||
| break; | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| int rt_hw_rtc_init(void) | ||
| { | ||
| rt_err_t result; | ||
|
|
||
| g_rtc_dev.type = RT_Device_Class_RTC; | ||
| g_rtc_dev.init = ns800_rtc_init; | ||
| g_rtc_dev.open = ns800_rtc_open; | ||
| g_rtc_dev.close = ns800_rtc_close; | ||
| g_rtc_dev.read = RT_NULL; | ||
| g_rtc_dev.write = RT_NULL; | ||
| g_rtc_dev.control = ns800_rtc_control; | ||
|
|
||
| result = rt_device_register(&g_rtc_dev, "rtc", | ||
| RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); | ||
| if (result != RT_EOK) { | ||
| rt_kprintf("RTC: device register failed!\n"); | ||
| return -1; | ||
| } | ||
| rt_kprintf("RTC: device registered successfully!\n"); | ||
|
|
||
| result = ns800_rtc_init(&g_rtc_dev); | ||
| if (result != RT_EOK) { | ||
| rt_kprintf("[MAIN] RTC hardware init FAILED!\n"); | ||
| return -1; | ||
| } | ||
| rt_kprintf("[MAIN] RTC hardware init SUCCESS! Ready to use.\n"); | ||
| return 0; | ||
| } | ||
|
|
||
| /* MSH cmd: use FINSH_FUNCTION_EXPORT instead */ | ||
| static void show_rtc(void) | ||
| { | ||
| time_t now; | ||
| rt_device_t dev = rt_device_find("rtc"); | ||
| if (dev) { | ||
| rt_device_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, &now); | ||
| rt_kprintf("[RTC] %s", ctime(&now)); | ||
| } | ||
| } | ||
| #include <finsh.h> | ||
| FINSH_FUNCTION_EXPORT(show_rtc, show rtc time) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /** | ||
| * @file drv_rtc.h | ||
| * @brief NS800RT7P65D RTC driver header file | ||
| */ | ||
|
|
||
| #ifndef __DRV_RTC_H__ | ||
| #define __DRV_RTC_H__ | ||
|
|
||
| #include <rtthread.h> | ||
| #include <rtdevice.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
|
|
||
| int rt_hw_rtc_init(void); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* __DRV_RTC_H__ */ |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rtthread有软件I2C框架,不建议直接用IO去操作,建议使用标准I2C去实现通讯/使用硬件I2C驱动 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| /* | ||
| * Copyright (c) 2026, NS800RT7P65D RTC Driver | ||
| * | ||
| * DS1307 RTC driver - GPIO bitbang I2C | ||
| * | ||
| * Hardware: DS1307 RTC module, I2C address 0x68, 5V supply | ||
| * Pins: PB2(SDA/GP34), PB3(SCL/GP35) | ||
| * | ||
| * NS800 GPIO configuration requirements: | ||
| * GPIO_setAnalogMode(..., GPIO_ANALOG_DISABLED) - enable digital input | ||
| * GPIO_setQualificationMode(..., GPIO_QUAL_ASYNC) - bypass input sampling | ||
| */ | ||
|
|
||
| #include <rtthread.h> | ||
| #include <rthw.h> | ||
| #include <string.h> | ||
| #include "ds1307.h" | ||
| #include "gpio.h" | ||
| #include "board.h" | ||
|
|
||
| #define ADDR 0x68 | ||
| #define PORT GPIOB | ||
| #define PIN_SDA GPIO_PIN_2 | ||
| #define PIN_SCL GPIO_PIN_3 | ||
| #define DELAY_CNT 3000 | ||
|
|
||
| /* ========== I2C bitbang primitives ========== */ | ||
| static void dly(void) { volatile uint32_t i; for(i=0;i<DELAY_CNT;i++); } | ||
|
|
||
| static void sda_l(void) { GPIO_setDirectionMode(PORT,PIN_SDA,GPIO_DIR_MODE_OUT); GPIO_clearPin(PORT,PIN_SDA); dly(); } | ||
| static void sda_h(void) { GPIO_setDirectionMode(PORT,PIN_SDA,GPIO_DIR_MODE_IN); dly(); } | ||
| static void scl_l(void) { GPIO_setDirectionMode(PORT,PIN_SCL,GPIO_DIR_MODE_OUT); GPIO_clearPin(PORT,PIN_SCL); dly(); } | ||
| static void scl_h(void) { GPIO_setDirectionMode(PORT,PIN_SCL,GPIO_DIR_MODE_IN); dly(); } | ||
| static uint8_t sda_r(void) { GPIO_setDirectionMode(PORT,PIN_SDA,GPIO_DIR_MODE_IN); return GPIO_readPin(PORT,PIN_SDA); } | ||
|
|
||
| static void i2c_init(void) | ||
| { | ||
| GPIO_setPinConfig(GPIO_34_GPIO34); | ||
| GPIO_setPinConfig(GPIO_35_GPIO35); | ||
| GPIO_setPadConfig(PORT,PIN_SDA,GPIO_PIN_TYPE_STD|GPIO_PIN_TYPE_PULLUP); | ||
| GPIO_setPadConfig(PORT,PIN_SCL,GPIO_PIN_TYPE_STD|GPIO_PIN_TYPE_PULLUP); | ||
| GPIO_setAnalogMode(PORT,PIN_SDA,GPIO_ANALOG_DISABLED); | ||
| GPIO_setAnalogMode(PORT,PIN_SCL,GPIO_ANALOG_DISABLED); | ||
| GPIO_setQualificationMode(PORT,PIN_SDA,GPIO_QUAL_ASYNC); | ||
| GPIO_setQualificationMode(PORT,PIN_SCL,GPIO_QUAL_ASYNC); | ||
| sda_h(); scl_h(); | ||
| } | ||
|
|
||
| static void i2c_sta(void) { sda_h();scl_h();dly();sda_l();scl_l(); } | ||
| static void i2c_sto(void) { sda_l();scl_h();dly();sda_h();dly(); } | ||
| static void i2c_bit(uint8_t b) { if(b)sda_h();else sda_l(); scl_h();scl_l(); } | ||
|
|
||
| static int i2c_send(uint8_t d) { | ||
| for(int i=7;i>=0;i--) i2c_bit((d>>i)&1); | ||
| sda_h();scl_h();dly(); int ack=sda_r()?1:0; scl_l();dly(); return ack; | ||
| } | ||
|
|
||
| static uint8_t i2c_recv(uint8_t nak) { | ||
| uint8_t d=0; sda_h(); | ||
| for(int i=7;i>=0;i--){ sda_h();dly();scl_h();dly(); if(sda_r()) d|=(1<<i); scl_l();dly(); } | ||
| if(nak)sda_h();else sda_l(); dly(); scl_h();dly();scl_l();dly();sda_h(); return d; | ||
| } | ||
|
|
||
| /* ========== DS1307 access ========== */ | ||
| static int ds_write(uint8_t reg, uint8_t *data, uint8_t len) { | ||
| rt_base_t l=rt_hw_interrupt_disable(); int r=0; | ||
| i2c_sta(); if(i2c_send(ADDR<<1)){i2c_sto();r=-1;goto out;} | ||
| if(i2c_send(reg)){i2c_sto();r=-1;goto out;} | ||
| for(int i=0;i<len;i++) if(i2c_send(data[i])){i2c_sto();r=-1;goto out;} | ||
| i2c_sto(); dly(); | ||
| out: rt_hw_interrupt_enable(l); return r; | ||
| } | ||
|
|
||
| static int ds_read(uint8_t reg, uint8_t *buf, uint8_t len) { | ||
| rt_base_t l=rt_hw_interrupt_disable(); int r=0; | ||
| i2c_sta(); if(i2c_send(ADDR<<1)){i2c_sto();r=-1;goto out2;} | ||
| if(i2c_send(reg)){i2c_sto();r=-1;goto out2;} i2c_sto(); dly(); | ||
| i2c_sta(); if(i2c_send((ADDR<<1)|1)){i2c_sto();r=-1;goto out2;} | ||
| for(int i=0;i<len;i++) buf[i]=i2c_recv(i<len-1?0:1); | ||
| i2c_sto(); dly(); | ||
| out2: rt_hw_interrupt_enable(l); return r; | ||
| } | ||
|
|
||
| /* ========== BCD helpers ========== */ | ||
| static inline uint8_t b2b(uint8_t x){return ((x>>4)*10)+(x&0xF);} | ||
| static inline uint8_t x2b(uint8_t v){return ((v/10)<<4)|(v%10);} | ||
|
|
||
| /* ========== Public API ========== */ | ||
| rt_err_t ds1307_init(void) { | ||
| uint8_t sec; i2c_init(); | ||
| rt_kprintf("[DS1307] Init...\n"); | ||
| if(ds_read(0x00,&sec,1)<0){rt_kprintf("No ACK\n");return -RT_ERROR;} | ||
| if(sec&0x80){sec&=0x7F; ds_write(0x00,&sec,1); rt_kprintf("Clock started\n");} | ||
| rt_kprintf("OK\n"); return RT_EOK; | ||
| } | ||
|
|
||
| rt_err_t ds1307_get_time(struct tm *t) { | ||
| uint8_t b[7]; if(!t||ds_read(0x00,b,7)<0) return -RT_ERROR; | ||
| memset(t,0,sizeof(*t)); | ||
| t->tm_sec=b2b(b[0]&0x7F); t->tm_min=b2b(b[1]&0x7F); t->tm_hour=b2b(b[2]&0x3F); | ||
| t->tm_mday=b2b(b[3]&0x3F); t->tm_wday=b[4]&0x07; t->tm_mon=b2b(b[5]&0x1F)-1; | ||
| t->tm_year=b2b(b[6])+100; return RT_EOK; | ||
| } | ||
|
|
||
| rt_err_t ds1307_set_time(struct tm *t) { | ||
| if(!t) return -RT_ERROR; | ||
| uint8_t v; | ||
| v=x2b(t->tm_year-100); if(ds_write(0x06,&v,1)<0) return -RT_ERROR; | ||
| v=x2b(t->tm_mon+1); if(ds_write(0x05,&v,1)<0) return -RT_ERROR; | ||
| v=x2b(t->tm_mday); if(ds_write(0x04,&v,1)<0) return -RT_ERROR; | ||
| v=t->tm_wday&0x07; if(ds_write(0x03,&v,1)<0) return -RT_ERROR; | ||
| v=x2b(t->tm_hour); if(ds_write(0x02,&v,1)<0) return -RT_ERROR; | ||
| v=x2b(t->tm_min); if(ds_write(0x01,&v,1)<0) return -RT_ERROR; | ||
| v=x2b(t->tm_sec); if(ds_write(0x00,&v,1)<0) return -RT_ERROR; | ||
| return RT_EOK; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| * @file ds1307.h | ||
| * @brief DS1307 RTC driver header | ||
| * | ||
| * Hardware: DS1307 RTC module, I2C address 0x68 | ||
| * Interface kept as ds1307_* for compatibility with drv_rtc.c | ||
| */ | ||
|
|
||
| #ifndef __DS1307_H__ | ||
| #define __DS1307_H__ | ||
|
|
||
| #include <rtthread.h> | ||
| #include <time.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| rt_err_t ds1307_init(void); | ||
| rt_err_t ds1307_get_time(struct tm *time); | ||
| rt_err_t ds1307_set_time(struct tm *time); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* __DS1307_H__ */ |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RTC这块需要对接到:components/drivers/rtc/dev_rtc.c