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);
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);
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;
tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
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);
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
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);
buf[PCF8563_REG_MO] = bin2bcd(tm.tm_mon + 1);
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;
buf[PCF8563_REG_MO] |= Centurybit;
buf[PCF8563_REG_DW] = tm.tm_wday & 0x07;
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