嵌入式技术论坛
直播中

王飞云

8年用户 1579经验值
私信 关注
[经验]

实时时钟RTC(PCF5863)驱动移植代码分享

PCF8563驱动其实并不多,主要就是两个函数。

pcf8563_get_datetime 和 pcf8563_set_datetime。 写完这两个也是基本完成了。

参考rtc_pcf8563.c rtc_pcf8563.rar 代码改写。

改写后部分内容如下:

pcf8563.h内容:

#ifndef _PCF8563_H
#define _PCF8563_H

#define RTC_RD_TIME 0
#define RTC_SET_TIME 1

typedef struct
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_wday;
int tm_mon;
int tm_year;
}rtc_time_t;

#endif

pcf8563.c内容:

主要也就是pcf8563_get_datetime 和 pcf8563_set_datetime两个函数和一个控制调用函数(pcf8563_rtc_ioctl),现就列这几个吧,其他就不贴出来了。

一些宏定义:

#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01

#define PCF8563_REG_SC 0x02 /* datetime */
#define PCF8563_REG_MN 0x03
#define PCF8563_REG_HR 0x04
#define PCF8563_REG_DM 0x05
#define PCF8563_REG_DW 0x06
#define PCF8563_REG_MO 0x07
#define PCF8563_REG_YR 0x08

#define PCF8563_REG_AMN 0x09 /* alarm */
#define PCF8563_REG_AHR 0x0A
#define PCF8563_REG_ADM 0x0B
#define PCF8563_REG_ADW 0x0C

#define PCF8563_REG_CLKO 0x0D /* clock out /
#define PCF8563_REG_TMRC 0x0E /
timer control /
#define PCF8563_REG_TMR 0x0F /
timer */

#define PCF8563_SC_LV 0x80 /* low voltage /
#define PCF8563_MO_C 0x80 /
century */

#define I2C_PCF8563 0xA2

static inline
int bin2bcd (int x)
{
return (x%10) | ((x/10) << 4);
}

static inline
int bcd2bin (int x)
{
return (x >> 4) * 10 + (x & 0x0f);
}

读RTC pcf8563数据:

static int pcf8563_get_datetime(int i2c_devaddress , rtc_time_t tm)
{
unsigned char buf[PCF8563_REG_YR+1] = { PCF8563_REG_ST1 };
/
status */
//buf[PCF8563_REG_ST1] = hi_i2c_read(i2c_devaddress, PCF8563_REG_ST1);
//buf[PCF8563_REG_ST2] = hi_i2c_read(i2c_devaddress, PCF8563_REG_ST2);

/* datetime */ 
    buf[PCF8563_REG_SC] = hi_i2c_read(i2c_devaddress, PCF8563_REG_SC); 
    buf[PCF8563_REG_MN] = hi_i2c_read(i2c_devaddress, PCF8563_REG_MN); 
    buf[PCF8563_REG_HR] = hi_i2c_read(i2c_devaddress, PCF8563_REG_HR); 
    buf[PCF8563_REG_DM] = hi_i2c_read(i2c_devaddress, PCF8563_REG_DM); 
    buf[PCF8563_REG_DW] = hi_i2c_read(i2c_devaddress, PCF8563_REG_DW); 
    buf[PCF8563_REG_MO] = hi_i2c_read(i2c_devaddress, PCF8563_REG_MO); 
    buf[PCF8563_REG_YR] = hi_i2c_read(i2c_devaddress, PCF8563_REG_YR); 
    buf[PCF8563_REG_ST1] = hi_i2c_read(i2c_devaddress, PCF8563_REG_ST1); 
    
    tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
    tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
    tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
    tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
    tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
    tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
    tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);

  #if 0
    printk("%s: secs=%d, mins=%d, hours=%d, "
            "mday=%d, mon=%d, year=%d, wday=%d\n",
            __func__ ,
            tm->tm_sec, tm->tm_min, tm->tm_hour,
            tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
  #endif 
    
    // Century bit. C = 0; indicates the century is 20xx.
 // C = 1; indicates the century is 19xx. 
    if(buf[PCF8563_REG_MO] & PCF8563_MO_C) 
        tm->tm_year += 1900; 
    else
        tm->tm_year += 2000; 
    return 0;

}

写RTC pcf8563数据:

static int pcf8563_set_datetime(int i2c_devaddress , rtc_time_t tm)
{
unsigned char buf[9];
int Centurybit;
#if 0
printk("%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
func,
tm.tm_sec, tm.tm_min, tm.tm_hour,
tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday);
#endif

/* hours, minutes and seconds */
    buf[PCF8563_REG_SC] = bin2bcd(tm.tm_sec);
    buf[PCF8563_REG_MN] = bin2bcd(tm.tm_min);
    buf[PCF8563_REG_HR] = bin2bcd(tm.tm_hour);

    buf[PCF8563_REG_DM] = bin2bcd(tm.tm_mday);

    /* month, 1 - 12 */
    buf[PCF8563_REG_MO] = bin2bcd(tm.tm_mon + 1);

    /* year and century */
    buf[PCF8563_REG_YR] = bin2bcd(tm.tm_year % 100);
    
    if (tm.tm_year >= 1900 && tm.tm_year < 2000)
        Centurybit = PCF8563_MO_C;
    else if (tm.tm_year >= 2000 && tm.tm_year < 3000)
        Centurybit = 0;
    else
        return -1;
    
    // Century bit. C = 0; indicates the century is 20xx.
 // C = 1; indicates the century is 19xx.    
    buf[PCF8563_REG_MO] |= Centurybit; //add Century bit    

    buf[PCF8563_REG_DW] = tm.tm_wday & 0x07;

    /* write register's data */
    hi_i2c_write(i2c_devaddress, PCF8563_REG_SC, buf[PCF8563_REG_SC]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_MN, buf[PCF8563_REG_MN]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_HR, buf[PCF8563_REG_HR]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_DM, buf[PCF8563_REG_DM]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_MO, buf[PCF8563_REG_MO]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_YR, buf[PCF8563_REG_YR]);
    hi_i2c_write(i2c_devaddress, PCF8563_REG_DW, buf[PCF8563_REG_DW]);

    return 0;

}

相关控制调用函数:

static int pcf8563_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
rtc_time_t tm;
switch (cmd)
{
case RTC_RD_TIME:
pcf8563_get_datetime(i2c_pcf8563, &tm);
return copy_to_user((void *)arg, &tm, sizeof(tm)) ? -EFAULT : 0;
case RTC_SET_TIME:
if (copy_from_user(&tm, (struct rtc_time_t *) arg, sizeof(tm)))
return -EFAULT;
return pcf8563_set_datetime(i2c_pcf8563, tm);
}
return 0;
}
static struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
.ioctl = pcf8563_rtc_ioctl,
.open = pcf8563_open,
.release = pcf8563_close
};
static struct miscdevice pcf8563_dev = {
MISC_DYNAMIC_MINOR,
"pcf8563",
&pcf8563_fops,
};

原作者:a746742897

回帖(1)

国产对标IC

2022-12-28 10:08:58
国产AIP8563可替代nxp8563
举报

更多回帖

发帖
×
20
完善资料,
赚取积分