|
ассемблерный файл
;****************************************************************************; Software Implemented I2C Drivers
; These routines allow an 80C51 based microcontroller to drive the I2C bus
; as a single master. The main program at the end demonstrates writing and
; reading several types of devices:; at24c64
; Written by M.Diatel, JSC "ALAY"
;****************************************************************************
name AsmFunc
public SendData
public RcvData
public SendData_w_Adr
public RcvData_w_Adr
I2C SEGMENT CODE
RSEG I2C
;****************************************************************************
; Definitions
;****************************************************************************
; Addresses of several I2C devices as connected on the Signetics I2C
; Evaluation Board.
extern data (pData);
extern data (AdrDat);Adress bytes for I2C.
extern data (SlvAdr);Slave address for I2C routines.
extern data (ByteCnt);Byte counter for I2C routines.
extern data (BitCnt);Bit counter for I2C routines.; Data storage locations
extern bit (NoAck);
extern bit (BusFault);
extern bit (I2CBusy);
extern bit (delay);
; I2C connections.SCLPin BIT P1.5 ;I2C serial clock line.
SDAPin BIT P1.4 ;I2C serial data line.
; BitDly - insures minimum high and low clock times on I2C bus.
; This routine must be tuned for the actual oscilator frequency used, shown
; here tuned for a 12MHz clock. Note that the CALL instruction that invokes
; BitDly already uses 2 machine cycles.BitDly:
NOP
NOP
NOP ;NOPs to delay 5 microseconds (minus 4
; machine cycles for CALL and RET).
RET
; SCLHigh - sends SCL pin high and waits for any clock stretching peripherals.SCLHigh: SETB SCLPin ;Set SCL from our end.
JNB SCLPin,$ ;Wait for pin to actually go high.
RET
; SendStop - sends an I2C stop, releasing the bus.SendStop: CLR SDAPin ;Get SDA ready for stop.
ACALL SCLHigh ;Set clock for stop.
ACALL BitDly
SETB SDAPin ;Send I2C stop.
ACALL BitDly
CLR I2CBusy ;Clear I2C busy status.
RET ;Bus should now be released.
; SendByte - sends one byte of data to an I2C slave device.
; Enter with:
; ACC = data byte to be sent.SendByte: MOV BitCnt,#8 ;Set bit count.
SBLoop: RLC A ;Send one data bit.
MOV SDAPin,C ;Put data bit on pin.
ACALL SCLHigh ;Send clock.
ACALL BitDly
CLR SCLPin
ACALL BitDly
DJNZ BitCnt,SBloop ;Repeat until all bits sent.
SETB SDAPin ;Release data line for acknowledge.
ACALL SCLHigh ;Send clock for acknowledge.
ACALL BitDly
JNB SDAPin,SBEX ;Check for valid acknowledge bit.
SETB NoAck ;Set status for no acknowledge.
SBEX: CLR SCLPin ;Finish acknowledge bit.
ACALL BitDly
; вставим задержку...
setb EA ; enable all interrupt
nop;
nop;
nop;
clr EA
RET
; GoMaster - sends an I2C start and slave address.
; Enter with:
; SlvAdr = slave address.GoMaster: SETB I2CBusy ;Indicate that I2C frame is in progress.
CLR NoAck ;Clear error status flags.
CLR BusFault
JNB SCLPin,Fault ;Check for bus clear.
JNB SDAPin,Fault
CLR SDAPin ;Begin I2C start.
ACALL BitDly
CLR SCLPin
ACALL BitDly ;Complete I2C start.
MOV A,SlvAdr ;Get slave address.
ACALL SendByte ;Send slave address.
RETFault: SETB BusFault ;Set fault status
RET ; and exit.
; SendData - sends one or more bytes of data to an I2C slave device.
; Enter with:
; ByteCnt = count of bytes to be sent.
; SlvAdr = slave address.
; @pData = data to be sent (the first data byte will be the
; subaddress, if the I2C device expects one).SendData:
; push R0;
mov R0,pData
ACALL GoMaster ;Acquire bus and send slave address.
JB NoAck,SDEX ;Check for slave not responding.
; push acc ;втолкнуть асс в стек.
SDLoop: MOV acc,@R0 ;Get data byte from buffer.
ACALL SendByte ;Send next data byte.
INC R0 ;Advance buffer pointer.
JB NoAck,SDEX ;Check for slave not responding.
DJNZ ByteCnt,SDLoop ;All bytes sent?
; pop acc
SDEX: ACALL SendStop ;Done, send an I2C stop.
; pop R0;
RET; SendData - sends one or more bytes of data to an I2C slave device.
; Enter with:
; ByteCnt = count of bytes to be sent.
; SlvAdr = slave address.
; @pData = data to be sent (the first data byte will be the
; subaddress, if the I2C device expects one).
; AdrDat = Adress For New Message.SendData_w_Adr:
push acc ;втолкнуть асс в стек.
clr EA
SETB NoAck;
ACALL GoMaster ;Acquire bus and send slave address.
JB NoAck,SDEX1 ;Check for slave not responding.
mov R0, AdrDat
MOV acc,@R0 ;записать в аккумулятор адрес начальной ячейки для передачи.
ACALL SendByte ;передать адрес начальной ячейки и получить подтверждение.
JB NoAck,SDEX1 ;если подтверждения нет - закончить сеанс.
inc R0;
MOV acc,@R0 ;записать в аккумулятор адрес начальной ячейки для передачи.
ACALL SendByte ;передать адрес начальной ячейки и получить подтверждение.
JB NoAck,SDEX1 ;если подтверждения нет - закончить сеанс.
mov R0,pData
SDLoop1: MOV acc,@R0 ;Get data byte from buffer.
ACALL SendByte ;Send next data byte.
INC R0 ;Advance buffer pointer.
JB NoAck,SDEX1 ;Check for slave not responding.
DJNZ ByteCnt,SDLoop1 ;All bytes sent?
SDEX1:
pop acc;
ACALL SendStop ;Done, send an I2C stop.
setb EA
RET
;RcvByte - receives one byte of data from an I2C slave device.
; Returns:
; ACC = data byte received.RcvByte: MOV BitCnt,#8 ;Set bit count.
RBLoop: ACALL SCLHigh ;Read one data bit.
ACALL BitDly
MOV C,SDAPin ;Get data bit from pin.
RLC A ;Rotate bit into result byte.
CLR SCLPin
ACALL BitDly
DJNZ BitCnt,RBLoop ;Repeat until all bits received.push ACC ;Save accumulator
MOV A,ByteCnt
CJNE A,#1,RBAck ;Check for last byte of frame.
SETB SDAPin ;Send no acknowledge on last byte.
SJMP RBAClkRBAck: CLR SDAPin ;Send acknowledge bit.
RBAClk: ACALL SCLHigh ;Send acknowledge clock.
pop ACC ;Restore accumulator
ACALL BitDly
CLR SCLPin
; вставим задержку...
setb EA ; enable all interrupt
nop;
nop;
nop;
clr EA
SETB SDAPin ;Clear acknowledge bit.
ACALL BitDly
RET
;RcvData - receives sends one or more bytes of data from an I2C slave device.
; Enter with:
; ByteCnt = count of bytes to be sent.
; SlvAdr = slave address.
; Returns:
; @pData = data received.; Note: to receive with a subaddress, use SendData to set the subaddress
; first (no provision for repeated start).RcvData_w_Adr:
; push R0
push acc ;втолкнуть асс в стек.
clr EA
ACALL GoMaster ;Acquire bus and send slave address.
JB NoAck,RDEX1 ;Check for slave not responding.
mov R0, AdrDat
MOV acc,@R0 ;записать в аккумулятор адрес начальной ячейки для передачи.
ACALL SendByte ;передать адрес начальной ячейки и получить подтверждение.
JB NoAck,RDEX1 ;если подтверждения нет - закончить сеанс.
inc R0;
MOV acc,@R0 ;записать в аккумулятор адрес начальной ячейки для передачи.
ACALL SendByte ;передать адрес начальной ячейки и получить подтверждение.
JB NoAck,RDEX1 ;если подтверждения нет - закончить сеанс.
SETB SDAPin;
ACALL SCLHigh;
INC SlvAdr ;Set for READ of slave.
ACALL GoMaster ;Acquire bus and send slave address.
JB NoAck,RDEX1 ;Check for slave not responding.mov R0,pData
RDLoop1:
ACALL RcvByte ;Recieve next data byte.
MOV @R0,acc ;Save data byte in buffer.
INC R0 ;Advance buffer pointer.
DJNZ ByteCnt,RDLoop1 ;Repeat untill all bytes received.
RDEX1: ACALL SendStop ;Done, send an I2C stop.
pop acc;
setb EA;
RET
;RcvData - receives sends one or more bytes of data from an I2C slave device.
; Enter with:
; ByteCnt = count of bytes to be sent.
; SlvAdr = slave address.
; Returns:
; @R0 = data received.; Note: to receive with a subaddress, use SendData to set the subaddress
; first (no provision for repeated start).RcvData: INC SlvAdr ;Set for READ of slave.
ACALL GoMaster ;Acquire bus and send slave address.
JB NoAck,RDEX ;Check for slave not responding.RDLoop: ACALL RcvByte ;Recieve next data byte.
MOV @R0,A ;Save data byte in buffer.
INC R0 ;Advance buffer pointer.
DJNZ ByteCnt,RDLoop ;Repeat untill all bytes received.RDEX: ACALL SendStop ;Done, send an I2C stop.
RET
end
#define EEPROM 0xA0void Ressive_Data(unsigned char Number,unsigned char Position,int Adress);
void Transmite_Data(unsigned char Number,unsigned char Position,int Adress);
extern void SendData_w_Adr (void);
extern void RcvData_w_Adr (void);extern data unsigned char* data pData;
extern data unsigned char* pLoading_Byte;
// code unsigned char * data Message;
extern data int* AdrDat;
extern data unsigned char SlvAdr;
extern data unsigned char ByteCnt;
extern data unsigned char BitCnt;
extern data unsigned char XmtDat[32];
extern data unsigned char RcvDat[32];
void Ressive_Data(unsigned char Number,unsigned char Position,int Adress)
{
//пример периёма по I2C
SlvAdr=EEPROM;
ByteCnt=Number;// СКОЛЬКО
pData=(&RcvDat[0]+Position);// Куда это записывать в памяти.
AdrDat=&Adress;// Откуда начинать в EEPROM.
RcvData_w_Adr();
}
void Transmite_Data(unsigned char Number,unsigned char Position,int Adress)
{
//пример передачи по I2C
SlvAdr=EEPROM;
ByteCnt=Number;
pData=(&XmtDat[0]+Position);
AdrDat=&Adress;
SendData_w_Adr();
return;
}
#define EEPROM 0xA0void Ressive_Data(unsigned char Number,unsigned char Position,int Adress);
void Transmite_Data(unsigned char Number,unsigned char Position,int Adress);
extern void SendData_w_Adr (void);
extern void RcvData_w_Adr (void);extern data unsigned char* data pData;
extern data unsigned char* pLoading_Byte;
// code unsigned char * data Message;
extern data int* AdrDat;
extern data unsigned char SlvAdr;
extern data unsigned char ByteCnt;
extern data unsigned char BitCnt;
extern data unsigned char XmtDat[32];
extern data unsigned char RcvDat[32];
void Ressive_Data(unsigned char Number,unsigned char Position,int Adress)
{
//пример периёма по I2C
SlvAdr=EEPROM;
ByteCnt=Number;// СКОЛЬКО
pData=(&RcvDat[0]+Position);// Куда это записывать в памяти.
AdrDat=&Adress;// Откуда начинать в EEPROM.
RcvData_w_Adr();
}
void Transmite_Data(unsigned char Number,unsigned char Position,int Adress)
{
//пример передачи по I2C
SlvAdr=EEPROM;
ByteCnt=Number;
pData=(&XmtDat[0]+Position);
AdrDat=&Adress;
SendData_w_Adr();
return;
}
E-mail: info@telesys.ru