1。我们要实现通过GPIO读写 DS1302的寄存器数据;
2。首先我们需要了解下DS1302的工作方式,它提供SCL、DATA、RST三个信号,然后可以参考其时序图进行数据的读写;
3。我们现在就是要通过GPIO来模拟整个读写的时序;
4。下面的代码是linux2.4下的,当然只能适合我的CPU,应该不同的CPU的GPIO寄存器地址都不一样,如果你使用需要修改;
头文件主要定义了DS1302的操作地址、及tm时间结构等;
/* $Id: rtc.h,v 1.3 2001/03/21 09:56:31 magnusmn Exp $ */
#ifndef DS1302_H
#define DS1302_H
#include <linux/config.h>
#include <linux/ioctl.h>
/* Dallas DS1302 clock/calendar register numbers */
/*
#define RTC_SECONDS 0
#define RTC_MINUTES 1
#define RTC_HOURS 2
#define RTC_DAY_OF_MONTH 3
#define RTC_MONTH 4
#define RTC_WEEKDAY 5
#define RTC_YEAR 6
#define RTC_CONTROL 7
*/
#define RTC_SECONDS 0x80
#define RTC_MINUTES 0x82
#define RTC_HOURS 0x84
#define RTC_DAY_OF_MONTH 0x86
#define RTC_MONTH 0x88
#define RTC_WEEKDAY 0x8a
#define RTC_YEAR 0x8c
#define RTC_CONTROL 0x8e
#define RTC_TRICKLECHARGER 0x90
/* Bits in CONTROL register */
#define RTC_CONTROL_WRITEPROTECT 0x80
//#define RTC_TRICKLECHARGER 8
/* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS */
#define RTC_TCR_PATTERN 0xA0 /* 1010xxxx */
#define RTC_TCR_1DIOD 0x04 /* xxxx01xx */
#define RTC_TCR_2DIOD 0x08 /* xxxx10xx */
#define RTC_TCR_DISABLED 0x00 /* xxxxxx00 Disabled */
#define RTC_TCR_2KOHM 0x01 /* xxxxxx01 2KOhm */
#define RTC_TCR_4KOHM 0x02 /* xxxxxx10 4kOhm */
#define RTC_TCR_8KOHM 0x03 /* xxxxxx11 8kOhm */
#ifdef CONFIG_ETRAX_DS1302
#define CMOS_READ(x) ds1302_readreg(x)
#define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
#define RTC_INIT() ds1302_init()
#else
/* no RTC configured so we shouldn't try to access any */
#define CMOS_READ(x) 42
#define CMOS_WRITE(x,y)
#define RTC_INIT() (-1)
#endif
/* conversions to and from the stupid RTC internal format */
#define BCD_TO_BIN(x) x = (((x & 0xf0) >> 3) * 5 + (x & 0xf))
#define BIN_TO_BCD(x) x = (x % 10) | ((x / 10) << 4)
/*
* The struct used to pass data via the following ioctl. Similar to the
* struct tm in <time.h>, but it needs to be here so that the kernel
* source is self contained, allowing cross-compiles, etc. etc.
*/
struct rtc_time {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
#define RTC_MAJOR_NR 230
/*
* ioctl calls that are permitted to the /dev/rtc interface
*/
#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */
#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
#define RTC_SET_CHARGE _IOW('p', 0x0b, int) /* Set CHARGE mode */
//#define RTC_RD_TIME 66
//#define RTC_SET_TIME 77
//#define RTC_SET_CHARGE 88
#endif
实现文件
/*!***************************************************************************
*!
*! FILE NAME : ds1302.c
*!
*! DESCRIPTION: Implements an interface for the DS1302 RTC through Etrax I/O
*!
*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status
*! ---------------------------------------------------------------------------
*!
*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
*!
*! $Id: ds1302.c,v 1.11 2001/06/14 12:35:52 jonashg Exp $
*!
*!***************************************************************************/
/*
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <asm/uaccess.h>
#include <asm/system.h>
//#include <asm/svinto.h>
#include <asm/io.h>*/
#include <linux/fs.h>
#include <linux/iobuf.h>
//#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/module.h>
//#include <asm/rtc.h>
//#include <linux/rtc.h>
#include "ds1302n.h"
static int init_module(void);
static void cleanup_module(void);
static int ds1302_open(struct inode*, struct file *);
static int ds1302_close(struct inode*, struct file *);
static int rtc_ioctl(struct inode*inode,struct file *flip,unsigned int cmd,unsigned long arg);
static void ds1302_release(struct inode*inode, struct file *filp);
#define GPIO_MODE_OUTOFF 0x00
#define GPIO_MODE_INOFF 0x04
#define GPIO_MODE_DIROFF 0x08
#define GPIO_MODE_PULLENOFF 0x18
#define GPIO_MODE_PULLTYOFF 0x1C
#define DS1302_RST 0x0001
#define DS1302_SCL 0x0002
#define DS1302_SDA 0x0004
#define INN 0
#define OUTT 1
//#define RTC_MAJOR_NR 121 /* local major, change later */
static const char ds1302_name[] = "ds1302";
/* The DS1302 might be connected to different bits on different products.
* It has three signals - SDA, SCL and RST. RST and SCL are always outputs,
* but SDA can have a selected direction.
* For now, only PORT_PB is hardcoded.
*/
/* The RST bit may be on either the Generic Port or Port PB. */
/*
#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
#define TK_RST_DIR(x)
#else
//#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
//#define TK_RST_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
#define TK_RST_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_RST,x)
#define TK_RST_DIR(x)
#endif
//#define TK_SDA_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
#define TK_SDA_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_SDA,x)
//#define TK_SCL_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
#define TK_SCL_OUT(x) write_gpio_bit(GPIO_MODE_OUT | DS1302_SCL,x)
//#define TK_SDA_IN() ((*R_PORT_PB_READ >> CONFIG_ETRAX_DS1302_SDABIT) & 1)
#define TK_SDA_IN() read_gpio_bit(DS1302_SDA)
//#define TK_SDA_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
//#define TK_SDA_DIR(x) (if(x==1) set_gpio_ctrl(GPIO_MODE_OUT | DS1302_SDA); else set_gpio_ctrl(GPIO_MODE_IN | DS1302_SDA); )
#define TK_SDA_DIR(x) set_gpio_ctrl(x | DS1302_SDA)
//#define TK_SCL_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
#define TK_SCL_DIR(x)*/
/* 1 is out, 0 is in */
void TK_SDA_OUT(char x)
{
int tmp;