码迷,mamicode.com
首页 > 其他好文 > 详细

用s5pc100的GPIO模拟IIC

时间:2015-07-06 16:02:18      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:

转载:http://blog.chinaunix.net/uid-26833883-id-3823530.html

 

一、硬件连线

先来看看LM75硬件的上的连线:

技术分享

 

其中I2C_SDA0是数据线,I2C_SCL0是时钟线,它们分别接到s5pc100的GPD3和GPD4,如下图所示
技术分享

在模拟IIC的时候,用GPD3引脚发送数据或读取数据,用GPD4引脚提供时钟信号即可。

 

二、数据结构

 
由于s5pc100的GPD这一组的引脚很多,不好单独对其中的某一个引脚操作,为了能单独对其中的某一个管脚单独操作,这里使用了C语言的位域。
typedef struct 
{ 
    uint8 GPDDAT_0:1;  
    uint8 GPDDAT_1:1; 
    uint8 GPDDAT_2:1; 
    uint8 GPDDAT_3:1; 
    uint8 GPDDAT_4:1; 
    uint8 GPDDAT_5:1; 
    uint8 GPDDAT_6:1; 
    uint8 GPDDAT_7:1; 
} gpddat_t; 

#define GPD_DAT (* (volatile gpddat_t *)0xE0300084) 

#define SDA GPD_DAT.GPDDAT_3 
#define SCL GPD_DAT.GPDDAT_4 

 

三、操作函数

(1)产生IIC起始信号

SCL 为高电平时,SDA由高电平向低电平跳变,开始传送数据
/*IIC START:SCL = 1,SDA = 1->0*/ 
void iic_start() 
{ 
    SDA = HIGH; 
    SCL  = HIGH; 
    delay(50); 

    //高到低的跳变产生start信号  
    SDA = LOW; 
    delay(50); 
 
    //在SCL高时,SDA必须保持稳定,SCL低时,SDA可以任意改变 
    //此处将SCL拉低的目的是,接下来就要发送数据了 
    SCL = LOW; 
    delay(50); 
    
    return; 
} 

 

(2)产生IIC停止信号

SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据
/*IIC STOP:SCL = 1,SDA = 0->1*/ 
void iic_stop() 
{ 
    SDA = LOW; 
    SCL = LOW; 
    delay(50); 

    SCL = HIGH; 
    delay(50); 
 

    //SCL为高电平时,SDA从低电平跳变到高电平 
    //,产生停止信号 
    SDA = HIGH; 
    delay(50); 

    return; 
} 

 

(3)发送数据

/*Write 1 Byte to IIC*/ 
void iic_write_byte(uint8 data) 
{ 
  uint8 loop; 
  
  for(loop = 8;loop > 0;loop --) 
  { 
    //先发送最高位,在SCL高电平时,SDA必须保持稳定 
    SDA = data >> 7; 
    SCL = HIGH; 
    delay(50); 
 
    //SCL为低电平时,SDA可以任意改变 
    SCL = LOW; 

    //低位向高位移动 
    data <<= 1; 
    delay(50); 
} 
  
  return; 
} 

 

(4)读取数据

/*Read 1 byte from IIC*/ 
uint8 iic_read_byte() 
{ 
    uint8 loop; 
    uint8 value = 0; 

    for(loop = 8; loop > 0;loop --) 
    { 
        SCL = HIGH; 
        delay(50); 
 
        value <<= 1; 
 
        //读取1位数据 
        value |= SDA; 
 
        SCL = LOW; 
        delay(50); 
    } 
        
    return value; 
} 

 

(5)主机向从机发送ACK信号

void iic_send_ack() 
{ 
    SCL = HIGH; 
    SDA = LOW; 
    delay(50); 

    SCL = LOW; 
    delay(50); 

    return; 
} 

 

(6)获取从机给主机的ACK信号

uint8 iic_get_ack() 
{ 
    uint8 ret; 

    SCL = HIGH; 
    delay(50); 
 
    ret = SDA; 

    SCL = LOW; 
    delay(50); 

    return ret;   
} 

 

四、读取LM75测量的温度值

 
通过IIC读取LM75测量温度值的时序如下:

 技术分享

实例代码如下:

unsigned int __read_lm75() 
{ 
    uint8 ack; 
    uint8 high,low; 

    //设置IIC连接的pin为输出模式 
    SET_GPIO_MODE(GPD.GPDCON,3,1); 
    SET_GPIO_MODE(GPD.GPDCON,4,1); 
    delay(100); 

    //产生起始信号 
    iic_start(); 

    //发送从机地址 
    iic_write_byte(0x91); 

    //设置IIC连接的pin(SDA)为输入模式 
    SET_GPIO_MODE(GPD.GPDCON,3,0); 

    //等待从机的ACK 
    do{ 
        ack = iic_get_ack(); 
        }while(ack); 

    //读取从机发送过来的数据 
    high = iic_read_byte(); 

    //设置IIC连接的pin(SDA)为输出模式 
    SET_GPIO_MODE(GPD.GPDCON,3,1); 

    //发送ACK信号 
    iic_send_ack(); 

    //设置IIC连接的pin(SDA)为输入模式 
    SET_GPIO_MODE(GPD.GPDCON,3,0); 

    //读取从机发送过来的数据 
    low = iic_read_byte(); 

    //设置IIC连接的pin(SDA)为输出模式 
    SET_GPIO_MODE(GPD.GPDCON,3,1); 

    //发送停止信号 
    iic_stop(); 

    return (high << 8) | low; 
}

 

实验的经验:
1.读不到从机发送的ACK信号,原因是没有将SDA的那根线设为输入模式
2.在做的过程中,一开始每次读取的时候温度的值一直没有改变,后来发现是由于每次没有发送停止信号产生的。 

完。

用s5pc100的GPIO模拟IIC

标签:

原文地址:http://www.cnblogs.com/pengdonglin137/p/4624469.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!