AVR单片机IIC读写范例IIC.C 或者IIC.H
i2c读写流程
i2c读写流程I2C读写流程I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路之间进行数据传输。
在本文中,我们将介绍I2C的读写流程,以帮助读者更好地理解和应用该协议。
I2C通信需要两个主要组件:主设备(master)和从设备(slave)。
主设备负责发起和控制通信,而从设备则接收和响应主设备的请求。
在I2C总线上,可以连接多个从设备,每个从设备都有一个唯一的地址,用于与主设备进行通信。
I2C的读写流程如下:1. 初始化I2C总线在开始进行I2C通信之前,首先需要初始化I2C总线。
这包括设置I2C的时钟频率、选择主设备或从设备模式等操作。
在初始化过程中,还需要配置主设备的地址,以便与从设备进行通信。
2. 发送起始信号一旦完成I2C总线的初始化,主设备就可以发送起始信号。
起始信号告诉从设备主设备即将发起通信。
3. 发送设备地址主设备发送从设备的地址,以选择要进行通信的从设备。
从设备的地址有7位或10位两种格式。
在发送地址之前,主设备需要确保总线上没有其他设备正在发送数据。
4. 发送读/写位根据通信需求,主设备发送读(R)或写(W)位。
读位表示主设备希望从设备发送数据,而写位表示主设备希望向从设备发送数据。
5. 接收应答位从设备接收到主设备发送的地址和读/写位后,会发送应答位。
应答位用于告知主设备从设备是否准备好进行通信。
如果从设备准备好通信,它会发送应答位(ACK);否则,它会发送非应答位(NACK)。
6. 发送数据如果主设备希望向从设备发送数据,它会发送数据字节。
从设备在接收到数据字节后,会发送应答位来确认接收到的数据。
7. 接收数据如果主设备希望从设备接收数据,它会接收从设备发送的数据字节,并发送应答位来告知从设备是否继续发送数据。
8. 停止通信一旦通信完成,主设备会发送停止信号,以告知从设备通信结束。
停止信号由一个高到低的跳变表示。
以上就是I2C的读写流程。
AVR单片机IIC读写范例IIC.C 或者IIC.H
资料简介:本程序简单的示范了如何使用ATMEGA16的TWI 读写AT24C02 IIC EEPROM TWI协议(即IIC协议,请认真参考IIC协议的内容,否则根本就不能掌握)一主多从的应用,M16作主机(M16做从机和多主多从的应用不多,请自行参考相关文档)中断模式(因为AVR的速度很高,而IIC的速度相对较低,采用查询模式会长时间独占CPU,令CPU的利用率明显下降。
特别是IIC速度受环境影响只能低速通讯时,对系统的实时性产生严重的影响。
查询模式可以参考其它文档和软件模拟IIC的文档)AT24C02/04/08的操作特点出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器*/#include <avr/io.h>#include <avr/signal.h>#include <avr/interrupt.h>#include <avr/delay.h>//时钟定为外部晶振7.3728MHz,F_CPU=7372800#include <compat/twi.h>//定义了各种模式下的状态码列表(TWSR已屏蔽预分频位),本文后面附上中文描述//管脚定义#define pinSCL0//PC0 SCL#define pinSDA1//PC1 SDA//为保险起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。
#define fSCL100000//TWI时钟为100KHz//预分频系数=1(TWPS=0)#if F_CPU < fSCL*36#define TWBR_SET 10;//TWBR必须大于等于10#else#define TWBR_SET(F_CPU/fSCL-16)/2;//计算TWBR值#endif#define TW_ACT(1<<TWINT)|(1<<TWEN)|(1<<TWIE)//TWCR只能IN/OUT,直接赋值比逻辑运算(|= &=)更节省空间#define SLA_24CXX0xA0//24Cxx系列的厂商器件地址(高四位)#define ADDR_24C020x00// AT24C02的地址线A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01 //TWI_操作状态#define TW_BUSY0#define TW_OK 1#define TW_FAIL 2//TWI_读写命令状态#define OP_BUSY0#define OP_RUN 1//TWI读写操作公共步骤#define ST_FAIL0//出错状态#define ST_START1//START状态检查#define ST_SLAW2//SLAW状态检查#define ST_WADDR3//ADDR状态检查//TWI读操作步骤#define ST_RESTART4//RESTART状态检查#define ST_SLAR5//SLAR状态检查#define ST_RDATA6//读取数据状态检查,循环n字节//TWI写操作步骤#define ST_WDATA7//写数据状态检查,循环n字节#define FAIL_MAX20//重试次数最大值//定义全局变量unsigned char ORGDATA[8]={0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04};//原始数据unsigned char CMPDATA[8];//比较数据unsigned char BUFFER[256];//缓冲区,可以装载整个AC24C02的数据struct str_TWI//TWI数据结构{volatile unsigned char STATUS;//TWI_操作状态unsigned char SLA;//从设备的器件地址unsigned int ADDR;//从设备的数据地址unsigned char*pBUF;//数据缓冲区指针unsigned int DATALEN;//数据长度unsigned char STATE;//TWI读写操作步骤unsigned char FAILCNT;//失败重试次数};struct str_TWI strTWI;//TWI的数据结构变量//仿真时在watch窗口,监控这些全局变量。
I2C读写流程范文
I2C读写流程范文I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路之间进行短距离的通信。
这个协议由飞利浦公司(现在的恩智浦半导体)在20世纪80年代初引入。
I2C由两根线构成,分别是时钟线(SCL)和数据线(SDA),其中时钟线由主设备控制发送,数据线用于主设备和从设备之间的双向数据传输。
I2C协议支持多主设备和多从设备的并行连接。
1.初始化:a.设置I2C总线的时钟频率。
b.初始化GPIO端口,将SCL和SDA设置为输出模式,并将它们拉高。
2.发送设备地址:a.主设备发送起始信号,即在SCL线上拉低SDA线,表示数据的传输即将开始。
b.主设备发送设备地址和读写位(0表示写,1表示读)到SDA线。
设备地址是从设备的标识符,主设备用它来选择要通信的从设备。
c.主设备发送读写位确认信号,即主设备将SCL线拉低一段时间,然后释放,之后从设备根据读写位作出响应。
3.发送数据:a.主设备将要发送的数据写入到SDA线上。
b.主设备发送数据确认信号,即主设备将SCL线拉低一段时间,然后释放。
c.从设备接收数据,并根据接收情况作出响应。
4.接收数据:a.主设备发出重新起始信号,即在SCL线上拉低SDA线,然后释放。
b.主设备发送设备地址和读写位到SDA线,指示要读取数据的从设备。
c.主设备发送读写位确认信号,即主设备将SCL线拉低一段时间,然后释放。
d.从设备将要发送的数据写入到SDA线上。
e.主设备接收数据,并根据接收情况作出响应。
5.终止通信:a.主设备发出停止信号,即在SCL线上拉低SDA线,然后释放。
b.从设备根据停止信号作出响应。
以上就是I2C读写的基本流程。
需要注意的是,I2C是一种同步通信协议,所有的数据传输都是通过时钟线同步的。
主设备控制时钟信号的频率,从设备负责根据时钟信号的变化作出响应。
通过这种方式,可以实现多个设备在同一总线上进行通信。
芯片IIC读写程序
I2C_GenerateSTOP(I2C1, ENABLE);
}
/*************************************************
**函数名:I2C_ByteWrite_24C
**功能:写一个字节
**注意事项:字写入同样需要调用忙判断
/*允许1字节1应答模式*/
I2C_AcknowledgeConfig(I2C1, ENABLE);
/* 发送起始位 */
I2C_GenerateSTART(I2C1, ENABLE);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/
#else
/*发送器件地址(读)24C01*/
I2C_Send7bitAddress(I2C1, addr<<1, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
**注意事项:本函数可以理解为:判忙
****************************************************/
void I2C_Standby_24C(void)
{
vu16 SR1_Tmp;
do
{
/*起始位*/
I2C_GenerateSTART(I2C1, ENABLE);
/*
操作对象为一24C02
*/
#include &ude "stm32f10x_i2c.h"
IIC总线读写EEPROM(深度诠释)
/*----------------------------------------------------------------------------------------------------------IIC总线读写EEPROM(串行扩展eeprom,24c02)(STC12C系列单片机自带eeprom,且有另外的eeprom操作方式)作者:Allen.H(帮同学修改的一个程序)时间:2010.11.5----------------------------------------------------------------------------------------------------------*/#include <reg52.h>#include <intrins.h>//是用括号还是双引号看情况,本地头文件用双引号,系统头文件用括号//这里使用了_nop_()函数,所以调用此头文件#define TRUE 1/*define宏定义一般用大写,宏定义并不会减少最终代码空间define多行语句时,每一行末尾写上\,最后一行可以不写,有时比较短的语句写成一个子函数会牺牲更多的时间,因为函数调用耗时比较多,这个时候用一个define语句更好*/#define FALSE 0typedef unsigned char uchar;//良好的程序风格,不应该用#define//#define uchar unsigned charsbit sda=P2^0; //---------你把sda和scl引脚可能定反了,我换过来了-------------------------------sbit scl=P2^1;//等号对其,变量名长短不一时,注意,且测试等于号"=="或者其他双目关系运算符两边都空一格//-----------------------------------------------------------------void delay(uchar z)//带参数很好{//大括号所在行不要写代码uchar i,j;//局部变量中用来自加自减可以用i,j之类的定义,计数建议不要用i,j//局部变量不占内存,函数调用时生成堆栈,不应该定义局部变量时作初始化//----局部变量命名后空一格,写正式代码for(i=z;i>0;i--)for(j=100;j>0;j--);//注明多少时间,在调试模式下,看窗口左边的SEC值}//函数与函数之间空一格void delay_7nop()//子程序命名最好顾名思义,比如delay_1ms(),这里考虑都是使用7nop,不带参数{/*程序代码每进一层逻辑就缩进一格TAB键,TAB设置为3,4格,在keil的view->options里面设置,不要使用几个空格来缩进,统一使用TAB键*/_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//这里0-1000多个_nop_都可以}//delay函数都放在一起,函数顺序不要乱放,相关的放一起,//--------------------------------------------------------------------void init(){sda=1;delay_7nop();scl=1;delay_7nop();}//---SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;//SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
IIC读写代码
#include<reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit sda=P2^1;sbit scl=P2^0;unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7 c,0x39,0x5e,0x79,0x71,0x00};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};void start(void);void stop(void);void ack(void);void noack(void);void iicwr_byte(uchar dat);uchar iicre_byte(void);void delay (void);void init(void);void delay1(void);void write_byte(uchar add,uchar dat);uchar read_byte(uchar add);///////////////////////////////////void delay1(void){uint a=30000;while(a--);}void delay (void){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}void start(void){sda=1;delay();scl=1;delay();sda=0;delay();}void stop(void)sda=0;delay();scl=1;delay();sda=1;delay();}void ack(void){uchar i;scl=1;delay();while((sda==1)&&(i<200))i++; scl=0;delay();}void noack(void){sda=1;delay();scl=1;delay();scl=0;delay();}void init(void){sda=1;scl=1;}void iicwr_byte(uchar dat){uchar i;scl=0;for(i=0;i<8;i++){if(dat&0x80){sda=1;}else{sda=0;dat=dat<<1;delay();scl=1;delay();scl=0;delay();}sda=1;delay();}uchar iicre_byte(void) {uchar i;uchar dat;scl=0;delay();sda=1;delay();for(i=0;i<8;i++){scl=1;delay();dat=dat<<1;if(sda){dat++;//}scl=0;delay();}return dat;}void main(){/* init();start();iicwr_byte(0xa0); ack();iicwr_byte(10);ack();iicwr_byte(0x55); ack();delay1();////////////////////////////////////////init();start();iicwr_byte(0xa0);ack();iicwr_byte(10);ack();start();iicwr_byte(0xa1);ack();P0=iicre_byte();noack();stop(); */uchar k;k=read_byte(7);k=k%10;P1=smg_du[k];k++;write_byte(7,k);while(1);}void write_byte(uchar add,uchar dat) {init();start();iicwr_byte(0xa0);ack();iicwr_byte(add);ack();iicwr_byte(dat);ack();stop();}uchar read_byte(uchar add){uchar a;init();start();iicwr_byte(0xa0);ack();iicwr_byte(add);start();iicwr_byte(0xa1); ack();a=iicre_byte(); noack();stop();return a;}。
iic通信协议读写时序
iic通信协议读写时序I2C(Inter-Integrated Circuit)是一种用于连接微控制器和各种外围设备的串行总线协议。
它只需要两根线:一根是双向的数据线SDA,另一根是时钟线SCL。
以下是I2C通信协议的基本读写时序:起始信号:当时钟线SCL为高电平时,数据线SDA由高电平变为低电平,表示开始传输。
这个信号只能由主设备(Master)发起。
地址传输:起始信号后,主设备发送一个7位的设备地址和一个读写位(共8位)。
设备地址用于寻址总线上的特定设备,读写位决定接下来的操作是读还是写。
应答信号:每个接收设备在接收到地址后,都会将其与自身的地址进行比较。
如果匹配,设备会产生一个应答信号(ACK)。
应答信号是在第9个时钟脉冲时,将SDA线拉低。
如果没有设备应答,主设备会检测到一个非应答信号(NACK),并可能终止传输或产生错误。
数据传输:在接收到应答信号后,主设备开始发送或接收数据。
数据是按字节传输的,每个字节后面都会跟随一个应答/非应答位。
数据的传输方向由起始信号后的读写位决定。
停止信号:当所有数据都传输完毕后,主设备会发送一个停止信号以结束传输。
停止信号是在时钟线SCL为高电平时,数据线SDA由低电平变为高电平。
对于写操作,主设备在发送完起始信号和设备地址(写)后,开始发送要写入的数据。
每个数据字节后面都需要等待一个应答信号。
当所有数据都发送完毕后,主设备发送停止信号。
对于读操作,主设备在发送完起始信号和设备地址(读)后,会释放SDA线并在SCL线上产生第9个时钟信号。
被选中的设备在确认是自己的地址后,开始在SDA线上传输数据。
主设备在每个数据字节后面都需要发送一个应答信号(除了最后一个字节)。
当读取完所有数据后,主设备发送一个非应答信号和一个停止信号。
以上是I2C通信协议的基本读写时序,但实际的实现可能会根据设备和需求有所不同。
iic读写位
IIC 读写位1. 什么是 IIC?IIC(Inter-Integrated Circuit)是一种用于在集成电路之间进行通信的串行通信协议。
它由飞利浦公司(Philips)在上世纪80年代提出,现已成为广泛应用的通信标准。
IIC 是一种双线制的通信协议,包括一条用于传输数据的数据线(SDA)和一条用于传输时钟信号的时钟线(SCL)。
这种双线制的设计使得 IIC 可以同时传输数据和控制信息。
IIC 采用主从结构,一个主设备可以控制多个从设备进行通信。
主设备负责发起通信和生成时钟信号,而从设备在接收到主设备的请求后进行响应。
2. IIC 读写位IIC 通信协议规定了数据的传输格式。
在 IIC 通信中,读操作和写操作的数据格式是不同的。
读操作是指主设备向从设备读取数据,写操作是指主设备向从设备发送数据。
数据格式包括起始位、从设备地址、读/写位、数据位和终止位。
其中,读/写位用于指示是读操作还是写操作。
IIC 读写位的具体含义如下:•读操作:读操作的读/写位为1,表示读取数据。
主设备先发送从设备地址,然后接收从设备发送的数据。
•写操作:写操作的读/写位为0,表示发送数据。
主设备先发送从设备地址,然后发送要写入的数据。
3. IIC 读写位的应用IIC 通信协议广泛应用于各种电子设备和模块之间的通信,例如传感器、存储器、显示屏和扩展模块等。
3.1 传感器许多传感器通过 IIC 总线与主控设备进行通信。
主控设备可以通过读操作获取传感器采集到的数据,也可以通过写操作发送配置信息给传感器。
以温度传感器为例,主控设备可以通过读操作获取当前的温度数值,并根据需要进行相应的控制。
主控设备还可以通过写操作发送配置信息,如采样率、报警阈值等,来对传感器进行配置。
3.2 存储器很多存储器芯片(如EEPROM、Flash)也采用了 IIC 通信协议。
通过 IIC 总线,主控设备可以对存储器进行读写操作,实现数据的存储和读取。
iic 多byte读写
IIC多byte读写技术IIC(Inter-Integrated Circuit)是一种串行通信协议,常用于连接微控制器与外设。
在某些应用中,需要一次读写多个字节的数据,这就涉及到了IIC多byte读写技术。
一、IIC简介IIC(Inter-Integrated Circuit)又称为I2C,由飞利浦公司于1982年首次推出,是一种广泛应用于数字集成电路芯片内部集成的串行通信总线。
IIC总线由两根信号线组成,分别为串行数据线(SDA)和串行时钟线(SCL)。
IIC总线支持多主机和多从机,并且能够实现多个设备的通信。
它是一个简单而有效的通信协议,能够高效地在多个设备之间传输数据。
二、IIC多byte读写通常情况下,IIC协议是通过逐字节进行读写的。
但是,在某些应用场景中,如读写存储器或传感器等,需要一次读写多个字节的数据,以提高数据传输的效率。
这就需要使用IIC多byte读写技术。
在IIC多byte读写中,需要考虑以下几个方面:1. 数据长度首先需要确定要读写的数据长度。
在IIC协议中,可以通过发送长度字节来指定要读写的数据长度。
长度字节告诉设备要传输的字节数量,这样设备就可以准确地处理接下来的读写操作。
2. 寄存器地址多byte读写通常需要设备具有寄存器或存储器的地址。
传输数据之前,需要将要读写的目标地址发送给设备,这样设备才知道要读写哪个寄存器或存储器单元。
3. 读写顺序在进行多byte读写时,需要考虑数据的读写顺序。
有些设备要求数据按照从高地址到低地址的顺序读写,而有些设备则要求按照从低地址到高地址的顺序读写。
在进行多byte读写之前,需要确定设备的读写顺序,以保证数据的正确传输。
4. 响应与确认在进行多byte读写操作时,设备需要正确地响应和确认数据的传输。
发送数据后,需要等待设备的响应或确认信号,以确保数据已经被正确接收。
如果设备没有正确响应或确认,可能需要重新发送数据或者进行错误处理。
I2C总线读写程序通用
//==========================头文件加载===============================#include <reg52.h> //加载52系列单片机头文件//===========================端口声明================================sbit CLK=P3^6; //74hc574时钟信号线sbit G=P2^4; //74hc574使能sbit IIC_SDA=P2^6; //声明IIC总线的数据线接在单片机的P2。
5端口。
sbit IIC_SCL=P2^5; //声明IIC总线的时钟线接在单片机的P2。
7端口。
unsigned char tabl[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x0BF,0x8C};//0,1,2,3,4,5,6,7,8,9,-,P//===========================函数声明================================ void display(unsigned char aa);void delay(unsigned int t);void delay_IIC(void);void IIC_Init(void);void IIC_start(void);void IIC_stop(void);bit IIC_Tack(void);void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data);unsigned char IIC_single_byte_read(unsigned char Daddr,unsigned char Waddr);void IIC_write_byte(unsigned char Data);unsigned char IIC_read_byte(void);//============================主函数================================= void main() //主函数{unsigned char Data=2,addr=0x01;//—-——-—--—————————-——--————-系统初始化——-—-—--—-—-—————-—---———-IIC_Init();//初始化IIC总线。
AVR单片机I2C读写程序
1./******************************************************************************/2./* 基于AVR单片机对数字定位器的I2C读写程序 */3./* AVR单片机型号:ATMEGA16 */4./* 数字定位器型号:intersil公司的ISL90840UIV2027z */5./* 程序功能:对数字定位器内部的4个独立可编程定位器进行写与读操作 */6./* 并在数码管上显示 */7./* 简要电路说明:共阴极数码管通过AVR的PORTA口驱动输出,ISL90840的芯片 */8./* 地址A2上拉到VCC,A1、A0都到地,即A2=1,A1=A0=0 */9./* 整理改编者:都口 2009.05.13 */10./******************************************************************************/11.12.13.#include<iom16v.h>14.#include<macros.h>15./*-----------------------------数据类型宏定义---------------------------------*/16.typedef unsigned char uchar; //无符号字符型17.typedef unsigned int uint; //无符号整型18.19./*--------------------------设定数字定位器芯片主地址--------------------------*/20.#define W_ADD 0x58 //写字节命令及器件地址(实际地址A2A1A0由电路设计决定)21.// 在此例中A2=1,A1=A0=0,0101 A2 A1 A0 0 (0101 1000)(0x58)22.#define R_ADD 0x59 //读字节命令及器件地址(实际地址A2A1A0由电路设计决定)23.// 在此例中A2=1,A1=A0=0,0101 A2 A1 A0 1 (0101 1001)(0x59)24.25./*-----------------设定数字定位器芯片内部四电位器各子地址---------------------*/26.#define DCP_0 0x00 //内部模块1地址 (0000 0000)选中第一个电位器27.#define DCP_1 0x01 //内部模块2地址 (0000 0001)选中第二个电位器28.#define DCP_2 0x02 //内部模块3地址 (0000 0010)选中第三个电位器29.#define DCP_3 0x03 //内部模块4地址 (0000 0011)选中第四个电位器30.31./*---------------------------设定I2C应答信号----------------------------------*/32.#define SLAW 0x18 //SLA_W 已正常发送代码,判断器件是否正常应答的常量33.34./*-----------------------------ms级延时调用程序-------------------------------*/35.void tms(uchar i)36. {37. uint j;38. uint q;39.for(q=i;q!=0;q--)40. {41.for (j=8000;j!=0;j--){;}42. }43. }44.45./*----------------------------I2C 总线初始化----------------------------------*/46.void twi_init(void)47.{48. TWCR= 0x00; //终止I2C twi49. TWBR= 0x32; //设置传输速率(中速)50. TWSR= 0x00; //设置预分步值(0分频)51. TWAR= 0x00; //设置从机地址(因为是主机模式,此处可以不用)52. TWCR= 0x04; //开启I2C twi53.}54.55./*--------------------------总线启动开始START---------------------------------*/56.void i2cstart(void)57.{58. TWCR= BIT(TWINT) | BIT(TWSTA) | BIT(TWEN);59.while (!(TWCR & BIT(TWINT)));60.}61.62./*-----------------------总线上写入一个字节返回TWI状态------------------------*/63.uchar i2cwt(uchar a)64.{65. TWDR = a;66. TWCR = BIT(TWINT) | BIT(TWEN);67.while (!(TWCR & BIT(TWINT)));68. _NOP();69.return(TWSR&0xF8);70.}71.72./*----------------------总线上读出一个字节返回所读数据------------------------*/73.uchar i2crd(void)74.{75. TWCR= BIT(TWINT) | BIT(TWEA) | BIT(TWEN);76.while (!(TWCR & BIT(TWINT)));77.return(TWDR);78.}79.80./*--------------------------总线结束停止STOP----------------------------------*/81.void i2cstop(void)82.{83. TWCR = BIT(TWINT) | BIT(TWSTO) | BIT(TWEN);84.}85.86./*----------------------------------------------------------------------------*/87./* 向数字定位器内选定某个定位器写入所需数据 */88./* 参数说明: dcp_n 要写入数据的内部某个电位器的子地址 */89./* number 要写入此电位器的数据 */90./*----------------------------------------------------------------------------*/91.92.void wt24c_dwq( uchar dcp_n,uchar number)93.{94.if(number=0x255) //数据不得超过25595. {96. i2cstart(); //发送起始信号97.if(i2cwt(W_ADD)==SLAW) //发送SLA_W, 写字节命令及主器件地址98. {99. i2cwt(dcp_n); //写字节命令及器件内部子地址100. i2cwt(number); //向所选定的定位器写入所需数据101. }102. i2cstop(); //发送停止信号103. tms(6); //延时6ms,完成写入104. }105.}106.107./*----------------------------------------------------------------------------*/ 108./* 从数字定位器内按顺序读出所有数据 */ 109./* 参数说明: *r_data要读入数据的主机内存地址指针 */110./*----------------------------------------------------------------------------*/ 111.v oid rd24c_n( uchar *r_data)112.{113. uchar i;114. i2cstart(); //发送起始信号115.if(i2cwt(W_ADD)==SLAW) //发送SLA_W, 写字节命令及主器件地址116. {117. i2cwt(DCP_0); //写字节命令及器件内部第一个子地址118. i2cstart(); //再次发送起始信号119. i2cwt(R_ADD); //读命令字节及主器件地址120.for(i=0;i<4;i++)121. {122. *r_data=i2crd(); //依次从器件读出数据,4个电位器则共4个字节数据123. r_data++;124. }125. }126. i2cstop(); //读完成停止结束127.}//只要把地址指针给一个4位的数组,即可得到所读数据128.129./*-----------------------------对端口进行初初化-------------------------------*/ 130.v oid port_init(void)131.{132.PORTA = 0x00; //PORTA口初始设置为输出0133.DDRA = 0xFF; //PORTA口设置为输出方式(用于数码管显示所读数据)134.PORTB = 0xFF;135.DDRB = 0x00;136.PORTC = 0xFF;137.DDRC = 0x00;138.PORTD = 0xFF;139.DDRD = 0xFF;140.}141.142./*------------------------对器件整体进行初始化--------------------------------*/ 143.v oid init_device(void)144.{145.port_init(); //端口初始化146.twi_init(); //I2C总线设置初始化147.}148.149./*----------------------------------------------------------------------------*/ 150./* 主程序 */ 151./* 功能:用于测试向数字定位器中定入数据,然后再依次读出 */ 152./* 写入的数据并通过数码管显示出来,查看正确与否 */ 153./*----------------------------------------------------------------------------*/ 154.v oid main(void)155.{156. uchar i,k;157. uchar r_buf[4]; //读取数据存储数组158. init_device(); //初使化159.for(i=0;i<4;i++) //读区清零160. {r_buf[i]=0;}161.162.wt24c_dwq(DCP_0,0x3f); //向内部第一个电位器写入0x3f,数码管显示值为'0' 163.tms(6);164.wt24c_dwq(DCP_1,0x21); //向内部第一个电位器写入0x21,数码管显示值为'1' 165.tms(6);166.wt24c_dwq(DCP_2,0x5b); //向内部第一个电位器写入0x5b,数码管显示值为'2' 167.tms(6);168.wt24c_dwq(DCP_3,0x73); //向内部第一个电位器写入0x73,数码管显示值为'3' 169.tms(6);170.171.rd24c_n(r_buf); //从数字电位器内部依次读出写入的数据给数组172.i=1;173.while(i)174.{175.for(k=0;k<4;k++)176. {177. PORTA=0x00;178. tms(50);179. PORTA=r_buf[k]; //由端口A的数码管依次显示所读数值,检验其正确性180. tms(50);181. }182. i=0; //循环显示一次183. }184.}185.186./******************************************************************************/ 187./*----------------------------------程序结束----------------------------------*/ 188./******************************************************************************/。
iic从机代码例程
iic从机代码例程全文共四篇示例,供读者参考第一篇示例:IIC,全称为Inter-Integrated Circuit,是一种常见的串行通信协议,用于在电子设备之间进行数据传输。
在很多电子产品中,IIC总线被广泛应用,比如各种传感器、存储器芯片、显示屏等等。
IIC总线有两种设备,即主机和从机,主机负责控制总线上的通信,而从机则被动地响应主机的命令。
在本文中,我们将重点讨论IIC从机代码例程的制作。
从机代码是指实现IIC通信协议的一组程序,用于从机设备与主机设备进行数据传输。
在制作IIC从机代码例程时,需要考虑一系列因素,包括从机设备的特性、通信协议的格式、数据传输的安全性等等。
制作IIC从机代码例程需要了解从机设备的硬件特性。
不同的从机设备在硬件上有不同的接口结构和通信要求,因此需要根据具体的从机设备来编写相应的代码。
通常来说,从机设备会有一个IIC接口或是IIC引脚,通过这个接口来进行数据传输。
在编写从机代码例程时,需要注意从机设备的接口类型、通信速率、寄存器地址等硬件相关的信息。
制作IIC从机代码例程需要了解通信协议的格式。
IIC通信协议有以下几个重要的部分:起始信号、地址和数据传输、应答位、停止信号。
在编写从机代码时,需要按照这个格式来进行通信。
起始信号是一个特定的电平变化,表示通信的开始;地址和数据传输是主机向从机发送命令或数据;应答位是从机设备返回的一个应答信号,表示是否成功接收数据;停止信号是一个特定的电平变化,表示通信的结束。
制作IIC从机代码例程需要考虑数据传输的安全性。
在IIC通信中,数据的正确传输是非常重要的。
为了确保数据的安全性,可以采用一些校验方法,比如CRC校验。
CRC校验是一种通过计算数据的校验和来检测数据是否传输正确的方法,可以有效减少数据传输错误的概率。
在编写从机代码时,可以加入CRC校验功能,以提高数据传输的可靠性。
制作IIC从机代码例程是一项涉及硬件、协议和安全性的复杂任务。
i2c读写格式
i2c读写格式
I2C的读写格式如下:
1. 起始条件:在进行I2C通信时,首先需要发送起始条件,即SDA(串行
数据线)从高电平切换到低电平时,同时SCL(串行时钟线)保持高电平。
这表示通信的开始。
2. 从设备地址:接下来需要发送从设备的地址,这是一个7位的地址,最低位用于指示读写操作。
如果要进行写操作,最低位为0;如果要进行读操作,最低位为1。
3. 寄存器地址:对于需要访问特定寄存器的设备,需要发送寄存器地址,以确定要读写的寄存器。
4. 读写的格式:在7位地址模式下的写操作格式为S(启动信号)+从机的
7位地址+0(写信号)+ACK(应答信号)+8位数据+ACK(应答信号)
+P(停止信号)。
在7位地址模式下的读操作格式为S(启动信号)+从机的7位地址+1(读信号)+ACK(应答信号)+8位数据+ACK(应答信号)+P(停止信号)。
在传输数据时,主机先发出S信号,然后发出8位数据,高7位是从设备地址,第8位是读写位(0-W,1-R)。
一般来说,每次一个字节的数据传输完,主机或者从机必须发出ACK信号,才能进行下一个
数据的传输。
这时主机发送一个P信号终止传输或者重新发出一个S信号开始新的传输。
5. 传输过程:如果从机在传输过程中不能接收更多的数据,它也不会发出ACK信号。
这时主机必须终止传输,发送一个P信号或者重新发出一个S 信号开始新的传输。
以上信息仅供参考,如需了解i2c的读写格式,建议咨询专业人士。
iic标准程序
IIC(Inter-Integrated Circuit)是一种串行通信协议,用于连接微控制器、传感器、存储器和其他外围设备。
以下是IIC标准程序的示例代码,用于在微控制器和外围设备之间进行通信:#include <stdio.h>#include <stdint.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/i2c-dev.h>int main(){int file;char *filename = "/dev/i2c-1"; // I2C bus 1 的设备文件路径uint8_t address = 0x50; // I2C 设备的地址char *buffer = malloc(2); // 用于存储从I2C 设备读取的数据的缓冲区// 打开I2C 总线设备文件file = open(filename, O_RDWR);if (file < 0) {perror("Failed to open i2c bus");return -1;}// 设置I2C 总线设备的地址和速率if (ioctl(file, I2C_SLAVE, address) < 0) {perror("Failed to acquire bus access and/or talk to slave");return -1;}// 向I2C 设备写入数据buffer[0] = 0x01; // 要写入的数据的第一个字节buffer[1] = 0x0A; // 要写入的数据的第二个字节int n = write(file, buffer, 2); // 将数据写入I2C 设备if (n < 1) {perror("Write failed");return -1;}// 从I2C 设备读取数据n = read(file, buffer, 1); // 从I2C 设备读取一个字节的数据到缓冲区中if (n < 1) {perror("Read failed");return -1;}printf("Read data: %x\n", buffer[0]); // 打印读取的数据的十六进制表示形式// 关闭I2C 总线设备文件close(file);free(buffer);return 0;}以上代码使用了Linux下的I2C-dev驱动,需要包含`<linux/i2c-dev.h>`头文件。
AVR单片机学习九iic总线及TWI模块的使用方法
AVR 单片机学习(九)iic总线及TWI模块的使用方法IIC总线定义与特点I2C总线的工作原理AVR的TWI模块的使用方法AT24C02IIC inter integrated circuit 总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。
I2C总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。
例如管理员可对各个组件进行查询,以管理系统的配置或掌握组件的功能状态,如:电源和系统风扇,可随时监控内存、硬盘、网络、系统温度等多个参数,增加了系统的安全性,方便了管理。
TWI:ATMega系列单片机内集成两线制串行接口模块,ATmegl文档称为TWI接口事实上TWI与PHILIOS的I2C总线是同一回事,之所以叫它TWI是因为这样命名可使ATmel避免交术语版税。
所以,TWI是兼容I2C的一种说法。
I2C总线最只要的优点是其简单性和有效性。
由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。
总线的长度可高达25英尺,并且能够以10KPS的最大传输率支持40个组件,I2C总线的另一个优点是,它支持多主控(MULTIMASTERING),其中任何能够进行发送和接受的设备都可以称为主总线,一个主控能够控制信号的传输和时钟频率。
当然,在任何时间点上只能有一个主控。
由于AVR 有上拉电阻所以 R1 R2可以不要。
其实还的共地应该是3根线。
在多主控上有个总线总裁的知识可以参阅相关文档学习。
呵呵、初学者不用了解。
I2C总线是由数据线SDA和时钟线SCL构成的串行总线,可发送和接受数据。
在CPU与被控IC之间、IC与IC之间进行双向传送、最高传送速率100KBPS.各种被控制电路均并联在这条总线上,最高传送速率100KBPS.各种被控制电路均并联在这条总线上,但就像电话机一样只有拨通各自的号码才能工作,所以每个电路和模块都有唯一的地址,在信息的传输过程中,I2C总线并接的每一模块电路既是主控器(或被控器),又是发送器(或接收器),这取决于它所要完成的功能,CPU发出的控制信号分为地址码和控制量两部分,地址码用来选址,即接通需要控制的电路,确定控制的种类;控制量决定调整的类别(如对比度、亮度等)及需要调整的量。
i2c读写程序的详细讲解
i2c读写程序的详细讲解I2C即Inter-IntegratedCircuit(内部集成电路),是一种同步串行总线技术,它可以用来连接多个芯片,并使用它们之间的2条双向数据总线进行通信。
I2C总线可以通过5根线实现,其中2条用于数据传输,另外3条用于控制传输过程:SCL(时间同步线)、SDA(数据线)、VCC(电源线)。
I2C在光学芯片、DSP和ARM芯片等领域都得到了广泛应用,能够实现在一个系统或介质中共享数据,有助于节省系统开发成本和实现系统节能。
第二部分:I2C读写程序I2C读写程序是通过I2C总线实现数据读写的特定程序,主要由以下步骤构成:1、设置I2C总线:通过一系列硬件设置完成I2C总线的初始化,以满足对应数据读写的要求;2、发送I2C开始信号:在进行数据读写前,需要发送一个开始信号,以通知主从端可以进行通信;3、发送I2C地址:根据读写操作,发送I2C地址;4、发送I2C数据:根据读写操作,发送相关数据;5、接收I2C数据:根据读写操作,接收相关数据;6、发送I2C停止信号:发送I2C停止信号,结束数据读写过程。
第三部分:I2C读写程序实例下面以C语言为例,介绍在I2C通讯操作中读写程序的编写流程: 1、I2C总线的初始化:可以使用如下函数来设置I2C总线的参数,完成I2C总线的初始化:#include <linux/i2c.h>#include <linux/i2c-dev.h>int i2c_init (int busno);其中busno表示I2C总线号;2、发送I2C开始信号:可以使用如下函数来发送I2C开始信号:int i2c_smbus_write_start(int busno, int addr);其中busno表示I2C总线号,addr表示要发送的I2C地址;3、发送I2C地址:可以使用如下函数来发送I2C地址:int i2c_smbus_write_byte(int busno, int addr);其中busno表示I2C总线号,addr表示要发送的I2C地址;4、发送I2C数据:可以使用如下函数发送I2C数据:int i2c_smbus_write_byte_data(int busno, int addr, int data);其中busno表示I2C总线号,addr表示要发送的I2C地址,data 表示要发送的数据;5、接收I2C数据:可以使用如下函数接收I2C数据:int i2c_smbus_read_byte_data(int busno, int addr);其中busno表示I2C总线号,addr表示要读取的I2C地址;6、发送I2C停止信号:可以使用如下函数发送I2C停止信号:int i2c_smbus_write_stop(int busno);其中busno表示I2C总线号;第四部分:结论以上就是I2C读写程序的详细讲解,可以看出,I2C读写程序的实现步骤非常简单,只需要对每个步骤做出正确的设置,就可以实现I2C数据读写操作。
I2C总线读写程序通用
//==========================头文件加载===============================#include <reg52.h> //加载52系列单片机头文件//===========================端口声明================================sbit CLK=P3^6; //74hc574时钟信号线sbit G=P2^4; //74hc574使能sbit IIC_SDA=P2^6; //声明IIC总线的数据线接在单片机的P2.5端口。
sbit IIC_SCL=P2^5; //声明IIC总线的时钟线接在单片机的P2.7端口。
unsigned char tabl[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x0BF,0x8C};//0,1,2,3,4,5,6,7,8,9,-,P//===========================函数声明================================void display(unsigned char aa);void delay(unsigned int t);void delay_IIC(void);void IIC_Init(void);void IIC_start(void);void IIC_stop(void);bit IIC_Tack(void);void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data);unsigned char IIC_single_byte_read(unsigned char Daddr,unsigned char Waddr);void IIC_write_byte(unsigned char Data);unsigned char IIC_read_byte(void);//============================主函数=================================void main() //主函数{u nsigned char Data=2,addr=0x01;//---------------------------系统初始化--------------------------I IC_Init();//初始化IIC总线。
iic的读写
IIC的读写IIC(Inter-Integrated Circuit)是一种常用的串行通信协议,其设计用于连接芯片和外部设备。
它在许多嵌入式系统中得到广泛应用,特别是连接传感器、存储器和其他外设。
IIC主要由两条线构成,即SDA(Serial Data Line)和SCL(Serial Clock Line)。
本文将介绍IIC的基本原理、通信模式以及读写操作。
IIC的基本原理IIC协议采用主从模式进行通信。
主设备(Master)负责控制整个通信过程,而从设备(Slave)则被主设备控制。
IIC总线上可以连接多个从设备,每个设备都有一个唯一的7位地址,主设备通过发送地址和读/写位来选择需要和哪个从设备通信。
在IIC总线上,数据传输是基于两条线上的时序关系进行的。
SCL线由主设备控制产生时钟信号,而SDA线用于传输数据。
数据传输都从一个起始位开始,后跟8位数据和一个读/写位,最后是一个停止位。
起始位和停止位都是由主设备控制,而数据和读/写位都是在时钟信号的边沿改变。
IIC的通信模式IIC协议支持两种不同的通信模式:标准模式和快速模式。
标准模式下,主设备工作时钟频率为100 kHz,而快速模式下则为400 kHz。
另外,还有一种高速模式(速度可达到3.4 MHz),但这超出了本文的讨论范围。
在标准模式下,IIC总线上传输的速度较慢,适用于较简单的通信需求。
而快速模式提供了更高的传输速度,适用于需要更高数据传输频率的应用。
IIC的读操作在IIC协议中,读操作由主设备发起。
读操作的基本流程如下:1.主设备发送起始位和从设备的地址(包括读/写位)。
2.主设备释放总线控制权,等待从设备响应。
3.从设备检测到地址匹配后,发送应答信号给主设备。
4.主设备接收应答信号后,开始读取从设备发送的数据。
5.主设备发送应答信号,表明还需要继续读取数据。
6.从设备继续发送数据,主设备接收并发送应答信号,直到读取完所有数据。
7.主设备发送停止位,结束读操作。
iic读写程序例程
iic读写程序例程我们需要了解IIC总线的基本原理。
IIC总线由两根线组成,分别是时钟线(SCL)和数据线(SDA)。
SCL线由主设备控制,用于产生时钟信号,而SDA线用于数据的传输。
在IIC总线上,每个设备都具有一个唯一的地址,通过地址可以进行设备的选择和寻址。
数据的传输是通过主设备发送起始信号和停止信号来实现的。
在编写IIC读写程序之前,我们需要明确需要读写的设备的地址和寄存器的地址。
设备的地址是设备的唯一标识,寄存器的地址是设备内部的某个存储单元的地址。
通过寄存器地址,我们可以对设备进行相应的配置和控制。
接下来,我们开始编写IIC读写程序。
首先,我们需要初始化IIC总线,并设置主设备的地址。
初始化包括配置时钟频率、使能IIC总线等操作。
然后,我们可以通过写操作向设备发送相应的配置命令,例如设置传感器的工作模式、配置存储器的读写参数等。
写操作需要指定设备地址和寄存器地址,以及需要写入的数据。
接下来,我们可以进行读操作,从设备中读取相应的数据。
读操作同样需要指定设备地址和寄存器地址。
通过读操作,我们可以获取传感器的测量数据、读取存储器中的数据等。
读取到的数据可以进行进一步的处理和分析,例如显示在屏幕上、保存到文件中等。
在编写IIC读写程序时,我们需要注意以下几点。
首先,要保证程序的正确性和稳定性,可以通过添加错误处理机制和异常处理机制来增强程序的健壮性。
其次,要注意处理设备的响应和超时情况,避免程序陷入死循环或无响应的状态。
此外,要充分利用设备提供的文档和示例代码,以便更好地理解和使用设备。
IIC读写程序是嵌入式系统中常见的一种程序,通过使用IIC总线,我们可以方便地实现设备之间的数据传输和通信。
在编写IIC读写程序时,我们需要了解IIC总线的基本原理,并根据设备的地址和寄存器的地址进行相应的配置和操作。
通过合理设计和编写,可以实现稳定、高效的IIC读写程序,为嵌入式系统的开发和应用提供强大的支持。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
资料简介:本程序简单的示范了如何使用ATMEGA16的TWI 读写AT24C02 IIC EEPROM TWI协议(即IIC协议,请认真参考IIC协议的内容,否则根本就不能掌握)一主多从的应用,M16作主机(M16做从机和多主多从的应用不多,请自行参考相关文档)中断模式(因为AVR的速度很高,而IIC的速度相对较低,采用查询模式会长时间独占CPU,令CPU的利用率明显下降。
特别是IIC速度受环境影响只能低速通讯时,对系统的实时性产生严重的影响。
查询模式可以参考其它文档和软件模拟IIC的文档)AT24C02/04/08的操作特点出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器*/#include <avr/io.h>#include <avr/signal.h>#include <avr/interrupt.h>#include <avr/delay.h>//时钟定为外部晶振7.3728MHz,F_CPU=7372800#include <compat/twi.h>//定义了各种模式下的状态码列表(TWSR已屏蔽预分频位),本文后面附上中文描述//管脚定义#define pinSCL0//PC0 SCL#define pinSDA1//PC1 SDA//为保险起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。
#define fSCL100000//TWI时钟为100KHz//预分频系数=1(TWPS=0)#if F_CPU < fSCL*36#define TWBR_SET 10;//TWBR必须大于等于10#else#define TWBR_SET(F_CPU/fSCL-16)/2;//计算TWBR值#endif#define TW_ACT(1<<TWINT)|(1<<TWEN)|(1<<TWIE)//TWCR只能IN/OUT,直接赋值比逻辑运算(|= &=)更节省空间#define SLA_24CXX0xA0//24Cxx系列的厂商器件地址(高四位)#define ADDR_24C020x00// AT24C02的地址线A2/1/0全部接地,SLAW=0xA0+0x00<<1+0x00,SLAR=0xA0+0x00<<1+0x01 //TWI_操作状态#define TW_BUSY0#define TW_OK 1#define TW_FAIL 2//TWI_读写命令状态#define OP_BUSY0#define OP_RUN 1//TWI读写操作公共步骤#define ST_FAIL0//出错状态#define ST_START1//START状态检查#define ST_SLAW2//SLAW状态检查#define ST_WADDR3//ADDR状态检查//TWI读操作步骤#define ST_RESTART4//RESTART状态检查#define ST_SLAR5//SLAR状态检查#define ST_RDATA6//读取数据状态检查,循环n字节//TWI写操作步骤#define ST_WDATA7//写数据状态检查,循环n字节#define FAIL_MAX20//重试次数最大值//定义全局变量unsigned char ORGDATA[8]={0xAA,0xA5,0x55,0x5A,0x01,0x02,0x03,0x04};//原始数据unsigned char CMPDATA[8];//比较数据unsigned char BUFFER[256];//缓冲区,可以装载整个AC24C02的数据struct str_TWI//TWI数据结构{volatile unsigned char STATUS;//TWI_操作状态unsigned char SLA;//从设备的器件地址unsigned int ADDR;//从设备的数据地址unsigned char*pBUF;//数据缓冲区指针unsigned int DATALEN;//数据长度unsigned char STATE;//TWI读写操作步骤unsigned char FAILCNT;//失败重试次数};struct str_TWI strTWI;//TWI的数据结构变量//仿真时在watch窗口,监控这些全局变量。
//AT24C02的读写函数(包括随机读,连续读,字节写,页写)//根据sla的最低位决定(由中断程序中判断)//bit0=1 TW_READ读//bit0=0 TW_WRITE 写// sla器件地址(不能搞错)//addr EEPROM地址(0~1023)//*ptr读写数据缓冲区//len读数据长度(1~1024),写数据长度(1 or 8 or 16)//返回值是否能执行当前操作unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len) {unsigned char i;if (strTWI.STATUS==TW_BUSY){//TWI忙,不能进行操作return OP_BUSY;}strTWI.STATUS=TW_BUSY;i=(addr>>8)<<1;i&=0x06;//考虑了24C04/08的EEPROM地址高位放在SLA里面strTWI.SLA=sla+i;strTWI.ADDR=addr;strTWI.pBUF=ptr;strTWI.DATALEN=len;strTWI.STATE=ST_START;strTWI.FAILCNT=0;TWCR=(1<<TWSTA)|TW_ACT;//启动start信号return OP_RUN;}/*TWI中断函数这个函数流程只是考虑了器件地址后有一个字节数据(命令)地址的IIC器件(大部分IIC接口器件都是这种类型,常见的例如AT24C01/02/04/08/16,DS1307,DS1721等) 对于有两个字节数据地址的IIC器件(例如AT24C32/64/128/256等大容量EEPROM),请稍作改动//根据strTWI.SLA的最低位决定//bit0=1 TW_READ读//bit0=0 TW_WRITE 写虽然中断服务程序很长,但每次只执行一个 case,所以耗时并不长。
*/SIGNAL(SIG_2WIRE_SERIAL){//IIC中断unsigned char action,state,status;action=strTWI.SLA&TW_READ;//取操作模式state=strTWI.STATE;status=TWSR&0xF8;//屏蔽预分频位if ((status>=0x60)||(status==0x00)){//总线错误或从机模式引发的中断,不予处理return;}switch(state){case ST_START://START状态检查if(status==TW_START){//发送start信号成功TWDR=strTWI.SLA&0xFE;//发送器件地址写SLAWTWCR=TW_ACT;//触发下一步动作,同时清start发送标志 }else{//发送start信号出错state=ST_FAIL;}break;case ST_SLAW://SLAW状态检查if(status==TW_MT_SLA_ACK){//发送器件地址成功TWDR=strTWI.ADDR;//发送eeprom地址TWCR=TW_ACT;//触发下一步动作}else{//发送器件地址出错state=ST_FAIL;}break;case ST_WADDR://ADDR状态检查if(status==TW_MT_DATA_ACK){//发送eeprom地址成功if (action==TW_READ){//读操作模式TWCR=(1<<TWSTA)|TW_ACT;//发送restart信号,下一步将跳到RESTART分支 }else{//写操作模式TWDR=*strTWI.pBUF++;//写第一个字节strTWI.DATALEN--;state=ST_WDATA-1;//下一步将跳到WDATA分支TWCR=TW_ACT;//触发下一步动作}}else{//发送eeprom地址出错state=ST_FAIL;}break;case ST_RESTART://RESTART状态检查,只有读操作模式才能跳到这里if(status==TW_REP_START){//发送restart信号成功TWDR=strTWI.SLA;//发器件地址读SLARTWCR=TW_ACT;//触发下一步动作,同时清start发送标志 }else{//重发start信号出错state=ST_FAIL;}break;case ST_SLAR://SLAR状态检查,只有读操作模式才能跳到这里if(status==TW_MR_SLA_ACK){//发送器件地址成功if (strTWI.DATALEN--){//多个数据TWCR=(1<<TWEA)|TW_ACT;//设定ACK,触发下一步动作}else{//只有一个数据TWCR=TW_ACT;//设定NAK,触发下一步动作}}else{//发送器件地址出错state=ST_FAIL;}break;case ST_RDATA://读取数据状态检查,只有读操作模式才能跳到这里state--;//循环,直到读完指定长度数据if(status==TW_MR_DATA_ACK){//读取数据成功,但不是最后一个数据*strTWI.pBUF++=TWDR;if (strTWI.DATALEN--){//还有多个数据TWCR=(1<<TWEA)|TW_ACT;//设定ACK,触发下一步动作}else{//准备读最后一个数据TWCR=TW_ACT;//设定NAK,触发下一步动作}}else if(status==TW_MR_DATA_NACK){//已经读完最后一个数据*strTWI.pBUF++=TWDR;TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了strTWI.STATUS=TW_OK;}else{//读取数据出错state=ST_FAIL;}break;case ST_WDATA://写数据状态检查,只有写操作模式才能跳到这里state--;//循环,直到写完指定长度数据if(status==TW_MT_DATA_ACK){//写数据成功if (strTWI.DATALEN){//还要写TWDR=*strTWI.pBUF++;strTWI.DATALEN--;TWCR=TW_ACT;//触发下一步动作}else{//写够了TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了strTWI.STATUS=TW_OK;//启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来//编程期间器件不响应任何命令}}else{//写数据失败state=ST_FAIL;}break;default://错误状态state=ST_FAIL;break;}if (state==ST_FAIL){//错误处理strTWI.FAILCNT++;if (strTWI.FAILCNT<FAIL_MAX){//重试次数未超出最大值,TWCR=(1<<TWSTA)|TW_ACT;//发生错误,启动start信号 }else{//否则停止TWCR=(1<<TWSTO)|TW_ACT;//发送停止信号,不会再产生中断了strTWI.STATUS=TW_FAIL;}}state++;strTWI.STATE=state;//保存状态}int main(void){unsigned char i;//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻PORTA=0xFF;//不用的管脚使能内部上拉电阻。