【RT-Thread】高精度RTC rx8900 驱动软件包

 2023-09-05 阅读 95 评论 0

摘要:文章目录1 介绍1.1 支持功能1.2 目录结构1.3 许可证1.4 依赖2 实现功能2.1 rx8900驱动描述2.2 rx8900读寄存器接口2.3 rx8900写寄存器接口2.4 RT-Thread设备虚拟文件接口2.5 片内温度获取接口2.6 rtc设备注册rx8900设备注册rx8900私有信息初始化3 获取 rx8900 软件包4 使用 r

文章目录

  • 1 介绍
    • 1.1 支持功能
    • 1.2 目录结构
    • 1.3 许可证
    • 1.4 依赖
  • 2 实现功能
    • 2.1 rx8900驱动描述
    • 2.2 rx8900读寄存器接口
    • 2.3 rx8900写寄存器接口
    • 2.4 RT-Thread设备虚拟文件接口
    • 2.5 片内温度获取接口
    • 2.6 rtc设备注册
      • rx8900设备注册
      • rx8900私有信息初始化
  • 3 获取 rx8900 软件包
  • 4 使用 rx8900 软件包
    • 4.1 初始化
    • 4.2 使用方式
    • 4.3 msh/finsh测试
  • 5 注意事项
  • 6 联系方式
  • 7 相关文章

1 介绍

  rx8900 软件包是针对RT-Thread驱动框架实现的实时时钟驱动,遵循RT-Thread RTC框架,可以从芯片内置RTC无缝切换使用外置高精度rx8900 RTC。rx8900是爱普生公司一款i2c接口的高精度RTC芯片,集成32768Hz晶振和温度传感器,并能根据环境温度调整频率,具有供电范围灵活、待机电流低、走时精度高等优点。

在这里插入图片描述

1.1 支持功能

  • 实时时钟
  • 闹钟
  • 片内温度读取

1.2 目录结构

名称说明
docs文档目录
inc头文件目录
src源代码目录
LICENSE许可证文件
SConscriptRT-Thread默认构建脚本

1.3 许可证

rx8900 软件包遵循 Apache license v2.0 许可,详见 LICENSE 文件。


1.4 依赖

  • RT-Thread 3.0+
  • RT-Thread I2C设备驱动框架
  • RT-Thread RTC设备驱动框架

2 实现功能

  实现rx8900驱动层的函数接口。

在这里插入图片描述


2.1 rx8900驱动描述

  RT-Thread rtc驱动设备继承其标准设备驱动,使用struct rt_device描述rx8900设备。rx8900访问接口是i2c,依赖于RT-Thread i2c总线框架,我们使用struct rt_device的私有数据user_data保存rx8900的i2c设备总线信息。后面过程则是实现struct rt_device函数指针实体。

/*** Device structure*/
struct rt_device
{struct rt_object          parent;                   /**< inherit from rt_object */enum rt_device_class_type type;                     /**< device type */rt_uint16_t               flag;                     /**< device flag */rt_uint16_t               open_flag;                /**< device open flag */rt_uint8_t                ref_count;                /**< reference count */rt_uint8_t                device_id;                /**< 0 - 255 *//* device call back */rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);#ifdef RT_USING_DEVICE_OPSconst struct rt_device_ops *ops;
#else/* common device interface */rt_err_t  (*init)   (rt_device_t dev);rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);rt_err_t  (*close)  (rt_device_t dev);rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
#endif#if defined(RT_USING_POSIX)const struct dfs_file_ops *fops;struct rt_wqueue wait_queue;
#endifvoid                     *user_data;                /**< device private data */
};
static struct rt_device rx8900_dev;		/* rx8900 device */

2.2 rx8900读寄存器接口

static rt_err_t  rx8900_write_reg(rt_device_t dev, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t data_size)
  • dev,rx8900设备描述地址
  • reg,寄存器地址
  • data,返回数据地址(缓存)
  • data_size,读取数据长度
  • 返回值,成功返回RT_EOK

2.3 rx8900写寄存器接口

static rt_err_t  rx8900_write_reg(rt_device_t dev, rt_uint8_t reg, rt_uint8_t *data, rt_uint8_t data_size)
  • dev,rx8900设备描述地址
  • reg,寄存器地址
  • data,待写数据地址
  • data_size,待写数据长度
  • 返回值,成功返回RT_EOK

2.4 RT-Thread设备虚拟文件接口

  RT-Thread设备虚拟文件接口,常用有open/read/write/control/close,RT-Thread rtc设备框架中,关于时间和闹钟的设置,使用的是control接口,实现该接口具体功能内容。

  • 获取实时时间
/* get time */case RT_DEVICE_CTRL_RTC_GET_TIME:time = (time_t *)args;ret = rx8900_read_reg(dev, REG_SEC, buff, 7);if(ret == RT_EOK){time_temp.tm_year  = bcd_to_hex(buff[6]) + 2000 - 1900;time_temp.tm_mon   = bcd_to_hex(buff[5]&0x1f) - 1;time_temp.tm_mday  = bcd_to_hex(buff[4]&0x3f);time_temp.tm_hour  = bcd_to_hex(buff[2]&0x3f);time_temp.tm_min   = bcd_to_hex(buff[1]&0x7f);time_temp.tm_sec   = bcd_to_hex(buff[0]&0x7f);*time = mktime(&time_temp);}break;
  • 设置实时时间
/* set time */case RT_DEVICE_CTRL_RTC_SET_TIME:{struct tm *time_new;time = (time_t *)args;time_new = localtime(time);buff[6] = hex_to_bcd(time_new->tm_year + 1900 - 2000);buff[5] = hex_to_bcd(time_new->tm_mon + 1);buff[4] = hex_to_bcd(time_new->tm_mday);buff[3] = hex_to_bcd(time_new->tm_wday+1);buff[2] = hex_to_bcd(time_new->tm_hour);buff[1] = hex_to_bcd(time_new->tm_min);buff[0] = hex_to_bcd(time_new->tm_sec);ret = rx8900_write_reg(dev, REG_SEC, buff, 7);}break;
  • 获取闹钟时间

  rx8900闹钟模式支持的最小精度是1分钟,因此闹钟秒数值(tm_sec)应设置为0。rx8900支持天数和星期闹钟,RT-Thread目前闹钟框架暂时支持时分秒匹配,天数和星期由软件实现。

/* get alarm time */case RT_DEVICE_CTRL_RTC_GET_ALARM:{ 	struct rt_rtc_wkalarm *alm_time;rt_uint8_t state[3] = {0x00};		ret = rx8900_read_reg(dev, REG_ALM_MIN, buff, 2);if(ret != RT_EOK){return -RT_ERROR;}alm_time = (struct rt_rtc_wkalarm *)args;alm_time->tm_hour  = bcd_to_hex(buff[1]&0x7f);	alm_time->tm_min   = bcd_to_hex(buff[0]&0x7f);alm_time->tm_sec   = 0;	/* hardware alarm precision is 1 minute */ret = rx8900_read_reg(dev, RGE_EXT, state, 3);if(ret != RT_EOK){return -RT_ERROR;}if (state[0] & VALUE_EXT_WADA){/* day alarm *//* todo, RTT not supported temporarily */	}else{/* week day alarm *//* todo, RTT not supported temporarily */}}
  • 设置闹钟时间

  针对RT-Thread闹钟框架,rx8900闹钟禁止天数(tm_day)和星期(tm_wday)匹配功能,只设置小时(tm_hour)和分钟(tm_minute),同时将秒数(tm_sec)设为0。

/* set alarm time */case RT_DEVICE_CTRL_RTC_SET_ALARM:{struct rt_rtc_wkalarm *alm_time;rt_uint8_t ctrl[2] = {0x00};alm_time = (struct rt_rtc_wkalarm *)args;buff[2] = ALM_DISABLE(0x00);	/* week and day alarm disable */	buff[1] = hex_to_bcd(ALM_ENABLE(alm_time->tm_hour));/* enable, alarm when hours and minutes match */buff[0] = hex_to_bcd(ALM_ENABLE(alm_time->tm_min));ret = rx8900_read_reg(dev, REG_FLAG, ctrl, 2);if (ret != RT_EOK){return -RT_ERROR;}if (ctrl[0]&VALUE_EXT_WADA){/* day alarm *//* todo, RTT not supported temporarily */}else{/* week day alarm *//* todo, RTT not supported temporarily */}/* write to hardware */ret = rx8900_write_reg(dev, REG_ALM_MIN, buff, 3);if (ret != RT_EOK){return -RT_ERROR;}/* clear alarm flag */ctrl[1] &= ~VALUE_FLAG_AF;ret = rx8900_write_reg(dev, REG_FLAG, &ctrl[1], 1);}break;

2.5 片内温度获取接口

  rx8900内部集成一个温度传感器和温度校准系数,读取温度寄存器值通过一定的换算公式计算出实际温度。rx8900芯片手册提供摄氏度(℃)与寄存器值转换公式如下。

在这里插入图片描述

寄存器值与温度转换

  获取温度接口

/**  @brief  Read temperature from rx8900*  @return Celsius temperature,-55~+125C,0.1C     */
float rx8900_get_temperature(void)
{rt_uint8_t value = 0;float temp = 0.0f;rx8900_read_reg(&rx8900_dev, REG_TEMP, (rt_uint8_t*)&value, 1);temp = (value*2-187.19)/3.218;return temp;
}

  我们把温度读取接口注册到RT-Thread的调试终端(msh/finsh),方便测试。

#ifdef RT_USING_FINSH
#include <finsh.h>void list_rx89_temp(void)
{float temp = 0.0f;temp = rx8900_get_temperature();rt_kprintf("rx8900 temperature: [%d.%dC] \n", (int)temp, (int)(temp * 10) % 10);
}
FINSH_FUNCTION_EXPORT(list_rx89_temp, list rx8900 temperature.)
#endif /* RT_USING_FINSH */#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
MSH_CMD_EXPORT(list_rx89_temp, list rx8900 temperature.);
#endif /* RT_USING_FINSH & FINSH_USING_MSH */

2.6 rtc设备注册

rx8900设备注册

  • rx8900使用的是系统“i2c1”,i2c1驱动请自行初始化注册;否则rx8900设备注册失败
  • rx8900设备中user_data保存i2c1总线信息,用于后续访问rx8900
  • rx8900设备名称保持与rtc设备框架的rtc名称一致,统一为“rtc”
int rt_hw_rx8900_init(void)
{	struct rt_i2c_bus_device *i2c_bus =RT_NULL;rt_uint8_t flags = 0;rt_bool_t  need_clear = RT_FALSE;rt_bool_t  need_reset = RT_FALSE;i2c_bus = rt_i2c_bus_device_find(RX8900_I2C_BUS);if (i2c_bus == RT_NULL){LOG_E("i2c bus device %s not found!\r\n", RX8900_I2C_BUS);return -RT_ERROR;}				 	/* register rtc device */rx8900_dev.type   	= RT_Device_Class_RTC;rx8900_dev.init    	= RT_NULL;rx8900_dev.open    	= rt_rx8900_open;rx8900_dev.close   	= RT_NULL;rx8900_dev.read   	= rt_rx8900_read;rx8900_dev.write  	= RT_NULL;rx8900_dev.control 	= rt_rx8900_control;rx8900_dev.user_data= (void*)i2c_bus;	/* save i2cbus */rt_device_register(&rx8900_dev, RX8900_DEVICE_NAME, RT_DEVICE_FLAG_RDWR);......
}

rx8900私有信息初始化

  rx8900私有信息初始化主要包括:

  • 获取rx8900状态寄存器值
  • 根据状态寄存器值每一bit的含义执行复位、初始化操作或者清除状态寄存器操作
	if (flags & VALUE_FLAG_VDET){LOG_D("Temperature compensation stop detected.\n");need_clear = RT_TRUE;}/* alarm */if (flags & VALUE_FLAG_AF) { LOG_D("Alarm was detected.\n");need_clear = RT_TRUE;}/* timer */if (flags & VALUE_FLAG_TF) {  LOG_D("Timer was detected.\n");need_clear = RT_TRUE;}......

3 获取 rx8900 软件包

  使用 rx8900 package, 需要在 RT-Thread 的包管理器中选择它,具体路径如下:

RT-Thread online packages --->peripheral libraries and drivers --->[*] extren rtc drivers  --->[*] rx8900:Extern RTC drivers fo rx8900 Version (latest)  --->

在这里插入图片描述
  然后让 RT-Thread 的包管理器自动更新,或者执行 pkgs --update 命令更新包到 BSP 中。


4 使用 rx8900 软件包

4.1 初始化

  首先需初始化rx8900 驱动,可以手动在初始化线程合适的地方调用rt_hw_rx8900 _init()初始化,也可以直接使用INIT_DEVICE_EXPORT通过RT-Thread的自动初始化机制来初始化注册。初始化成功后,会注册名称为“rtc”的驱动设备。

INIT_DEVICE_EXPORT(rt_hw_rx8900_init);	/* 通过RTT的自动初始化机制初始化rx8900 */

注:

如果开启了芯片内部RTC,需先禁止内部RTC


4.2 使用方式

  查看设备是否注册成功。

在这里插入图片描述

  对于时间和闹钟的访问,使用RT-Thread标准RTC和闹钟接口访问。片内温度读取,则由软件包提供一个函数接口。

  • 获取当前时间
time_t time(time_t *t)
time_t now;      
now = time(RT_NULL);
  • 设置时间
 #define RT_DEVICE_CTRL_RTC_SET_TIME     0x11        /**< set time */rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
  • 获取闹钟时间
 #define RT_DEVICE_CTRL_RTC_GET_ALARM    0x12        /**< get alarm */rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
  • 设置闹钟时间
 #define RT_DEVICE_CTRL_RTC_SET_ALARM    0x13      /**< set alarm */rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)

注:

详细用法可以参考“/components/drivers/rtc.c”和“/components/drivers/alarm.c”源码。


  • 提供一个获取片内温度接口
float rx8900_get_temperature(void)

4.3 msh/finsh测试

  • msh获取时间
msh >date
Sat Jan  1 00:00:04 2000
  • msh设置时间
msh date 2020 04 10 17 41 10  
msh >date
Fri Apr 10 17:41:15 2020
  • finsh获取时间
finsh >list_date()
Fri Apr 10 17:41:49 2020
  • finsh设置时间
finsh >set_date(2020,5,1)0, 0x00000000
finsh >set_time(12,0,0)  0, 0x00000000
finsh >list_date()
Fri May  1 12:00:04 2020
  • msh打印温度
msh >list_rx89_temp
rx8900 temperature: [27.5C] 
  • finsh打印温度
finsh >list_rx89_temp()
rx8900 temperature: [27.5C]

5 注意事项

使用RT-Thread的RTC框架,RTC设备注册名称为“rtc”,注意需先屏蔽芯片内置RTC驱动。


6 联系方式

  • 维护:Acuity
  • 主页:https://github.com/Prry/rtt-rx8900

7 相关文章

【1】pcf8563匹配RT-Thread驱动
【2】RT-Thread DS3231驱动软件包

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/134.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息