Página 1 de 1

Problemas em gravação e leitura de memoria 24C04

MensagemEnviado: 03 Ago 2019 10:37
por Brynden
Gente gostaria de uma ajuda se possível for. Estou tentando efetuar a gravação e leitura em uma memoria I2C (24C04), e estou batendo muito a cabeça, ja tentei de diversas formas, sem exito, por fim tentei fazer um código o mais detalhado possível, simplesmente sequencial (sem pulos, ou com a menor quantidade de pulos possíveis) para que eu pudesse acompanhar, e não obtive exito. Gostaria por favor que alguém me desse uma luz. Estou usando um cristal de 24,576MHz (característica que eu não posso alterar) e um uC compatível com as instruções da família 8051. Faço uma observação que esse código não é minha aplicação final e sim apenas um teste.

I2C_SDA EQU P1.6
I2C_SCL EQU P1.7

ORG 0000h
;--------------------------------------------------------------------------------------------------------------------------------------------
INICO:
MOV 2Fh, #10100000b ;ENDEREÇO DO CI
MOV 2Eh, #00000000b ;ENDEREÇO DE MEMORIA A SER GRAVADA
MOV 2Dh, #10101010b ;DADO
ACALL I2C_ESCRITA
ACALL I2C_LEITURA

LOOPING:

MOV P2, A
SJMP LOOPING



;--------------------------------------------------------------------------------------------------------------------------------------------
I2C_ESCRITA:

I2C_STARTCONDITION:

SETB I2C_SDA
SETB I2C_SCL
I2C_START:

NOP
CLR I2C_SDA
NOP
NOP
CLR I2C_SCL

I2C_ADDRESS:

MOV A, 2Fh
MOV R6, #08h

I2C_ADDRESS2:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_ADDRESS2
CLR I2C_SDA

I2C_ACK:

NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_ENDMEN:

MOV R6, #08h
MOV A, 2Eh

I2C_ENDMEN2:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_ENDMEN2

I2C_ACK2:

CLR I2C_SDA
NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_DATA:

MOV R6, #08h
MOV A, 2Dh

I2C_DATA2:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_DATA2

I2C_ACK3:

CLR I2C_SDA
NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_STOP:

NOP
NOP
NOP
NOP
SETB I2C_SCL
NOP
SETB I2C_SDA
NOP
NOP

I2C_WCT:

MOV R6, #0FFh
MOV R7, #15h

I2C_WCT2:

DJNZ R6, I2C_WCT2
MOV R6, #0FFh
DJNZ R7, I2C_WCT2
RET
;--------------------------------------------------------------------------------------------------------------------------------------------
I2C_LEITURA:

I2C_STARTCONDITION2:

SETB I2C_SDA
SETB I2C_SCL

I2C_START2:

NOP
CLR I2C_SDA
NOP
NOP
CLR I2C_SCL

I2C_ADDRESS3:

MOV A, 2Fh
MOV R6, #08h

I2C_ADDRESS4:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_ADDRESS4
CLR I2C_SDA

I2C_ACK4:

NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_ENDMEN3:

MOV R6, #08h
MOV A, 2Eh

I2C_ENDMEN4:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_ENDMEN4

I2C_ACK5:

CLR I2C_SDA
NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_RSTART:

NOP
SETB I2C_SDA
NOP
NOP
SETB I2C_SCL
NOP
NOP
CLR I2C_SDA
NOP
CLR I2C_SCL

I2C_ADDRESS5:

MOV A, #0A1h
MOV R6, #08h

I2C_ADDRESS6:

RLC A
MOV I2C_SDA, C
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL
DJNZ R6, I2C_ADDRESS6
CLR I2C_SDA

I2C_ACK6:

NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_READ:

MOV R6, #08h
NOP

I2C_READ2:

NOP
NOP
SETB I2C_SCL
NOP
NOP
MOV C, I2C_SDA
RLC A
CLR I2C_SCL
DJNZ R6, I2C_READ2

I2C_NOACK:

SETB I2C_SDA
NOP
SETB I2C_SCL
NOP
NOP
NOP
NOP
CLR I2C_SCL

I2C_STOP2:

CLR I2C_SDA
NOP
NOP
NOP
SETB I2C_SCL
NOP
NOP
SETB I2C_SDA
NOP

I2C_WCT3:

MOV R6, #0FFh
MOV R7, #15h

I2C_WCT4:

DJNZ R6, I2C_WCT4
MOV R6, #0FFh
DJNZ R7, I2C_WCT4
RET
;--------------------------------------------------------------------------------------------------------------------------------------------
END

Re: Problemas em gravação e leitura de memoria 24C04

MensagemEnviado: 03 Ago 2019 17:33
por tcpipchip
Ele executa uma instrução a cada 1 ciclo ? Ou 12 ciclos ?

Será que não está muito rápido o i2c ?

Que tal uns NOP nas instruções ?

Re: Problemas em gravação e leitura de memoria 24C04

MensagemEnviado: 03 Ago 2019 17:40
por Brynden
é da familia 8051 o clock externo é dividido por 12, gera um ciclo de maquina de 0,488x10-6s

Re: Problemas em gravação e leitura de memoria 24C04

MensagemEnviado: 07 Ago 2019 08:18
por ze
Olá. Me lembro que também ralei com isso. Olha aí minha contribuição. Fiz no começo do século (milênio) nos primórdios da www. De fato, perceba os nop's intuídos pelo amigo tcp. Funcionou direitin. Não lembro a freq do clk. Coloque + alguns nop's ou rotininha delay se for o caso.
Código: Selecionar todos
#define sda p2.0
#define scl p2.1

void e2promwrite(unsigned int a,unsigned char d)
{

addr=a;
data1=d;
#asm 

;**********************************************************************
; Write a byte "byte write sequence". The address to write is stored  *
; in addr. The data to write is stored in data1.                      *
;**********************************************************************

wrbyt:  mov      a,_data1    ; write to byte pointed to by addr the
        mov      r5,a     ; value in location 'data1'
        call     start      ; send start command
        mov      a,_addr     ; build slave address for write
        clr      c
        rlc      a
        orl      a,#0a0h
        mov      _data1,a
        call     outbyt     ; send slave address
        call     nack       ; send sda hi to receive an acknowledge
        mov      a,_addr+1
        mov      _data1,a
        call     outbyt     ; send word address
        call     nack       ; send sda hi to receive an acknowledge
        mov      a,r5
        mov      _data1,a
        call     outbyt     ; send write data
        call     nack       ; send sda hi to receive an acknowledge
        call     stop       ; send stop
        call     ackpol       ; use acknowledge polling

#endasm

}

unsigned char e2promread(unsigned int a)
{
addr=a;

#asm

   call     start      ; read a byte from the address indicated
        mov      a,_addr     ; in 'addr'
        clr      c
        rlc      a
        orl      a,#0a0h    ; build slave address for write
        mov      r5,a
        mov      _data1,a
        call     outbyt     ; send slave address
        call     nack       ; send sda hi to receive an acknowledge
        mov      a,_addr+1
        mov      _data1,a
        call     outbyt     ; send word address
        call     nack       ; send sda hi to receive an acknowledge
        call     start      ; send start command
        mov      a,r5     ; build slave address for read
        orl      a,#01h     ; r/w bit = 1
        mov      _data1,a
        call     outbyt     ; send slave address
        call     nack       ; send sda hi to receive an acknowledge
        call     inbyt      ; read data from x24c04
        call     nack       ; clock without acknowledge
        call     stop       ; send stop command

#endasm;

return(data1);

}
/*************************************************/
/* Rotinas usadas pelas funcoes e2prom asm acima */
/*************************************************/

#asm

;***************************************************************
; Read 8 bits from the dut. The results are returned in data1. *
;***************************************************************

inbyt:  setb     sda         ; read 8 bits, make sda an input
        mov      r6,#08h
loopi:  call     clock       ; clock data
        mov      a,_data1     ; build byte using data1
        rlc      a           ; roll in next bit from dut
        mov      _data1,a     ; save data
        djnz     r6,loopi ; loop until 8 bits are read
        ret

;*********************************************************
; Write 8 bits to the dut. The data to send is in data1. *
;*********************************************************

outbyt: mov      r6,#08h   ; prepare to shift out 8 bits
loopo:  mov      a,_data1      ; load data to be sent to dut
        rlc      a            ; rotate bit to send into carry flag
        mov      sda,c        ; send carry to sda
        mov      _data1,a      ; save rotated data
        call     clock        ; send clock signal to dut
        djnz     r6,loopo  ; loop until all 8 bits have been sent
        ret

;*********************************************************************
; Perform acknowledge polling to determine when the write cycle      *
; completes. Upon return from this routine the carry bit indicates   *
; whether the dut ever acknowledged the write. carry=0 part          *
; acknowledged, carry=1 no acknowledge received.                     *
;*********************************************************************

ackpol: mov      r7,#080h ; max number of times to check the part
akloop: djnz     r7,look  ; return if the part
        sjmp     outack       ; never issues an acknowledge.
look:   call     start        ; set up for a read
        mov      a,#0a0h      ; make slave address for a read
        mov      _data1,a
        call     outbyt       ; send slave address
        call     nack         ; get acknowledge
        jc       akloop       ; loop if no acknowledge received
outack: call     stop         ; issue a stop before returning
        ret

;***********************
; Issue a stop command *
;***********************

stop:   clr      sda          ; send stop condition to dut, sda low
        setb     scl          ; scl high
        nop                   ; make sure the set up time is valid
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop

        setb     sda          ; sda high
        ret

;************************
; Issue a start command *
;************************

start:  setb     sda          ; send start condition to dut, sda high
        setb     scl          ; scl high
        nop                   ; make sure scl set up time is valid
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        clr      sda          ; sda low
        nop                   ; make sure the set up time is valid
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        clr      scl          ; scl low
        ret

;************************
; Issue an acknowledge. *
;************************

ack:    clr      sda          ; perform an acknowledge, sda low
        call     clock        ; generate a clock pulse
        ret

;****************************************************
; Send sda high. The nack routine does not check    *
; to see if the dut actually issues an acknowledge. *
;****************************************************

nack:   setb     sda          ; sda high
        call     clock        ; generate a clock pulse
        ret

;*****************************************************************
; Issue a clock pulse. While the clock is high the value on the  *
; sda line is placed in the carry flag. when a read is taking    *
; place the carry flag will indicate the value from the dut.     *
;*****************************************************************

clock:  nop                  ; make sure the data set up time is valid
        setb    scl         ; generate a clock pulse, scl high
        nop                  ; make sure clock high time is valid
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        mov     c,sda       ; read state on sda, save in carry flag
        clr     scl         ; scl low
        ret

#endasm

Perceba a mensagem subliminar implícita pra vc cogitar elevar um pouco o nível pra c.
abç