Forum: Mikrocontroller und Digitale Elektronik EEPROM sequentiel lesen I2C


von groovie (Gast)


Lesenswert?

hallo,

ich habe einen atmega 8515 mit 7.3728 Mhz, den habe ich mit portb pin 0 
und 1 an ein i2c eeprom geschlossen ein CAT24WC16P

jetz habe ich versucht einfach mal in adresse 00 was abzuspeichern und 
in adresse 01.

das geht.

auch auslesen der einzelnen werte geht.

jetzt wollte ich sequentiell lesen da ist das 1. Byte stimmt, das 2. 
byte immer null.

ich habe alles mögliche probiert. keine ahnung was da falsch ist. 
hiiiiiiiiilfe.


das listing ist aus einer atmel aplication note.




das listing

;**** A P P L I C A T I O N N O T E A V R 3 0 0 ************************
;*
;* Title : I2C (Single) Master Implementation
;* Version : 1.0 (BETA)
;* Last updated : 19.12.2008
;* Target : Atmel 8515
;* Frequenz MCU fOsc = 7372800 Hz (7.3728 Mhz)
;*
;* zum ausrechnen der verzögerungs(delay) zeiten für 5 µs
;* n = t * fosc    ->  = 7372800 Hz * 0,000005 sec = 36,864
;*
;* n      |  Delay method
;* 
----------+------------------------------------------------------------- 
-------
;* < 1      |  Remove all calls to the delay routine
;* 1 < n < 2 |  Replace all calls to the delay routine with one "nop" 
instruction
;* 2 < n < 3 |  Replace all calls to the delay routine with an "rjmp 1" 
instruction
;* 2 < n < 7 |  The delay routine should consist of one "ret" 
instruction only
;* > 7      |  Use the following routine :
;        ldi TWIdelay, 1+ (n-7)/3
;        loop: dec TWIdelay
;        brne loop
;        ret
;        (this routine is used in the program code!)
;*
;*
;*  (36,864-7)/3+1 = 10,95466 = 10 = 0A hex
;*
;* DESCRIPTION
;* Basic routines for communicating with I2C slave devices. This
;* "single" master implementation is limited to_one bus master_on the
;* I2C bus. Most applications do not need the multimaster ability
;* the I2C bus provides. A single master implementation uses, by far,
;* less resources and is less XTAL frequency dependent.
;*
;* Some features :
;* * All interrupts are free, and can be used for other activities.
;* * Supports normal and fast mode.
;* * Supports both 7-bit and 10-bit addressing.
;* * Supports the entire AVR microcontroller family.
;*
;* Main I2C functions :
;* 'i2c_start' - Issues a start condition and sends address
;* and transfer direction.
;* 'i2c_rep_start' - Issues a repeated start condition and sends
;* address and transfer direction.
;* 'i2c_do_transfer' - Sends or receives data depending_on
;* direction given in address/dir byte.
;* 'i2c_stop' - Terminates the data transfer by issue a
;* stop condition.
;*
;* USAGE
;* Transfer formats is described in the AVR300 documentation.
;* (An example is shown in the 'main' code).
;*
;* NOTES
;* The I2C routines can be called either from non-interrupt or
;* interrupt routines, not both.
;*
;* STATISTICS
;* Code Size : 81 words (maximum)
;* Register Usage : 4 High, 0 Low
;* Interrupt Usage : None
;* Other Usage : Uses two I/O pins_on port D
;* XTAL Range : N/A
;*
;*********************************************************************** 
****

;**** Includes ****
.include "m8515def.inc"



;**** Global I2C Constants ****

.equ SCLP = 1 ; SCL Pin number (port B)
.equ SDAP = 0 ; SDA Pin number (port B)

.equ b_dir = 0 ; transfer direction bit in i2cadr

.equ i2crd = 1
.equ i2cwr = 0


.equ I2cOUT = 0x72


;**** Global Register Variables ****

.def i2cdelay= r16 ; Delay loop variable
.def i2cdata = r17 ; I2C data transfer register
.def i2cadr = r18 ; I2C address and direction register
.def i2cstat = r19 ; I2C bus status register
.def wr0 = r20

;**** Interrupt Vectors ****


.CSEG

;---------------------------------- 
Interruptvektoren_______________________


.org 000
   rjmp reset ; Reset Handler
   RETI; EXT_INT0 ; IRQ0 Handler
   RETI; EXT_INT1 ; IRQ1 Handler
   RETI; TIM1_CAPT ; Timer1 Capture Handler
   RETI; TIM1_COMPA ; Timer1 Compare A Handler
   RETI; TIM1_COMPB ; Timer1 Compare B Handler
   RETI; TIM1_OVF ; Timer1 Overflow Handler
   RETI; TIM0_OVF ; Timer0 Overflow Handler
   RETI; SPI_STC ; SPI Transfer Complete Handler
   RJMP USART_RXC ; USART RX Complete Handler
   RETI; USART_UDRE ; UDR0 Empty Handler
   RETI; USART_TXC ; USART TX Complete Handler
   RETI; ANA_COMP ; Analog Comparator Handler
   RETI; EXT_INT2 ; IRQ2 Handler
   RETI; TIM0_COMP ; Timer0 Compare Handler
   RETI; EE_RDY ; EEPROM Ready Handler
   RETI; SPM_RDY ; Store Program memory Ready

;----------------------------------------------------------------------- 
-----






RESET:

  CLI

ini_Stackpointer:
  ldi   wr0,Low(RAMEND)  ; Funktion als Hilfsregister
  out   SPL,wr0
  ldi   wr0,High(RAMEND)
  out   SPH,wr0      ; Stackpointer setzen


; ********** ini I2C **********
  rcall i2c_init

; ********** ini USART ***********
ini_USART:
  ;enable reciver and transmitter and rx complete interrupt enable 
datenblatt seite 156
  ldi wr0, (1<<RXCIE | 1<<RXEN | 1<<TXEN)
  out UCSRB,wr0

  ldi wr0, (0<<U2X | 0<<MPCM)  ; doppelte uart transmission speed = aus,
                ; multiprozessor modus = aus, datenblatt seite 155
  out UCSRA,wr0

  ;set frame format 8 data 1 stopp bit No paritycheck    datenblatt 
seite 157/158
  ldi wr0, (1<<URSEL | 0<<USBS | 3<<UCSZ0 | 0<<UPM0 | 0<<UMSEL | 
0<<UCPOL)
  out UCSRC,wr0

  ;baudrate 9600    bei 7.3728 mhz siehe datenblatt seite 161
  ldi wr0, (0<<URSEL | 0<<UBRR11 | 0<<UBRR10 | 0<<UBRR9 | 0<<UBRR8)
  out UBRRH,wr0
  ldi wr0, 0x2F
  out UBRRL,wr0
; ********************************************

  SEI


HAUPT:




schleife:
  rjmp schleife




















;********************Interrupts************

USART_RXC:


; bei übertragung einer "01" wird in adresse 0x00 des eeproms
; eine 0x14 gespeichert

; bei übertragung einer "02" soll sequentiell adresse 00 und 01 des
; eeproms ausgelesen und über rs232 ausgegeben werden.

  push wr0
  in wr0, udr

  cpi wr0, 0x01
  brne next

  out udr, wr0

  ldi wr0, 0x01

  ldi i2cadr, 0xA0
  rcall i2c_start
  brcs fehler

        ldi i2cdata, 0x00
  rcall i2c_write
  brcs fehler


  ldi i2cdata, 0x14
  rcall i2c_write
  brcs fehler

  rcall i2c_stop

  rjmp usart_ende

next:

cpi wr0, 0x02
  brne usart_ende

  out udr, wr0

  ldi i2cadr, 0xA0
  rcall i2c_start
  brcs fehler

  ldi i2cdata, 0x00
  rcall i2c_write
  brcs fehler


  ldi i2cadr, 0xA1
  rcall i2c_rep_start
  brcs fehler


  clc    ; ack
  rcall i2c_read

  mov wr0, i2cdata
  sec   ; no ack
  rcall i2c_read



  rcall i2c_stop




USART_Transmita:
; Wait for empty transmit buffer
sbis UCSRA,UDRE
rjmp USART_Transmita
; Put data (r16) into buffer, sends the data
  out udr, wr0

USART_Transmitc:
; Wait for empty transmit buffer
sbis UCSRA,UDRE
rjmp USART_Transmitc
; Put data (r16) into buffer, sends the data
  out udr, i2cdata





usart_ende:
  pop wr0

  RETI







fehler:    ; das ist nur temporär um zu sehen ob alles ok ist


USART_Transmitb:
; Wait for empty transmit buffer
sbis UCSRA,UDRE
rjmp USART_Transmitb
; Put data (r16) into buffer, sends the data
                ldi wr0, 0x11
    out udr, wr0
rjmp usart_ende






;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_hp_delay
;* i2c_qp_delay
;*
;* DESCRIPTION
;* hp - half i2c clock period delay (normal: 5.0us / fast: 1.3us)
;* qp - quarter i2c clock period delay (normal: 2.5us / fast: 0.6us)
;*
;* SEE DOCUMENTATION !!!
;*
;* USAGE
;* no parameters
;*
;* RETURN
;* none
;*
;*********************************************************************** 
****

i2c_hp_delay:
    ldi i2cdelay, 0x0A
  loop:
    dec i2cdelay
    brne loop
    ret


i2c_qp_delay:
    ldi i2cdelay,0x04
  i2c_qp_delay_loop:
    dec i2cdelay
    brne i2c_qp_delay_loop
    ret


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_rep_start
;*
;* DESCRIPTION
;* Assert repeated start condition and sends slave address.
;*
;* USAGE
;* i2cadr - Contains the slave address and transfer direction.
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to the address.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_start.
;*
;*********************************************************************** 
****

i2c_rep_start:

  sbi DDRB,SCLP ; force SCL low
  cbi DDRB,SDAP ; release SDA
  rcall i2c_hp_delay ; half period delay
  cbi DDRB,SCLP ; release SCL
  rcall i2c_qp_delay ; quarter period delay


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_start
;*
;* DESCRIPTION
;* Generates start condition and sends slave address.
;*
;* USAGE
;* i2cadr - Contains the slave address and transfer direction.
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to the address.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_write.
;*
;*********************************************************************** 
****

i2c_start:
  mov i2cdata,i2cadr ; copy address to transmitt register
  sbi DDRB,SDAP ; force SDA low
  rcall i2c_qp_delay ; quarter period delay


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_write
;*
;* DESCRIPTION
;* Writes data (one byte) to the I2C bus. Also used for sending
;* the address.
;*
;* USAGE
;* i2cdata - Contains data to be transmitted.
;*
;* RETURN
;* Carry flag - Set if the slave respond transfer.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_get_ack.
;*
;*********************************************************************** 
****

i2c_write:
  sec ; set carry flag
  rol i2cdata ; shift in carry and out bit_one
  rjmp i2c_write_first
i2c_write_bit:
  lsl i2cdata ; if transmit register empty
i2c_write_first:
  breq i2c_get_ack ; goto get acknowledge
  sbi DDRB,SCLP ; force SCL low

  brcc i2c_write_low ; if bit high
  nop ; (equalize number of cycles)
  cbi DDRB,SDAP ; release SDA
  rjmp i2c_write_high
i2c_write_low: ; else
  sbi DDRB,SDAP ; force SDA low
  rjmp i2c_write_high ; (equalize number of cycles)
i2c_write_high:
  rcall i2c_hp_delay ; half period delay
  cbi DDRB,SCLP ; release SCL
  rcall i2c_hp_delay ; half period delay

  rjmp i2c_write_bit


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_get_ack
;*
;* DESCRIPTION
;* Get slave acknowledge response.
;*
;* USAGE
;* (used_only by i2c_write in this version)
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to a request.
;*
;*********************************************************************** 
****

i2c_get_ack:
  sbi DDRB,SCLP ; force SCL low
  cbi DDRB,SDAP ; release SDA
  rcall i2c_hp_delay ; half period delay
  cbi DDRB,SCLP ; release SCL

i2c_get_ack_wait:
  sbis PINB,SCLP ; wait SCL high
;(In case wait states are inserted)
  rjmp i2c_get_ack_wait

  clc ; clear carry flag
  sbic PINB,SDAP ; if SDA is high
  sec ; set carry flag
  rcall i2c_hp_delay ; half period delay
  ret


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_do_transfer
;*
;* DESCRIPTION
;* Executes a transfer_on bus. This is_only a combination of i2c_read
;* and i2c_write for convenience.
;*
;* USAGE
;* i2cadr - Must have the same direction as when i2c_start was called.
;* see i2c_read and i2c_write for more information.
;*
;* RETURN
;* (depends_on type of transfer, read or write)
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_read.
;*
;*********************************************************************** 
****

i2c_do_transfer:
  sbrs i2cadr,b_dir ; if dir = write
  rjmp i2c_write ; goto write data


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_read
;*
;* DESCRIPTION
;* Reads data (one byte) from the I2C bus.
;*
;* USAGE
;* Carry flag - If set no acknowledge is given to the slave
;* indicating last read operation before a STOP.
;* If cleared acknowledge is given to the slave
;* indicating more data.
;*
;* RETURN
;* i2cdata - Contains received data.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_put_ack.
;*
;*********************************************************************** 
****

i2c_read:

  rol i2cstat ; store acknowledge
; (used by i2c_put_ack)
  ldi i2cdata,0x01 ; data = 0x01
i2c_read_bit: ; do
  sbi DDRB,SCLP ; force SCL low
  rcall i2c_hp_delay ; half period delay

  cbi DDRB,SCLP ; release SCL



  rcall i2c_hp_delay ; half period delay

  clc ; clear carry flag
  sbic PINB,SDAP ; if SDA is high
  sec ; set carry flag

  rol i2cdata ; store data bit
  brcc i2c_read_bit ; while receive register not full


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_put_ack
;*
;* DESCRIPTION
;* Put acknowledge.
;*
;* USAGE
;* (used_only by i2c_read in this version)
;*
;* RETURN
;* none
;*
;*********************************************************************** 
****

i2c_put_ack:
  sbi DDRB,SCLP ; force SCL low

  ror i2cstat ; get status bit
  brcc i2c_put_ack_low ; if bit low goto assert low
  cbi DDRB,SDAP ; release SDA
  rjmp i2c_put_ack_high
i2c_put_ack_low: ; else
  sbi DDRB,SDAP ; force SDA low
i2c_put_ack_high:

  rcall i2c_hp_delay ; half period delay
  cbi DDRB,SCLP ; release SCL
i2c_put_ack_wait:
  sbis PINB,SCLP ; wait SCL high
  rjmp i2c_put_ack_wait
  rcall i2c_hp_delay ; half period delay
  ret


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_stop
;*
;* DESCRIPTION
;* Assert stop condition.
;*
;* USAGE
;* No parameters.
;*
;* RETURN
;* None.
;*
;*********************************************************************** 
****

i2c_stop:
  sbi DDRB,SCLP ; force SCL low
  sbi DDRB,SDAP ; force SDA low
  rcall i2c_hp_delay ; half period delay
  cbi DDRB,SCLP ; release SCL
  rcall i2c_qp_delay ; quarter period delay
  cbi DDRB,SDAP ; release SDA
  rcall i2c_hp_delay ; half period delay
  ret


;*********************************************************************** 
****
;*
;* FUNCTION
;* i2c_init
;*
;* DESCRIPTION
;* Initialization of the I2C bus interface.
;*
;* USAGE
;* Call this function_once to initialize the I2C bus. No parameters
;* are required.
;*
;* RETURN
;* None
;*
;* NOTE
;* PORTB and DDRB pins not used by the I2C bus interface will be
;* set to Hi-Z (!).
;*
;* COMMENT
;* This function can be combined with other PORTD initializations.
;*
;*********************************************************************** 
****

i2c_init:
  clr i2cstat ; clear I2C status register (used
  ; as a temporary register)
  out PORTB,i2cstat ; set I2C pins to open colector
  out DDRB,i2cstat
  ret

von groovie (Gast)


Lesenswert?

so habs doch selber gefunden, dachte andere hätten auch diese probleme. 
hatte zum beispiel mal hier im forum geesen das jemand versuchte einen 
temp fühler per i2c auszulesen und auch nur den ersten wert bekam, die 
nachkommastelle im 2. read war auch immer null.


die application note von atmel hat einen fehler !

in der rouine

i2c_read:

  rol i2cstat ; store acknowledge
; (used by i2c_put_ack)
  ldi i2cdata,0x01 ; data = 0x01
i2c_read_bit: ; do
  sbi DDRB,SCLP ; force SCL low
  rcall i2c_hp_delay ; half period delay

;********** MUSS HIER NOCH DIESER BEFEHL REIN !!!!

cbi DDRB,SDAP ; release SDA



;*******************************************

  cbi DDRB,SCLP ; release SCL



;***** und hier sollte überprüft werden ob nicht der slave im waitstate 
ist

w:
 sbis PINB,SCLP ; wait SCL high
  rjmp w


;**************************************



  rcall i2c_hp_delay ; half period delay

  clc ; clear carry flag
  sbic PINB,SDAP ; if SDA is high
  sec ; set carry flag

  rol i2cdata ; store data bit
  brcc i2c_read_bit ; while receive register not full
----------------------------------------------------------------------


denn wenn man sequentiell lesen will muss nach dem readbyte aufruf ein 
acknoledge folgen. dabei wird die sda leitung auf low gesetzt. wenn man 
danach wieder die read routine anspringt gibt es kein sda release. 
deswegen erhält man als 2. datenbyte und x. datenbyte immer null.

jetzt geht alles prima.

bekam hier im forum immer tolle tips und hoffe so mal was zurückzugeben 
zu können.

grüße
groovie

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.