您的位置 首页 被动

S3C2440模仿IIC方法操作EEPROM

先简单介绍一下基本情况:在S3C2440下,编写iic程序,可以有一下三种方法,其实就是2种:1.自己编写模拟iic程序,控制IO口的变化。2.使用驱…

先简略介绍一下根本情况:

S3C2440下,编写iic程序,能够有一下三种办法,其实便是2种:

1.自己编写模仿iic程序,操控IO口的改变。

2.运用驱动自身带的模仿iic程序,也便是bit-banging。

3.运用硬件iic,这不在我的评论规模之内,有时间也能够弥补上来。

我现在运用的是在linux操作系统上完成的代码:

贴出完成的代码(不运用内核中的模仿iic程序):

榜首部分是驱动层的代码:

1.EEPROM.c代码:


********************copyright by wit_yuan 2016-09-17 at beijing 龙兴园北区**/
#include #include #include #include #include #include #include #include #include #include #include #include

#define SDA_DELAY 5
#define SCL_DELAY 5

/*
*
* 本函数是操作在S3C2440上的GPIO模仿IIC程序,不运用内核供给的模仿GPIO操作,也便是不调用:
* i2c-dev.c,i2c-algo-bit.c,i2c-core.c,i2c-gpio.c文件的内容。
*
* 在开发板上找到两个引脚,SCL,SDA如下所示:
* IICSCL GPE14
* IICSDA GPE15
*
*/
/*
*
* 操作思路:(详细能够参阅STM32的模仿IIC来做)
* 1.运用根本的文件读写操作办法,为应用层供给根本的open,read,write函数。
* 2.供给根本的设备注册,类注册办法。
*
* GPECON:0x56000040 GPE15[31:30] 00-input,01-output 10-IICSDA GPE14[29:28] 10-IICSCL
* GPEDAT:0x56000044 GPE15[15:0]
* GPEUP :0x56000048
*
*
*/
struct device *g_p_device;
struct class *g_p_class;
static int g_major;
static volatile unsigned int *GPECON;
static volatile unsigned int *GPEDAT;

#define SDA_OUT() do{*GPECON &= ~(0x3 << 30); *GPECON |= (1<<30);} while(0);
#define SDA_IN() do{*GPECON &= ~(0x3 << 30);} while(0);
#define READ_SDA ((*GPEDAT)&(1<<15)) #define SCL_INIT() do{*GPECON &= ~(0x3 << 28); *GPECON |= (1<<28);} while(0);
#define SDA_INIT() do{*GPECON &= ~(0x3 << 30); *GPECON |= (1<<30);} while(0);
#define EEPROM_MAGIC m
#define EEPROM_WRITE _IOW(EEPROM_MAGIC,0,int)
#define EEPROM_READ _IOR(EEPROM_MAGIC,1,int)

#define IIC_SDA(a) \
do{\
if(a==0){\
*GPEDAT &= ~(1<<15);\
}\
else\
{\
*GPEDAT |= (1<<15);\
}\
}while(0);

#define IIC_SCL(a) \
do{\
if(a==0){\
*GPEDAT &= ~(1<<14);\
}\
else\
{\
*GPEDAT |= (1<<14);\
}\
}while(0);

typedef struct IIC_Struct{
unsigned char u_device_address;
unsigned char u_reg_address;

}T_IIC_Struct;

static T_IIC_Struct g_t_iic_struct;

static void IIC_Init(void)
{
SCL_INIT();
SDA_INIT();

//敞开设置初始状况
IIC_SDA(1);
udelay(SDA_DELAY);

IIC_SCL(1);
udelay(SCL_DELAY);
}

/**
*
* 这部分是EEPROM的模仿IIC的完成部分。需求细心
*
*
*
*
*
*
*/
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA(1);
udelay(SDA_DELAY);

IIC_SCL(1);
udelay(SCL_DELAY);

IIC_SDA(0);
udelay(SDA_DELAY);

IIC_SCL(0);
udelay(SCL_DELAY);
}

void IIC_Stop(void )
{
SDA_OUT();

IIC_SDA(0);
udelay(SDA_DELAY);

IIC_SCL(1);
udelay(SCL_DELAY);

IIC_SDA(1);
udelay(SDA_DELAY);
}

unsigned char IIC_Wait_Ack(void)
{
unsigned short ucErrTime=0;

IIC_SCL(0);
udelay(SCL_DELAY);

SDA_IN(); //SDA设置为输入

while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1; //超时,标明数据传输有问题
}
}
IIC_SCL(1);
udelay(SCL_DELAY);

IIC_SCL(0);//时钟输出0
udelay(SCL_DELAY);

return 0;
}

//发生ACK应对
void IIC_Ack(void)
{
IIC_SCL(0);
udelay(SCL_DELAY);

//added by wit_yuan 2016-09-16
SDA_OUT();
IIC_SDA(1);
udelay(SDA_DELAY);

IIC_SDA(0);
udelay(SDA_DELAY);

IIC_SCL(1);
udelay(SCL_DELAY);
IIC_SCL(0);
udelay(SCL_DELAY);

//////add 2016-09-16 by wit_yuan///////////
IIC_SDA(1);
udelay(SDA_DELAY);
}

//不发生ACK应对
void IIC_NAck(void)
{
SDA_OUT();
IIC_SCL(0);
udelay(SCL_DELAY);

IIC_SDA(1);
udelay(SDA_DELAY);

IIC_SCL(1);
udelay(SCL_DELAY);
IIC_SCL(0);
udelay(SCL_DELAY);
}

void IIC_Send_Byte(unsigned char txd)
{
unsigned char t;
SDA_OUT();
IIC_SCL(0);//拉低时钟开端数据传输
udelay(SCL_DELAY);
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
{
IIC_SDA(1);
}
else
{
IIC_SDA(0);
}
txd<<=1;
udelay(SDA_DELAY);
IIC_SCL(1);
udelay(SCL_DELAY);
IIC_SCL(0);
udelay(SCL_DELAY);
}
}

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
unsigned char IIC_Read_Byte( void )
{
unsigned char i,u_receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL(0);
udelay(SCL_DELAY);
IIC_SCL(1);
udelay(SCL_DELAY);
u_receive<<=1;
if(READ_SDA)
u_receive++;
}

return u_receive;
}

ssize_t EEPROM_Write(struct file *p_file, const char __user *p_buf, size_t len, loff_t *p_lof)
{

unsigned int i;
unsigned int i_err = 0;

unsigned char *p_buffer;

if(len <= 0)
return 0;

p_buffer = kzalloc(sizeof(char) * len, GFP_KERNEL);
copy_from_user(p_buffer,p_buf,len);

printk(“—-EEPROM write device—–\n”);

IIC_Start();
IIC_Send_Byte(g_t_iic_struct.u_device_address << 1);
i_err |= IIC_Wait_Ack();

IIC_Send_Byte(g_t_iic_struct.u_reg_address);
i_err |= IIC_Wait_Ack();

for( i = 0 ; i < len ; i ++ )
{
IIC_Send_Byte(p_buffer[i]);

i_err |= IIC_Wait_Ack();
}
IIC_Stop();

kfree(p_buffer);

if(i_err == 0)
return 0;

return 1;
}

ssize_t EEPROM_Read(struct file *p_file, char __user *p_buf, size_t len, loff_t *p_lof)
{
int i = 0;
printk(“—-EEPROM read device—–\n”);

unsigned char u_temp;
unsigned char u_wait_err = 0;

unsigned char *p_buffer;
p_buffer = kzalloc(sizeof(char) * len, GFP_KERNEL);

if(len <= 0)
return 0;

IIC_Start();
IIC_Send_Byte(g_t_iic_struct.u_device_address << 1);
u_wait_err |= IIC_Wait_Ack();

IIC_Send_Byte(g_t_iic_struct.u_reg_address);
u_wait_err |= IIC_Wait_Ack();

IIC_Start();
IIC_Send_Byte((g_t_iic_struct.u_device_address << 1)+1);
u_wait_err |= IIC_Wait_Ack();

for(i = 0 ; i < len - 1 ; i ++)
{
//p_buffer[i] = IIC_Read_Byte( );
*p_buffer = IIC_Read_Byte( );
IIC_Ack();
p_buffer ++;
}
//p_buffer[len-1] = IIC_Read_Byte( );
*p_buffer = IIC_Read_Byte( );

IIC_NAck();//不需求呼应

IIC_Stop();

#if 0
printk(“read data is 0x%0x\n”,u_temp);
printk(“error status:%d\n”,u_wait_err);
#endif

copy_to_user(p_buf,p_buffer – len + 1,len);

#if 0
printk(“kernel array : \n”);
for(i = 0 ; i < len ; i ++)
printk(“0x%0x \n”,p_buf[i]);
printk(“\n”);
#endif

kfree(p_buffer);

if(u_wait_err == 0)
return 0;
return 1;
}

int EEPROM_Open(struct inode *p_inode, struct file *p_file)
{
printk(“—-EEPROM open device—–\n”);

//本句是将GPIO初始化。
IIC_Init();

return 0;
}

/*
*
* 规则:
* 在IOCTL中接纳应用层传过来的根本操控指令,包含i2c设备的地址,寄存器地址等。
* 在write,read函数中,才能够写入buffer.
*
*/
long EEPROM_Ioctl (struct file *p_file, unsigned int cmd, unsigned long args)
{
switch(cmd)
{
case EEPROM_WRITE:
printk(“—-ioctl write—\n”);

copy_from_user(&g_t_iic_struct,(T_IIC_Struct *)args,4);

printk(“u_device_address=0x%0x\n”,g_t_iic_struct.u_device_address);
printk(“u_reg_address=0x%0x\n”,g_t_iic_struct.u_reg_address);

break;
case EEPROM_READ:
printk(“—-ioctl read—\n”);

copy_to_user((T_IIC_Struct *)args,&g_t_iic_struct,4);
printk(“u_device_address=0x%0x\n”,g_t_iic_struct.u_device_address);
printk(“u_reg_address=0x%0x\n”,g_t_iic_struct.u_reg_address);

break;
}
return 0;
}

static const struct file_operations EEPROM_File_Ops = {
.owner = THIS_MODULE,
.open = EEPROM_Open,
.read = EEPROM_Read,
.write = EEPROM_Write,
.unlocked_ioctl = EEPROM_Ioctl,

};

static int __init EEPROM_init(void)
{
int ret;
printk(“—–EEPROM Init———\n”);

g_major = register_chrdev(0,”EEPROM_Chrdev”,&EEPROM_File_Ops);
g_p_class = class_create(THIS_MODULE, “EEPROM”);
g_p_device = device_create(g_p_class, NULL,MKDEV(g_major, 0), NULL,
“i2c-%d”, 1);

GPECON = ioremap(0x56000040,4);
GPEDAT = ioremap(0x56000044,4);

return ret;
}

static void __exit EEPROM_exit(void)
{
printk(“—–EEPROM Exit———\n”);

iounmap(GPECON);
iounmap(GPEDAT);

device_destroy(g_p_class,MKDEV(g_major, 0));
class_destroy(g_p_class);
unregister_chrdev(g_major,”EEPROM_Chrdev”);

}

module_init(EEPROM_init);
module_exit(EEPROM_exit);

MODULE_AUTHOR(“wit_yuan”);
MODULE_DESCRIPTION(“I2C-EEPROM by wit_yuan 2016-09-17 at beijing”);
MODULE_LICENSE(“GPL”);

/*************end of file for EEPROM driver*****************************/

2.EEPROM.h文件:


#ifndef _EEPROM_H_
#define _EEPROM_H_

#endif

第二部分是Makefile文件内容:


obj-m:=EEPROM.o

KERNEL_DIR:= /home/wityuan/Downloads/linux-3.12.57

PWD:=$(shell pwd)

all:
make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules

clean:
rm *.o *.ko *.mod.clean

第三部分是应用层的测验程序EEPROM_App.c文件:


#include
#include
#include
#include
#include
#include

#define EEPROM_MAGIC m
#define EEPROM_WRITE _IOW(EEPROM_MAGIC,0,int)
#define EEPROM_READ _IOR(EEPROM_MAGIC,1,int)

typedef struct IIC_Struct{
unsigned char u_device_address;
unsigned char u_reg_address;

}T_IIC_Struct;

static T_IIC_Struct g_t_iic_struct;

int main(int argc,char *argv[])
{
int i_fd;
int i = 0;
unsigned char u_array_buf[10];

unsigned char u_array_write_buffer[10];

i_fd = open(“/dev/i2c-1”,O_RDWR);

if(i_fd < 0)
{
printf(“open device error\n”);
return -1;
}

printf(“—-open device ok—-\n”);

g_t_iic_struct.u_device_address = 0x50;
g_t_iic_struct.u_reg_address = 0x0;

//初始化写数据的数组
for(i = 0 ; i < 10 ; i ++)
u_array_write_buffer[i] = i + 1;

ioctl(i_fd,EEPROM_WRITE,&g_t_iic_struct);

//写数据内容
write(i_fd,u_array_write_buffer,10);

//读取EEPROM的数据

read(i_fd,u_array_buf,10);

printf(“\nread :\n”);
for(i = 0; i < 10 ; i ++)
printf(“0x%0x “,u_array_buf[i]);

printf(“\n”);

while(1);

return 0;
}

代码完毕了,详细的iic协议解释性内容,仍是相同,参阅stm32的模仿iic操作EEPROM吧。

这次,贴出一个完成效果图:

好了,这便是本节的内容了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/beidong/252328.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部