linux2.4 GPIO模拟实现I2C数据传输-DS1302

本文档介绍如何利用Linux2.4版本下的GPIO模拟实现与DS1302实时时钟的I2C数据传输。通过理解DS1302的工作方式和时序图,利用GPIO模拟读写时序,详细代码适用于特定CPU,不同平台可能需要调整GPIO寄存器地址。
摘要由CSDN通过智能技术生成

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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值