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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.