ATmega32L als TWI/I2C Slave

SolarMicha

Neues Mitglied
02. Dez. 2008
7
0
0
Kaltennordheim
Sprachen
Hallo ihr Lieben,

wie ihr wisst bin ein ich ein absoluter Frischling, was die embedded-Programierung angeht. Im AVR32_Linux_Forum habe ich kurz mein Solarprojekt beschrieben. Hierfür brauche ich dringend ein Kommunikation zwischen dem NGW100 und dem ATmega32L.
Inzwischen läuft der NGW100 als I2C-Master. Aber mit dem ATmega32 habe ich ein großes Probleme. Nach jedem Empfang startet das ASM-Programm neu und ich weiß nicht warum.
Hier der von mir angepasste Quellcode.
Code:
; TWI I2C SLAVE					
; 10/2005						
; Bernhard.Erfurt@gmx.de		
; Adaption 2009/03 Michael Hößel
; TAKT=8.0 MHZ					
;								
.include "m32def.inc"


; TWI Slave Receiver Codes
.equ TW_SR_SLA_ACK        	= 0x60; x60	01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)													
.equ TW_SR_ARB_LOST_SLA_ACK = 0x68; x68	01101000 (Arbitration verloren in SLA+R/W als MASTER;  SLA+W wurde empfangen;  ACK wurde zurückgesendet		
.equ TW_SR_GCALL_ACK      	= 0x70; x70	01110000 (General call address wurde empfangen;  ACK wurde zurückgesendet									
.equ TW_SR_ARB_LOST_GCALL_ACK=0x78; x78	01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
.equ TW_SR_DATA_ACK      	= 0x80; x80	10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen;  ACK wurde zurückgesendet					
.equ TW_SR_DATA_NACK      	= 0x88; x88	10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet				
.equ TW_SR_GCALL_DATA_ACK   = 0x90; x90	10010000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde zurückgesendet			
.equ TW_SR_GCALL_DATA_NACK  = 0x98; x98	10011000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde nicht zurückgesendet	
.equ TW_SR_STOP        		= 0xA0; xA0	10100000 (STOP wurde empfangen, oder wiederholter Start)													
; TWI Slave Transmitter Codes
.equ TW_ST_SLA_ACK        	= 0xA8; xA8 10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)												
.equ TW_ST_ARB_LOST_SLA_ACK = 0xB0; xB0 10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)								
.equ TW_ST_DATA_ACK      	= 0xB8; xB8 10111000 (TWDR ist übertragen worden;  ACK ist empfangen worden											
.equ TW_ST_DATA_NACK      	= 0xC0; xC0 11000000 (TWDR ist übertragen worden;  ACK ist NICHT empfangen worden									
.equ TW_ST_LAST_DATA      	= 0xC8; xC8 11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0");  Ack ist empfangen worden		
.equ TW_NO_INFO        		= 0xF8; xF8 11111000 (Keine relevanten Zustandinformationen vorhanden;  TWINT = "0" keine TWDR-Tätigkeit 			
.equ TW_BUS_ERROR        	= 0x00; x00 00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit 						

; TWI SLAVE EINSTELLUNGEN
.equ TWI_SLAVE_ADRESSE		= 77	; eigene SLAVE ADRESSE 1...127			
.equ TWI_GENERAL_CALL_enable= 0		; 1=Generral Call enabled / 0=disabled	
; REGISTER
.def DATA=R15

.def TEMP = R16
.def TEMP1= R17
.def TEMP2= R18
.def TEMP3= R19
.def TEMP4= R20


.cseg					;Beginn eines Code-Segmentes
.org 0					;Startadresse=0

rjmp RESET      ; Reset Handler                           
reti ;rjmp EXT_INT0   ; IRQ0 Handler                      
reti ;rjmp EXT_INT1   ; IRQ1 Handler                      
reti ;rjmp TIM2_COMP  ; Timer2 Compare Handler            
reti ;rjmp TIM2_OVF   ; Timer2 Overflow Handler           
reti ;rjmp TIM1_CAPT  ; Timer1 Capture Handler            
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler           
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler           
reti ;rjmp TIM1_OVF   ; Timer1 Overflow Handler           
reti ;rjmp TIM0_OVF   ; Timer0 Overflow Handler           
reti ;rjmp SPI_STC    ; SPI Transfer Complete Handler     
reti ;rjmp USART_RXC  ; USART RX Complete Handler         
reti ;rjmp USART_UDRE ; UDR Empty Handler                 
reti ;rjmp USART_TXC  ; USART TX Complete Handler         
reti ;rjmp ADC        ; ADC Conversion Complete Handler   
reti ;rjmp EE_RDY     ; EEPROM Ready Handler              
reti ;rjmp ANA_COMP   ; Analog Comparator Handler         
rjmp TWSI       	  ; Two-wire Serial Interface Handler 
reti ;rjmp SPM_RDY    ; Store Program Memory Ready Handler

RESET:                        
	
;STACK initialisieren		
	ldi temp, LOW(RAMEND)
    out SPL, temp
    ldi temp, HIGH(RAMEND)
    out SPH, temp
; PORT B + D alles AUSGÄNGE	
	ldi temp, 0b11111111
	out DDRB, temp
	out PORTB,temp
	out DDRD, temp
	out PORTD,temp
; PORT C alles EINGÄNGE		
	clr TEMP
	out DDRC,temp
	ldi temp, 6
	out PORTC,temp
; TWI INITIALISIERUNG		
	rcall TWI_INI
; STARTWERTE				
	clr DATA
; alle Interrupts freigeben
sei 


LOOP:


rjmp LOOP


; #############################################################################
; #############################################################################
; #############################################################################
; TWI INTERRUPPT-Routine		
TWSI:
	push temp           ; temp auf dem Stack sichern            
	in TEMP,SREG		; Einlesen des SREG 
	push TEMP	    	; Schreiben von  SREG  im Stack (KOPIE)
;-------
	
	in temp, TWSR		; Status-Register abfragen						
	andi temp, 0xF8		; Bit0...2 ausblenden (Prescaler und Reserve-Bit)
	
	cpi temp, TW_SR_SLA_ACK			 	; x60	
	breq TWSI_TW_SR_SLA_ACK
	cpi temp, TW_SR_DATA_ACK      		; x80	
	breq TWSI_TW_SR_DATA_ACK      	
	cpi temp, TW_SR_ARB_LOST_SLA_ACK 	; x68	
	breq TWSI_TW_SR_ARB_LOST_SLA_ACK
	cpi temp, TW_SR_GCALL_ACK			; x70	
	breq TWSI_TW_SR_GCALL_ACK
	cpi temp, TW_SR_ARB_LOST_GCALL_ACK	; x78	
	breq TWSI_TW_SR_ARB_LOST_GCALL_ACK
	cpi temp, TW_SR_DATA_NACK      		; x88	
	breq TWSI_TW_SR_DATA_NACK
	cpi temp, TW_SR_GCALL_DATA_ACK   	; x90	
	breq TWSI_TW_SR_GCALL_DATA_ACK   
	cpi temp, TW_SR_GCALL_DATA_NACK		; x98	
	breq TWSI_TW_SR_GCALL_DATA_NACK
	cpi temp, TW_SR_STOP        		; xA0	
	breq TWSI_TW_SR_STOP        	
; 	
	cpi temp, TW_ST_SLA_ACK        		; 0xA8 	
	breq TWSI_TW_ST_SLA_ACK	
	cpi temp, TW_ST_ARB_LOST_SLA_ACK	; 0xB0 	
	breq TWSI_TW_ST_ARB_LOST_SLA_ACK
	cpi temp, TW_ST_DATA_ACK      		; 0xB8	
	breq TWSI_TW_ST_DATA_ACK
	cpi temp, TW_ST_DATA_NACK      		; 0xC0	
	breq TWSI_TW_ST_DATA_NACK
	cpi temp, TW_ST_LAST_DATA      		; 0xC8	
	breq TWSI_TW_ST_LAST_DATA 
	cpi temp, TW_NO_INFO        		; 0xF8	
	breq TWSI_TW_NO_INFO
	cpi temp, TW_BUS_ERROR        		; 0x00	
	breq TWSI_TW_BUS_ERROR 
	rjmp TWSI_TW_BUS_ERROR				; nicht behandelte Status-Zustände	

; SLAVE RECEIVER				
TWSI_TW_SR_SLA_ACK:						; x60	01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)
	;ldi temp, 255
	;out PORTB,temp	; LED's alle aus
	;cbi PORTB,0
	rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_SLA_ACK:			; x68	01101000 (Arbitration verloren in SLA+R/W als MASTER;  SLA+W wurde empfangen;  ACK wurde zurückgesendet
	;cbi PORTB,1
	rjmp TWSI_w
TWSI_TW_SR_GCALL_ACK:					; x70	01110000 (General call address wurde empfangen;  ACK wurde zurückgesendet		
	;cbi PORTB,2
	rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_GCALL_ACK:			; x78	01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
	;cbi PORTB,3
	rjmp TWSI_w
TWSI_TW_SR_DATA_ACK:					; x80	10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen;  ACK wurde zurückgesendet	
	;cbi PORTB,4
	in DATA, TWDR	; DATA
	out PORTB,DATA
	rjmp TWSI_w
TWSI_TW_SR_DATA_NACK:      				; x88	10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet
	;cbi PORTB,5
	rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_ACK:				; x90	10010000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde zurückgesendet	
	;cbi PORTB,6
	rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_NACK:				; x98	10011000 (die vorher adressierten (General call) Daten wurden empfangen;  ACK wurde nicht zurückgesendet	
	;cbi PORTB,7
	rjmp TWSI_w
TWSI_TW_SR_STOP:						; xA0	10100000 (STOP wurde empfangen, oder wiederholter Start)
	;cbi PORTB,7
	rjmp TWSI_w

;	SLAVE TRANSMITTER		
TWSI_TW_ST_SLA_ACK:						; xA8 	10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)		
	;ldi temp,255
	;out PORTB,temp		; LEDs alle aus
	;cbi PORTB,0	
	OUT TWDR, DATA		; DATA
	rjmp TWSI_w
TWSI_TW_ST_ARB_LOST_SLA_ACK:			; xB0 	10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)	
	;cbi PORTB,1
	rjmp TWSI_w
TWSI_TW_ST_DATA_ACK:					; xB8	10111000 (TWDR ist übertragen worden;  ACK ist empfangen worden
	;cbi PORTB,2	
	OUT TWDR, DATA		; DATA
	rjmp TWSI_w
TWSI_TW_ST_DATA_NACK:					; xC0	11000000 (TWDR ist übertragen worden;  ACK ist NICHT empfangen worden
	;cbi PORTB,3	
	OUT TWDR, DATA		; DATA
	rjmp TWSI_w
TWSI_TW_ST_LAST_DATA:					; xC8	11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0");  Ack ist empfangen worden
	;cbi PORTB,4	
	rjmp TWSI_w
TWSI_TW_NO_INFO:						; xF8	11111000 (Keine relevanten Zustandinformationen vorhanden;  TWINT = "0" keine TWDR-Tätigkeit 
	;cbi PORTB,5	
	rjmp TWSI_w
TWSI_TW_BUS_ERROR:						; x00	00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit 
	rcall TWI_ERROR	

	;rjmp TWSI_w

;-------
TWSI_w:	
	
;	rcall wait_1s		; diese Warteschleife ist nicht nötig, kann entfernd werden

;das TWINT-Flag löschen ((logisch 1)	
	ldi temp, 1<<TWINT|1<<TWEA|1<<TWEN|1<<TWIE
;	ldi temp, 1<<TWINT|1<<TWEN
	out TWCR,temp


;-------
	pop	TEMP			; LESEN von SREG vom STACK (KOPIE)
	out	SREG,TEMP		; Wiederherstellen von SREG       
	pop temp      		; temp wiederherstellen                    

reti
; #############################################################################
; #############################################################################
; #############################################################################
TWI_INI:
	; TWI TWAR (nur SLAVE) 	Adress-Register		
	ldi temp,(TWI_SLAVE_ADRESSE<<TWA0 | TWI_GENERAL_CALL_ENABLE<<TWGCE)
	out TWAR,temp
	; TWI TWCR 				Control-REGISTER	
	ldi temp, 1<<TWINT|1<<TWEA|0<<TWSTA|0<<TWSTO|0<<TWWC|1<<TWEN|1<<TWIE
	out TWCR,temp
	; Teiler wird 1
	ldi temp,1	
	out TWBR,temp
ret
; #############################################################################
; #############################################################################
; #############################################################################
TWI_ERROR:

	cbi PORTD,0

; TWI STOP				
	ldi r16, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
	out TWCR, r16
; TWI aus				
	ldi r16, (0<<TWEN)
	out TWCR, r16
; TWI INITIALISIERUNG	
 	rcall TWI_INI
	
	rcall wait_1s
	
	sbi PORTD,0


ret
; #############################################################################
; #############################################################################
; #############################################################################
; Wait for TWINT Flag set. 
TWI_TWINT_wait:
	in temp, TWCR
	sbrs temp, TWINT
	rjmp TWI_TWINT_wait
ret
; #############################################################################
; #############################################################################
; #############################################################################
WAIT_1s:
	push temp1           ; temp1 auf dem Stack sichern            
	push temp2           ; temp2 auf dem Stack sichern            
	push temp3           ; temp3 auf dem Stack sichern            

;------------
	ldi	temp3,5			
	clr temp2
	clr	temp1			
wait1s_w:	
	dec	temp1
	brne	wait1s_w
	dec	temp2		
	brne	wait1s_w
	dec	temp3
	brne	wait1s_w
;------------
	pop temp3      		; temp3 wiederherstellen                    
	pop temp2      		; temp2 wiederherstellen                    
	pop temp1      		; temp1 wiederherstellen                    
ret
Entwicklungsumgebung: AVR Studio 4
Target: AVR-Dragon

meine Fragen hierzu:
1. Ist m32def.inc das richtige Include?
2. Was wird mit ".cseg" und ".org 0" erreicht?
3. Wieso steht die Interrupt-Vector-Tabelle hinter dem RESET?
4. Wer bestimmt die Reihenfolge der Interrupt-Vectoren?
5. In den Fuses kann ich den internen Oszillator auf 8 MHz einstellen.
Was bedeudet &CK +0, +4 und +8 ms?
6. In der TWI-Beschreibung des atmel steht, dass die internen pullup-Widerstände für SDA und SCL mittels PORTCn eingeschaltet werden könne. Habe ich das mit "out PORTC, 6" getan?
7. Warum landet das Programm nach jedem korrekten Empfang eines einzelnen Bytes wieder beim RESET???
 
Hallo Micha,
1. Ist m32def.inc das richtige Include?
Ja, das ist die richtige Definitionsdatei für den ATmega32.
2. Was wird mit ".cseg" und ".org 0" erreicht?
Mit .cseg sagst du dem Assembler, dass alles folgende ins CodeSegment soll, beim AVR also ins Flash. Daneben gibte es noch .dseg (DataSegment->SRAM) und .eseg (EepromSegment).
.org setzt den Adresszeiger.

.cseg
.org 0x00
setzt den Adresszeiger für den folgenden Opcode oder die folgenden Daten im Flash auf Adresse 0x0000 (das ist der Reset-Vector).
3. Wieso steht die Interrupt-Vector-Tabelle hinter dem RESET?

Die Einsprungadressen für die Interrupts befinden sich bei AVR immer hinter dem Reset, Reihenfolge und Abstände der Einsprungadressen sind nicht bei alles AVRs gleich, die Anzahl der Interruptquellen ist natürlich auch nicht immer gleich.
4. Wer bestimmt die Reihenfolge der Interrupt-Vectoren?
Atmel. Die Reihenfolge steht im Datenblatt des jeweiligen Mikrocontrollers, bzw. in der Definitionsdatei.
5. In den Fuses kann ich den internen Oszillator auf 8 MHz einstellen.
Was bedeudet &CK +0, +4 und +8 ms?
Du meinst wahrscheinlich die Verzögerung nach Reset?! Wird über Fusebits SUT1..0 eingestellt.
6. In der TWI-Beschreibung des atmel steht, dass die internen pullup-Widerstände für SDA und SCL mittels PORTCn eingeschaltet werden könne. Habe ich das mit "out PORTC, 6" getan?
"out PORTC, 6" wird assembliert? Normalerweise benötigt man ein Register als Quelle.
Um die Portbits des TWI zu setzen, müsstest du PC0 (SCL) und PC1 (SDA) setzen. Das geht zum Beispiel so:

sbi PORTC, PC0
sbi PORTC, PC1

Wenn du externe Pullup-Widerstände verwendest, hast du den Vorteil die Widerstände dem System (Leitungslänge, Kapazitäten) anzupassen.

7. Warum landet das Programm nach jedem korrekten Empfang eines einzelnen Bytes wieder beim RESET???

Wie macht sich das bemerkbar, bzw. woher weißt du, daß ein Reset erfolgt?


Grüße,
Dirk
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)