I2C模拟程序
- 格式:doc
- 大小:103.00 KB
- 文档页数:19
谁有单片机io口模拟i2c读写AT24C256的程序?悬赏分:100 - 解决时间:2009-11-8 12:49问题补充:我自己写了一个,是修改别人的,但就是不管写什么,读出来一个字节都是255,郁闷啊!有调好的程序发给我,谢了。
我的晶振是24M的。
单片机是c8051f0202。
cuikaimin@提问者:崔凯敏000 - 三级最佳答案你这个单片机是带I2C接口的那个SMBus就是,我用这个系列的单片机写过,模拟的还没有借口直接来的好。
我的空间里面有我调好的一篇247519442你说的全部是0xff也是正常的,因为外部存储一般都是高电平为空,也就是说你的数据没有写进去我给你一个模拟的看看#include<reg51.h>#include <Intrins.h>#define uchar unsigned char#define uint unsigned intsbit pcf8563_scl=P0^5;//时钟频率sbit pcf8563_sda=P0^4;//串行数据传输脚bit busy=0;uchar sg;//时高位uchar sd;//时低位uchar fg;//分高位uchar fd;//分低位uchar mg;//秒高位uchar md;//秒低位uchar hou=0;uchar min=0;uchar sec=0;uchar subadd;//地址uchar dat;//数据uchar number;void start_pcf8563();//开始数据void send_pcf8563_byte();//发送void stop_pcf8563();//结束数据void receive_pcf8563_byte();//接收void spit_time();//分别计算时、分、秒的各位数字void spit_time()//分别计算时、分、秒的各位数字{sg=(int)hou/10;sd=(int)hou%10;fg=(int)min/10;fd=(int)min%10;mg=(int)sec/10;md=(int)sec%10;}void Send_pcf8563_byte(uchar bb) //向PCF8563发送一个字节{uchar aa;pcf8563_scl=0;for(aa=0;aa<8;aa++){if((bb&0x80)==0x80){pcf8563_sda=1;}else{pcf8563_sda=0;}pcf8563_scl=1;pcf8563_scl=0;bb=bb<<1;}_nop_();_nop_();pcf8563_sda=1;pcf8563_scl=1;busy=0;if(pcf8563_sda){busy=1;}else{_nop_();_nop_();pcf8563_scl=0;busy=0;}}void write_pcf8563(uchar subadd,uchar dat)// 向PCF8563对应地址写数据{start_pcf8563();Send_pcf8563_byte(0xa2);if(!busy){Send_pcf8563_byte(subadd);if(!busy){Send_pcf8563_byte(dat);}}stop_pcf8563();}void read_pcf8563() //读当时的时,分,钞{start_pcf8563();Send_pcf8563_byte(0xa2);if(!busy){Send_pcf8563_byte(0x02);if(!busy){start_pcf8563();Send_pcf8563_byte(0xa3);receive_pcf8563_byte();sec=number&0x7f;start_pcf8563();Send_pcf8563_byte(0xa3);receive_pcf8563_byte();min=number&0x7f;start_pcf8563();Send_pcf8563_byte(0xa3);receive_pcf8563_byte();hou=number&0x3f;}}stop_pcf8563();}void receive_pcf8563_byte() //从PCF8563接受一个字节{uchar cc;pcf8563_sda=1;number=0;for(cc=0;cc<8;cc++){number<<=1;pcf8563_scl=0;pcf8563_scl=1;_nop_();_nop_();number= number|pcf8563_sda;}pcf8563_scl=0;_nop_();_nop_();}void start_pcf8563() //开启PCF8563IIC{pcf8563_sda=1;pcf8563_scl=1;pcf8563_sda=0;//SCL为高,SDA执行一个下跳pcf8563_scl=0;//SCL为低,嵌住数据线}void stop_pcf8563() //关闭PCF8563IIC{pcf8563_sda=0;pcf8563_scl=1;pcf8563_sda=1;//SCL为高,SDA执行一个上跳pcf8563_scl=0;//SCL为低,嵌住数据线}void main(void){write_pcf8563(0x02,sec); //写钞write_pcf8563(0x03,min); //写分write_pcf8563(0x04,hou); //写时while(1){read_pcf8563();//读当前时间spit_time(); //切换时间,为显示做准备} }。
软件模拟I2C总线的C51实现摘要:介绍51系列单片机上的I2C总线主节点模拟程序,从而实现与具有I2C接口的器件通信。
1I2C总线简介1.1硬件结构I2C串行总线支持所有NMOS、CMOS、I2L工艺制造的器件。
从物理上看由两根双向I/O线组成,一根为数据线(SDA),一根为时钟线(SCL),通过这两根线把所有器件连接到总线上,并通过SDA和SCL在各器件间传递信息(根据地址识别每个器件)。
SDA和SCL通过上拉电阻接正电源,总线空闲时,两根线都是高电平。
这两根I/O线在电气上允许“线与”操作,其输出的驱动形式为集电极开路或漏极开路。
根据通信速度的不同,I2C总线分为三种工作模式:标准模式、快速模式和高速模式。
它们分别对应不同的波特率:100kb/s、400kb/s和3.4Gb/s。
总线上允许的设备数以总线上的电容量不超过400pF为限。
1.2数据传输I2C总线上数据为同步传输。
挂在I2C总线上的每一个器件都有一个独立的地址,而且在传输过程中有主节点和从节点的区分,主节点的作用是启动和结束一次通信,并负责控制总线时钟,总线上可以有多个主节点或多个从节点,但是在一次通信中只能有一个节点作为主节点。
主从机之间一次数据的传输称为一帧,由启动信号、地址信息、应答位及停止位组成。
其传送格式见图1。
2MCS-51与I2C总线芯片接口及程序2.18051经I2C总线扩展存储器PCF8582对于内部没有硬件I2C总线接口的51系列单片机,可以采用软件模拟的方法实现I2C总线接口功能。
硬件连接如图2所示。
用8051的P1.6和P1.7作为I2C总线的SCL利SDA信号,在总线上连接256*8的EEPROM芯片PCF8582。
8051单片机与PCF8582进行数据传递时,首先传送器件的从机地址SLA,格式如下:START为起始信号,从机地址的固定部分是4位——1010,可编程部分由,则该片的从机地址为引脚A2、A1、A0确定。
I2C硬件与模拟的区别
硬件I2C对应芯⽚上的I2C外设,有相应I2C驱动电路,其所使⽤的I2C管脚也是专⽤的,因⽽效率要远⾼于软件模拟的I2C;⼀般也较为稳定,但是程序较为繁琐。
硬件(固件)I2C是直接调⽤内部寄存器进⾏配置;⽽软件I2C是没有寄存器这个概念的。
软件I2C⼀般是使⽤GPIO管脚,⽤软件控制SCL,SDA线输出⾼低电平,模拟i2c协议的时序。
主要对⽐:
1.硬件IIC⽤法⽐较复杂,模拟IIC的流程更清楚⼀些。
2.硬件IIC速度⽐模拟快,并且可以⽤DMA
3.模拟IIC可以在任何管脚上,⽽硬件只能在固定管脚上。
有些单⽚机的硬件i2c不太稳定,调试问题较多。
例如⽹上很多⼈吐槽的STM32…。
//I2C从模式(适用用于PIC16F1705/1708/1709)//函数初始化与主体函数,经过反复检验,程序OK,程序贴出来帮助和我同样曾经迷惑的人们. //如有疑问可以联系我,QQ:370886719 ………给更多的人照亮道路void i2c_slave_init(void){ANSA4=0;ANSA2=0;WPUAbits.WPUA2 = 0;WPUAbits.WPUA4 = 0;RA4PPS=0X10; //CLKRA2PPS=0X11; //SDASSP1CON1bits.SSPM0 = 0;SSP1CON1bits.SSPM1 = 1;SSP1CON1bits.SSPM2 = 1;SSP1CON1bits.SSPM3 = 0; // I2C slave mode ,7bit addressSSP1CON1bits.CKP = 1; // enable clocSSP1STAT =0;SSP1MSK=0XFE; //允许数据地址匹配SSPCON2bits.SEN=1;SSPCON3bits.SDAHT=1;SSPCON3bits.SBCDE = 1; // Enable slave bus collision detect interrupts//SSPCON3bits.AHEN=1; ////////////////////////////////SSPCON3bits.DHEN=1; /////////////////////////////SSPCON3bits.BOEN=1;PIR1bits.SSP1IF = 0; // Clear the serial port interrupt flagPIR2bits.BCL1IF = 0; // Clear the bus collision interrupt flagPIE2bits.BCL1IE = 1; // Enable bus collision interruptsPIE1bits.SSP1IE = 1;//Enabe interrupt MSSPINTCONbits.PEIE = 1;INTCONbits.GIE = 1;}#include"proc.h"//#include <stdio.h>//#include <stdlib.h>//#define RX_BUF_LEN 16#define while_delay 10000u8i2c_address,word_address,array_receive_x[32]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,1 9,20,21,22,23,24,25,26,27,28,29,30,31};u8array_receive_y[32]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, 28,29,30,31};u8 Register_flow[5]={10,1,2,3,4};u8 Register_temp[9]={36,1,2,3,4,5,6,7,8};u8 Register[17];u8 i2c_counter,RX_BUF_LEN,TX_BUF_LEN;bit read_temp_F,receive_data_end_F;/***********************************************************************/void i2c_slave_tx(void){u16 timercounter;PIR2bits.BCL1IF = 0; // Clear the bus collision interrupt flag//asm("nop");asm("nop");asm("nop");asm("nop");if(SSP1STATbits.R_nW ==0)//Read operation.{PIR1bits.SSP1IF = 0;i2c_address = SSP1BUF;//i2c_counter = word_address; //得到要发送的数据地址i2c_counter = 0;if(read_temp_F==0){TX_BUF_LEN=5; //发送5个温度相关数据给上位机while(i2c_counter < TX_BUF_LEN){SSP1BUF=Register_flow[i2c_counter]; //send datatimercounter=while_delay;while( PIR1bits.SSP1IF == 0){timercounter--;if(timercounter==0){return;}}//waiting for ~`ACKPIR1bits.SSP1IF = 0;asm("nop");asm("nop");asm("nop");asm("nop");if(SSP1CON2bits.ACKSTAT == 1) //主机没有应答{return ; //NOACK}else{i2c_counter++;//ACK}}SSP1IF = 0;}else //协议切换,发送流量传感器数据给上位机{TX_BUF_LEN=9; //发送5个温度相关数据给上位机while(i2c_counter < TX_BUF_LEN){while( PIR1bits.SSP1IF == 0){timercounter--;if(timercounter==0){return;}}//waiting for ~`ACKPIR1bits.SSP1IF = 0;asm("nop");asm("nop");asm("nop");asm("nop");if(SSP1CON2bits.ACKSTAT == 1) //主机没有应答{return ; //NOACK}else{i2c_counter++;//ACK}}SSP1IF = 0;read_temp_F=0;}}}/*****************************************************************/void i2c_salve_rx(void) //master writer{if(SSP1STATbits.R_nW ==0){PIR1bits.SSP1IF = 0;i2c_address = SSP1BUF;// timercounter=while_delay;/*while(PIR1bits.SSP1IF == 0){timercounter--;if(timercounter==0){timercounter=while_delay;return ;}} //waiting for send ~ACKPIR1bits.SSP1IF = 0;*///word_address = SSP1BUF;// i2c_address = SSP1BUF;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");word_address=0;return ;}if(SSP1STATbits.R_nW ==0 && SSP1STATbits.D_nA==1){/****************************************************************/if(Register[0]==0xd0) //读温度模式{read_temp_F=1;RX_BUF_LEN=0;SSP1CON1bits.CKP=1;return;}/****************************************************************/if(Register[0]==0xc0) //{RX_BUF_LEN=3;read_temp_F=0;}/***************************************************************/switch (Register[0]){case 0xe0: read_temp_F=0;RX_BUF_LEN=17;if(word_address>0 && word_address<=16){*(array_receive_x+word_address-1)=*(Register+word_address);}break;case 0xe1: read_temp_F=0;RX_BUF_LEN=17;if(word_address>0 && word_address<=16){*(array_receive_x+word_address+16-1)=*(Register+word_address);}break;case 0xe2: read_temp_F=0;RX_BUF_LEN=17;if(word_address>0 && word_address<=16){*(array_receive_y+word_address-1)=*(Register+word_address);}break;case 0xe3: read_temp_F=0;RX_BUF_LEN=17;if(word_address>0 && word_address<=16){*(array_receive_y+word_address+16-1)=*(Register+word_address);}break;}word_address++;/**************************************************************/if(word_address>=RX_BUF_LEN){word_address=0;if(Register[0]==0xe3){receive_data_end_F=1; //所有完整的数据都已经收到}}asm("nop");asm("nop");asm("nop");asm("nop");return;}}。
SCL BIT P1.0SDA BIT P1.1;----------------------------ORG 0RESET:SETB SCLSETB SDACALL I2C_WAITSTART ;等待起始信号CALL I2C_RXBYTE ;接收地址数据CLR CCALL I2C_TXACK ;回应ACKSETB C ;读/写 IDATA[80H - FFH] RRC A ;读/写位->CMOV R0,A ;地址送入R0JC READDATA ;C=1(读) C=0(写) WRITEDATA:CALL I2C_RXBYTE ;接收数据MOV @R0,A ;写入IDATAINC R0 ;地址+1CLR CCALL I2C_TXACK ;回应ACKCALL I2C_WAITSTOP ;等待停止信号JMP RESETREADDATA:MOV A,@R0INC R0CALL I2C_TXBYTE ;发送IDATA数据CALL I2C_RXACK ;接收ACKCALL I2C_WAITSTOP ;等待停止信号JMP RESET;----------------------------;等待起始信号;----------------------------I2C_WAITSTART:JNB SCL,$ ;等待时钟->高JB SDA,$ ;等待数据线下降沿JB SCL,$ ;等待时钟->低RET;----------------------------;等待结束信号;----------------------------I2C_WAITSTOP:JNB SCL,$ ;等待时钟->高JNB SDA,$ ;等待数据线上升沿RET;----------------------------;发送ACK/NAK信号;----------------------------第 1 页I2C_TXACK:MOV SDA,C ;送ACK数据JNB SCL,$ ;等待时钟->高JB SCL,$ ;等待时钟->低SETB SDA ;发送完成RET;----------------------------;接收ACK/NAK信号;----------------------------I2C_RXACK:SETB SDA ;准备读数据JNB SCL,$ ;等待时钟->高MOV C,SDA ;读取ACK信号JB SCL,$ ;等待时钟->低RET;----------------------------;接收一字节数据;----------------------------I2C_RXBYTE:MOV R7,#8 ;8位计数RXNEXT:JNB SCL,$ ;等待时钟->高MOV C,SDA ;读取数据口RLC A ;保存数据JB SCL,$ ;等待时钟->低DJNZ R7,RXNEXT ;收下一位RET;----------------------------;发送一字节数据;----------------------------I2C_TXBYTE:MOV R7,#8 ;8位计数TXNEXT:RLC A ;移出数据位MOV SDA,C ;数据送数据口JNB SCL,$ ;等待时钟->高JB SCL,$ ;等待时钟->低DJNZ R7,TXNEXT ;送下一位RET;----------------------------END第 2 页。
2.1 虚拟I2C总线汇编程序软件包2.1.1 概述为了非常方便地对I2C从器件进行快速的、正确的读写操作,我们为此而设计出虚拟I2C总线操作平台软件包。
本软件包是主方式下的虚拟I2C总线软件包,只要用户给子程序提供几个主要的参数,即可轻松地完成任何I2C总线外围器件的应用程序设计。
2.1.2I2C串行总线I2C总线是PHILIPS公司推出的芯片间串行数据传输总线,2根线(SDA、SCL)即可实现完善的全双工同步数据传送,能够十分方便地地构成多机系统和外围器件扩展系统。
I2C器件是把I2C的协议植入器件的I/O接口,使用时器件直接挂到I2C总线上,这一特点给用户在设计应用系统带来了极大的便利。
I2C器件无须片选信号,是否选中是由主器件发出的I2C从地址决定的,而I2C器件的从地址是由I2C总线委员会实行统一发配。
我们推出的I2C总线的操作平台软件包,只要你给出器件从地址[,子地址(注:PCF8574无子地址)],即可进行字节读,字节写,多字节读,多字节写,能够非常方便地使用I2C器件,无须你介入底层的I2C操作协议。
2.1.3汇编软件包说明此软件包是用在单主I2C总线上,硬件接口是SDA,SCL,使用MCU的I/O口来模拟SDA/SCL总线。
设计有/无子地址的子程序是根据I2C器件的特点,目的在于将地址和数据彻底分开。
软件包的接口界面为:IRDBYTE (无子地址)读单字节数据(现行地址读)IWRBYTE (无子地址)写单字节数据(现行地址写)IRDNBYTE (有子地址)读N字节数据IWRNBYTE (有子地址)写N字节数据说明:现行地址读/写即专指无子地址的器件,不给定子地址的读/写操作。
;平台占用内部资源:R0,R1,R2,R3,ACC,Cy。
;使用前须定义变量:SLA 器件从地址,SUBA器件子地址,NUMBYTE读/写的字节数,位变量ACK ;使用前须定义常量:SDA 、SCL 总线位,MTD 发送数据缓冲区首址,MRD 接收数据缓冲区首址;(※子程序出口参数ACK为0时表示从器件无应答)2.1.4软件包清单;--------------------------------------------------------------------------------------------------------;VI2C_ASM.ASM;I2C 软件包的底层子程序,使用前要定义好SCL和SDA。
在标准80C51模式;(12 Clock)下,对主频要求是不高于12MHz(1个机器周期1us);若Fosc>12MHz;则要增加相应的NOP指令数。
在使用本软件包时,请在你的程序的未尾加入;$INCLUDE (VI2C_ASM.ASM)即可。
;--------------------------------------------------------------------------------------------------------;启动I2C总线子程序START: SETB SDASETB SCL ;起始条件建立时间大于4.7usNOPNOPNOPNOPNOPCLR SDANOP ;起始条件锁定时大于4usNOPNOPNOPNOPCLR SCL ;钳住总线,准备发数据NOPRET;结束总线子程序STOP: CLR SDANOPSETB SCL ;发送结束条件的时钟信号NOP ;结束总线时间大于4usNOPNOPNOPNOPSETB SDA ;结束总线NOP ;保证一个终止信号和起始信号的空闲时间大于4.7usNOPNOPNOPRET;发送应答信号子程序MACK: CLR SDA ;将SDA置0NOPNOPSETB SCLNOP ;保持数据时间,即SCL为高时间大于4.7usNOPNOPNOPNOPCLR SCLNOPRET;发送非应答信号MNACK: SETB SDA ;将SDA置1NOPNOPSETB SCLNOPNOP ;保持数据时间,即SCL为高时间大于4.7usNOPNOPNOPCLR SCLNOPNOPRET; 检查应答位子程序; 返回值,ACK=1时表示有应答CACK: SETB SDANOPNOPSETB SCLCLR ACKNOPNOPMOV C,SDAJC CENDSETB ACK ;判断应答位CEND: NOPCLR SCLNOPRET;发送字节子程序;字节数据放入ACC;每发送一字节要调用一次CACK子程序,取应答位WRBYTE: MOV R0,#08HWLP: RLC A ;取数据位JC WR1SJMP WR0 ;判断数据位WLP1: DJNZ R0,WLPRETWR1: SETB SDA ;发送1NOPSETB SCLNOPNOPNOPNOPNOPCLR SCLSJMP WLP1WR0: CLR SDA ;发送0NOPSETB SCLNOPNOPNOPNOPNOPCLR SCLSJMP WLP1;读取字节子程序;读出的值在ACC;每取一字节要发送一个应答/非应答信号RDBYTE: MOV R0,#08HRLP: SETB SDANOPSETB SCL ;时钟线为高,接收数据位NOPNOPMOV C,SDA ;读取数据位MOV A,R2CLR SCL ;将SCL拉低,时间大于4.7usRLC A ;进行数据位的处理MOV R2,ANOPNOPNOPDJNZ R0,RLP ;未够8位,再来一次RET; 无子地址器件写字节数据; 入口参数: 数据为ACC、器件从地址SLA; 占用: A、R0、CYIWRBYTE: PUSH ACCIWBLOOP: LCALL START ;起动总线MOV A,SLALCALL WRBYTE ;发送器件从地址LCALL CACKJNB ACK,RETWRB ;无应答则跳转POP ACC ;写数据LCALL WRBYTELCALL CACKLCALL STOPRETRETWRB: POP ACCLCALL STOPRET;无子地址器件读字节数据;入口参数: 器件从地址SLA;出口参数: 数据为ACC;占用A 、R0、R2 、CYIRDBYTE: LCALL STARTMOV A,SLA ;发送器件从地址INC ALCALL WRBYTELCALL CACKJNB ACK,RETRDBLCALL RDBYTE ;进行读字节操作LCALL MNACK ;发送非应信号RETRDB: LCALL STOP ;结束总线RET;向器件指定子地址写N个数据;入口参数: 器件从地址SLA、器件子地址SUBA 、发送数据缓冲区MTD、发送字节数NUMBYTE ; 占用: A 、R0 、R1 、R3 、CYIWRNBYTE: MOV A,NUMBYTEMOV R3,ALCALL START ;起动总线MOV A,SLALCALL WRBYTE ;发送器件从地址LCALL CACKJNB ACK,RETWRN ;无应答则退出MOV A,SUBA ;指定子地址LCALL WRBYTELCALL CACKMOV R1,#MTDWRDA: MOV A,@R1LCALL WRBYTE ;开始写入数据LCALL CACKJNB ACK,IWRNBYTEINC R1DJNZ R3,WRDA ;判断写完没有RETWRN: LCALL STOPRET;向器件指定子地址读取N个数据;入口参数: 器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE ;出口参数: 接收数据缓冲区MTD;占用:A、R0、R1、R2、R3、CYIRDNBYTE: MOV R3,NUMBYTELCALL STARTMOV A,SLALCALL WRBYTE ;发送器件从地址LCALL CACKJNB ACK,RETRDNMOV A,SUBA ;指定子地址LCALL WRBYTELCALL CACKLCALL START ;重新起动总线MOV A,SLAINC A ;准备进行读操作LCALL WRBYTELCALL CACKJNB ACK,IRDNBYTEMOV R1,#MRDRDN1: LCALL RDBYTE ;读操作开始MOV @R1,ADJNZ R3,SACKLCALL MNACK ;最后一字节发非应答位RETRDN: LCALL STOP ;并结束总线RETSACK: LCALL MACKINC R1SJMP RDN12.1.5应用举例;平台定义变量ACK BIT 10H ;应答标志位SLA DA TA 50H ;器件从地址SUBA DA TA 51H ;器件子地址NUMBYTE DA TA 52H ;读/写的字节数;使用前定义常量SDA EQU P1.3 ; I2C总线定义SCL EQU P1.2MTD EQU 30H ;发送数据缓冲区首址(缓冲区30H-3FH)MRD EQU 40H ;接收数据缓冲区首址(缓冲区40-4FH);定义器件地址PCF8574 EQU 40HSAA1064 EQU 70HCSI24WCXX EQU 0A0HORG 0000HAJMP MAINORG 0080HMAIN: MOV R4,#0F0H ;延时,等待其它芯片复位好DJNZ R4,$MOV SP,#60HMOV SLA,#PCF8574 ;读取命令字(读PCF8574的I/O值,单字节读,读出值在ACC)LCALL IRDBYTECJNE A,#0FFH,NEXT ;命令判断ACALL RD24WCXX ;为0FFH,读24WCXXNEXT: CJNE A,#00H,NEXT1ACALL WR24WCXX ;为00H,写24WCXXNEXT1: ACALL TESTIO ;其它则进行I/O测试;读24WCXX;对24WCXX指定单元进行读,并显求出来(本例选用24WC02,因为子地址;是00--FFH)。
;地址由PCF8574的I/O值给出, LED1 LED2 显示地址;LED3 LED4 显示读出的数据,;把显求数据区设为53H 54H。
RD24WCXX:MOV SLA,#PCF8574LCALL IRDBYTEMOV 53H,A ;读取PCF8574的I/O值,放入显示数据区MOV SUBA,A ;对指定存储单元进行读取MOV SLA,#CSI24WCXXMOV NUMBYTE,#01HLCALL IRDNBYTEMOV R1,#MRD ;取得的数据放入显示数据区MOV 54H,@R1ACALL DISP_DA T ;显示操作数据MOV R6,#0FFH ;短延时DJNZ R6,$SJMP RD24WCXX;对显示数据的数据进行显示;显求数据区为53H 54H;53H的高4位在LED1显示; 低4位在LED2显示;53H的高4位在LED3显示, 低4位在LED4显示DISP_DA T:MOV R1,#MTDMOV DPTR,#TAB_IOMOV A,53H ;把显示数据区的数据拆分ANL A,#0F0H ;分别放到发送缓冲区SWAP AMOVC A,@A+DPTR ;将数据转换MOV @R1,A ;LED1数据MOV A,53HANL A,#0FHMOVC A,@A+DPTRINC R1MOV @R1,A ;LED2数据INC R1MOV A,54HANL A,#0F0HSWAP AMOVC A,@A+DPTR ;LED3数据MOV @R1,AMOV A,54HANL A,#0FHMOVC A,@A+DPTRINC R1MOV @R1,A ;LED4数据;将处理好的数据发送给SAA1064显示MOV NUMBYTE,#04H ;写字节数MOV SLA,#SAA1064 ;器件从地址MOV SUBA,#01H ;器件子地址LCALL IWRNBYTERET…$INCLUDE (VI2C_ASM.ASM) ;包含VIIC软件包;END2.1.6特殊应用情况对比较特殊的器件操作,如24WC256,它的子地址是16位的,而软件包只提供8位器件子地址,这种情况该如何对它进行操作?现行地址读/写:直接调用IRDBYTE 和IWRBYTE1. 指定地址读(1)先写入16位地址……MOV MTD,#suba1;把子地址低8位放在MTD的开头MOV SUBA,#subah ;对指定存储单元进行写MOV SLA,#CSI24WC256MOV NUMBYTE,#01HLCALL IWRNBYTE;指定子16位地址(2) 读入字节数据LCALL IRDBYTE;读取一个字节若要连续读N个字节,只能用循环“单字节读出”,它会顺序读(不能用IRDNBYTE)。