PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frage zu TWI-Programmierung



yvuu
05.04.2012, 10:12
Hallo!

Als Vorübung zu meinem nächsten Projekt habe ich zwei AT-Mega8 per TWI verbunden. Die Codes habe ich den Datenblättern und div. Anleitungen entnommen, teilweise auch vom myAVR-CodeWizard.

Die erste MCU bekommt Daten per USB vom PC (funktioniert) und soll sie per TWI zur zweiten MCU übertragen. Die zweite MCU soll empfangene Daten per LCD darstellen.

Nun funktioniert aber leider die Kommunikation nicht :(

Wo kann der Fehler liegen? Zur Vereinfachung habe ich nur Auszüge meiner Sourcecodes angehängt:

Master
;Vorübung für Krabbler: Experimentierplatine an PC über USB, LCD-Erweiterung angeschlossen
;a- Zeichen, vom PC gesendet, werden auf dem LCD angezeigt --------------- erfolgreich beendet
;b- beide Experimentierplatinen über TWI verbinden, Daten von PC über beide Platinen auf LCD darstellen
;c- endgültige Krabblersoftware erstellen
;+-----------------------------------------------------------------------------
;| Titel : Krabbler - Vorübung b-
;+-----------------------------------------------------------------------------
;| Funktion : Empfang von Daten vom PC durch MCU, Übertragung auf andere MCU per TWI
;| : Ausgabe der Zeichen auf dem LCD-Modul
;| Schaltung : zwei MK2USB-Boards verbunden Port C4 und C5 (TWI) und Spannungsversorgung
;| : Netzteil angeschlossen
;| : Port D2 = RS, D3 = E, D4-7 = DB4-7, für LCD
;+-----------------------------------------------------------------------------
;| Prozessor : ATmega8
;| Takt : 3,6864 MHz
;| Sprache : Assembler
;| Datum : 5.4.2012
;| Version : 2 Teil a
;| Autor : U.S. / Routinen myAVR
;+-----------------------------------------------------------------------------
.include "AVR.H"
.equ F_CPU,3686400
.equ TWI_CLOCK,100000 ; Geschwindigkeit des TWI-Busses ca., durch Rundungsfehler etwas höher
.equ FCPU,3686400
.equ BAUD,9600
.equ Temp,0x10 ; r16 wird zur Übergabe an Unterprogramme benutzt
.equ ZSP,0x13 ; r19 Zwischenspeicher für empfangene Zeichen
;-----------------------------------------------------------------------------
begin: rjmp main ; RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 External Interrupt Request 0
reti ; INT1 External Interrupt Request 1
reti ; TIMER2 COMP Timer/Counter2 Compare Match
reti ; TIMER2 OVF Timer/Counter2 Overflow
reti ; TIMER1 CAPT Timer/Counter1 Capture Event
reti ; TIMER1 COMPA Timer/Counter1 Compare Match A
reti ; TIMER1 COMPB Timer/Counter1 Compare Match B
reti ; TIMER1 OVF Timer/Counter1 Overflow
reti ; TIMER0 OVF Timer/Counter0 Overflow
reti ; SPI, STC Serial Transfer Complete
reti ; USART, RXC USART, Rx Complete
reti ; USART, UDRE USART Data Register Empty
reti ; USART, TXC USART, Tx Complete
reti ; ADC ADC Conversion Complete
reti ; EE_RDY EEPROM Ready
reti ; ANA_COMP Analog Comparator
reti ; TWI 2-wire Serial Interface
reti ; SPM_RDY Store Program Memory Ready
;------------------------------------------------------------------------------
main: ldi Temp,hi8(RAMEND) ; Main program start
out SPH,Temp ; Set Stack Pointer to top of RAM
ldi Temp,lo8(RAMEND)
out SPL,Temp
rcall UART_init
rcall twiInitMaster
sbi DDRB,0
sbi DDRB,1
;------------------------------------------------------------------------------
mainloop: rcall UART_Empf ; wartet auf Empfang und übergibt das empfangene Zeichen in ZSP
rcall AnzeigeRot
rcall twiStart
ldi r16,0b11111110 ; Slave-Adresse + W
rcall twiWriteByte
mov r16,ZSP ; Zeichen wird in Register 16 an TWI-Schreibroutine übergeben
rcall twiWriteByte
rcall twiStopp
rcall AnzeigeGelb
rjmp mainloop
;------------------------------------------------------------------------------
UART Routinen sind ausgelassen - funktionsfähig
;-----------------------------------------------------------------------------
; twiInitMaster (ohne Interrupt)
; gestattet die Benutzung von TWI und setzt die Master-Clock-Rate
;-----------------------------------------------------------------------------
twiInitMaster:
push r16
; Clock
ldi r16,10 ;((F_CPU/TWI_CLOCK)-16)/2
out TWBR,r16
;TWI-Status-Register (Vorteiler)
ldi r16,0
out TWSR,r16
; Enable
ldi r16,0b11000100 ;_TWINT _TWEA _TWEN
out TWCR,r16
pop r16
ret
;------------------------------------------------------------------------
twiStart:
push r16
ldi r16,0b10100100 ; TWINT TWSTA TWEN
out TWCR,r16
rcall twiTWINTwarten ; warten bis TWINT gesetzt
pop r16
ret
;------------------------------------------------------------------------
twiStopp:
push r16
ldi r16,0b10010100 ; TWINT TWSTO TWEN
out TWCR,r16
pop r16
ret
;------------------------------------------------------------------------
twiWriteByte: ; Write Byte per TWI (ohne Interrupt)
push r16 ; Daten in Reg 16 übergeben
out TWDR,r16 ; Daten bereitlegen
ldi r16,0b11000100 ; TWINT TWEA TWEN (->ACK??)
out TWCR,r16 ; senden
rcall twiTWINTwarten ; warten bis TWINT gesetzt
pop r16
ret
;------------------------------------------------------------------------
twiTWINTwarten:
in r16,TWCR
sbrs r16,7 ; TWINT
rjmp twiTWINTwarten
ret
;------------------------------------------------------------------------------
AnzeigeRot: ;LED-Anzeige als Funktionstest


Slave
;Vorübung für Krabbler: Experimentierplatine an PC über USB, LCD-Erweiterung angeschlossen
;a- Zeichen, vom PC gesendet, werden auf dem LCD angezeigt --------------- erfolgreich beendet
;b- beide Experimentierplatinen über TWI verbinden, Daten von PC über beide Platinen auf LCD darstellen
;c- endgültige Krabblersoftware erstellen
;+-----------------------------------------------------------------------------
;| Titel : Krabbler - Vorübung b-
;+-----------------------------------------------------------------------------
;| Funktion : Empfang von Daten vom PC durch MCU, Übertragung auf andere MCU per TWI
;| : Ausgabe der Zeichen auf dem LCD-Modul
;| Schaltung : zwei MK2USB-Boards verbunden Port C4 und C5 (TWI) und Spannungsversorgung
;| : Netzteil angeschlossen
;| : Port D2 = RS, D3 = E, D4-7 = DB4-7, für LCD
;+-----------------------------------------------------------------------------
;| Prozessor : ATmega8
;| Takt : 3,6864 MHz
;| Sprache : Assembler
;| Datum : 4.4.2012
;| Version : 2 Teil b
;| Autor : U.S. / Routinen myAVR
;+-----------------------------------------------------------------------------
.include "AVR.H"
.equ F_CPU,3686400
.equ TWI_CLOCK,100000 ; Geschwindigkeit des TWI-Busses ca.
.equ FCPU,3686400
.equ BAUD,9600
.equ Temp,0x10 ; r16 wird zur Übergabe an Unterprogramme benutzt
.equ ZSP,0x13 ; r19 Zwischenspeicher für empfangene Zeichen
;-----------------------------------------------------------------------------
begin: rjmp main ; RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 External Interrupt Request 0
reti ; INT1 External Interrupt Request 1
reti ; TIMER2 COMP Timer/Counter2 Compare Match
reti ; TIMER2 OVF Timer/Counter2 Overflow
reti ; TIMER1 CAPT Timer/Counter1 Capture Event
reti ; TIMER1 COMPA Timer/Counter1 Compare Match A
reti ; TIMER1 COMPB Timer/Counter1 Compare Match B
reti ; TIMER1 OVF Timer/Counter1 Overflow
reti ; TIMER0 OVF Timer/Counter0 Overflow
reti ; SPI, STC Serial Transfer Complete
reti ; USART, RXC USART, Rx Complete
reti ; USART, UDRE USART Data Register Empty
reti ; USART, TXC USART, Tx Complete
reti ; ADC ADC Conversion Complete
reti ; EE_RDY EEPROM Ready
reti ; ANA_COMP Analog Comparator
reti ; TWI 2-wire Serial Interface
reti ; SPM_RDY Store Program Memory Ready
;------------------------------------------------------------------------------
main: ldi Temp,hi8(RAMEND) ; Main program start
out SPH,Temp ; Set Stack Pointer to top of RAM
ldi Temp,lo8(RAMEND)
out SPL,Temp
rcall LCD_init
rcall LCD_clear
rcall twiInitSlave
sbi DDRB,0
;------------------------------------------------------------------------------
mainloop: ; warten bis TWINT
in r16,TWCR
sbrs r16,7 ;TWINT gesetzt?
rjmp mainloop
rcall AnzeigeRot ;Funktionstest rote LED für 200 mS an
in r16,TWDR
;ldi r16,60 ; Testdaten
rcall LCD_data ; Zeichen aus Register16 auf LCD ausgeben
rjmp mainloop
;------------------------------------------------------------------------------
;LCD-Routinen ausgelassen - funktionsfähig
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
twiInitSlave:
push r16
ldi r16,0b11111110 ;TWI_Slave_Adresse ohne General Call
out TWAR,r16 ; Adressregister
ldi r16,0b11000101 ; TWINT TWEA TWEN TWIE
out TWCR,r16 ; Enable
pop r16
ret
;------------------------------------------------------------------------------
AnzeigeRot: ; LED für 200 mS an


U.

yvuu
05.04.2012, 22:39
Funktioniert jetzt.
Die bisher im Netz zu findenden Sourcecodes sind immer sehr umfangreich. Deswegen habe ich den Quellcode auf das Minimum reduziert, keine Fehlerroutinen etc.
Interrupts waren nicht gewünscht.
Der Teil Slave muss noch verbessert werden - drei Schleifen Mainloop sind nicht wirklich elegant.
Über Rückmeldungen oder Fragen werde ich mich freuen.
U.

Master:

; zwei ATMega8 sind per TWI verbunden

.equ ZSP,0x13 ; r19 Zwischenspeicher für empfangene Zeichen

;-----------------------------------------------------------------------------
begin: rjmp main ; RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 External Interrupt Request 0
reti ; INT1 External Interrupt Request 1
reti ; TIMER2 COMP Timer/Counter2 Compare Match
reti ; TIMER2 OVF Timer/Counter2 Overflow
reti ; TIMER1 CAPT Timer/Counter1 Capture Event
reti ; TIMER1 COMPA Timer/Counter1 Compare Match A
reti ; TIMER1 COMPB Timer/Counter1 Compare Match B
reti ; TIMER1 OVF Timer/Counter1 Overflow
reti ; TIMER0 OVF Timer/Counter0 Overflow
reti ; SPI, STC Serial Transfer Complete
reti ; USART, RXC USART, Rx Complete
reti ; USART, UDRE USART Data Register Empty
reti ; USART, TXC USART, Tx Complete
reti ; ADC ADC Conversion Complete
reti ; EE_RDY EEPROM Ready
reti ; ANA_COMP Analog Comparator
reti ; TWI 2-wire Serial Interface
reti ; SPM_RDY Store Program Memory Ready
;------------------------------------------------------------------------------
main: ldi Temp,hi8(RAMEND) ; Main program start
out SPH,Temp ; Set Stack Pointer to top of RAM
ldi Temp,lo8(RAMEND)
out SPL,Temp
;..................
rcall twiInitMaster
;------------------------------------------------------------------------------
mainloop: ; zu sendende Daten liegen im Register ZSP
rcall twiStart
ldi r16,0b11111110 ; Slave-Adresse + W
rcall twiWriteByte
mov r16,ZSP ; Zeichen wird in Register 16 an TWI-Schreibroutine übergeben
rcall twiWriteByte
rcall twiStopp
rjmp mainloop
;-----------------------------------------------------------------------------
twiInitMaster:
push r16
; Clock
ldi r16,10 ;((F_CPU/TWI_CLOCK)-16)/2
out TWBR,r16
;TWI-Status-Register (Vorteiler)
ldi r16,0
out TWSR,r16
; Enable
ldi r16,0b11000100 ;_TWINT _TWEA _TWEN
out TWCR,r16
pop r16
ret
;------------------------------------------------------------------------
twiStart:
push r16
ldi r16,0b10100100 ; TWINT TWSTA TWEN
out TWCR,r16
rcall twiTWINTwarten ; warten bis TWINT gesetzt
pop r16
ret
;------------------------------------------------------------------------
twiStopp:
push r16
ldi r16,0b10010100 ; TWINT TWSTO TWEN
out TWCR,r16
pop r16
ret
;------------------------------------------------------------------------
twiWriteByte:
push r16 ; Daten in Reg 16 übergeben
out TWDR,r16 ; Daten bereitlegen
ldi r16,0b10000100 ; TWINT TWEN
out TWCR,r16 ; senden
rcall twiTWINTwarten ; warten bis TWINT gesetzt
pop r16
ret
;------------------------------------------------------------------------
twiTWINTwarten:
in r16,TWCR
sbrs r16,7 ; TWINT
rjmp twiTWINTwarten
ret
;------------------------------------------------------------------------------



Slave:

.include "AVR.H"
.equ Temp,0x10 ; r16 wird zur Übergabe an Unterprogramme benutzt
;-----------------------------------------------------------------------------
begin: rjmp main ; RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 External Interrupt Request 0
reti ; INT1 External Interrupt Request 1
reti ; TIMER2 COMP Timer/Counter2 Compare Match
reti ; TIMER2 OVF Timer/Counter2 Overflow
reti ; TIMER1 CAPT Timer/Counter1 Capture Event
reti ; TIMER1 COMPA Timer/Counter1 Compare Match A
reti ; TIMER1 COMPB Timer/Counter1 Compare Match B
reti ; TIMER1 OVF Timer/Counter1 Overflow
reti ; TIMER0 OVF Timer/Counter0 Overflow
reti ; SPI, STC Serial Transfer Complete
reti ; USART, RXC USART, Rx Complete
reti ; USART, UDRE USART Data Register Empty
reti ; USART, TXC USART, Tx Complete
reti ; ADC ADC Conversion Complete
reti ; EE_RDY EEPROM Ready
reti ; ANA_COMP Analog Comparator
reti ; TWI 2-wire Serial Interface
reti ; SPM_RDY Store Program Memory Ready
;------------------------------------------------------------------------------
main: ldi Temp,hi8(RAMEND) ; Main program start
out SPH,Temp ; Set Stack Pointer to top of RAM
ldi Temp,lo8(RAMEND)
out SPL,Temp
;..................
rcall twiInitSlave
;------------------------------------------------------------------------------
mainloop: ; warten bis TWINT
in r16,TWCR
sbrs r16,7 ;TWINT
rjmp mainloop
;der Slave wurde adressiert
ldi r16,0b11000100 ; TWINT TWEA TWEN ->ACK an Master
out TWCR,r16
ml2: in r16,TWCR
sbrs r16,7 ;TWINT
rjmp ml2
in r20,TWDR ; Daten sind eingetroffen
ldi r16,0b11000100 ; TWINT TWEA TWEN ->ACK an Master
out TWCR,r16
ml3: in r16,TWCR
sbrs r16,7 ;TWINT
rjmp ml3
;Stoppbedingung muss quittiert werden
ldi r16,0b11000100 ; TWINT TWEA TWEN ->ACK an Master
out TWCR,r16

; die empfangenen Daten liegen jetzt in Register R20 zur weiteren Verarbeitung
rjmp mainloop
;------------------------------------------------------------------------------
twiInitSlave: ;ohne Interrupt
push r16
ldi r16,0b11111110 ;TWI_Slave_Adresse ohne General Call
out TWAR,r16 ; Adressregister
ldi r16,0b01000100 ; TWEA TWEN
out TWCR,r16 ; Enable
pop r16
ret