佚名通过本文主要向大家介绍了i2c rtc,stm32 模拟i2c,stm32模拟i2c程序,模拟i2c,模拟i2c程序等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题: Linux GPIO模拟I2C做RTC驱动
描述:
描述一下细节问题:
当没有经过零点的时候,每次写入多少,断电一段时间后读出来的都很准。但是如果我写入2014-01-05 23:59,断电后过一会读出来的却是2014-01-10 00:01,只有日期寄存器的值变了,而且每次都是乘以2,也就是日期该加1,但却x2。
驱动程序里面只是简单的写入和读取,根本没有对是否经过零点做处理啊!求各位帮忙解答啦。
驱动代码如下:
#define RX8010_REG_SC 0x10 /* datetime */
#define RX8010_REG_MN 0x11
#define RX8010_REG_HR 0x12
#define RX8010_REG_DM 0x13
#define RX8010_REG_DW 0x14
#define RX8010_REG_MO 0x15
#define RX8010_REG_YR 0x16
#define RX8010_MO_C 0x80 /* century */
#define RTC_DEV_ADDR 0x32
#define GPIO_0_BASE 0x201A0000 //need change
void __iomem *reg_gpio0_base_va;
#define IO_ADDRESS_VERIFY(x) (reg_gpio0_base_va + ((x)-(GPIO_0_BASE)))
//define direction!
#define GPIO_0_DIR IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x400)
#define SCL (1 << 4) /* GPIO 5_4 */
#define SDA (1 << 3) /* GPIO 5_3 */
#define GPIO_I2C_SDA_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x20)
#define GPIO_I2C_SCL_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x40)
#define GPIO_I2C_SCLSDA_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x60)
//read register value!
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define DELAY(us) time_delay_us(us)
static int s_c_polarity = 0; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
/*
* I2C by GPIO simulated read data routine.
*
* @return value: a bit for read
*
*/
static unsigned char i2c_data_read(void)
{
unsigned char regvalue;
regvalue = HW_REG(GPIO_0_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_0_DIR) = regvalue;
DELAY(1);
regvalue = HW_REG(GPIO_I2C_SDA_REG);
if((regvalue&SDA) != 0)
return 1;
else
return 0;
}
/*
* sends a start bit via I2C rountine.
*
*/
static void i2c_start_bit(void)
{
DELAY(1);
i2c_set(SDA | SCL);
DELAY(1);
i2c_clr(SDA);
DELAY(1);
}
/*
* sends a stop bit via I2C rountine.
*
*/
static void i2c_stop_bit(void)
{
/*clock the ack*/
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
/* actual stop bit */
DELAY(1);
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_set(SDA);
DELAY(1);
}
/*
* sends a character over I2C rountine.
*
* @param c: character to send
*
*/
static void i2c_send_byte(unsigned char c)
{
int i;
local_irq_disable();
for (i=0; i<8; i++)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
if (c & (1<<(7-i)))
i2c_set(SDA);
else
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
}
DELAY(1);
local_irq_enable();
}
/* receives a character from I2C rountine.
*
* @return value: character received
*
*/
static unsigned char i2c_receive_byte(void)
{
int j=0;
int i;
unsigned char regvalue;
local_irq_disable();
for (i=0; i<8; i++)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_set(SCL);
regvalue = HW_REG(GPIO_0_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_0_DIR) = regvalue;<
描述:
RX8010RTCI2C驱动
最近用爱普生的RX8010芯片做rtc驱动,发现每次在经过零点的时候,读出来的日期寄存器的值都会乘以2,求问各位有没有遇见过啊?或者能给提下意见吗?不胜感激~~~描述一下细节问题:
当没有经过零点的时候,每次写入多少,断电一段时间后读出来的都很准。但是如果我写入2014-01-05 23:59,断电后过一会读出来的却是2014-01-10 00:01,只有日期寄存器的值变了,而且每次都是乘以2,也就是日期该加1,但却x2。
驱动程序里面只是简单的写入和读取,根本没有对是否经过零点做处理啊!求各位帮忙解答啦。
驱动代码如下:
#define RX8010_REG_SC 0x10 /* datetime */
#define RX8010_REG_MN 0x11
#define RX8010_REG_HR 0x12
#define RX8010_REG_DM 0x13
#define RX8010_REG_DW 0x14
#define RX8010_REG_MO 0x15
#define RX8010_REG_YR 0x16
#define RX8010_MO_C 0x80 /* century */
#define RTC_DEV_ADDR 0x32
#define GPIO_0_BASE 0x201A0000 //need change
void __iomem *reg_gpio0_base_va;
#define IO_ADDRESS_VERIFY(x) (reg_gpio0_base_va + ((x)-(GPIO_0_BASE)))
//define direction!
#define GPIO_0_DIR IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x400)
#define SCL (1 << 4) /* GPIO 5_4 */
#define SDA (1 << 3) /* GPIO 5_3 */
#define GPIO_I2C_SDA_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x20)
#define GPIO_I2C_SCL_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x40)
#define GPIO_I2C_SCLSDA_REG IO_ADDRESS_VERIFY(GPIO_0_BASE + 0x60)
//read register value!
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define DELAY(us) time_delay_us(us)
static int s_c_polarity = 0; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
/*
* I2C by GPIO simulated read data routine.
*
* @return value: a bit for read
*
*/
static unsigned char i2c_data_read(void)
{
unsigned char regvalue;
regvalue = HW_REG(GPIO_0_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_0_DIR) = regvalue;
DELAY(1);
regvalue = HW_REG(GPIO_I2C_SDA_REG);
if((regvalue&SDA) != 0)
return 1;
else
return 0;
}
/*
* sends a start bit via I2C rountine.
*
*/
static void i2c_start_bit(void)
{
DELAY(1);
i2c_set(SDA | SCL);
DELAY(1);
i2c_clr(SDA);
DELAY(1);
}
/*
* sends a stop bit via I2C rountine.
*
*/
static void i2c_stop_bit(void)
{
/*clock the ack*/
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
/* actual stop bit */
DELAY(1);
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_set(SDA);
DELAY(1);
}
/*
* sends a character over I2C rountine.
*
* @param c: character to send
*
*/
static void i2c_send_byte(unsigned char c)
{
int i;
local_irq_disable();
for (i=0; i<8; i++)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
if (c & (1<<(7-i)))
i2c_set(SDA);
else
i2c_clr(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
}
DELAY(1);
local_irq_enable();
}
/* receives a character from I2C rountine.
*
* @return value: character received
*
*/
static unsigned char i2c_receive_byte(void)
{
int j=0;
int i;
unsigned char regvalue;
local_irq_disable();
for (i=0; i<8; i++)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_set(SCL);
regvalue = HW_REG(GPIO_0_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_0_DIR) = regvalue;<