S5PV210下gpio模擬i2c

簡單的示例,根據各自的情況修改~

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/gpio.h>


#define GPIO_W_ADDR     0x6a
#define GPIO_R_ADDR    (GPIO_W_ADDR | 0x1)

#define GPIO_SDA S5PV210_GPH3(3)                                        //隨便寫的gpio
#define GPIO_SCL S5PV210_GPH3(4)

#define GPIO_SDA_OUTP s3c_gpio_cfgpin(GPIO_SDA, S3C_GPIO_OUTPUT) 	//設定SDA輸出
#define GPIO_SDA_INP  s3c_gpio_cfgpin(GPIO_SDA, S3C_GPIO_INPUT)  	//設定SDA輸入

#define GPIO_SCL_OUTP s3c_gpio_cfgpin(GPIO_SCL, S3C_GPIO_OUTPUT) 	//設定SCL輸出

#define GPIO_SDA_H gpio_set_value(GPIO_SDA, 1)
#define GPIO_SDA_L gpio_set_value(GPIO_SDA, 0)

#define GPIO_SCL_H gpio_set_value(GPIO_SCL, 1)
#define GPIO_SCL_L gpio_set_value(GPIO_SCL, 0)


/************************************
         GPIO  初始化
*************************************/
void gpio_init(void)
{
	s3c_gpio_setpull(GPIO_SCL, S3C_GPIO_PULL_NONE);		//disable pull up&down
	s3c_gpio_setpull(GPIO_SDA, S3C_GPIO_PULL_NONE);

	GPIO_SDA_OUTP;
	GPIO_SCL_OUTP;
}

/************************************
         總線初始化
*************************************/
void i2c_init(void)
{
    GPIO_SCL_L;
    udelay(5);			
    GPIO_SDA_H;
    udelay(5);			
    GPIO_SCL_H;
    udelay(5);			
}

/************************************
         接收ACK
*************************************/
void receive_ack(void)
{
     unsigned long ack;

     GPIO_SDA_INP;            		// Function <- Input (SDA)

     GPIO_SCL_L;
     udelay(5);
     GPIO_SCL_H;
     udelay(5);
     ack = gpio_get_value(GPIO_SDA);
     GPIO_SCL_H;
     udelay(5);

     while(ack!=0)			      //接收到非應答信號,等待!這裏最好不要寫成死循環的形式,因爲是示例,我就隨意了!
	 {
	 	GPIO_SCL_L;
     	udelay(5);
     	GPIO_SCL_H;
     	udelay(5);
     	ack = gpio_get_value(GPIO_SDA);
	printk("++++++++there is no ack +++++++++\n");
	 }

	 GPIO_SCL_L;
	 udelay(5);

	 GPIO_SDA_OUTP;                // Function <- Output (SDA)
}

/************************************
         起始信號
*************************************/
void i2c_start(void)
{
     GPIO_SCL_L;
     udelay(5);
     GPIO_SDA_H;
     udelay(5);
     GPIO_SCL_H;
     udelay(5);
     GPIO_SDA_L;
     udelay(5);
}

/************************************
         停止信號
*************************************/
void i2c_stop(void)
{
     GPIO_SCL_L;
     udelay(5);
     GPIO_SDA_L;
     udelay(5);
     GPIO_SCL_H;
     udelay(5);
     GPIO_SDA_H;
     udelay(5);  
}

/************************************
         寫一個字節
*************************************/
void i2c_byte_write(unsigned char dat)
{
     unsigned long i;
     
     for(i = 8; i > 0; i--)
     {
          GPIO_SCL_L;                                //SCL拉低,使SDA變化有效
          udelay(5);
          if((dat >> (i-1)) & 0x0001)
          	GPIO_SDA_H;                              //SDA變化
          else
          	GPIO_SDA_L;
          udelay(5);
          GPIO_SCL_H;                               //SCL拉高, 從機讀取SDA
          udelay(5);
     }
     GPIO_SCL_L; 
     udelay(5);
     GPIO_SDA_H;                                    //主機釋放SDA,等待從機發送ACK或者NOACK
     udelay(5);
     receive_ack();
}

/************************************
         讀一個字節
*************************************/
unsigned char i2c_byte_read(void)
{
     unsigned long i, dat = 0;
     
     GPIO_SDA_H;					 				//釋放SDA
     udelay(5);
     
     GPIO_SDA_INP;                              // Function <- Input

     for(i = 0; i < 8; i++)
     {
          GPIO_SCL_H;                            //SCL拉高,等待從機發出SDA
          udelay(5);
          dat = (dat<<1)|(gpio_get_value(GPIO_SDA));   //讀取從機發出的SDA
          udelay(5);                      
          GPIO_SCL_L;                           //SCL拉低,使從機改變或者SDA
          udelay(5);
     }
     
     GPIO_SCL_H;
     udelay(5);
     GPIO_SCL_L;
     udelay(5);
     GPIO_SCL_L;
     udelay(5);
     GPIO_SCL_H;
     udelay(5);

     GPIO_SDA_OUTP;                              // Function <- Output (SDA)

     return (unsigned char)dat;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章