参考网址:http://blog.chinaunix.net/uid-23404636-id-2369606.html
由于产品板中没有PCF8563驱动,需要写驱动程序。
PCF8563驱动其实并不多,主要就是两个函数。
pcf8563_get_datetime 和 pcf8563_set_datetime。 写完这两个也是基本完成了。
参考rtc_pcf8563.c
rtc_pcf8563.rar 代码改写。
![](http://blog.chinaunix.net/blog/image/attachicons/rar.gif)
改写后部分内容如下:
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,
- };