i2c裸机与理论

版权声明:本文为博主原创文章,未经博主允许不得转载。
https://blog.csdn.net/huangweiqing80/article/details/82802371

1、i2c协议简要分析

i2c总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。

在这里插入图片描述

它具有以下特点。

  • 1、只有两条双向信号线:一条串行数据线SDA,一条串行时钟线SCL。
  • 2、每个连接到总线的器件都可以使用软件根据它的唯一的地址来确定。
  • 3、传输数据的设备之间是简单的主从关系。
  • 4、主机可以用作主机发送器或者主机接收器。
  • 5、它是一个真正的多主机总线,两个或多个主机同时发起数据传输时,可以通过冲突检测和仲裁来防止数据被破坏。
  • 6、串行的8位双向传输,位速在标准模式下可达 100kbit/s,在快速模式下可达400kbit/s,在高速模式下可待3.4Mbit/s。
  • 7、片上的滤波器可以增加抗干扰能力,保证数据的完整性。
  • 8、连接到同一总线上的IC数量只受到总线的最大电容400Pf的限制。

在这里插入图片描述

如上图所示,启动一个传输时,主机先发送一个S信号,然后发送8位数据。这8位数据的前7位为从机地址,第八位表示传输的方向(0表示写,1表示读),如果有数据则继续发送,最后发出P信号停止。
系统中的所有外围器件都具有一个7位的从器件专用地址码,其中高4位为器件类型,由生产厂家制定,在生产厂商生产是就已经固定到芯片上的了,低3位为器件引脚定义地址,由使用者定义。主设备发送地址时,主线上的每个从设备都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正在被主设备寻址。根据R/W位将自己定义为发送器或者接收器。

在这里插入图片描述

信号类型:

注意:

  • 正常数据传输时,SDA 在 SCL 为低电平时改变,在 SCL 为高电平时保持稳定。即当SCL 由高电平变为为低电平时,表示这个bit(0/1)已经传输完成;SDA 状态开始变为下一个比特(0/1),此时SCL 由低电平变为高电平,确定要传输的时(0/1)。这样就完成了数据的传输。
  • 开始信号 S 信号:
    SCL 为高电平时,SDA由高电平向低电平跳变,开始传送数据。
  • 结束信号 P 信号:
    SCL 为高电平时,SDA由低电平向高电平跳变,结束传送数据。
  • 响应信号 ACK:
    接收器在接收到8位数据后,在第9个时钟周期,拉低 SDA 电平

注意:
在第9个时钟周期,发送器保持SDA为高,如果有ACK,那么第9个时钟周期SDA为低电平,如果没有为高电平,发送器根据电平高低分辨是否有ACK信号。

如果使能了IIC中断,发送完8bit数据后,主机自动进入中断处理函数,此时SCL被发送器拉低,让接收器被迫等待。恢复传输只需要清除中断挂起。

i2c设置中断的原因

IIC接收数据只是存到指定的寄存器中,如果你不取走,下次再接收数据就直接冲掉了,所以IIC接收到数据之后给CPU中断,中断服务程序去处理这些收到的数据!发送数据也类似!

2、 s3c2440 读写流程

在这里插入图片描述

在这里插入图片描述

  • 1、设置传输模式 IICSTAT[7-6],我们做实验与AT24C08通信时,2440作为主机,因此只用到主机发模式和主机收模式。

  • 2、写入从机地址到 IICDS[7-1],此时IICDS[7-1]位表示从机地址,第0位不关心。如 AT24C08 为 0xA0(最低位写0了,发送到数据线上的7位地址的后边以为才表示收发,这里虽然写0但并不是根据这里的0来真正发送的)。

  • 3、写 0xF0(写) 或 0xB0(读)到 IICSTAT 寄存器, 高两位表示 传输模式前边设置过了,设置IICSTT[5-4] 为 11,使能传输,发送S信号。

  • 4、IIC控制器自动将第2步中设置的 IICDS[7-1] 再根据 传输模式 补充 IICDS[0]位,发送出去。

  • 5、进入第9个时钟周期,此时,从机决定是否发出ACK信号,主机进入中断,判断是否收到ACK信号,以及是否继续传输。

  • 6、继续发送:
    6.1、将数据写入 IICDS
    6.2、清除中断挂起,SCL时钟恢复,IICDS的数据被自动发送到 SDA 线上,回到第5步。

  • 7、停止发送:
    7.1、写 0xD0(写) 和 0x90(读) 到 IICATAT ,IICATAT[7-6]还是表示的传输模式,IICATAT[5-4] == 0 1,发送停止信号
    7.2、清除中断挂起,SCL时钟恢复,发出停止信号
    7.3、延时,等待停止信号发出

读写操作中的中断:

发送模式中,当发送数据时, 在(IICDS)寄存器收到新数据之前 IIC 总线接口将会一直等待。即在新数据写入到寄存器之前,SCL 线将会保持为低,然后在其写入后发送的时候释放。S3C2440A 应该等待中断来确定当前数据是否发送完成。在 CPU 收到中断请求后,表示第一次数据发送完成,这次发送的是从设备地址,需要再次写一个新数据到 IICDS 寄存器中,这次的数据才是真正的数据。接收模式中,当收到了数据时,在读取 IICDS 寄存器前 IIC 接口将会一直等待。在新数据读出前,SCL 线将会保持为低,然后在其读取后释放。S3C2440A 应该等待中断来确定当前数据接收的完成。在 CPU 收到中断请求后,需要从 IICDS 寄存器中读取数据。

3、 AT24C08 读写分析

3.1、写过程

在这里插入图片描述

写过程与2440芯片的里的写流程相一致,按照流程写就OK

3.2、读过程

在这里插入图片描述

读过程是由2440芯片里的一个写流程加一个读流程组合而成,其中写流程结束没有发出P信号,而是直接发出了S信号开始读流程,也就是我为什么加了一道红线的原因。

4、裸机程序

附上一份简单的裸机程序,仅供参考:基于MINI2440

#include <stdio.h>
#include "s3c2440.h"
 
void Delay(int time);
 
#define WRDATA      (1)
#define RDDATA      (2)
 
typedef struct tI2C {
    unsigned char *pData;   /* 数据缓冲区 */
    volatile int DataCount; /* 等待传输的数据长度 */
    volatile int Status;    /* 状态 */
    volatile int Mode;      /* 模式:读/写 */
    volatile int Pt;        /* pData中待传输数据的位置 */
}tS3C24xx_I2C, *ptS3C24xx_I2C;
 
static tS3C24xx_I2C g_tS3C24xx_I2C;
 
/*
 * I2C初始化
 */
void i2c_init(void)
{
    GPEUP  |= 0xc000;       // 禁止内部上拉
/*
 *	AT24C08 两根线 I2CSCL I2CSDA 与 2440芯片相连
 *  配置2440 GPECON GPE15 GPE14引脚为I2C功能
 */
    GPECON |= 0xa0000000;   // 选择引脚功能:GPE15:IICSDA, GPE14:IICSCL
/* 开INT_IIC中断 */
    //INTMSK &= ~(BIT_IIC);
 
    /* bit[7] = 1, 使能ACK
     * bit[6] = 0, IICCLK = PCLK/16
     * bit[5] = 1, 使能中断
     * bit[3:0] = 0xf, Tx clock = IICCLK/16
     * PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz
     */
    IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);  // 0xaf
 
    //IICADD  = 0x10;     // S3C24xx slave address = [7:1]
    IICSTAT = 0x10;     // I2C串行输出使能(Rx/Tx)
}
 
void I_Write(unsigned int slvaddr, unsigned char addr, unsigned char data)  
{  
    unsigned int ack;  
	// 写从地址
	IICSTAT |= 0x1<<6;//主机写模式   
    IICSTAT |= 0x1<<7;  
    IICDS = slvaddr;//0xa0;  //write slave address to IICDS   
    IICCON&=~0x10; //clear pending bit   
    IICSTAT = 0xf0;  //(M/T start)   
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
    // 写寄存器地址    
    IICDS = addr;  
    IICCON&=~0x10; //clear pending bit   
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
	// 写数据
    IICDS = data;  
    IICCON&=~0x10; //clear pending bit   
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
	// 发出停止信号
    IICSTAT = 0xD0; //write (M/T stop to IICSTAT)   
    IICCON&=~0x10; //clear pending bit   
 
    while((IICSTAT & 1<<5) == 1);  
}  
unsigned char I_Read(unsigned int slvaddr, unsigned char addr)  
{  
    unsigned char data  = 1;  
    int ack;  
	// 写从地址
	IICSTAT |= 0x1<<6;//主机写模式   
    IICSTAT |= 0x1<<7;  
	slvaddr = 0xA0;    
    IICDS = slvaddr;//0xa0;  //write slave address to IICDS   
    IICCON&=~0x10; //clear pending bit   
    IICSTAT = 0xf0;  //(M/T start)   
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
  
    // 写寄存器地址
    IICDS = addr;  
    IICCON&=~0x10; //clear pending bit   
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
 
    // 写从地址(读模式)
    slvaddr = 0xA1;
    IICSTAT &= ~(0x1<<6);//主机接受模式  
    IICSTAT |= 0x1<<7;  
    IICDS = slvaddr;  
    IICCON&=~0x10; //clear pending bit   
    IICSTAT = 0xb0;  //(M/R Start)   
    while((IICCON & 1<<4) == 0);//udelay(10);//uart_SendByte('o');//ack period and then interrupt is pending::   
 
	// 读数据
    data = IICDS;  
    //IICCON&=~0x10; //clear pending bit
	IICCON = 0x2f;	//清挂起状态,并设置无应答
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
    data = IICDS;  
    
	//IICCON&=~0x10; //clear pending bit   
	IICCON = 0x2f;	//清挂起状态,并设置无应答
    while((IICCON & 1<<4) == 0);//udelay(10);//ack period and then interrupt is pending   
 
 
    IICSTAT = 0x90;  
	IICCON = 0xaf;
    //IICCON &= ~0x10; //clear pending bit   
 
    while((IICSTAT & 1<<5) == 1);  
 
    return data;  
      
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值