I2C程序和流程图
i2c 高速模式时序
i2c 高速模式时序I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器和外围设备。
高速模式是I2C协议的一种工作模式,它提供了更高的数据传输速率。
本文将介绍I2C高速模式的时序,包括起始条件、数据传输和停止条件等。
一、起始条件在I2C高速模式下,起始条件是指主设备(如微控制器)向从设备发送起始位的过程。
起始条件包括以下几个步骤:1. 主设备将SCL(时钟线)拉低,表示开始通信。
2. 主设备将SDA(数据线)从高电平拉低,表示起始位。
3. 主设备保持SCL为低电平,等待从设备响应。
二、数据传输在I2C高速模式下,数据传输是指主设备向从设备发送数据或接收数据的过程。
数据传输包括以下几个步骤:1. 主设备将数据位(包括地址和数据)依次发送到SDA线上。
2. 主设备在每个数据位发送后,将SCL拉高一段时间,等待从设备读取数据。
3. 从设备在接收到数据位后,发送应答位(ACK)到SDA线上,表示成功接收到数据。
4. 主设备在接收到应答位后,继续发送下一个数据位,直到所有数据都发送完毕。
5. 主设备在发送完最后一个数据位后,将SCL拉高一段时间,等待从设备读取数据。
三、停止条件在I2C高速模式下,停止条件是指主设备向从设备发送停止位的过程。
停止条件包括以下几个步骤:1. 主设备将SCL拉低,表示结束数据传输。
2. 主设备将SDA从低电平拉高,表示停止位。
3. 主设备保持SCL为高电平,等待下一次通信。
I2C高速模式的时序图如下所示:起始条件:SCL为高电平时,SDA从高电平拉低数据传输:SCL拉高一段时间,等待从设备响应;从设备发送应答位,表示接收成功停止条件:SCL为高电平时,SDA从低电平拉高需要注意的是,I2C高速模式的时序与标准模式的时序略有不同。
高速模式的时序更为紧凑,可以实现更高的数据传输速率。
然而,高速模式对于电路设计和信号完整性要求更高,需要更精确的时钟和数据线控制。
详解IIC总线应用规范
个与共享资源连接,广泛适用于从MP3播放器到服务器等计算、通信和网络应用领域,从而使制造商和终端用户从中获益。
PCA9541可以使两个I2C主设备在互不连接的情况下与同一个从设备相连接,从而简化了设计的复杂性。
此外,新产品以单器件替代了I2C多个主设备应用中的多个芯片,有效节省了系统成本。
2、硬件结构I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。
所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
典型的I2C总线结构如图1所示。
为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。
设备与总线的接口电路如图2所示。
设备上的串行数据线SDA接口电路应该是双向的,输出电路用于向总线上发送数据,输入电路用于接收总线上的数据。
而串行时钟线也应是双向的,作为控制总线数据传送的主机,一方面要通过SCL输出电路发送时钟信号,另一方面还要检测总线上的SCL电平,以决定什么时候发送下一个时钟脉冲电平;作为接受主机命令的从机,要按总线上的SCL信号发出或接收SDA 上的信号,也可以向SCL线发出低电平信号以延长总线时钟信号周期。
总线空闲时,因各设备都是开漏输出,上拉电阻Rp使SDA和SCL线都保持高电平。
任一设备输出的低电平都将使相应的总线信号线变低,也就是说:各设备的SDA是“与”关系,SCL也是“与”关系。
总线对设备接口电路的制造工艺和电平都没有特殊的要求(NMOS、CMOS 都可以兼容)。
在I2C总线上的数据传送率可高达每秒十万位,高速方式时在每秒四十万位以上。
另外,总线上允许连接的设备数以其电容量不超过400pF为限。
总线的运行(数据传输)由主机控制。
所谓主机是指启动数据的传送(发出启动信号)、发出时钟信号以及传送结束时发出停止信号的设备,通常主机都是微处理器。
被主机寻访的设备称为从机。
I2C总线的写操作的流程
I2C总线的写操作的流程
在I2C写操作包括字节写及页面写两种。
字节写是只置换特定的1个地址;而页面写可置换汇总了16字节界限内的连续的地址范围(页)。
各种写操作的流程图如图所示。
1. 字节写
这是指定任意的地址(8位)写人数据的方式。
起始字节的DEVSEL按照前面描述的起始数据的格式,位7~4是“1010”的固定模式,位操作(“1”)还是写操作(“0”)。
如果存储器处于写保护状态(WC引脚为高电平等),则在接收地址之前一直返回ACK信号,对于之后传输的数据,则返回No-ACK信号。
数据发送完毕后,如果检测出来自主机的结束条件,则EEP-ROM内部开始进行写入操作。
根据数据手册可查出完成写入操作所需要的时间。
+5V的产品需要5ms,其他的产品大约需要10ms左右的时间。
EEPROM内部的替换周期在进行过程中,即使发送下一个指令也将返回NoACK信号。
因此,利用该NoACK信号就可判断内部的操作是否完成。
2. 页面写
页面写操作本身与字节写是相同的。
由于在存取后地址自动进位,因而可以按序发送1页(16字节)以内的数据。
实际上向存储器单元的写人操作,与字节写相同,都是在检测出结束条件后进行的,所以需要等待,直到操作结束,然后再进行下一个操作。
欢迎转载,信息。
I2C通信原理及程序详细讲解
I2C 通信:起始条件:SCL为高电平,SDA电平从高变低,这一变化即完成了通信的起始条件。
起始条件和数据通信间,通常会有延时要求具体的指标见设备说明。
数据传输阶段:一字节需要9个时钟周期;且每一位需要一个时钟周期;如上图所示,ADDRESS为目标设备的地址,R/ w为通信的的方向位;"1"时表示读,即后续的数据由目标设备发出,主机进行接收;"0"时表示写,即后续的数据由主机发出目标设备进行接收。
当ACK信号为"0"时,说明接收成功;为"1"时,说明接收失败。
每个字节的传输都是由高位(MSB)到低位(LSB)依次进行传输。
在数据通信过程中,总是由数据接收方发出ACK信号。
终止阶段:当主机完成数据通信,并终止本次传输时会发出终止信号。
当SCL 是高电平时,SDA电平由低变高,这个变化意味着传输终止。
注:每个时钟周期的高电平期间,SDA的数据状态达到稳定。
下面给出了模拟I2C总线进行读写的伪代码,用以说明如何使用GPIO 实现I2C通信:int i2c_start() /* I2C起始条件*/{//初始化GPIO口set_gpio_direction(SDA, OUTP); //设置SDA方向为输出set_gpio_direction (SCL, OUTP); //设置SCL方向为输出set_gpio_value(SDA, 1); //设置SDA为高电平set_gpio_value(SCL, 1); //设置SCL为高电平delay(); //延时//起始条件set_gpio_value(SDA, 0); //SCL为高电平时,SDA由高变低delay(); //适当延时}void i2c_stop() /* I2C终止条件*/{set_gpio_value(SCL, 1);set_gpio_direction(SDA, OUTP);set_gpio_value(SDA, 0);delay();set_gpio_value(SDA, 1); //SCL高电平时,SDA由低变高}/* I2C读取ACK信号(写数据时使用)返回值:0表示ACK信号有效;非0表示ACK信号无效*/unsigned char i2c_read_ack(){unsigned char r;set_gpio_direction(SDA, INP); //设置SDA方向为输入set_gpio_value(SCL,0); // SCL变低r = get_gpio_value(SDA); //读取ACK信号delay();set_gpio_value(SCL,1); // SCL变高delay();return r;}/* I2C发出ACK信号(读数据时使用) */int i2c_send_ack(){set_gpio_direction(SDA, OUTP); //设置SDA方向为输出set_gpio_value(SCL,0); // SCL变低set_gpio_value(SDA, 0); //发出ACK信号delay();set_gpio_value(SCL,1); // SCL变高delay();}void i2c_write_byte(unsigned char b) /* I2C字节写*/{int i;set_gpio_direction(SDA, OUTP); //设置SDA方向为输出for (i=7; i>=0; i--){set_gpio_value(SCL, 0); // SCL变低delay();set_gpio_value(SDA, b & (1<<i)); //从高位到低位依次发送数据set_gpio_value(SCL, 1); // SCL变高delay();}i2c_read_ack(); //检查目标设备的ACK信号}/* I2C字节读*/unsigned char i2c_read_byte(){int i;unsigned char r = 0;set_gpio_direction(SDA, INP); //设置SDA方向为输入for (i=7; i>=0; i--){set_gpio_value(SCL, 0); // SCL变低delay();r = (r <<1) | get_gpio_value(SDA); //高位到低位依次数据读取set_gpio_value(SCL, 1); // SCL变高delay();}i2c_send_ack(); //向目标设备发送ACK信号return r;}/* I2C读操作addr:目标设备地址buf:读缓冲区len:读入字节的长度*/void i2c_read(unsigned char addr, unsigned char* buf, int len){int i;unsigned char t;i2c_start(); //起始条件,开始数据通信//发送地址和数据读写方向t = (addr << 1) | 1; //低位为1,表示读数据i2c_write_byte(t);//读入数据for (i=0; i<len; i++)buf[i] = i2c_read_byte();i2c_stop(); //终止条件,结束数据通信}/* I2C写操作addr:目标设备地址buf:写缓冲区len:写入字节的长度*/void i2c_write (unsigned char addr, unsigned char* buf, int len){int i;unsigned char t;i2c_start(); //起始条件,开始数据通信//发送地址和数据读写方向t = (addr << 1) | 0; //低位为0,表示写数据i2c_write_byte(t);//写入数据for (i=0; i<len; i++)i2c_write_byte(buf[i]);i2c_stop(); //终止条件,结束数据通信}。
第11章 I2C总线图文图文课件
编号;
位 为1,表示要对器
01
3.数据传输 在数据传送过程中,SCL为高电平时,SDA必须是一稳定的高或低电平,此时
数据有效。SDA线的改变只能发生在SCL为低电平。 4.传输应答
所有数据都是按字节发送的,每次发送的字节数不限,但每发完每一个字节 要释放SDA线(呈高电平),然后由接收器下拉SDA线(呈低电平)产生应答位,表 示传输成功,此时主控器必须产生一个与此位相应的额外时钟脉冲。I2C 总线 数据传送时,每成功地传送一个字节数据后接收器都必须产生一个应答信号, 应答的器件在第9 个时钟周期时将SDA 线拉低,表示其已收到一个8 位数, 24C04在接收到起始信号和从器件地址之后响应一个应答信号,如果器件已选择 了写操作,则在每接收一个8 位字节之后响应一个应答信号。当24C04 工作于
主机发送地址时,总线上的每一个从机都将这7位地址码与自已的器件地址 进行比较,如果相同则认为自已正被主机寻址,根据读写位将自已确定为发送 器或接收器。
从机的地址由一个固定部分和一个可编程部分组成。固定部分为器件的编号
02 例如24C02的地址格式如下:
其中高四位1010为器件标识类型。 A2~A0:引脚地址,对应于该芯片引脚A2~A0的取值,当A2-A0引脚均接低电 平时,该器件的地址为A0H或A1H,如果为A0H表示写数据到该器件,A1H表示从 该器件读数据。 说明:从机地址只表明选择挂在总线的哪一个器件及传送方向,而器件内 部的地址是由编程者传送的第一数据中指定的,即第一个数据为器件内的子地 址。
功能:该函数与rcvbyte() 不同,它包含了从启动总线、 发送从器件地址、读数据到结 束总线的全过程。
如其果中返:回1表示操作成功, 否则s操la作:有从错器。件地址
I2C串行通信原理及代码演示
I2C串行通信原理及代码演示I2C串行通信标准的从属模式和多主控模式,串行接口仅由两条信号线组成:串行时钟(SCL)和串行数据(SDA)。
串行数据(SDA)SDA引脚是一个开漏极双向输入/输出引脚,用于在设备之间连续传输数据。
SDA引脚必须使用外部向上拉式电阻拉动(值不超过10 kΩ),并且可以与同一母线上其他设备的任意数量的其他开漏或开路集电器引脚相连。
串行时钟(SCL)SCL引脚用于为设备提供一个时钟,并控制进出设备的数据流。
SDA引脚上的命令和输入数据总是锁定在SCL的上升边缘上,而SDA引脚上的输出数据则锁定在SCL的下降边缘上。
当串行总线空闲时,SCL必须被强制高或使用外部上拉电阻拉高。
SCL引脚用于接收来自主的的时钟信号,而双向SDA引脚用于接收来自主机的的命令和数据信息,并将数据发送回主机。
数据总是被锁定在SCL上升边缘的中,并且总是从SCL下降边缘的设备输出。
在总线通信期间,每个时钟周期传输一个数据比特,在传输8位(1字节)数据之后,接收设备必须在主设备生成的第9个时钟周期(ACK/NACK时钟周期)中以确认(ACK)或不确认(NACK)响应比特进行响应。
因此,传输的数据每一个字节需要9个时钟周期。
在数据传输期间,SDA引脚上的数据只能在SCL低时改变,并且当SCL高时数据必须保持稳定。
如果当SCL较高时,SDA销上的数据发生变化,则将发生开始或停止条件。
启动和停止条件用于启动和结束主设备和从设备之间的所有串行总线通信。
在开始和停止条件之间传输的数据字节数不受限制,并由主节点决定。
为了使串行总线空闲,SCL和SDA引脚必须同时处于逻辑高状态。
时钟和数据转换要求SDA引脚是一个开漏端,因此必须用外部的拉式电阻拉高。
SCL是一个输入端,可以驱动高或拉高使用外部拉上电阻。
SDA引脚上的数据只能在SCL的低时间段内发生变化。
SCL高电平期间的数据变化将定义的开始或停止条件。
1、启动条件启动条件当SDA引脚发生“高到低”的转变,而SCL引脚处于稳定的逻辑“1”状态,将使设备脱离待机状态。
I2C通信详解
I2C通信详解什么是I2C通信物理接⼝:SCL + SDA(1)SCL(serial clock):时钟线,传输CLK信号,⼀般是I2C主设备向从设备提供时钟的通道(2)SDA(serial data):数据线,I2C通信的通信数据都通过SDA线来传输通信特征:串⾏、同步、⾮差分、低速率(1)I2C属于串⾏通信,所有的数据以位为单位在SDA上串⾏传输(2)同步通信就是通信双⽅⼯作在同⼀个时钟下⾯,⼀般是通信的A⽅通过⼀根CLK线传输A⾃⼰的时钟给B,B⼯作在A传输的时钟下。
所以通信的显著特征就是:通信中有CLK(3)⾮差分:因为I2C的通信速率不⾼,所以使⽤电平信号通信,⽽且通信双⽅距离很近,所以使⽤电平信号通信(4)低速率:I2C⼀般是⽤在同⼀个板⼦上的两个IC之间的通信,⽽且⽤来传输的数据量也不⼤,所以本⾝通信速率很低(⼀般⼏百KHz,不同的I2C芯⽚的通信速率可能不同,具体编程的时候要看⾃⼰所使⽤的设备所允许I2C的最⾼通信速率,不能超过这个速率)突出特征1:主设备+从设备(1)I2C通信的时候,通信双⽅地位是不对等的,⽽是分为主设备和从设备。
通信由主设备发起,由主设备主导,从设备只是按照I2C 协议被动的接收主设备的通信,并及时响应。
(2)谁是主设备,谁是从设备是由我们通信双⽅来定的,I2C协议并没有规定,⼀般来说⼀个芯⽚可以只做主设备,也可以只做从设备,也可以既当主设备,也当从设备。
突出设备2:可以多个设备同时挂在⼀条总线上(从设备地址)(1)I2C通信可以⼀对⼀(⼀个主设备对应⼀个从设备),也可以⼀对多(⼀个主设备对应多个从设备)(2)主设备来负责调度总线,决定某⼀时间和哪个设备从设备通信,注意:同⼀时间内,I2C总线只能传输⼀对设备的通⽤信息。
所以同⼀时间内,只能有⼀个从设备和主设备通信,⽽其他从设备处于“”“冬眠”状态,不能出来捣乱,否则通信就会乱套。
(3)每⼀个I2C从设备在通信中都会有⼀个I2C设备地址,这个设备地址是从设备本⾝固有的属性,然后通信时,主设备需要知道⾃⼰将要通信的那个设备的地址,然后在通信中通过地址来甄别是不是⾃⼰要找的那个从设备。
i2c的工作流程
i2c的工作流程
I2C(Inter-Integrated Circuit)是一种串行通信总线,它主要由两条线路组成:一条是串行数据线(SDA),另一条是串行时钟线(SCL)。
I2C总线具有以下特点:
1. 只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;
2. 每个连接到总线的器件都可以通过唯一的地址寻址;
3. 传送数据必须以8位字节方式传送;
4. I2C设备发送数据高位在前;
5. SCL时钟线始终由主设备控制。
I2C总线的工作流程如下:
1. 开始命令:在SCL线处于高电平期间,SDA线由高电平跳变为低电平,这被称为负
跳变。
2. 停止命令:在SCL线处于低电平期间,SDA线由低电平跳变为高电平,这被称为正
跳变。
3. 数据传输:I2C设备之间的数据传输是在SCL线为高电平时完成的。
只有在SCL线
处于低电平时,发送方才能改变所发送的数据。
4. 写应答:主设备每向从设备写完一次数据(一字节8位)后,都需要等待从设备的应答信号。
从设备的应答信号是在SCL的第九个脉冲时将SDA线置为低电平。
5. 读应答:主设备在读完一次数据(一字节8位)后,需要给从设备一个应答信号。
读应答实际上是从设备在接收完一个字节后,在SCL的第九个脉冲时将SDA线置为高电平。
6. 重复上述步骤:在完成一次数据传输后,I2C总线可以进行下一次数据传输。
整个I2C通信过程由主设备发起和控制,从设备根据主设备的指令进行响应。
通过I2C总线,主设备可以与多个从设备进行通信,实现系统的监控和控制功能。
i2c标准读写流程
i2c标准读写流程
I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器和外围设备。
以下是I2C标准的读写流程:
1. 主设备发送起始信号:主设备将SCL线拉低,然后将SDA线拉低,表示起始信号的开始。
2. 主设备发送设备地址和读写位:主设备将设备地址和读写位发送到SDA 线上,然后保持SCL线保持低电平。
3. 从设备响应:从设备检测到起始信号后,根据地址进行响应。
如果从设备地址匹配,从设备将拉低SDA线,表示响应;否则,从设备将保持SDA线为高电平,表示无响应。
4. 主设备发送数据:主设备继续发送需要写入的数据到SDA线上,并在每个数据字节后等待从设备的ACK(应答)。
5. 从设备应答:从设备接收到每个字节后,将拉低SDA线表示ACK;如果出现错误或数据无法接受,从设备将保持SDA线高电平,表示NACK(非应答)。
6. 主设备继续发送数据:如果从设备成功应答,主设备将继续发送数据。
7. 主设备发送停止信号:主设备发送停止信号,即将SCL线保持高电平,然后将SDA线拉高,表示通信结束。
注意事项:
- 在发送和接收数据之间,主设备和从设备都需要在每个字节后进行ACK/NACK。
- 从设备的地址包括7位设备地址和1位读写位(最低位)。
- 主设备可以连续发送多个数据字节,直到发送停止信号。
- 从设备可以在主设备发送数据之前发送请求,以指示其需要哪些数据。
- 在整个通信过程中,主设备控制时钟线(SCL),从设备控制数据线(SDA)。
以上是I2C标准的读写流程,具体实现可能会根据设备的要求和通信需求有所不同。
i2c 读写时序
i2c 读写时序I2C(Inter-Integrated Circuit)是一种通信协议,用于在集成电路之间进行短距离的串行数据传输。
在许多电子设备中,I2C被广泛应用于连接各种芯片和传感器。
I2C通信的核心是传输数据的主设备(Master)和接收数据的从设备(Slave)。
主设备负责控制总线并发送读写指令,从设备则响应这些指令并返回数据。
在I2C通信中,主设备和从设备之间的数据传输需要遵循一定的时序规则。
1. I2C 读取时序在I2C的读取过程中,主设备发送读取请求,从设备返回数据。
以下是一个典型的I2C读取时序示意图:___ ___ ____________| S | |AD+W| | A | | A | | . . . | | NACK | | P ||____|---|____|---|_____|____|---|_____|____|---|________|---|_______|---|____|--注释:- S:启动信号(Start),主设备发送一个低电平信号来启动通信。
- AD+W:从设备地址和写入位(Address + Write),主设备发送从设备地址和一个写入位来指定要进行数据传输的从设备。
- A:应答位(Acknowledge),每个字节的传输结束后,接收器返回一个应答位,表示已成功接收数据。
- NACK:非应答位(Not Acknowledge),主设备在读取数据时,如果从设备不再发送数据,将发送一个非应答位。
- P:停止信号(Stop),主设备发送一个高电平信号来结束通信。
在I2C读取时序中,主设备首先发送启动信号(S),然后发送从设备地址和写入位(AD+W)。
接下来,从设备返回应答位(A)。
主设备接着发送内部寄存器地址(A),再次收到从设备的应答位(A)。
随后,主设备发送读取请求,从设备返回数据,并以应答位(A)响应。
若后续还有数据需要读取,主设备持续发送读取请求,直到不再需要数据时,主设备发送非应答位并发送停止信号(P)来结束通信。
IIC总线的串行扩展
(1)控制字节 在起始条件之后,必须是器件的控制字节,其中,高四位
为器件类型识别符(不同的芯片类型有不同的定义,如E2PROM 为1010),接着三位为片选,最低位为读写控制位,为“1”时 为读操作,为“0”时为写操作。如下图所示。
6
(2)写操作 写操作分为字节写和页面写两种操作,对于页面写,根据
1
3. I2C总线协议 I2C总线在传送数据过程中共有三种类型信号:开始信号、
停止信号和应答信号。
开始信号:SCL保持高电平的状态下,SDA出现下降沿。出现 开始信号以后,总线被认为“忙”。
停止信号:SCL保持高电平的状态下,SDA出现上升沿。停止 信号过后,总线被认为“空闲”。
应答信号:接收数据的器件在接收到8位数据后,向发送数据的 器件发出特定的低电平脉冲,表示已收到数据。
总线空闲:SCL和SDA都保持高电平。
总线忙:在数据传送开始以后,SCL为高电平的时候,SDA的 数据必须保持稳定,只有当SCL为低电平的时候才允许SDA上 的数据改变。
2
4. I2C总线的传送格式
I2C总线的传送格式为主从式,对系统中的某一器件来说有 四种工作方式:主发送方式、从发送方式、主接收方式、从接 收方式。 (1)主发送从接收
2. I2C总线系统结构 一个典型的I2C总线结构如下图所示。系统中所有的器件均
有I2C总线接口,所有器件通过两根线SDA(串行数据线)和 SCL(串行时钟线)连接到I2C总线上,并通过寻址识别。
I2C总线中的器件既可以作为主控器,也可以作为被控器, 系统中每个器件均具有惟一的地址,各器件之间通过寻址确定 数据交换方。任何时刻总线只能由一个主控制器,数据的传输 只能在主、从器件间进行。
4.串行外设总线SPI
十三.I2C使用2——主从机程序编写
⼗三.I2C使⽤2——主从机程序编写在前⾯⼀章我们已经铺垫了I2C的使⽤流程,下⾯我们就按照I2C的通讯流程写对应的代码,这个流程应该严格按照参考⼿册给出的定义上⾯两幅图就是I2C通讯的流程master代码流程I2C的代码流程⽐较复杂,我们⼀个个函数来说初始化⾸先是初始化void i2c_init(I2C_Type *base){base->I2CR &= ~(1<<7); //disable I2Cbase->IFDR= 0x15; //640分频,clk=103.125KHzbase->I2CR |= (1<<7); //I2C Enable}初始化⾥只是设置了个分频器,我们使⽤的时钟源是66MHz,选择640分频,速率为103.125KHz,设置分频器前要将I2C停⽌,设置完成后⼀定要使能I2C,其他寄存器操作时有些是要求I2C使能的。
产⽣Start流程在完成初始化后,数据可以有主机先⾏发送。
发送数据时,要先检查I2C的BUSY标志位是否为0(I2C_I2SR[IBB]),标志位为0时才能发送数据。
发送第⼀组数据时要将从机的地址写⼊I2C_I2DR寄存器,从机地址是7位的,地址后⾯要跟⼀个读写标志。
/*** @brief ⽣成start信号** @param base I2C结构体* @param address 从机地址* @param direction ⽅向* @return unsigned char*/unsigned char i2c_master_start(I2C_Type *base,unsigned char address,enum i2c_direction direction){if((base->I2SR) & (1<<5)){ //IBB,I2C忙标志位return1; //IBB=1时,I2C忙,返回1}//设置为主机模式base->I2CR |= ((1<<5) | (1<<4)); //[5]MSTA master mode,[4]MXT 发送模式//产⽣Start信号base->I2DR = ((unsigned int)address <<1) | ((direction== kI2C_Read)?1 :0); //address位⾼7位为地址,低位为读写标志return0; //⽆异常,返回0}函数中先判定是否为总线忙,如果总线忙跳出函数,抛出异常,如果正常就将设备设置成master、发送模式,将数据寄存器写⼊从机地址。
i2c读取流程
i2c读取流程I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,用于连接微控制器和外围设备。
它是一种多主机、多从机的通信方式,可以实现多个设备之间的数据传输。
本文将详细介绍I2C的读取流程,包括起始信号、地址传输、数据传输和停止信号等步骤。
I2C的读取流程如下:1. 发送起始信号:主机在总线上发送一个低电平的起始信号,表示开始一次通信。
这个起始信号告诉从机们主机即将开始传输数据。
2. 发送设备地址:主机发送要读取的设备的地址。
I2C总线上每个从机都有一个唯一的7位地址,主机通过发送这个地址来选择要读取的设备。
3. 等待应答信号:主机发送设备地址后,会等待从机发送应答信号。
如果从机存在,并且地址与主机发送的地址匹配,从机会发送一个低电平的应答信号,表示已经准备好接收数据。
4. 发送内部地址:一些设备需要在读取数据之前先发送一个内部地址。
主机通过发送这个内部地址来指定要读取的数据的位置。
5. 重复起始信号:主机发送一个重复起始信号,用于告诉从机主机要读取数据了。
6. 发送设备地址和读取位:在重复起始信号之后,主机再次发送设备地址,但是在地址的最后一位上设置为1,表示要进行读取操作。
7. 等待应答信号:主机发送设备地址和读取位后,再次等待从机发送应答信号。
8. 读取数据:主机从从机读取数据。
主机每次从总线上读取一个字节的数据,然后发送一个应答信号告诉从机是否继续发送下一个字节的数据。
9. 停止信号:主机发送停止信号表示本次通信结束。
停止信号是一个从高电平转为低电平的信号,表示主机释放总线。
以上就是I2C的读取流程。
通过这个流程,主机可以与从机进行数据的交换和传输。
I2C作为一种简单、灵活的串行通信协议,被广泛应用于各种嵌入式系统和电子设备中。
需要注意的是,不同的设备在实现I2C协议时可能会有一些细微的差异,因此在具体应用中,需要参考设备的数据手册和相关文档,了解设备对I2C协议的具体要求和实现细节。
i2c总线协议标准与规范
i2c 总线协议标准与规范I2C 总线协议I2C 协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。
起始和结束信号总是由主设备产生。
总线在空闲状态时,SCL 和SDA 都保持着高电平,当SCL 为高电平而SDA 由高到低的跳变,表示产生一个起始条件;当SCL 为高而SDA 由低到高的跳变,表示产生一个停止条件。
在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C 器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。
如图所示:在了解起始条件和停止条件后,我们再来看看在这个过程中数据的传输是如何进行的。
前面我们已经提到过,数据传输以字节为单位。
主设备在SCL 线上产生每个时钟脉冲的过程中将在SDA 线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA 线,回传给主设备一个应答位,此时才认为一个字节真正的被传输完成。
当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否定应答位。
数据传输的过程如图所示:在前面我们还提到过,I2C 总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7 位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0 表示主设备向从设备写数据,1 表示主设备向从设备读数据。
如图所示:I2C 协议2 条双向串行线,一条数据线SDA,一条时钟线SCL。
SDA 传输数据是大端传输,每次传输8bit,即一字节。
支持多主控(mulTImastering),任何时间点只能有一个主控。
总线上每个设备都有自己的一个addr,共7 个bit,广播地址全0.系统中可能有多个同种芯片,为此addr 分为固定部分和可编程部份,细节视芯片而定,看datasheet。
i2c信号
图14-3 I2C通信流程解析起始信号:UART通信是从一直持续的高电平出现一个低电平标志起始位;而I2C通信的起始信号的定义是SCL为高电平期间,SDA由高电平向低电平变化产生一个下降沿,表示起始信号,如图14-3中的start部分所示。
前几章我们学了一种通信协议叫做UART异步串口通信,这节课我们要来学习第二种常用的通信协议I2C。
I2C总线是由PHILIPS公司开发的两线式串行总线,多用于连接微处理器及其外围设备。
I2C总线的主要特点是接口方式简单,两条线可以挂多个参与通信的器件,即多机模式,而且任何一个器件都可以作为主机,当然同一时刻只能一个主机。
从原理上来讲,UART属于异步通信,比如电脑发送给单片机,电脑只负责把数据通过TXD发送出来即可,接收数据是单片机自己的事情。
而I2C属于同步通信,SCL时钟线负责收发双方的时钟节拍,SDA数据线负责传输数据。
I2C的发送方和接收方都以SCL这个时钟节拍为基准进行数据的发送和接收。
从应用上来讲,UART通信多用于板间通信,比如单片机和电脑,这个设备和另外一个设备之间的通信。
而I2C多用于板内通信,比如单片机和我们本章要学的EEPROM之间的通信。
14.1 I2C时序初步认识在硬件上,I2C总线是由时钟总线SCL和数据总线SDA两条线构成,连接到总线上的所有的器件的SCL都连到一起,所有的SDA都连到一起。
I2C总线是开漏引脚并联的结构,因此我们外部要添加上拉电阻。
对于开漏电路外部加上拉电阻的话,那就组成了线“与”的关系。
总线上线“与”的关系,那所有接入的器件保持高电平,这条线才是高电平。
而任意一个器件输出一个低电平,那这条线就会保持低电平,因此可以做到任何一个器件都可以拉低电平,也就是任何一个器件都可以作为主机,如图14-1所示,我们添加了R63和R64两个上拉电阻。
图14-1 I2C总线的上拉电阻虽然说任何一个设备都可以作为主机,但绝大多数情况下我们都是用微处理器,也就是我们的单片机来做主机,而总线上挂的多个器件,每一个都像电话机一样有自己唯一的地址,在信息传输的过程中,通过这唯一的地址可以正常识别到属于自己的信息,在我们的KST-51开发板上,就挂接了2个I2C设备,一个是24C02,一个是PCF8591。
I2C多机通讯
*******************************************************************/ void event_loop(void) { uchar i,err; Delay(1000); ISendStrExt(SLAVE1,DataTab,10); LED=~LED; Delay(1000); if(IRcvStrExt(SLAVE1,buff,10)) { err=0; for(i=0;i<10;i++) if(buff[i]!=DataTab[i]) for(i=0;i<10;i++) { buff[i]=0; } Delay(1000); } ISendStrExt(SLAVE2,DataTab,10); LED=~LED; //向从机 2 发起写操作 {err=1;} //正确则取反 LED1 表示 //清空数据接收区 if(!err) {LED1=~LED1;} //判断接收到的数据是否符合数据表内容 //向从机 1 发起读操作 //向从机 1 发起写操作
U1
LPC932
主机
11 12 P13 P12
P03 P02
VSS
VDD
24 25
7
P03 P02
VSS
SDA
SCL
从机 1
U3 LPC932
VCC 21
P13 P12
11 12
VDD
P03 P02
11 12 P13 P12
VSS
24 25
7
R5 1k
R6 1k
LED20 LED21
从机 2
图1
P89LPC932 I2C一主多从通信电路图
I2C程序和流程图
程序和流程图:IIC.hvoid Init_IIC(void);void EEPROM_ByteWrite(unsigned char nAddr,unsigned char nVal); unsigned char EEPROM_RandomRead(unsigned char nAddr); unsigned char EEPROM_CurrentAddressRead(void);void EEPROM_AckPolling(void);void Init_CLK(void);void Init_IIC_Port(void);Main.C/*******************************************IIC for AT24c16 OR AT24CXXX 系列只要控制好IICRM IICSTP IICSTT 其硬件会自动完成SCL SDA的一系列时序只要注意各个发送与接收的控制标志位.******************************************/#include <MSP430x16x.h>#include "IIC.h"volatile unsigned char Data[6];void main(void){//volatile unsigned char Data[6];//停止看门狗WDTCTL = WDTPW+WDTHOLD;//初始化端口Init_IIC_Port();//初始化时钟Init_CLK();//I2C初始化Init_IIC(); //置传输方式及控制方式//打开中断_EINT();//写入数据EEPROM_ByteWrite(0x0000,0x12);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0001,0x34);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0002,0x56);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0003,0x78);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0004,0x9A);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0005,0xBC);//等待写操作完成EEPROM_AckPolling();//读出数据,随机读Data[0] = EEPROM_RandomRead(0x0000); //地址自动加1 //读出数据,当前地址读Data[1] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[2] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[3] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[4] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[5] = EEPROM_CurrentAddressRead();}IIC.C#include <MSP430x16x.h>#include "IIC.h"#define SLAVEADDR 0x50;int tx_count;int rx_count;unsigned char I2CBuffer[3];void Init_IIC(void){//将P3.1和P3.3设置为I2C管脚P3SEL = 0x0A;//设置P3.1和P3.3管脚的方向P3DIR &= ~0x0A;//选择为I2C模式U0CTL |= I2C + SYNC;//禁止I2C模块U0CTL &= ~I2CEN;//设置I2C为7位地址模式,不使用DMA,//字节模式,时钟源为SMCLK,//设置成传输模式I2CTCTL = I2CTRX + I2CSSEL_2;//定义从器件地址I2CSA = SLAVEADDR;//设置本身的地址I2COA = 0x01A5;//I2C时钟为SMCLK / 160I2CPSC = 159;//SCL 高电平为:5 *I2C 时钟I2CSCLH = 0x03;//SCL 低电平为:5 *I2C 时钟I2CSCLL = 0x03;//I2C 模块有效U0CTL |= I2CEN;tx_count = 0;rx_count = 0;}void I2CWriteInit(void) //对于AT24CXXX的写操作是置成主模式并置位中断使能. {//主(Master)模式U0CTL |= MST;//传输模式,R/W 为:0I2CTCTL |= I2CTRX;//清除中断标志I2CIFG &= ~TXRDYIFG;//发送中断使能I2CIE = TXRDYIE;}void I2CReadInit(void){//接收模式,R/W 为:1I2CTCTL &= ~I2CTRX;//接收中断使能I2CIE = RXRDYIE;}void EEPROM_ByteWrite(unsigned char nAddr, unsigned char nVal){//等待I2C模块完成所有操作 //在选定的地址写入数据.while (I2CDCTL&I2CBUSY) ;//设置地址数据I2CBuffer[1] = nAddr;//设置数据I2CBuffer[0] = nVal;//设置缓冲区指针tx_count = 1;//写数据初始化I2CWriteInit(); //设置为主模式//发送数据的长度//1个控制字节,2个数据字节I2CNDAT = 2;//开始和停止条件产生//开始I2C通信I2CTCTL |= I2CSTT+I2CSTP;return;}unsigned char EEPROM_CurrentAddressRead(void){//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//读操作的初始化I2CReadInit();//主(Master)模式U0CTL |= MST;//接收1个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG) ;//返回数据return I2CBuffer[0];}unsigned char EEPROM_RandomRead(unsigned char nAddr) {//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//设置地址I2CBuffer[0] = nAddr;//设置缓冲区指针tx_count = 0;//写操作初始化I2CWriteInit();//传输数据长度//1个控制字节和一个地址数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//起始条件产生I2CTCTL |= I2CSTT;//等待传输完成while ((~I2CIFG)&ARDYIFG);//读操作初始化I2CReadInit();//接收一个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件 I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG);//返回数据return I2CBuffer[0];}void EEPROM_AckPolling(void){unsigned int count;//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);count=0;//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL |= I2CRM;//使能I2C模块U0CTL |= I2CEN;//设置NACKIFG标志I2CIFG = NACKIFG;while (NACKIFG & I2CIFG){//清除中断标志I2CIFG=0x00;//主(Master)模式U0CTL |= MST;//设置传输模式I2CTCTL |= I2CTRX;//产生起始条件I2CTCTL |= I2CSTT;//等待I2CSTT被清除while (I2CTCTL & I2CSTT) ; //产生停止条件I2CTCTL |= I2CSTP;//等待停止条件复位while (I2CDCTL & I2CBUSY) ; count = count + 1;}//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL &= ~I2CRM;//使能I2CU0CTL |= I2CEN;return;}#if __VER__ < 200interrupt [USART0TX_VECTOR] void ISR_I2C(void)#else#pragma vector=USART0TX_VECTOR__interrupt void ISR_I2C(void)#endif //上面的程序其实只要编写 ://#pragma vector=USART0TX_VECTOR __interrupt void ISR_I2C(void)就行. {switch (I2CIV){case I2CIV_AL:{//仲裁中断break;}case I2CIV_NACK:{//NACK中断break;}case I2CIV_OA:{//自己地址中断break;}case I2CIV_ARDY:{//访问准备好中断break;}case I2CIV_RXRDY:{//接收准备好中断I2CBuffer[0]=I2CDRB;break;}case I2CIV_TXRDY:{//发送准备好中断I2CDRB = I2CBuffer[tx_count];tx_count = tx_count - 1;if (tx_count < 0){//禁止发送中断I2CIE &= ~TXRDYIE;}break;}case I2CIV_GC:{//一般调用中断break;}case I2CIV_STT:{//起始条件中断break;}}}void Init_IIC_Port(void){//初始化端口寄存器与IIC口无关的PX口关闭以便于对编写系统板的综合程序. //P1DIR = 0xFF;//P2DIR = 0xFF;P3DIR = 0xF5;//P4DIR = 0xFF;P5DIR = 0x7F;//P6DIR = 0xFF;//P4OUT = 0X11;//P5OUT &= 0XF0;P3SEL|=BIT1+BIT3; //在这里如果设置成}void Init_CLK(void){unsigned int i;//将寄存器的内容清零//XT2震荡器开启//LFTX1工作在低频模式//ACLK的分频因子为1BCSCTL1 = 0X00;do{// 清除OSCFault标志IFG1 &= ~OFIFG;for (i = 0x20; i > 0; i--);}while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1//open XT2, LFTX2 选择低频率BCSCTL1 &= ~(XT2OFF + XTS); //BCSCTL1=0X00 功能一样//DCO Rsel=7(Freq=3200k/25摄氏度)BCSCTL1 |= RSEL0 + RSEL1 + RSEL2;BCSCTL1 |= 0x07;//MCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELM1;//SMCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELS;}//对于系统时钟的选择关系到整个程序运行稳定性./*************************************************************文件名:msp430f169i2c.c*整体描述:MSP430F169单片机硬件IIC软件,字节方式,主方式* IIC接口:P3.3=SCL,P3.1=SDA;(开漏输出)* 相应寄存器:地址寄存器I2COA 用于存放自身从地址(从方式时才有用)* 地址寄存器I2CSA 用于存放外围的从机地址(主方式时才有用)* 控制寄存器U0CTL 硬件I2C的设置、使能、模式等。
驱动编写流程图 (精炼)
Struct bus_type i2c_bus_type = { .name = “i2c”, .match = i2c_device_match, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, .pm = &i2c_device_pm_opw, };
模块加载函数: static int s5pc100_platform_init(void)
注册platform_driver; Platform_driver_register( &s5pc100_adc_driver );
结束
模块卸载函数: static int __init s5pc100_platform_init(void)
switch(cmd)
注册设备号,设备号名; register_chrdev_region(devno, 1, "s5pc100_beep");
初始化cdev,结合file_opertions cdev_init( &cdev, &s5pc100_beep_ops );
注册cdev,结合设备号 cdev_add(&cdev, devno, 1);
static void beep_on(void) { writel((readl(S5PC100_GPG3_BASE + 4) | (0x1 << 1)), S5PC100_GPD_BASE + 4); }
i2c通信过程
i2c通信过程
i2c通信过程如下:
1. 主设备向从设备发送起始信号(Start Condition)。
2. 主设备发送从设备的地址和读写标志(Write/Read Bit)。
3.从设备返回应答信号(ACK/NACK),表示该设备存在或不存在。
4. 主设备发送数据(Data)给从设备,从设备返回应答信号
(ACK/NACK)。
5. 如果需要连续传输数据,主设备发送重复起始信号(Repeated Start Condition)。
6. 主设备发送从设备的地址和读写标志(Write/Read Bit)。
7.从设备返回应答信号(ACK/NACK),表示该设备存在或不存在。
8. 主设备接收数据(Data)从从设备,向从设备发送应答信号(ACK)或停止接收信号(NACK)。
9. 主设备发送停止信号(Stop Condition)。
10.通信结束。
在i2c通信过程中,主设备是控制通信的中心,从设备是被动接收数
据并回应的设备。
主设备和从设备都有一个7位或10位的地址,用来标
识设备。
在通信过程中,主设备通过发送起始信号和地址来选择要通信的
从设备,并发送数据给从设备。
从设备接收数据后,进行处理并返回应答
信号。
i2c简易时序图
启动信号:SCL为高电平的时候,SDA由高电平向低电平跳变。
结束信号:SCL为高电平的时候,SDA由低电平向高电平跳变。
应答信号:I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功,对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。
如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
写时序:开始信号:主机+从设备地址+写命令,从机应答,应答成功,表示有这个设备,然后主机+设备内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址,主机写入数据,从机应答,是否继续发送,不发送的话,发送停止信号P。
读时序:要想读设备,首先要知道将要所读取设备的地址告诉从设备,从设备才能将数据放到(发送)SDA上使主设备读取,从设备将数据放入SDA上的过程,由硬件主动完成,不用人为的写入。
所以首先先写入从机地址,然后+写控制命令,从机应答,应答成功,表示有这个设备,然后写入内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址。
然后主机继续发出:写入从机地址,然后+读命令,从机应答,应答成功,此时便可以读取数据了,从设备已经将数据放入到SDA上了。
地址跟设备已经验证了,不用再进行验证。
启动信号与停止信号的时序图如下图所示:数据位发送:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
程序和流程图:IIC.hvoid Init_IIC(void);void EEPROM_ByteWrite(unsigned char nAddr,unsigned char nVal); unsigned char EEPROM_RandomRead(unsigned char nAddr); unsigned char EEPROM_CurrentAddressRead(void);void EEPROM_AckPolling(void);void Init_CLK(void);void Init_IIC_Port(void);Main.C/*******************************************IIC for AT24c16 OR AT24CXXX 系列只要控制好IICRM IICSTP IICSTT 其硬件会自动完成SCL SDA的一系列时序只要注意各个发送与接收的控制标志位.******************************************/#include <MSP430x16x.h>#include "IIC.h"volatile unsigned char Data[6];void main(void){//volatile unsigned char Data[6];//停止看门狗WDTCTL = WDTPW+WDTHOLD;//初始化端口Init_IIC_Port();//初始化时钟Init_CLK();//I2C初始化Init_IIC(); //置传输方式及控制方式//打开中断_EINT();//写入数据EEPROM_ByteWrite(0x0000,0x12);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0001,0x34);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0002,0x56);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0003,0x78);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0004,0x9A);//等待写操作完成EEPROM_AckPolling();//写入数据EEPROM_ByteWrite(0x0005,0xBC);//等待写操作完成EEPROM_AckPolling();//读出数据,随机读Data[0] = EEPROM_RandomRead(0x0000); //地址自动加1 //读出数据,当前地址读Data[1] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[2] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[3] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[4] = EEPROM_CurrentAddressRead();//读出数据,当前地址读Data[5] = EEPROM_CurrentAddressRead();}IIC.C#include <MSP430x16x.h>#include "IIC.h"#define SLA VEADDR 0x50;int tx_count;int rx_count;unsigned char I2CBuffer[3];void Init_IIC(void){//将P3.1和P3.3设置为I2C管脚P3SEL = 0x0A;//设置P3.1和P3.3管脚的方向P3DIR &= ~0x0A;//选择为I2C模式U0CTL |= I2C + SYNC;//禁止I2C模块U0CTL &= ~I2CEN;//设置I2C为7位地址模式,不使用DMA,//字节模式,时钟源为SMCLK,//设置成传输模式I2CTCTL = I2CTRX + I2CSSEL_2;//定义从器件地址I2CSA = SLAVEADDR;//设置本身的地址I2COA = 0x01A5;//I2C时钟为SMCLK / 160I2CPSC = 159;//SCL 高电平为:5 *I2C 时钟I2CSCLH = 0x03;//SCL 低电平为:5 *I2C 时钟I2CSCLL = 0x03;//I2C 模块有效U0CTL |= I2CEN;tx_count = 0;rx_count = 0;}void I2CWriteInit(void) //对于AT24CXXX的写操作是置成主模式并置位中断使能. {//主(Master)模式U0CTL |= MST;//传输模式,R/W 为:0I2CTCTL |= I2CTRX;//清除中断标志I2CIFG &= ~TXRDYIFG;//发送中断使能I2CIE = TXRDYIE;}void I2CReadInit(void){//接收模式,R/W 为:1I2CTCTL &= ~I2CTRX;//接收中断使能I2CIE = RXRDYIE;}void EEPROM_ByteWrite(unsigned char nAddr, unsigned char nVal){//等待I2C模块完成所有操作//在选定的地址写入数据.while (I2CDCTL&I2CBUSY) ;//设置地址数据I2CBuffer[1] = nAddr;//设置数据I2CBuffer[0] = nVal;//设置缓冲区指针tx_count = 1;//写数据初始化I2CWriteInit(); //设置为主模式//发送数据的长度//1个控制字节,2个数据字节I2CNDAT = 2;//开始和停止条件产生//开始I2C通信I2CTCTL |= I2CSTT+I2CSTP;return;}unsigned char EEPROM_CurrentAddressRead(void){//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//读操作的初始化I2CReadInit();//主(Master)模式U0CTL |= MST;//接收1个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG) ;//返回数据return I2CBuffer[0];}unsigned char EEPROM_RandomRead(unsigned char nAddr) {//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);//设置地址I2CBuffer[0] = nAddr;//设置缓冲区指针tx_count = 0;//写操作初始化I2CWriteInit();//传输数据长度//1个控制字节和一个地址数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//起始条件产生I2CTCTL |= I2CSTT;//等待传输完成while ((~I2CIFG)&ARDYIFG);//读操作初始化I2CReadInit();//接收一个字节的数据I2CNDAT = 1;//清除中断标志I2CIFG &= ~ARDYIFG;//开始接收,产生重新起始和停止条件I2CTCTL |= I2CSTT + I2CSTP;//等待传输完成while ((~I2CIFG)&ARDYIFG);//返回数据return I2CBuffer[0];}void EEPROM_AckPolling(void){unsigned int count;//等待I2C模块完成所有操作while (I2CDCTL&I2CBUSY);count=0;//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL |= I2CRM;//使能I2C模块U0CTL |= I2CEN;//设置NACKIFG标志I2CIFG = NACKIFG;while (NACKIFG & I2CIFG){//清除中断标志I2CIFG=0x00;//主(Master)模式U0CTL |= MST;//设置传输模式I2CTCTL |= I2CTRX;//产生起始条件I2CTCTL |= I2CSTT;//等待I2CSTT被清除while (I2CTCTL & I2CSTT) ;//产生停止条件I2CTCTL |= I2CSTP;//等待停止条件复位while (I2CDCTL & I2CBUSY) ;count = count + 1;}//清除I2CEN位U0CTL &= ~I2CEN;I2CTCTL &= ~I2CRM;//使能I2CU0CTL |= I2CEN;return;}#if __VER__ < 200interrupt [USART0TX_VECTOR] void ISR_I2C(void)#else#pragma vector=USART0TX_VECTOR__interrupt void ISR_I2C(void)#endif //上面的程序其实只要编写://#pragma vector=USART0TX_VECTOR __interrupt void ISR_I2C(void)就行. {switch (I2CIV){case I2CIV_AL:{//仲裁中断break;}case I2CIV_NACK:{//NACK中断break;}case I2CIV_OA:{//自己地址中断break;}case I2CIV_ARDY:{//访问准备好中断break;}case I2CIV_RXRDY:{//接收准备好中断I2CBuffer[0]=I2CDRB;break;}case I2CIV_TXRDY:{//发送准备好中断I2CDRB = I2CBuffer[tx_count];tx_count = tx_count - 1;if (tx_count < 0){//禁止发送中断I2CIE &= ~TXRDYIE;}break;}case I2CIV_GC:{//一般调用中断break;}case I2CIV_STT:{//起始条件中断break;}}}void Init_IIC_Port(void){//初始化端口寄存器与IIC口无关的PX口关闭以便于对编写系统板的综合程序.//P1DIR = 0xFF;//P2DIR = 0xFF;P3DIR = 0xF5;//P4DIR = 0xFF;P5DIR = 0x7F;//P6DIR = 0xFF;//P4OUT = 0X11;//P5OUT &= 0XF0;P3SEL|=BIT1+BIT3; //在这里如果设置成}void Init_CLK(void){unsigned int i;//将寄存器的内容清零//XT2震荡器开启//LFTX1工作在低频模式//ACLK的分频因子为1BCSCTL1 = 0X00;do{// 清除OSCFault标志IFG1 &= ~OFIFG;for (i = 0x20; i > 0; i--);}while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1//open XT2, LFTX2 选择低频率BCSCTL1 &= ~(XT2OFF + XTS); //BCSCTL1=0X00 功能一样//DCO Rsel=7(Freq=3200k/25摄氏度)BCSCTL1 |= RSEL0 + RSEL1 + RSEL2;BCSCTL1 |= 0x07;//MCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELM1;//SMCLK的时钟源为TX2CLK,分频因子为1BCSCTL2 += SELS;}//对于系统时钟的选择关系到整个程序运行稳定性./*************************************************************文件名:msp430f169i2c.c*整体描述:MSP430F169单片机硬件IIC软件,字节方式,主方式* IIC接口:P3.3=SCL,P3.1=SDA;(开漏输出)* 相应寄存器:地址寄存器I2COA 用于存放自身从地址(从方式时才有用)* 地址寄存器I2CSA 用于存放外围的从机地址(主方式时才有用)* 控制寄存器U0CTL 硬件I2C的设置、使能、模式等。