RT_thread中使用ntp对时,将外部时钟BM8563挂起到I2C中读取时间

 一、首先需要把BM8563设备挂起到I2C设备总线上

根据board.h中I2C的挂起方式将I2C挂起

打开宏定义,根据你实际的管脚,把对应的管脚写进去。。

新建.c和.h文件

drv_hw_rtc_.c文件内容:

#include "drv_hw_rtc.h"

#define RTC_IIC_NAME            "i2c1"
#define RTC_IIC_WRITE_ADDR      (0XA3)
#define RTC_IIC_READ_ADDR       (0XA2)
#define RTC_IIC_ADDR            (RTC_IIC_WRITE_ADDR>>1)

#define RTC_SECOND_REG_ADDR     (0X02) //秒计数器地址
#define RTC_MINUTE_REG_ADDR     (0X03)
#define RTC_HOUR_REG_ADDR       (0X04)
#define RTC_DAY_REG_ADDR        (0X05)
#define RTC_WEEK_REG_ADDR       (0X06)
#define RTC_MONTH_REG_ADDR      (0X07)
#define RTC_YEAR_REG_ADDR       (0X08)

struct rt_i2c_bus_device* rtc_iic_handler;

/**
 * 八位无符号数转为BCD码
 * @param decimal
 * @param bcd
 */
rt_uint8_t DecimaltoBCD(rt_uint8_t decimal)
{
    return ((decimal / 10) << 4) | (decimal % 10);
}

rt_uint8_t BCDtoDecimal(rt_uint8_t BCD)
{
    return ((BCD >> 4) * 10 + (BCD & 0x0f));
}

void hw_rtc_init(void)
{
    rtc_iic_handler = (struct rt_i2c_bus_device*) rt_device_find(RTC_IIC_NAME);
    if (rtc_iic_handler == RT_NULL)
    {
        rt_kprintf("I2C Bus Not Find\n");
    }
}

rt_err_t hw_rtc_read(rt_uint8_t reg_addr, rt_uint8_t *recv_buff)
{
    struct rt_i2c_msg msgs[2];
    msgs[0].addr = RTC_IIC_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = &reg_addr;
    msgs[0].len = 1;

    msgs[1].addr = RTC_IIC_ADDR;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = recv_buff;
    msgs[1].len = 1;

    if (rt_i2c_transfer(rtc_iic_handler, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
 *
 * @param year  年 0~99
 * @param month 月
 * @param day   日
 * @return
 */
rt_err_t hw_rtc_set_date(rt_uint8_t year, rt_uint8_t month, rt_uint8_t day)
{
    rt_uint8_t buf[5];
    struct rt_i2c_msg msgs;

    //将uint8_t转为BCD码
    year = DecimaltoBCD(year);
    month = DecimaltoBCD(month);
    day = DecimaltoBCD(day);

    //寄存器起始地址 BM8563 地址会自增
    buf[0] = RTC_DAY_REG_ADDR;
    buf[1] = day;
    buf[2] = 0;
    buf[3] = month;
    buf[4] = year;

    msgs.addr = RTC_IIC_ADDR;
    msgs.flags = RT_I2C_WR;
    msgs.buf = buf;
    msgs.len = 5;

    if (rt_i2c_transfer(rtc_iic_handler, &msgs, 1) == 1)
    {
        return RT_EOK;
    }
    else
    {
        rt_kprintf("set date for hw_rtc failed\n");
        return -RT_ERROR;
    }

}

/**
 *
 * @param hour      时
 * @param minute    分
 * @param second    秒
 * @return
 */
rt_err_t hw_rtc_set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
{
    rt_uint8_t buf[4];
    struct rt_i2c_msg msgs;

    //将uint8_t转为BCD码
    second = DecimaltoBCD(second);
    minute = DecimaltoBCD(minute);
    hour = DecimaltoBCD(hour);

    //寄存器起始地址 BM8563 地址会自增
    buf[0] = RTC_SECOND_REG_ADDR;
    buf[1] = second;
    buf[2] = minute;
    buf[3] = hour;

    msgs.addr = RTC_IIC_ADDR;
    msgs.flags = RT_I2C_WR;
    msgs.buf = buf;
    msgs.len = 4;

    if (rt_i2c_transfer(rtc_iic_handler, &msgs, 1) == 1)
    {
        return RT_EOK;
    }
    else
    {
        rt_kprintf("set time for hw_rtc failed\n");
        return -RT_ERROR;
    }

}

rt_err_t hw_rtc_get_time(hw_time *tm)
{
    rt_uint8_t reg_addr = RTC_SECOND_REG_ADDR;
    rt_uint8_t recv_buffer[7] = { 0 };
    rt_uint8_t i;
    struct rt_i2c_msg msgs[2];

    msgs[0].addr = RTC_IIC_ADDR;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = &reg_addr;
    msgs[0].len = 1;

    msgs[1].addr = RTC_IIC_ADDR;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = recv_buffer;
    msgs[1].len = 7;

    if (rt_i2c_transfer(rtc_iic_handler, msgs, 2) != 2)
    {
        return -RT_ERROR;
    }

    //剔除一些不需要的位
    recv_buffer[0] &= 0x7F;
    recv_buffer[1] &= 0x7F;
    recv_buffer[2] &= 0x3F;
    recv_buffer[3] &= 0x3F;
    //星期不需要
    recv_buffer[4] &= 0x07;
    //月
    recv_buffer[5] &= 0x1F;

    //由BCD码转为十进制
    for (i = 0; i < 7; i++)
    {
        recv_buffer[i] = BCDtoDecimal(recv_buffer[i]);
    }

    tm->year = recv_buffer[6];
    tm->month = recv_buffer[5];
    tm->day = recv_buffer[3];
    tm->hour = recv_buffer[2];
    tm->min = recv_buffer[1];
    tm->sec = recv_buffer[0];

    return RT_EOK;
}

drv_hw_rtc.h内容:
typedef struct{
    rt_uint8_t year;
    rt_uint8_t month;
    rt_uint8_t day;
    rt_uint8_t hour;
    rt_uint8_t min;
    rt_uint8_t sec;
}hw_time;

void hw_rtc_init(void);
rt_err_t hw_rtc_set_date(rt_uint8_t year,rt_uint8_t month,rt_uint8_t day);
rt_err_t hw_rtc_set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second);
rt_err_t hw_rtc_get_time(hw_time *tm);
 

此程序封装了三个函数,写入年月日、写入时分秒、读取年月日时分秒的函数。

这个时候直接调用这个三个函数,写的时候需要将写入函数一起写入。

到关键了!!!!!!!!!!!!

如何使用ntp对时呢?其实rt_thread中有很成熟的软件包了!!!,只需要打开软件包就可以!

这个是rt_thread给的软件包!

这其中有三个服务器,如果你需要有特殊的接口就写特殊的,不是特殊的就默认就可以了。!!

然后就可以直接使用里面软件包封装的函数直接获取时间了!!

/*ntp对时,将时间同步到rtc bm8563中*/
void ntp_rtcget_time(void)
{
    time_t cur_time;
    cur_time = ntp_sync_to_rtc(NULL);
    if (cur_time)
    {
    struct tm *local_time = localtime(&cur_time);
     // 设置RTC时间
    hw_rtc_set_time(local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
    hw_rtc_set_date(local_time->tm_year, local_time->tm_mon, local_time->tm_mday);
    }
}

我是封装了一个函数,让程序运行起来先进行ntp对时,时间写入内部时钟里面,再从其他的地方获取时间!

  struct tm *local_time 这个结构体是rt_thread中自带的结构体,直接可以用,不需要重新定义了。

这就可以通过ntp进行对时,再把时间写入到定时器BM8563中了。

读取时间的话,直接调用我写好的hw_rtc_get_time()就可以了。这个需要自己定义一个新得结构体,系统自带得结构体数据很多,可能存在问题,所以我巨自己定义了个结构体接收。

以上就是我关于ntp对时且把获取到的时间写入到BM8563中封装好的函数了。 

如果有大佬看到小弟代码可以优化得地方,帮忙给弟弟提提把,弟弟目前还在学习阶段。感谢大佬!!!

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值