Forum: Mikrocontroller und Digitale Elektronik TWI Source Code


von Beat (Gast)


Angehängte Dateien:

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

von HenrikJ (Gast)


Lesenswert?

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

von Beat (Gast)


Lesenswert?

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

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Du solltest vielleicht noch abfragen, ob die Stop-Condition auch
erfolgreich war.

von Beat (Gast)


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...

von Philip K. (praktikant)


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

von Fabian (Gast)


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]

von Fabian (Gast)


Lesenswert?

Sorry jetzt nochmal richtig den code:
1
;LM75 data
2
.EQU LM75_1_T_HYST    = 57      ; 57 centigrade
3
.EQU LM75_1_T_OS    = 60      ; 60 centigrade
4
.EQU LM75_1_WRITE    = 0b10010000  ; Write address for first LM75
5
.EQU LM75_1_READ    = 0b10010001  ; Read  address for first LM75
6
7
; TWI data
8
.EQU TWI_BIT_RATE    = 48      ; Bit-Rate  (1...255)
9
.EQU TWI_PRESCALER    = $1      ; Prescaler: 0=1 1=4 2=16 3=64
10
11
;*****************************************************************
12
13
;               TWI ROUTINES
14
15
;*****************************************************************
16
17
; SET POINTER ON LM75
18
TEMP_READ_POINTER:
19
  rcall  TWI_START        ; ...jump
20
  ; STATUSKONTROLLE
21
  rcall  TWI_LM75_1_WRITE    ; ...jump
22
  ; STATUSKONTROLLE
23
  ldi    r16,$00          ; r16 = 0
24
  out    TWDR,r16        ; TWI data register on AT8 = 0
25
  rcall  TWI_DATA        ; send data to LM75, pointer on LM75 = 0
26
  ; STATUSKONTROLLE
27
; READ TEMPERATURE ON LM75, POINTER MUST BE SET!
28
TEMP_READ:
29
  rcall  TWI_START        ; ...jump
30
  ; STATUSKONTROLLE
31
  rcall  TWI_LM75_1_READ      ; ...jump
32
  ; STATUSKONTROLLE
33
  ldi    r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN)  ; start Transfer,
34
                    ; send ACK after communication
35
  out    TWCR,r16
36
  rcall  CHECK_TWINT          ; ...jump
37
  in    r15,TWDR          ; TEMPERATURE NOW IN r15 (HIGHBYTE)
38
  ; STATUSKONTROLLE
39
  ldi   r16, (1<<TWINT) | (0<<TWEA)  | (1<<TWEN); start transfer,
40
                    ; send NACK after communication
41
  out   TWCR, r16          ; ...jump
42
  rcall  CHECK_TWINT          ; ...jump
43
  in    r14,TWDR          ; TEMPERATURE NOW IN r15 (LOWBYTE)
44
  ; STATUSKONTROLLE
45
  rcall  TWI_STOP          ; ...jump
46
  ; STATUSKONTROLLE
47
  ret                  ; go back
48
49
; CHECK TWINT bit @AT8 (transfer complete?)
50
CHECK_TWINT:
51
  in    r16,TWCR        ; r16 = TWCR (two wire control register)
52
  sbrs  r16,TWINT        ; check if bit 7 (TWINT) = 1
53
  rjmp  CHECK_TWINT        ; yes: go back, no: loop
54
  ret
55
56
; LOAD LM75 address and readbit in TW data register
57
TWI_LM75_1_READ:
58
  ldi    r16,LM75_1_READ
59
  out    TWDR,r16
60
  rcall  TWI_DATA
61
  ret
62
63
; LOAD LM75 address and writebit in TW data register
64
TWI_LM75_1_WRITE:
65
  ldi    r16,LM75_1_WRITE
66
  out    TWDR,r16
67
  rcall  TWI_DATA
68
  ret
69
70
; START TWI COMMUNICATION (address must be in TWDR)
71
TWI_START:
72
  ldi    r16,(1<<TWINT) | (1<<TWSTA) | (1<<TWEN)
73
  out    TWCR,r16
74
  rcall  CHECK_TWINT
75
  ret
76
77
; STOP TWI COMMUNICATION
78
TWI_STOP:
79
  ldi    r16,(1<<TWINT) | (1<<TWSTO) | (1<<TWEN)
80
  out    TWCR,r16            ; send STOP
81
  ret
82
83
; SEND DATA
84
TWI_DATA:
85
  ldi    r16,(1<<TWINT) | (1<<TWEN)
86
  out    TWCR,r16
87
  rcall  CHECK_TWINT
88
  ret
89
90
; initialise TWI
91
TWI_INIT:
92
  ldi    r16,TWI_BIT_RATE
93
  out    TWBR,r16
94
  ldi    r16,TWI_PRESCALER
95
  out   TWSR,r16
96
;set T_hyst
97
  rcall  TWI_START
98
  ;STATUSKONTROLLE
99
  rcall   TWI_LM75_1_WRITE
100
  ;STATUSKONTROLLE
101
  ldi    r16,0b00000010            ; r16 = LM75 pointeraddress
102
  out    TWDR,r16
103
  rcall  TWI_DATA              ; set pointer = T_HYST
104
  ;STATUSKONTROLLE
105
  ldi    r16,LM75_1_T_HYST
106
  out    TWDR,r16
107
  rcall  TWI_DATA              ; send MS databyte
108
  ;STATUSKONTROLLE
109
  out    TWDR,r17
110
  rcall  TWI_DATA              ; send LS databyte
111
  ;STATUSKONTROLLE
112
  rcall  TWI_STOP              ; STOP TWI
113
;read T_hyst (pointer is set)
114
  rcall  WAIT_5ms              ; wait for TW BUS
115
  rcall  TWI_START              ; START TWI
116
  rcall  TWI_LM75_1_READ            ; ...jump
117
  ldi    r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN)  ; receive data and send
118
ACK
119
  out    TWCR,r16
120
  rcall  CHECK_TWINT
121
  in    r15,TWDR              ; T_hyst (highbyte) now on r15
122
  ; STATUSKONTROLLE
123
  ldi   r16, (1<<TWINT) | (0<<TWEA)  | (1<<TWEN)
124
  out   TWCR, r16
125
  rcall  CHECK_TWINT        ; T_hyst lowbyte not needed but received
126
                  ; !!! required !!!
127
  ; STATUSKONTROLLE
128
  rcall  TWI_STOP
129
  ; STATUSKONTROLLE
130
  mov    r16,r15
131
  rcall  BCD_start            ; start BCD
132
; write T_hyst (fan stop) on LCD
133
  ldi    r16,193
134
  mov    r22,r18
135
  rcall  LCD_TEST
136
  ldi    r16,194
137
  mov    r22,r19
138
  rcall  LCD_TEST
139
  ldi    r16,195
140
  ldi    r22,254          ; write .
141
  rcall  LCD_TEST
142
  ldi    r16,196
143
  ldi    r22,0
144
  rcall  LCD_TEST
145
  ldi    r22,'C'-48
146
  ldi    r16,198
147
  rcall  LCD_TEST
148
; write T_os
149
  rcall   TWI_START
150
  ;STATUSKONTROLLE
151
  rcall   TWI_LM75_1_WRITE
152
  ;STATUSKONTROLLE
153
  ldi    r16,0b00000011
154
  out    TWDR,r16
155
  rcall  TWI_DATA        ; set pointer = T_OS
156
  ;STATUSKONTROLLE
157
  ldi    r16,LM75_1_T_OS
158
  out    TWDR,r16
159
  rcall  TWI_DATA
160
  ;STATUSKONTROLLE
161
  out    TWDR,r17
162
  rcall  TWI_DATA
163
  ;STATUSKONTROLLE
164
  rcall  TWI_STOP
165
  rcall  WAIT_5ms
166
; read T_os (pointer is set)
167
  rcall  TWI_START
168
  rcall  TWI_LM75_1_READ
169
  ldi    r16,(1<<TWINT) | (1<<TWEA) | (1<<TWEN)
170
  out    TWCR,r16
171
  rcall  CHECK_TWINT
172
  in    r15,TWDR
173
  ; STATUSKONTROLLE
174
  ldi   r16, (1<<TWINT) | (0<<TWEA)  | (1<<TWEN)
175
  out   TWCR, r16
176
  rcall  CHECK_TWINT
177
178
  ; STATUSKONTROLLE
179
  rcall  TWI_STOP
180
  ; STATUSKONTROLLE
181
  mov    r16,r15
182
  rcall  BCD_start
183
; write T_os (fan start) on LCD
184
  ldi    r16,173
185
  mov    r22,r18
186
  rcall  LCD_TEST
187
  ldi    r16,174
188
  mov    r22,r19
189
  rcall  LCD_TEST
190
  ldi    r16,175
191
  ldi    r22,254          ; write .
192
  rcall  LCD_TEST
193
  ldi    r16,176
194
  ldi    r22,0
195
  rcall  LCD_TEST
196
  ldi    r22,'C'-48
197
  ldi    r16,178
198
  rcall  LCD_TEST
199
  ret

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.