<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > S3C2440模擬IIC方式操作EEPROM

          S3C2440模擬IIC方式操作EEPROM

          作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          先簡單介紹一下基本情況:

          S3C2440下,編寫iic程序,可以有一下三種方法,其實就是2種:

          本文引用地址:http://www.ex-cimer.com/article/201612/325195.htm

          1.自己編寫模擬iic程序,控制IO口的變化。

          2.使用驅(qū)動本身帶的模擬iic程序,也就是bit-banging。

          3.使用硬件iic,這不在我的討論范圍之內(nèi),有時間也可以補充上來。

          我目前使用的是在linux操作系統(tǒng)上實現(xiàn)的代碼:

          貼出實現(xiàn)的代碼(不使用內(nèi)核中的模擬iic程序):

          第一部分是驅(qū)動層的代碼:

          1.EEPROM.c代碼:

          ********************copyright by wit_yuan 2016-09-17 at beijing 龍興園北區(qū)**/
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include
          #include



          #define SDA_DELAY 5
          #define SCL_DELAY 5

          /*
          *
          * 本函數(shù)是操作在S3C2440上的GPIO模擬IIC程序,不使用內(nèi)核提供的模擬GPIO操作,也就是不調(diào)用:
          * i2c-dev.c,i2c-algo-bit.c,i2c-core.c,i2c-gpio.c文件的內(nèi)容。
          *
          * 在開發(fā)板上找到兩個引腳,SCL,SDA如下所示:
          * IICSCL GPE14
          * IICSDA GPE15
          *
          */
          /*
          *
          * 操作思路:(具體可以參考STM32的模擬IIC來做)
          * 1.使用基本的文件讀寫操作方法,為應(yīng)用層提供基本的open,read,write函數(shù)。
          * 2.提供基本的設(shè)備注冊,類注冊方法。
          *
          * 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();

          //開啟設(shè)置初始狀態(tài)
          IIC_SDA(1);
          udelay(SDA_DELAY);

          IIC_SCL(1);
          udelay(SCL_DELAY);
          }


          /**
          *
          * 這部分是EEPROM的模擬IIC的實現(xiàn)部分。需要仔細
          *
          *
          *
          *
          *
          *
          */
          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設(shè)置為輸入

          while(READ_SDA)
          {
          ucErrTime++;
          if(ucErrTime>250)
          {
          IIC_Stop();
          return 1; //超時,表明數(shù)據(jù)傳輸有問題
          }
          }
          IIC_SCL(1);
          udelay(SCL_DELAY);

          IIC_SCL(0);//時鐘輸出0
          udelay(SCL_DELAY);

          return 0;
          }

          //產(chǎn)生ACK應(yīng)答
          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);
          }

          //不產(chǎn)生ACK應(yīng)答
          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);//拉低時鐘開始數(shù)據(jù)傳輸
          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個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
          unsigned char IIC_Read_Byte( void )
          {
          unsigned char i,u_receive=0;
          SDA_IN();//SDA設(shè)置為輸入
          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();//不需要響應(yīng)

          IIC_Stop();

          #if 0
          printk("read data is 0x%0xn",u_temp);
          printk("error status:%dn",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;
          }


          /*
          *
          * 規(guī)定:
          * 在IOCTL中接收應(yīng)用層傳過來的基本控制命令,包括i2c設(shè)備的地址,寄存器地址等。
          * 在write,read函數(shù)中,才可以寫入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%0xn",g_t_iic_struct.u_device_address);
          printk("u_reg_address=0x%0xn",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%0xn",g_t_iic_struct.u_device_address);
          printk("u_reg_address=0x%0xn",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文件內(nèi)容:

          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


          第三部分是應(yīng)用層的測試程序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 errorn");
          return -1;
          }

          printf("----open device ok----n");

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

          //初始化寫數(shù)據(jù)的數(shù)組
          for(i = 0 ; i < 10 ; i ++)
          u_array_write_buffer[i] = i + 1;


          ioctl(i_fd,EEPROM_WRITE,&g_t_iic_struct);

          //寫數(shù)據(jù)內(nèi)容
          write(i_fd,u_array_write_buffer,10);

          //讀取EEPROM的數(shù)據(jù)

          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;
          }


          代碼結(jié)束了,具體的iic協(xié)議解釋性內(nèi)容,還是一樣,參考stm32的模擬iic操作EEPROM吧。

          這次,貼出一個實現(xiàn)效果圖:

          好了,這就是本節(jié)的內(nèi)容了。



          關(guān)鍵詞: S3C2440模擬IICEEPRO

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();