Hallo zusammen
Ich bin Anfänger im C programmieren.
Ich wollter das TWI Interface des ATmega64L ausprobieren und in Betrieb
nehmen. Dabei schrieb ich mit Hilfe der Programmbesipiele von Atmel
(auch andere Bsp.) den Source code im Anhang.
Dies funktioniert aber in keiner Weise! Der Chip sendet nicht einmal
eine Start Condition!
Ich habe meinen Code mit vielen verschiedenen Bsp. codes verglichen und
finde keinen Fehler.
Vieleicht wais jo jemand von euch was ich falsch mache!
Mit freundlichen Grüssen Beat
Ja da gebe ich dir recht! Aber er sendet sie ja gar nicht! Das konnte
ich messen! Und wenn er sie gar nicht sendet, nützt es auch nicht viel
wenn ich abfrag ob die Start Condition gesendet wurde..
Ist halt meine erste Programmversion für TWI und nur zum ausprobieren
gedacht...
Also funkioniert TWI ohne Interrupt-Conditions gar nicht?! Egal wie?!
Auch wenn ich nur ein Display ansteuern will, welches ja selber keine
Signale zurückgibt?!
Gruß
der Praktikant
Also mit dem TWI Interface habe ich damals auch etwas länger
rumgeknobelt und es ist nicht gerade meine Lieblingsübertragungsart ;)
Schließlich hats dann funktioniert.
Folgender Code ist für eine Datenübertragung zwischen einem Atmega8
(Master; 4 MHz) und einem LM75 Tempfühler.
das ganze wurde mit einem Timer ausgelöst, der alle 4 Sekunden die
Temperatur erneut abgefragt hat.
Du solltest darauf achten, zwischen den TWI Durchläufen ein paar ms
pause einzulegen. Zwar steht in der TWI Anleitung, dass der Slave die
Datenübertragung verlangsamen kann, indem er einfach den clock gegen
Masse zieht aber in meiner Anwendung hat das nicht so super geklappt und
mein Tempfühler hat sich aufgehängt, somit hing auch das Programm, da
ich keinen Schutzmechanismus mit Watchdogtimer oder sonstwas eingebaut
habe.
[AVRSAM]
;LM75 data
.EQU LM75_1_T_HYST = 57 ; 57 centigrade
.EQU LM75_1_T_OS = 60 ; 60 centigrade
.EQU LM75_1_WRITE = 0b10010000 ; Write address for first LM75
.EQU LM75_1_READ = 0b10010001 ; Read address for first LM75
; TWI data
.EQU TWI_BIT_RATE = 48 ; Bit-Rate (1...255)
.EQU TWI_PRESCALER = $1 ; Prescaler: 0=1 1=4 2=16 3=64
;*****************************************************************
; TWI ROUTINES
;*****************************************************************
; SET POINTER ON LM75
TEMP_READ_POINTER:
rcall TWI_START ; ...jump
; STATUSKONTROLLE
rcall TWI_LM75_1_WRITE ; ...jump
; STATUSKONTROLLE
ldi r16,$00 ; r16 = 0
out TWDR,r16 ; TWI data register on AT8 = 0
rcall TWI_DATA ; send data to LM75, pointer on LM75 = 0
; STATUSKONTROLLE
; READ TEMPERATURE ON LM75, POINTER MUST BE SET!
TEMP_READ:
rcall TWI_START ; ...jump
; STATUSKONTROLLE
rcall TWI_LM75_1_READ ; ...jump
; STATUSKONTROLLE
ldi r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN) ; start Transfer,
; send ACK after communication
out TWCR,r16
rcall CHECK_TWINT ; ...jump
in r15,TWDR ; TEMPERATURE NOW IN r15 (HIGHBYTE)
; STATUSKONTROLLE
ldi r16, (1<<TWINT) | (0<<TWEA) | (1<<TWEN); start transfer,
; send NACK after communication
out TWCR, r16 ; ...jump
rcall CHECK_TWINT ; ...jump
in r14,TWDR ; TEMPERATURE NOW IN r15 (LOWBYTE)
; STATUSKONTROLLE
rcall TWI_STOP ; ...jump
; STATUSKONTROLLE
ret ; go back
; CHECK TWINT bit @AT8 (transfer complete?)
CHECK_TWINT:
in r16,TWCR ; r16 = TWCR (two wire control register)
sbrs r16,TWINT ; check if bit 7 (TWINT) = 1
rjmp CHECK_TWINT ; yes: go back, no: loop
ret
; LOAD LM75 address and readbit in TW data register
TWI_LM75_1_READ:
ldi r16,LM75_1_READ
out TWDR,r16
rcall TWI_DATA
ret
; LOAD LM75 address and writebit in TW data register
TWI_LM75_1_WRITE:
ldi r16,LM75_1_WRITE
out TWDR,r16
rcall TWI_DATA
ret
; START TWI COMMUNICATION (address must be in TWDR)
TWI_START:
ldi r16,(1<<TWINT) | (1<<TWSTA) | (1<<TWEN)
out TWCR,r16
rcall CHECK_TWINT
ret
; STOP TWI COMMUNICATION
TWI_STOP:
ldi r16,(1<<TWINT) | (1<<TWSTO) | (1<<TWEN)
out TWCR,r16 ; send STOP
ret
; SEND DATA
TWI_DATA:
ldi r16,(1<<TWINT) | (1<<TWEN)
out TWCR,r16
rcall CHECK_TWINT
ret
; initialise TWI
TWI_INIT:
ldi r16,TWI_BIT_RATE
out TWBR,r16
ldi r16,TWI_PRESCALER
out TWSR,r16
;set T_hyst
rcall TWI_START
;STATUSKONTROLLE
rcall TWI_LM75_1_WRITE
;STATUSKONTROLLE
ldi r16,0b00000010 ; r16 = LM75 pointeraddress
out TWDR,r16
rcall TWI_DATA ; set pointer = T_HYST
;STATUSKONTROLLE
ldi r16,LM75_1_T_HYST
out TWDR,r16
rcall TWI_DATA ; send MS databyte
;STATUSKONTROLLE
out TWDR,r17
rcall TWI_DATA ; send LS databyte
;STATUSKONTROLLE
rcall TWI_STOP ; STOP TWI
;read T_hyst (pointer is set)
rcall WAIT_5ms ; wait for TW BUS
rcall TWI_START ; START TWI
rcall TWI_LM75_1_READ ; ...jump
ldi r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN) ; receive data and send
ACK
out TWCR,r16
rcall CHECK_TWINT
in r15,TWDR ; T_hyst (highbyte) now on r15
; STATUSKONTROLLE
ldi r16, (1<<TWINT) | (0<<TWEA) | (1<<TWEN)
out TWCR, r16
rcall CHECK_TWINT ; T_hyst lowbyte not needed but received
; !!! required !!!
; STATUSKONTROLLE
rcall TWI_STOP
; STATUSKONTROLLE
mov r16,r15
rcall BCD_start ; start BCD
; write T_hyst (fan stop) on LCD
ldi r16,193
mov r22,r18
rcall LCD_TEST
ldi r16,194
mov r22,r19
rcall LCD_TEST
ldi r16,195
ldi r22,254 ; write .
rcall LCD_TEST
ldi r16,196
ldi r22,0
rcall LCD_TEST
ldi r22,'C'-48
ldi r16,198
rcall LCD_TEST
; write T_os
rcall TWI_START
;STATUSKONTROLLE
rcall TWI_LM75_1_WRITE
;STATUSKONTROLLE
ldi r16,0b00000011
out TWDR,r16
rcall TWI_DATA ; set pointer = T_OS
;STATUSKONTROLLE
ldi r16,LM75_1_T_OS
out TWDR,r16
rcall TWI_DATA
;STATUSKONTROLLE
out TWDR,r17
rcall TWI_DATA
;STATUSKONTROLLE
rcall TWI_STOP
rcall WAIT_5ms
; read T_os (pointer is set)
rcall TWI_START
rcall TWI_LM75_1_READ
ldi r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN)
out TWCR,r16
rcall CHECK_TWINT
in r15,TWDR
; STATUSKONTROLLE
ldi r16, (1<<TWINT) | (0<<TWEA) | (1<<TWEN)
out TWCR, r16
rcall CHECK_TWINT
; STATUSKONTROLLE
rcall TWI_STOP
; STATUSKONTROLLE
mov r16,r15
rcall BCD_start
; write T_os (fan start) on LCD
ldi r16,173
mov r22,r18
rcall LCD_TEST
ldi r16,174
mov r22,r19
rcall LCD_TEST
ldi r16,175
ldi r22,254 ; write .
rcall LCD_TEST
ldi r16,176
ldi r22,0
rcall LCD_TEST
ldi r22,'C'-48
ldi r16,178
rcall LCD_TEST
ret
[/AVRASM]