S3C2440模拟IIC方式操作EEPROM

发布者:chaohuangmeitao最新更新时间:2016-10-05 来源: eefocus关键字:S3C2440  模拟IIC  EEPROM 手机看文章 扫描二维码
随时随地手机看文章
先简单介绍一下基本情况:

在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吧。

这次,贴出一个实现效果图:

 

S3C2440模拟IIC方式操作EEPROM - yuanzhaoming901030@126 - wit_yuans space
 

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

关键字:S3C2440  模拟IIC  EEPROM 引用地址:S3C2440模拟IIC方式操作EEPROM

上一篇:stm32的USART_IT_TXE和USART_IT_TC
下一篇:STM32使用模拟IIC操作EEPROM

推荐阅读最新更新时间:2024-03-16 15:13

基于S3C2440的Ethercat实现
  1 引言   工业以太网由于低成本、易于组网和具有相当高的数据传输速率、资源共享能力强以及易于Internet连接等特点,以太网(Ethernet)指的是由Xerox公司创建并由Xerox、Intel和DEC公司联合开发的基带局域网规范,是当今现有局域网采用的最通用的通信协议标准。以太网络使用CSMA/CD(载波监听多路访问及冲突检测)技术,并以10M/S的速率运行在多种类型的电缆上。以太网与IEEE802·3系列标准相类似。以太网最早由Xerox(施乐)公司创建,在1980年,DEC、lntel和Xerox三家公司联合开发成为一个标准。以太网是应用最为广泛的局域网,包括标准的以太网(10Mbit/s)、快速以太网(100Mb
[单片机]
基于<font color='red'>S3C2440</font>的Ethercat实现
Corelis的I2C总线分析仪可作为EEPROM编程器
Corelis公司近日推出一款I2C总线分析仪CAS-1000-I2C,该产品的JTAG控制器可支持高达5Mbps的数据率。 CAS-1000-I2C可作为试验器、调试器、测试仪及编程器使用。该产品支持I2C总线标准、快速和高速模式。其主动可编程和交互式流量生成支持模式,包括主设备、多主从设备等,同时还能同时仿真1个主设备与/或多达32个从设备。 该系统支持I2C的总线分析仪兼容验证(v2.1),包括电子/时序特性、协议规范、错误捕获/报告以及上升/下降波形捕获/显示等,也可使用户提供被动流量监控和记录功能。此外该分析仪还具有时间标记、消息过滤和符号转换等功能。 另外,用户还能利用CAS-1000-I2C设置可编程触发事件来
[新品]
S3C2440 nand sdram启动时代码的运行转移过程
在reset期间,S3C2440 Nand Flash控制器通过和nand flash相连的管脚pin的状态获得信息(NCON,GPG13,GPG14,GPG15).启动电源或者系统复位后,NAND Flash控制器 会自动的下载4Kboot loader代码,下载了的boot loader 代码之后就在setppingstone 开始执行了。 S3C2440的boot code能够在外部的nand flash内存中执行。为了支持nand flash 的boot 引导,S3C2440有一个内部的SDRAM缓存称为“Steppingstone”,当booting的时候,Nand Flash的首4kbyte会被导入到Stepping
[单片机]
S3C2440和S5PV210的声卡对比
IIS(Inter-IC Sound)由飞利浦公司开发,是一种常用的音频设备接口,主要用于CD、MD、MP3等设备。 1.播放音频的过程: IIS接口发送声音 DDR—— S5PV210—————————— 解码芯片WM8960(DAC的过程)—— 耳机 2.录音的过程: IIS接收声音数据 MIC—— 编码芯片WM8960(ADC的过程)——————————— S5PV210—— DDR 3.IIS接口(共有5个引脚用于IIS): LRCK----------------------------------左右声道控制信号 SCLK-------------
[单片机]
<font color='red'>S3C2440</font>和S5PV210的声卡对比
s3c2440 ads程序移植到keil中(三) 初步完成
如果我把参数配置发生改变呢 然后再一次编译 要包错误 如下所示 其实我们到这里离 在s3c2440 ads程序移植到keil中(二)中看到这个网友不值提供了方法 而且提供了几个文件的下载地址 http://download.csdn.net/detail/googlemi/5176844 我直接下载下来了 把其中的2440init.s文件直接拷贝复制替代我工作中的2440init.s 该错误消失了 但是出现了 这一个错误 反正修改就能解决 然后 提示了一个错误 意思 就nand.c和nand.h 没有加上去 让后加上去了 编译成功没有错误 这种方式到此结束
[单片机]
<font color='red'>s3c2440</font> ads程序移植到keil中(三) 初步完成
MSP430非模拟IIC总线控制程序
对于MSP430的学习经历一个从痛苦到对430很有感情的转变.当然开始学习的时候那是相当恼火.网上也没有什么很多的相关资料.就算有资料也是给不全.参考与学习都不很方便.经过多方面的努力和找书再到对程序的仔细读,感到非模拟的总线带来的方便还是很多的. 下面就是程序和流程图: IIC.h void Init_IIC(void); void EEPROM_ByteWrite(unsigned char nAddr,unsigned char nVal); unsigned char EEPROM_RandomRead(unsigned char nAddr); unsigned char EEPROM_CurrentAddres
[单片机]
MSP430非<font color='red'>模拟</font><font color='red'>IIC</font>总线控制程序
ARM中断区别-LPC2142与S3C2440的区别
/*************************************************** *说 明 :ARM中断区别-LPC2142与S3C2440的区别 ***************************************************/ LPC 与三星ARM的区别就是三星固定了中断向量的地址,而LPC的就没有。例如三星的S3C2440 所有的中断源都有相对应的中断向量。 关于三星ARM (1)使用向量中断 ENTRY b ResetHandler ; 0x00 b HandlerUndef ; 0x04 b
[单片机]
基于Linux和s3C2440的GPC控制器设计
近年来,基于Internet的网络化控制系统已成为国内外测控领域研究的热点,在石油勘探开发、钢铁化工等领域有着广阔的应用前景。而控制器的设计和研发是整个网络控制系统的关键和核心。在一些地域高度分散以及环境恶劣的控制现场,使用嵌入式系统作为控制器节点,可更有利于多点分布式综合布控及并行处理,实现更好的测控效果。然而由于网络传输本身的特点,网络时延会不可避免地影响网络控制系统的控制性能和稳定性,因此本文提出基于S3C2440A及嵌入式Linux的GPC(Generalized PredictiveControl)控制器的设计方案,具有一定的通用性。 1 控制器硬件平台设计 控制器节点是嵌入式网络化测控系统的中心。在测控系统中
[工业控制]
基于Linux和<font color='red'>s3C2440</font>的GPC控制器设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved