gpio模拟i2c 读取24c02寄存器的值为0xff?
我把24c02的A0,A1,A2悬空,把wp接地,用的是hi3515板子,下面是我的代码:
#include <linux/module.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include "gpio_i2c.h"
/* GPIO0_0 */
#define SCL (1 << 6) /* 6 indicated 6th bit*/
/* GPIO0_1 */
#define SDA (1 << 7)
#define GPIO_I2C_BASE 0x20180000
#define GPIO_I2C_DIR IO_ADDRESS(GPIO_I2C_BASE + 0x400)
#define GPIO_I2C_SDA_REG IO_ADDRESS(GPIO_I2C_BASE + (SDA<<2)) /* data reg */
#define GPIO_I2C_SCL_REG IO_ADDRESS(GPIO_I2C_BASE + (SCL<<2))
#define GPIO_I2C_SCLSDA_REG IO_ADDRESS(GPIO_I2C_BASE + 0x300)
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define DELAY(us) time_delay_us(us)
static void i2c_clr(unsigned char whichline)
{
unsigned char regvalue;
if(whichline == SCL)
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= SCL;
HW_REG(GPIO_I2C_DIR) = regvalue; /* set scl dir output */
HW_REG(GPIO_I2C_SCL_REG) = 0; /* set scl data 0 */
return;
}
else if(whichline == SDA)
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= SDA;
HW_REG(GPIO_I2C_DIR) = regvalue;
HW_REG(GPIO_I2C_SDA_REG) = 0;
return;
}
else if(whichline == (SDA|SCL))
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= (SDA|SCL);
HW_REG(GPIO_I2C_DIR) = regvalue;
HW_REG(GPIO_I2C_SCLSDA_REG) = 0;
return;
}
else
{
printk("Error input.\n");
return;
}
}
static void i2c_set(unsigned char whichline)
{
unsigned char regvalue;
if(whichline == SCL)
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= SCL;
HW_REG(GPIO_I2C_DIR) = regvalue;
HW_REG(GPIO_I2C_SCL_REG) = SCL;
return;
}
else if(whichline == SDA)
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= SDA;
HW_REG(GPIO_I2C_DIR) = regvalue;
HW_REG(GPIO_I2C_SDA_REG) = SDA;
return;
}
else if(whichline == (SDA|SCL))
{
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue |= (SDA|SCL);
HW_REG(GPIO_I2C_DIR) = regvalue;
HW_REG(GPIO_I2C_SCLSDA_REG) = (SDA|SCL);
return;
}
else
{
printk("Error input.\n");
return;
}
}
void time_delay_us(unsigned int usec)
{
int i,j;
for(i=0;i<usec * 5;i++)
{
for(j=0;j<47;j++)
{;}
}
}
static unsigned char i2c_data_read(void)
{
unsigned char regvalue;
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_I2C_DIR) = regvalue;
DELAY(1);
regvalue = HW_REG(GPIO_I2C_SDA_REG);
if((regvalue & SDA) != 0)
return 1;
else
return 0;
}
static void i2c_start_bit(void)
{
DELAY(1);
i2c_set(SDA | SCL);
DELAY(1);
i2c_clr(SDA);
DELAY(2);
}
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);
}
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();
}
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(2);
i2c_set(SCL);
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_I2C_DIR) = regvalue;
DELAY(1);
if (i2c_data_read())
j+=(1<<(7-i));
DELAY(1);
i2c_clr(SCL);
}
local_irq_enable();
DELAY(1);
return j;
}
static int i2c_receive_ack(void)
{
int nack;
unsigned char regvalue;
DELAY(1);
regvalue = HW_REG(GPIO_I2C_DIR);
regvalue &= (~SDA);
HW_REG(GPIO_I2C_DIR) = regvalue;
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_set(SCL);
DELAY(1);
nack = i2c_data_read();
DELAY(1);
i2c_clr(SCL);
DELAY(1);
if (nack == 0)
return 1;
return 0;
}
static void i2c_send_ack(void)
{
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_set(SDA);
DELAY(1);
i2c_set(SCL);
DELAY(1);
i2c_clr(SCL);
DELAY(1);
i2c_clr(SDA);
DELAY(1);
}
unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
{
int rxdata;
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress));
i2c_receive_ack();
i2c_send_byte(address);
i2c_receive_ack();
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress) | 1);
i2c_receive_ack();
rxdata = i2c_receive_byte();
i2c_send_ack();
i2c_stop_bit();
return rxdata;
}
void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char data)
{
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress));
i2c_receive_ack();
i2c_send_byte(address);
i2c_receive_ack();
i2c_send_byte(data);
i2c_stop_bit();
}
unsigned char gpio_sccb_read(unsigned char devaddress, unsigned char address)
{
int rxdata;
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress));
i2c_receive_ack();
i2c_send_byte(address);
i2c_receive_ack();
i2c_stop_bit();
i2c_start_bit();
i2c_send_byte((unsigned char)(devaddress) | 1);
i2c_receive_ack();
rxdata = i2c_receive_byte();
i2c_send_ack();
i2c_stop_bit();
return rxdata;
}
static unsigned int gpioinitialized =0;
static int __init gpio_i2c_init(void)
{
if(gpioinitialized == 0)
{
printk(KERN_INFO "Hisilicon GPIO control for I2C Driver \n");
i2c_clr(SCL | SDA);
gpioinitialized =1;
return 0;
}
else
{
printk("GPIO control for I2C has been initialized.\n");
return 0;
}
}
static void __exit gpio_i2c_exit(void)
{
gpioinitialized =0;
}
module_init(gpio_i2c_init);
module_exit(gpio_i2c_exit);
#ifdef MODULE
#include <linux/compile.h>
#endif
MODULE_INFO(build, UTS_VERSION);
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(gpio_i2c_read);
EXPORT_SYMBOL(gpio_i2c_write);
运行./i2c_write(0xa0,0x10,0x22)
./i2c_read(0xa0,0x10)
结果为0xff
求高人指点。。。
[解决办法]
帮你顶》。。。。