求解51单片机I2C对24c02读写汇编程序
ORG 0000H LJMP MAIN SCL BIT P2.1 SDA BIT P2.0 TEMP EQU 30H BYTE_ADDR EQU 31H;---------------I2C通讯程序----------------;------------------------------------------;---------------读取I2C数据----------------;读取一个字节;输入:BYTE_ADDR,读取字节地址;输出:A;------------------------------------------ I2CREAD: LCALL I2C_START ;起始 MOV A,#0A0H LCALL I2C_TXBYTE ;发送芯片地址数据+写信号 LCALL I2C_RXACK ;接收ACK MOV A,BYTE_ADDR LCALL I2C_TXBYTE ;发送RAM地址数据 LCALL I2C_RXACK ;接收ACK LCALL I2C_START ;起始 MOV A,#0A1H LCALL I2C_TXBYTE ;发送地址数据+读信号 LCALL I2C_RXACK ;接收ACK LCALL I2C_RXBYTE ;接收数据 SETB C ;读一个字节C=1 LCALL I2C_TXACK ;发送NAK LCALL I2C_STOP ;读取完成 RET;----------------------------;R4=读出字节数;BYTE_ADDR=读出初始地址;R1=数据指针;---------------------------- I2C_PAGE_RD: LCALL I2C_START ;起始 MOV A,#0A0H LCALL I2C_TXBYTE ;发送芯片地址数据+写信号 LCALL I2C_RXACK ;接收ACK MOV A,BYTE_ADDR LCALL I2C_TXBYTE ;发送RAM地址数据 LCALL I2C_RXACK ;接收ACK LCALL I2C_START ;起始 MOV A,#0A1H LCALL I2C_TXBYTE ;发送地址数据+读信号 LCALL I2C_RXACK ;接收ACK NXT_BYTE: LCALL I2C_RXBYTE ;接收数据 MOV @R1,A INC R1 CLR C ;连续读C=0 LCALL I2C_TXACK ;发送NAK LCALL I2C_DELAY DJNZ R4,NXT_BYTE LCALL I2C_NOACK ;NOACK LCALL I2C_STOP ;读取完成 RET;----------------写一字节I2C数据------------;写入一个字节;输入:BYTE_ADDR,写入字节地址;A=写入数据;输出:无;------------------------------------------ I2CWRITE: PUSH ACC LCALL I2C_START ;开始写 MOV A,#0A0H LCALL I2C_TXBYTE ;发送地址数据+写信号 LCALL I2C_RXACK ;接收ACK MOV A,BYTE_ADDR LCALL I2C_TXBYTE ;发送RAM地址数据 LCALL I2C_RXACK ;接收ACK POP ACC LCALL I2C_TXBYTE ;写数据 LCALL I2C_RXACK ;接收ACK LCALL I2C_STOP ;写完成 LCALL I2C_DLYMS ;延时1ms RET;----------------------------;R4=写入字节数;BYTE_ADDR=写入初始地址;R1=数据指针;---------------------------- I2C_PAGE_WR: LCALL I2C_START ;开始写 MOV A,#0A0H LCALL I2C_TXBYTE ;发送地址数据+写信号 LCALL I2C_RXACK ;接收ACK MOV A,BYTE_ADDR LCALL I2C_TXBYTE ;发送RAM地址数据 LCALL I2C_RXACK ;接收ACK NEXT_DATA: ;WRITE 16 BYTES TO MOV A,@R1 ;EEPROM LCALL I2C_TXBYTE ;写数据 LCALL I2C_RXACK ;接收ACK INC R1 DJNZ R4,NEXT_DATA LCALL I2C_STOP ;写完成 LCALL I2C_DLYMS ;延时1ms RET;----------------------------;发送I2C起始信号;---------------------------- I2C_START: SETB SCL ;时钟高电平时数据下降沿为启动信号 LCALL I2C_DELAY SETB SDA LCALL I2C_DELAY CLR SDA ;数据线下降沿 LCALL I2C_DELAY ;延时 CLR SCL ;时钟->低 LCALL I2C_DELAY ;延时 RET;----------------------------;发送I2C停止信号;---------------------------- I2C_STOP: CLR SDA LCALL I2C_DELAY ;延时 SETB SCL ;时钟->高 LCALL I2C_DELAY ;延时 SETB SDA ;数据线上升沿 LCALL I2C_DELAY ;延时 CLR SCL RET ;----------------------------;发送ACK/NAK信号;---------------------------- I2C_TXACK: MOV SDA,C ;送ACK数据 LCALL I2C_DELAY ;延时 SETB SCL ;时钟->高 LCALL I2C_DELAY ;延时 CLR SCL ;时钟->低 LCALL I2C_DELAY ;延时 SETB SDA ;发送完成 RET;----------------------------;接收ACK/NAK信号;---------------------------- I2C_RXACK: SETB SDA ;准备读数据 LCALL I2C_DELAY ;延时 SETB SCL ;时钟->高 LCALL I2C_DELAY ;延时 MOV C,SDA ;读取ACK信号 CLR SCL ;时钟->低 LCALL I2C_DELAY ;延时 RET;---------------------------- I2C_NOACK: SETB SDA ;NO ACKNOWLEDGE LCALL I2C_DELAY SETB SCL LCALL I2C_DELAY CLR SCL LCALL I2C_DELAY RET;----------------------------;发送一字节数据;---------------------------- I2C_TXBYTE: MOV R7,#8 ;8位计数 TXNEXT: RLC A ;移出数据位 MOV SDA,C ;数据送数据口 SETB SCL ;时钟->高 LCALL I2C_DELAY ;延时 CLR SCL ;时钟->低 LCALL I2C_DELAY ;延时 DJNZ R7,TXNEXT ;送下一位 RET;----------------------------;接收一字节数据;---------------------------- I2C_RXBYTE: MOV R7,#8 ;8位计数 RXNEXT: SETB SCL ;时钟->高 LCALL I2C_DELAY ;延时 MOV C,SDA RLC A CLR SCL ;时钟->低 LCALL I2C_DELAY ;延时 DJNZ R7,RXNEXT ;收下一位 RET;---------------------------- I2C_DELAY: ; NOP NOP RET ;;---------------------------- I2C_DLYMS: PUSH 0 PUSH 1 MOV R1,#2 I2CDL: MOV R0,#248 DJNZ R0,$ DJNZ R1,I2CDL POP 1 POP...
求MCS
归一化模拟I2C总线软件包(C51)/****************************************************************************** I2C.H 标准80C51模拟I2C总线程序头文件******************************************************************************/#ifndef I2C_H#define I2C_H//定义I2C操作模式#define I2C_RECV 0 /* 接收模式 */#define I2C_SEND 1 /* 发送模式 */#define I2C_SrRECV 2 /* 带Sr接收 *///I2C总线初始化 void I2C_Init();/****************************************************************************** 函数:void I2C_On() 功能:启动I2C总线收发数据 返回:0-正常,1-异常(无应答) 说明:参数Mode是操作模式,决定I2C总线收发格式。
常见的收发格式有3种,具体如下: 0-接收模式,格式:S | SLA+R | Data... | P 1-发送模式,格式:S | SLA+W | Addr | Data... | P 2-带Sr接收,格式:S | SLA+W | Addr | Sr | SLA+R | Data... | P******************************************************************************/ bit I2C_On( unsigned char Mode, //操作模式 unsigned char SLA, //从机地址 unsigned char Addr, //子地址 unsigned char *Buf, //数据缓冲区 unsigned char Size //数据长度);#endif //I2C_H/****************************************************************************** I2C.C 标准80C51模拟I2C总线程序(主模式,通用)******************************************************************************/ #i nclude #i nclude "I2C.H"//模拟I2C总线的管脚定义 sbit I2C_SCL = P1^6; //定义I2C总线时钟信号 sbit I2C_SDA = P1^7; //定义I2C总线数据信号/****************************************************************************** 函数:I2C_Delay() 功能:模拟I2C总线延时 说明:请根据具体情况调整延时值******************************************************************************/ void I2C_Delay() { unsigned char t; t = 10; while ( --t != 0 ); //延时2*t个机器周期 }/****************************************************************************** 函数:I2C_Init() 功能:I2C总线初始化,使总线处于空闲状态 说明:在main()函数的开始处,应当执行一次本函数******************************************************************************/ void I2C_Init() { I2C_SCL = 1; I2C_Delay(); I2C_SDA = 1; I2C_Delay(); }/****************************************************************************** 函数:I2C_Start() 功能:产生I2C总线的起始条件 说明:SCL处于高电平期间,当SDA出现下降沿时启动I2C总线 本函数也用来产生重复起始条件******************************************************************************/ void I2C_Start() { I2C_SDA = 1; I2C_Delay(); I2C_SCL = 1; I2C_Delay(); I2C_SDA = 0; I2C_Delay(); I2C_SCL = 0; I2C_Delay(); }/****************************************************************************** 函数:I2C_Write() 功能:向I2C总线写1个字节的数据 参数:dat是要写到总线上的数据******************************************************************************/ void I2C_Write(unsigned char dat) { unsigned char t = 8; do { I2C_SDA = (bit)(dat & 0x80); dat I2C_SCL = 1; I2C_Delay(); I2C_SCL = 0; I2C_Delay(); } while ( --t != 0 ); }/****************************************************************************** 函数:I2C_Read() 功能:从从机读取1个字节的数据 返回:读取的1个字节数据******************************************************************************/ unsigned char I2C_Read() { unsigned char dat; unsigned char t = 8; I2C_SDA = 1; //在读取数据之前,要把SDA拉高,使之处于输入状态 do { I2C_SCL = 1; I2C_Delay(); dat if ( I2C_SDA ) dat++; I2C_SCL = 0; I2C_Delay(); } while ( --t != 0 ); return dat; }/****************************************************************************** 函数:I2C_GetAck() 功能:读取从机应答位(应答或非应答),用于判断:从机是否成功接收主机数据 返回:0-从机应答 1-从机非应答 说明:从机在收到每一个字节后都要产生应答位,主机如果收到非应答则应当终止传输******************************************************************************/ bit I2C_GetAck() { bit Ack; I2C_SDA = 1; I2C_Delay(); I2C_SCL = 1; I2C_Delay(); Ack = I2C_SDA; I2C_SCL = 0; I2C_Delay(); return Ack; }/****************************************************************************** 函数:I2C_PutAck() 功能:主机产生应答位(应答或非应答),用于通知从机:主机是否成功接收从机数据 参数:Ack = 0:主机应答 Ack = 1:主机非应答 说明:主机在收到每一个字节后都要产生应答,在收到最后一个字节时,应当产生非应答******************************************************************************/ void I2C_PutAck(bit Ack) { I2C_SDA = Ack; I2C_Delay(); I2C_SCL = 1; I2C_Delay(); I2C_SCL = 0; I2C_Delay(); }/****************************************************************************** 函数:I2C_Stop() 功能:产生I2C总线的停止条件 说明:SCL处于高电平期间,当SDA出现上升沿时停止I2C总线******************************************************************************/ ...
I2C怎么接线
问题补充:比如采样3个信号,I2C是可以一起输出表达这三个信号量,还是一次只能输出一个。
----这个事,你得问对方。
对方,喜欢一次收一个,你就一次发一个;对方,喜欢一次收两个,你就一次发两个;对方,喜欢一次收三个,你就一次发三个。
问别人那行?谁能知道你们之间的事?
我现在要做I2C的仿真,不用设计电路,做出功能仿真就行了,用什么...
展开全部 贴个程序给你看看,,,单片机没有I2C总线接口,只能靠软件模拟/*程序的I2C从器件地址为1010,片选地址为000*/#include #include #define uchar unsigned char#define uint unsigned intsbit SDA=P1^7;sbit SCL=P1^6;void Delay(uint us){ for(us;us>0;us--);}void start_iic() // 启动I2C总线{ SDA=1; // 发送起始条件数据信号,启动时, SCL=1; // 必需使数据线、时钟信号线处于高电平(空闲态) Delay(10); // 使用I2C总线必需考虑保持时间和建立时间,故延时 SDA=0; //产生下降沿,发送起始信号 Delay(10); SCL=0; }void stop_iic() { SDA=0; //为产生上跳沿做准备 SCL=1; //打开时钟线 Delay(10); SDA=1; //产生停止信号(上跳沿有效) Delay(10); SCL=0; //时钟线恢复无效态//}void ack_iic() { SDA=0; // 接受器件发送应答信号 SCL=1; Delay(10); SCL=0; SDA=1; //应答信号低电平有效,故需将其重新置高电平}void nack_iic() { SDA=1; //主器件发非应答信号,通知AT24C08不再发送数据 SCL=1; Delay(10); SCL=0; SDA=0; //非应答信号高电平有效,故需将其重新置低电平}Write_byte(uchar c) { uchar i; for(i=0;i<8;i++) { if(c&0x80)SDA=1; else SDA=0; SCL=1; Delay(10); SCL=0; //因为当时钟线有效是,数据线必须保持稳定的电平, c=c<<1; //要改变SDA电平,应先将SCL拉低 } SDA=1; //释放I2C总线,准备接受应答信号 SCL=1; Delay(10); if(SDA==1)F0=0; //没有接到应答位 else F0=1; SCL=0;}uchar Read_byte() { uchar i; uchar r=0; SDA=1; //置数据线为输入方式 for(i=0;i<8;i++) { r=r<<1; SCL=1; Delay(10); //保证一定的电平保持时间 if(SDA==1)r++; //从高位开始,一位一位的读 SCL=0; } return r;}main(){ uchar slave=0xa0; //I2C总线从器件地址(注意:硬件电路的接法要是片选地址为0,否则不能工作) uchar Rslave=slave+1; //主器件发送读控制字字节 uchar addre=0x20; // 指定的写数据地址 uchar wbuf=0x23; //将要写进addre的数据 uchar rbuf; //存放读出的数据的临时变量 start_iic(); //产生起始信号 Write_byte(slave); //发送从器件地址 if(F0==0)return 0; //检查应答位 Write_byte(addre); //发送目的地址 if(F0==0)return 0; Write_byte(wbuf); //发送8为数据 if(F0==0)return 0; stop_iic(); //停止信号 /*8位的数据发送完毕*/ Delay(1000); start_iic(); Write_byte(slave); if(F0==0)return 0; Write_byte(addre); if(F0==0)return 0; start_iic(); //再次产生起始信号,不能少 Write_byte(Rslave); //送读控制字 if(F0==0)return 0; rbuf=Read_byte(); //读出指定单元的内容 nack_iic(); //非应答信号 stop_iic(); /*8位的数据读取完毕*/ TMOD=0x20; //串口调试 TL1=0xfd; TH1=0xfd; SCON=0x40; PCON=0x00; TR1=1; while(1) { SBUF=rbuf; //放入缓冲 while(TI==0); TI=0; Delay(10000); }}
ZLG7290的软件库及调用说明
(1)I2C头文件库⑴ void I2C_Delay(); I2C延时程序⑵ void I2C_Init(); I2C 总线初始化,使总线处于空闲状态⑶ void I2C_Start(); 产生I2C 总线的起始状态⑷ void I2C_Write(char dat); 向I2C 总线写1 个字节的数据⑸ char I2C_Read(); 从从机读取1 个字节的数据⑹ bit I2C_GetAck(); 读取从机应答位⑺ void I2C_PutAck(bit ack); 主机产生应答位或非应答位⑻ void I2C_Stop(); 产生I2C 总线的停止状态⑼ void idle(); 将I2C总线置于空闲状态,即将时钟线和数据线都拉高⑽ bit I2C_Puts(unsigned char SlaveAddr,unsigned int SubAddr,unsigned char SubMod,char *dat,unsigned int Size); I2C 总线综合发送函数,向从机发送多个字节的数据⑾ bit I2C_Gets(unsigned char SlaveAddr,unsigned int SubAddr,unsigned char SubMod,char *dat,unsigned int Size);I2C 总线综合接收函数,从从机接收多个字节的数据⑿ char gets2(unsigned char subaddr);(2)ZLG7290函数库首先要包含另一个库ZLG7290B.h,里面定义了ZLG7290的各个寄存器地址和它本身的地址。
而zlg7290.h包含的函数如下:⑴ bit ZLG7290_WriteReg(unsigned char RegAddr, char dat) 向ZLG7290 的某个内部寄存器写入数据⑵ unsigned char ZLG7290_ReadReg(unsigned char regaddr) 从ZLG7290 的某个内部寄存器读出数据⑶ bit ZLG7290_cmd(char cmd0, char cmd1) 向ZLG7290 发送控制命令⑷ bit ZLG7290_SegOnOff(char seg, bit b) 段寻址,单独点亮或熄灭数码管(或LED)中的某一段⑸ bit ZLG7290_Download(char addr, bit dp, bit flash, char dat) 下载数据并译码说明:⑴,⑵,⑶,⑷,⑸中的函数都有返回值,0表示正常返回,1表示访问ZLG7290 时出现异常。
(3)主函数ZLG7290B.c;void INT0_SVC() interrupt 0 中断服务函数void Delay1(unsigned int t) 延时函数void SystemInit() 系统初始化函数,用于初始化定时器和让ZLG7290复位void ClearAll() 清除所有数码管显示函数void Test_DispBuf() 测试直接写显存函数,void Test_Download() 测试下载数据函数void Test_ScanNum() 测试扫描不同数码管函数void Test_Flash() 测试闪烁功能函数void Test_SegOnOff() 测试段寻址函数,用于将数码管分段点亮void DispValue(char x, unsigned char dat) 以十进制显示数据函数void DispHexValue(char x, unsigned char dat) 以十六进制显示数据函数void Test_Key() 测试按键函数,自动读出键值并且在数码管上显示
gpio中断 是硬件还是软件
最近做一个项目,涉及到芯片级的通信方面的知识(IIC和SPI方面的通信)。
但是方案选择的时候,发现自身对模拟IO口通信还是固件驱动通信一直没有一个很全面的认识,所以就在此记录一下。
所谓硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。
硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
模拟I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。
如果要从具体硬件上来看,可以去看下芯片手册。
因为固件I2C的端口是固定的,所以会有所区别。
至于如何区分它们可以看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC,否则就是模拟可以看IIC写函数,看里面有木有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。
根据代码量判断,模拟的代码量肯定比固件的要大。
为什么要在i2c总线电路设计中使用总线缓冲器
你说的加总线缓冲器,是个别的,并不是一定要加的。
通常是不加的。
你是从哪里听说的要加的?一个不确定的答案,是没有为什么的。
假如,在总线上挂有许多个从器件,为了提高总线的驱动能力,才需要加缓冲器的。
可是一般情况下,总线也不可能挂许多的器件的。