- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: I2C für Tiny26 - Assembler.

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.07.2006
    Ort
    Karlsruhe/München
    Alter
    34
    Beiträge
    587

    I2C für Tiny26 - Assembler.

    Hi @all.

    Ich habe eine Frage wegen einer I2C-Routine in Assembler für USIP. Leider wenn ich die SPA und SCl im Avr-Studio Teste springt der Interrupt nicht an.

    Was habe ich falsch gemacht? oder liegt das am Avr-Studio?

    Nochetwas: Irgendwie springt der (nachdem man das Interrupt manuell eingesetzt hat, und Daten gesendet hat, nie zurück. Was ist dort falsch?

    Hier mal der Source:
    Code:
    ; This program emulates an I2C bus expander PCF8574 on address 0x40.
    ; Fuses:
    ; RSTDISBL programmed (0) - External Reset disabled
    ; BODEN unprogrammed (1) - Brown out detector disabled
    ; PLLCK unprogrammed (1) - PLL disabled
    ; CKOPT unprogrammed (1) - internal capacitors for an Xtal oscillator disabled
    ; SUT=10 - long start-op time 65ms
    ; CKSEL=0100 - Internal RC Oscillator 8MHz
    
    .include "tn26def.inc"
    
    ; port A - parallel data
    
    ; port B
    .equ	SDA		=0
    .equ	PAR_STROBE	=1	;control
    .equ	SCL		=2
    .equ	PAR_ERROR	=3	;status
    .equ	PAR_INIT	=4	;control
    .equ	PAR_BUSY	=5	;status
    .equ	PAR_ACK		=6	;status
    
    .def	Flags		=r16
    ; meaning of individual bits
    .equ	START_DETECTED	=7	;set by the USI Start handler when the start
    				;condition detected
    
    .def	Temp1		=r17	;local temporary variable
    .def	DeviceAddress	=r18
    
    .org	0x0000
    
    		rjmp	reset		;Reset handler
    		reti			;IRQ0 handler
    		reti			;Pin change handler
    		reti			;Timer1 compare match 1A
    		reti			;Timer1 compare match 1B
    		reti			;Timer1 overflow handler
    		reti			;Timer0 overflow handler
    		rjmp	usi_strt	;USI Start handler
    		reti			;USI Overflow handler
    		reti			;EEPROM Ready handler
    		reti			;Analog Comparator handler
    		reti			;ADC Conversion Handler
    
    reset:		ldi	Temp1,RAMEND
    		out	SP,Temp1
    
    		ldi	Temp1,0x00
    		out	PORTA,Temp1
    		out	DDRA,Temp1
    		out	PORTB,Temp1
    		out	DDRB,Temp1
    
    ; USI settings:
    ; Start Condition Interrupt Enable
    ; Counter Overflow Interrupt Enable
    ; Two-wire mode
    ; Shift Register Clock Source - External, positive edge
    ; 4-bit Counter Clock Source - External, both edges
    		ldi	Temp1,(1<<USISIE)+(0<<USIOIE)+(1<<USIWM1)+(0<<USIWM0)+(1<<USICS1)+(0<<USICS0)+(0<<USICLK)
    		out	USICR,Temp1
    		sei
    
    main_loop:	cbi	DDRB,SDA
    		cbr	Flags,(1<<START_DETECTED)
    		ldi	Temp1,(1<<USIPF)
    		out	USISR,Temp1
    ; wait for the start condition
    main_1:		sbrs	Flags,START_DETECTED
    		rjmp	main_1
    ; start condition detected
    start_cond:	cbr	Flags,(1<<START_DETECTED)
    		ldi	Temp1,(1<<USIOIF)+0x0F	;1 SCL edge
    		out	USISR,Temp1
    ; skip the first falling SCL edge after the start condition
    main_2:	;	sbic	USISR,USIPF	;stop condition detected?
    	;	rjmp	main_loop
    		sbrc	Flags,START_DETECTED ;start condition detected?
    		rjmp	start_cond
    		sbis	USISR,USIOIF
    		rjmp	main_2
    		ldi	Temp1,(1<<USIOIF)+0x00	;10 SCL edges
    		out	USISR,Temp1
    ; wait until the master sends the Device Address
    main_3:	;	sbic	USISR,USIPF	;stop condition detected?
    	;	rjmp	main_loop
    		sbrc	Flags,START_DETECTED ;start condition detected?
    		rjmp	start_cond
    		sbis	USISR,USIOIF
    		rjmp	main_3
    		in	DeviceAddress,USIDR
    		mov	Temp1,DeviceAddress
    		andi	Temp1,0xFE	;ignore the R/W bit
    		cpi	Temp1,0x40	;PCF8574 device address
    		brne	main_loop
    ; valid Device Address received from the master,
    ; read or write?
    		sbrc	DeviceAddress,0	;R/W bit
    		rjmp	read
    
    ; prepare the ATtiny26 to send the ACK bit to the master
    write_loop:	ldi	Temp1,(1<<USIOIF)+0x0E	;2 SCL edges
    		out	USISR,Temp1
    		cbi	PORTB,SDA
    		sbi	DDRB,SDA
    ; wait until the master reads the ACK bit
    write_1:	sbis	USISR,USIOIF
    		rjmp	write_1
    		cbi	DDRB,SDA
    ; the master sends data to the ATtiny26
    		ldi	Temp1,(1<<USIOIF)+0x00	;16 SCL edges
    		out	USISR,Temp1
    		ldi	Temp1,0		;ACK=0
    		out	USIDR,Temp1	;bit 0 will be send as ACK
    ; wait until the master sends the Data Byte
    write_2: ;	sbic	USISR,USIPF	;stop condition detected?
    	;	rjmp	main_loop
    		sbrc	Flags,START_DETECTED ;start condition detected?
    		rjmp	start_cond
    		sbis	USISR,USIOIF
    		rjmp	write_2
    		in	Temp1,USIDR
    		com	Temp1
    		out	DDRA,Temp1
    		rjmp	write_loop
    
    ; prepare the ATtiny26 to receive the ACK bit from the master
    read:		ldi	Temp1,(1<<USIOIF)+0x0E	;2 SCL edges
    		out	USISR,Temp1
    		cbi	PORTB,SDA
    		sbi	DDRB,SDA
    ; wait until the master reads the ACK bit
    read_1:		sbis	USISR,USIOIF
    		rjmp	read_1
    ;
    ; the master reads data from the ATtiny26
    read_loop:	in	Temp1,PINA
    		out	USIDR,Temp1
    		ldi	Temp1,(1<<USIOIF)+0x00	;16 SCL edges
    		out	USISR,Temp1
    		sbi	PORTB,SDA
    		sbi	DDRB,SDA
    ; wait until the master reads the Data Byte
    read_2:		sbis	USISR,USIOIF
    		rjmp	read_2
    		cbi	DDRB,SDA
    ; prepare the ATtiny26 to receive the ACK bit from the master
    		ldi	Temp1,(1<<USIOIF)+0x0E	;2 SCL edges
    		out	USISR,Temp1
    ; wait until the master sends the ACK bit
    read_3:	;	sbic	USISR,USIPF	;stop condition detected?
    	;	rjmp	main_loop
    		sbrc	Flags,START_DETECTED ;start condition detected?
    		rjmp	start_cond
    		sbis	USISR,USIOIF
    		rjmp	read_3
    		in	Temp1,USIDR
    		sbrs	Temp1,0		;test the ACK bit	
    		rjmp	read_loop
    ; no acknowledge, wait for a stop or start condition
    read_4:	;	sbic	USISR,USIPF	;stop condition detected?
    	;	rjmp	main_loop
    		sbrc	Flags,START_DETECTED ;start condition detected?
    		rjmp	start_cond
    		rjmp	read_4
    
    
    ; USI Start handler - called when the start condition detected
    usi_strt:	push	Temp1
    		in	Temp1,SREG
    		push	Temp1
    		ldi	Temp1,(1<<USISIF)
    		out	USISR,Temp1
    		sbr	Flags,(1<<START_DETECTED)
    		pop	Temp1
    		out	SREG,Temp1
    		pop	Temp1
    		reti
    Grüße

    s.o.

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.06.2007
    Ort
    München
    Alter
    61
    Beiträge
    199
    hast Du den Code selbst geschrieben?
    bin auch an dem Thema interessiert.
    Hast Du das Problem schon gelöst?
    Die Start-Condition geht ja davon aus, dass die SDA Leitung auf low geht, während SCL low ist. Kann man diese Dynamik im AVR Simulator überhaupt nachbilden?

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Hallo,
    der AVR Simulator unterstützt USI nicht, das kann man nur mit Onboard Debugger testen z.B. einem Dragon

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Zitat Zitat von uffi
    hast Du den Code selbst geschrieben?
    bin auch an dem Thema interessiert.
    Als kleinen Tip: Atmel bietet auch hierzu ne Appnote an.

    Grüße,
    Hanni
    Grundregeln des Forenpostings:
    1. Nutze niemals die Suchfunktion!
    2. Überprüfe niemals die Topics nach Ähnlichkeiten!
    3. Schreibe alles in hellgelb!

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.06.2007
    Ort
    München
    Alter
    61
    Beiträge
    199
    Hab jetzt den Assembler Code oben auf einem ATtiny26 als Slave impementiert und lasse ihn von einem ATMEGA16 als Master addressieren (mit der Software-Bibliothek von Peter Fleury -> das Assembler File, welches mit jedem AVR-Pin läuft auch ohne TWI support). In der Assembler Routine des Slaves (siehe oben) wird beim Warten auf den USI overflow ja in der Warteschleife immer auch überprüft, ob eine neue Start- oder eine Stop-Condition vorliegt. Im Code oben ist die Abfrage der Stop-Condition auskommentiert.

    So, nun das überraschende: Der Assembler Code des Slave (siehe oben) läuft und empfängt die Adresse und das Command-Byte richtig, so lange ich nicht die Stop-Condition abfrage. Sobald ich dies aber tue, wird die I2C Kommunikation sofort abgebrochen, weil offenbar eine Stop-Condition vorliegt. Ich hab die Signale am Oszi angeschaut und da ist aber definitiv keine Stop-Condition vorhanden, erst am Ende der Übertragung.

    Also hatte das wohl schon seinen Grund, dass der Autor des Codes oben die Abfrage der Stop-Condition auskommentiert hatte.

    Hat jemand eine Erklärung für dieses unerwartete Verhalten? Kann das eine Störung sein, die man am Oszi nicht sieht? Oder ist das ein bekannter Fehler mit dem Stop-Condition Bit (USIPF) im USISR (USI Status Register?

    Danke und Gruß, uffi.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Hat jemand eine Erklärung für dieses unerwartete Verhalten? Kann das eine Störung sein, die man am Oszi nicht sieht? Oder ist das ein bekannter Fehler mit dem Stop-Condition Bit (USIPF) im USISR (USI Status Register?
    Ich habe hier einen USI slave seit paar Monaten auf einem Tiny24 laufen, ich prüfe auch den USIPF, kann aber keine Probleme feststellen.
    Der Slave rennt um sein Leben

    Hier mal mein USI_STRaddr Interrupt:
    Code:
    usi_start:
    	in sregret,SREG
    	in tmpi1,USISR
    	ldi USI_TWI_OVERFLOW_STATUS,USI_SLAVE_CHECK_ADDRESS
    	cbi USI_DDR,USI_SDA
    usi_start1:
    	sbrc tmpi1,USIPF
    	rjmp usistart2
    	sbic USI_PIN,USI_SCL
    	rjmp usi_start1
    usistart2:
    	ldi tmpi1,(1<<USISIE)|(1<<USIOIE)|(1<<USIWM1)|(1<<USIWM0)|(1<<USICS1)
    	out USICR,tmpi1
    	ldi tmpi1,(1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)
    	out USISR,tmpi1
    	out SREG,sregret
    	reti
    Gruß Sebastian

    P.S. Achso, als Master habe ich bis jetzt Hardware Twi von m8 m16 und m128 gehabt.
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.06.2007
    Ort
    München
    Alter
    61
    Beiträge
    199
    Hallo izaseba,

    danke für Deine ausführliche Antwort. Nachdem Dein Code ja gut läuft: kannst Du mir die ganze Assembler-Source für Deinen Slave zur Verfügung stellen? Das wäre super nett.

    Ich habe den Autor des Original-Codes, den s.o. oben eingestellt hat, ausfindig gemacht, es ist Piotr Piatek [piotr433@pisi.com.pl], der Code stammt orginal von dieser Internet Seite:

    http://www.pisi.com.pl/piotr433/pcf_12.asm

    Ich habe folgendes Statement von Piotr erhalten:

    Hello Dirk,

    On Mon, 26 Nov 2007 15:18:24 +0100, you wrote:

    >Now the surprise: your code works properly and the address and command
    >byte are well received by the slave, as long as the check for a stop
    >condition is left as comment as in your original file. However, when
    >removing the comment signs and thereby activating the check of a stop
    >condition in the wait loops for USI overflow, the I2C communication is
    >always stopped. I watched the signals on osci. I could not find a stop
    >condition except at the end of transmission.
    >
    >Do you have an explanation?

    I experienced the same behaviour, but couldn't explain it. The USIPF bit seemed to be permanently set regardless of the bus state. An attempt to clear it by software failed as well. I don't know whether this was a bug in the silicon, or did I misunderstand the datasheet.

    >Obviously, you had a reason to comment the check for stop condition and
    >not use it in the real code?

    It was only a quick fix to make the code work. Eventually I decided to abandon the USI at all, and to do everything in software.

    Later I found a similar I2C slave implementation written by someone else (in the attachment, not tested). Please note that it doesn't check for stop condition, either.

    Best regards

    Piotr
    Ich vermute nun, dass die Stop-Condition-Flag USIPF in dem Code versehentlich jeweils in folgender Anweisung gesetzt wird, da das Bit USIPF (in USISR) laut Datenbuch nur durch Beschreiben mit einer 1 gelöscht wird (also möglicherweise durch Schreiben einer 0 dann auch gesetzt wird?):

    • ldi Temp1,(1<<USIOIF)+0x00 ;10 SCL edges
      out USISR,Temp1


    Was meint ihr? Ich werd es heute abend ausprobieren.

    Gruß, uffi.[/b]

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Hallo uffi,
    Ich habe Dir eine Mail geschickt.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.684
    Hallo uffi und izaseba,

    MEIN GLÜCK dass ich über diesen Thread gestolpert bin. Vielleicht könnt Ihr mir helfen, bitte?

    Ich will auf einem 2313 zwei Motoren ansteuern (L293) und zwei Encoder auslesen. Die Motorvorgaben und Encoderwerte sollen mit einem anderen Controller ausgetauscht werden. Nun habe ich allererste Ergebnisse mit ner RS232 in C (mit viel Hilfe von anderen) - aber der Maschinencode ist da relativ lang. Ich will nur jeweils vier, max acht Werte (etwa vier Bytes und zwei words) hin- und vier, max acht andere Werte zurückschaufeln. Jetz sehe ich, dass Ihr I2C auf den Tiny´s in Assembler macht. Bascom kann und will ich nicht, C ist bei mir noch völlig ungenügend - aber ich lerne, Assembler mit AVR geht relativ gut.

    Kann ich(man) den Code von s.o. dafür nehmen? Den Code für Tiny26 könnte ich ja schnell umändern für den 2313. Und I2C kann ja wohl bequem ohne externen Quarz laufen, ich könnte den max232 sparen und ein Interrupt-Timer für PWM wär wohl kein Problem! Wie habt Ihr die Fallstricke gelöst? Was muss ich am Code oben ändern?

    Danke im Voraus,
    Ciao sagt der JoeamBerg

  10. #10
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Zum Verbinden von 2 Controllern ist I2C nicht allzu gut geeignet. Einen I2C Master, wie ober zu programmieren ist relativ einfach gegen den slave (gegenseite). Vermutlich wäre SPI einfacher, denn es wird von der Hardware unterstützt (USI Modul). Auch die UART wäre möglich, besonders wenn beide Prozessoren vom gleichen Takt gespeißt werden. Wenn die Verbindung über kurze Distanzen ist, kann man die MAX232 natürlich weglassen und die Daten direkt auf CMOS Pegel übertragen.
    Das der Maschinen code den der C Compliler für die UART communication ausgibt lang ist, hat nicht viel zu sagen, das ist auch bei einem "Hallo World" schon so. Der Code für I2C wird ziehmlich sicher deutlich länger.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen