www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik TWI Source Code


Autor: Beat (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: HenrikJ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Öööhhhh.... Musst du vielleicht noch das Interrupt System aktivieren?!
Will selber bald mit WI anfangen.
Also mal an sei() einhacken.

Autor: Beat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte diese Problem nicht mit Interrupts lösen (sollte doch gehen,
oder?)

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest vielleicht noch abfragen, ob die Stop-Condition auch
erfolgreich war.

Autor: Beat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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]

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry jetzt nochmal richtig den code:

;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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.