Forum: Mikrocontroller und Digitale Elektronik I²C über SPI an ATtiny ?


von André M. (killroymenzel)


Lesenswert?

hallo,

gibt es eigentlich ein I²C interface für SPI?

Ich wollte ein I²C Temperatursensor mit einem ATtiny auslesen.

Oder gibt es andere möglichkeiten dies zu realisieren?

Ich würde ja gerne einen grösseren Proz nehmen, der das Interface schon 
von Hause aus mitbringt, aber habe derbe Platzprobleme, dass nur ein 
"kleiner" (Gehäuseform) Proz sein soll.

von Marcus P. (marc2100)


Lesenswert?

Hi,
also wenn du wirklich Platzprobleme hast, wieso willst du dann noch ein 
extra IC draufpacken?
Du kannst das I2C-Interface auch in Software laufen lassen, das wäre das 
Platzsparendste.

Gruß
Marcus

von André M. (killroymenzel)


Lesenswert?

Da habe ich noch gar nicht daran gedacht....Danke..

Hast Du zufälligerweise ein Assembler Beispiel?

von Marcus P. (marc2100)


Lesenswert?

leider nein, kann selbst nur C, und nehme daher meist "größere" ARVs.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Je nach Tiny gibs da nen USI, das kannste für UART oder I2C nutzen.
Steht im DB wie man das programmiert.
Beispiele gibs im Inet.

von H.Joachim S. (crazyhorse)


Lesenswert?

Wollte gerade fragen -welcher Tiny hat denn SPI, aber kein TWI??
Mir fällt keiner ein.

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

>Hast Du zufälligerweise ein Assembler Beispiel?

Gab mal eine App-Note von Atmel.

MfG Spess

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Tiny 13/15/24/25/87/2313
Haben SPI aber kein TWI (eher nen USI was TWI kann)

Der Tiny20 hätte SPI und TWI

von Steffen H. (Gast)


Lesenswert?

Hallo,

Hier mal meine Software I2C Routinen in ASM. Als Beispiel wird hier ein 
Temperatursensor LM92 verwendet.
1
; I2C-Ein-/Ausgänge:
2
.equ  I2C_PORT  = PORTA
3
.equ  SDA       = PA0  ; SDA = PortA/Bit0
4
.equ  SCL       = PA1  ; SCL = PortA/Bit1
5
6
; I2C-Slave-Adressen:
7
.equ  LM92_addr   = 0x4B  ; Adresse des Temperatursensors
8
9
10
11
12
13
;***************************** I2C MACROS **********************************
14
15
.macro SCL_Up      ; steigende Flanke von SCL
16
  cbi  I2C_PORT-1,SCL  ; SCL = hochohmig
17
.endmacro
18
19
.macro SCL_Dwn      ; fallende Flanke von SCL
20
  sbi  I2C_PORT-1,SCL  ; SCL = log. 0
21
.endmacro
22
23
.macro SDA_Hi      ; setzt SDA auf 1
24
  cbi  I2C_PORT-1,SDA  ; SDA = hochohmig
25
.endmacro
26
27
.macro SDA_Lo      ; setzt SDA auf 0
28
  sbi  I2C_PORT-1,SDA  ; SDA = log. 0
29
.endmacro
30
31
32
;************************** Sensor Temperatur ******************************
33
; Sub: Liest Temperatur vom Sensor
34
; Parameter:  -
35
; Return:  Temperatur TEMP_H, TEMP_L
36
; Scratch-Reg:  r16, r17
37
;***************************************************************************
38
39
read_temperatur:
40
    ldi  r16, LM92_addr
41
    clc      ; I2C Write
42
    rol  r16
43
    rcall  i2c_start  ; Start + I2C Adresse + Write senden
44
    in  r16, SREG
45
    sbrs  r16,SREG_T
46
    rjmp  no_sensor  ; NACK: Sensor nicht ansprechbar
47
    clr  r16
48
    rcall  i2c_write  ; Pointerregister -> TemperaturRegister LM92
49
    in  r16, SREG
50
    sbrs  r16,SREG_T
51
    rjmp  no_sensor
52
    ldi  r16, LM92_addr
53
    sec      ; I2C Read
54
    rol  r16
55
    rcall  i2c_rep_start  ; Start + I2C Adresse + Read senden
56
    in  r16, SREG
57
    sbrs  r16,SREG_T
58
    rjmp  no_sensor  ; NACK: Sensor nicht ansprechbar
59
    set
60
    rcall  i2c_read
61
    sts  TEMP_MSB,r16
62
    clt
63
    rcall  i2c_read
64
    sts  TEMP_LSB,r16
65
    rcall  i2c_stop
66
    ret
67
no_sensor:
68
    ret
69
70
71
#ifdef  LM92_SHUTDOWN
72
;************************** Sensor Temperatur ******************************
73
; Sub: Setzt den LM92 in Shutdown
74
; Parameter:  -
75
; Return:    
76
; Scratch-Reg:  r16, r17
77
;***************************************************************************
78
79
LM92_shutdown_on:
80
    ldi  r16, LM92_addr
81
    clc      ; I2C Write
82
    rol  r16
83
    rcall  i2c_start  ; Start + I2C Adresse + Write senden
84
    in  r16, SREG
85
    sbrs  r16,SREG_T
86
    rjmp  no_sensor; NACK: Sensor nicht ansprechbar
87
    ldi  r16,1    ; Pointerregister -> ConfigurationRegister LM92
88
    rcall  i2c_write
89
    in  r16, SREG
90
    sbrs  r16,SREG_T
91
    rjmp  no_sensor
92
    ldi  r16,1    ; ConfigurationRegister LM92 -> set Shutdown Bit
93
    rcall  i2c_write
94
    in  r16, SREG
95
    sbrs  r16,SREG_T
96
    rjmp  no_sensor
97
    rcall  i2c_stop
98
    ret
99
100
101
LM92_shutdown_off:
102
    ldi  r16, LM92_addr
103
    clc      ; I2C Write
104
    rol  r16
105
    rcall  i2c_start  ; Start + I2C Adresse + Write senden
106
    in  r16, SREG
107
    sbrs  r16,SREG_T
108
    rjmp  no_sensor  ; NACK: Sensor nicht ansprechbar
109
    ldi  r16,1  ; Pointerregister -> ConfigurationRegister LM92
110
    rcall  i2c_write
111
    in  r16, SREG
112
    sbrs  r16,SREG_T
113
    rjmp  no_sensor
114
    ldi  r16,0  ; ConfigurationRegister LM92 -> clear Shutdown Bit
115
    rcall  i2c_write
116
    in  r16, SREG
117
    sbrs  r16,SREG_T
118
    rjmp  no_sensor
119
    rcall  i2c_stop
120
    ret
121
#endif
122
123
;************************** Software I2C Routinen **************************
124
wait1us:    ; @ 8Mhz
125
  nop
126
  ret
127
128
i2c_init:
129
  cbi  I2C_PORT, SCL
130
  cbi  I2C_PORT, SDA
131
  SCL_Up
132
  SDA_Hi
133
  ret  
134
135
i2c_rep_start:      ; Wiederholen der Startbedingung
136
  SCL_Dwn      ; setzt SCL auf 0
137
  rcall   wait1us    ; Zeitschleife
138
  nop
139
  nop
140
  nop
141
  SCL_up      ; setzt SCL auf 1
142
  rcall   wait1us    ; Zeitschleife
143
  nop
144
  nop
145
  nop
146
i2c_start:        
147
  SDA_Lo      ; SDA = 0: Startbedingung
148
  rcall   wait1us    ; Zeitschleife
149
  rcall   wait1us
150
151
i2c_write:      ; schreibt ein Byte zum Slave
152
  sec      ; Carry = 1
153
  rol     r16    ; nach links schieben, 1->LSB, MSB->C
154
  rjmp    i2c_bit1  ; Sonderbehandlung für das 1. Bit
155
156
i2c_wr_bit:
157
  lsl     r16    ; wenn r16 leer ist, ...
158
i2c_bit1:
159
  breq    i2c_get_ack  ; ... ist der Transfer abgeschlossen
160
  SCL_Dwn      ; fallende Flanke von SCL
161
  brcc    i2c_wr_low  ; Sprung, wenn Bit im Carry = 0
162
  nop      ; zum Ausgleich der Laufzeiten
163
  SDA_Hi      ; setzt SDA auf 1
164
  rjmp    i2c_scl_high
165
i2c_wr_low:
166
  SDA_Lo      ; setzt SDA auf 0
167
  rjmp    i2c_scl_high; zum Ausgleich der Taktzeiten
168
169
i2c_scl_high:
170
  rcall   wait1us
171
  SCL_Up      ; steigende Flanke von SCL
172
i2c_WB1:
173
  sbis    I2C_PORT-2,SCL  ; Wait-State des Slaves ?
174
  rjmp    i2c_WB1
175
  rcall   wait1us    ; Zeitschleife
176
  rjmp    i2c_wr_bit
177
178
i2c_get_ack:      ; Acknowledge des Slaves einlesen
179
  SCL_Dwn      ; fallende Flanke von SCL
180
  SDA_Hi      ; setzt SDA hochohmig
181
  rcall   wait1us    ; Zeitschleife
182
  nop
183
  nop
184
  nop
185
  SCL_Up      ; steigende Flanke von SCL
186
i2c_GA1:  
187
  sbis    I2C_PORT-2,SCL  ; Test, ob Wait-State des Slaves
188
  rjmp    i2c_GA1
189
  clt      ; Ack-Flag = 0 (T-Flag in SREG)  [NACK]
190
  sbis    I2C_PORT-2,SDA  ; wenn SDA = 1,
191
  set         ; Ack-Flag = 1 (T-Flag in SREG) [ACK]
192
  rcall   wait1us    ; Zeitschleife
193
  ret
194
195
i2c_read:
196
  ldi     r16,1    ; als Bitzähler vorbesetzen
197
i2c_RB1:
198
  SCL_Dwn      ; fallende Flanke von SCL
199
  SDA_Hi      ; setzt SDA hochohmig
200
  rcall  wait1us    ; Zeitschleife 5us
201
  nop
202
  nop
203
  nop
204
  SCL_Up      ; steigende Flanke von SCL
205
206
i2c_RB2:
207
  sbis    I2C_PORT-2,SCL   ; Test, ob Wait-State des Slaves
208
  rjmp    i2c_RB2
209
  clc      ; Carry = 0
210
  sbic    I2C_PORT-2,SDA   ; wenn SDA = 1
211
  sec      ;   Carry = 1
212
  rcall   wait1us    ; Zeitschleife
213
  nop
214
  rol     r16    ; gelesenes Bit ins Byte schieben
215
  brcc    i2c_RB1    ; Sprung, wenn Einlesen nicht beendet
216
217
i2c_ack:      ; gibt Acknowledge aus
218
  SCL_Dwn      ; fallende Flanke von SCL
219
  in  r17, SREG
220
  sbrc    r17,SREG_T  ; Skip, wenn ACK = 1
221
  rjmp    i2c_SA1    ; Sprung, wenn NACK = 0
222
  nop
223
  SDA_Hi      ; setzt SDA auf 1
224
  rjmp    i2c_SA2
225
i2c_SA1:
226
  SDA_Lo      ; setzt SDA auf 0
227
  nop      ; zum Ausgleich der Taktzeiten
228
  nop      ; zum Ausgleich der Taktzeiten
229
i2c_SA2:
230
  rcall  wait1us
231
  SCL_Up      ; steigende Flanke von SCL
232
i2c_SA3:
233
  sbis    I2C_PORT-2,SCL   ; Test, ob Wait-State des Slaves
234
  rjmp    i2c_SA3
235
  rcall   wait1us    ; Zeitschleife
236
  ret
237
238
i2c_stop:      ; gibt Stopp-Bedingung aus
239
  SCL_Dwn      ; fallende Flanke von SCL
240
  SDA_Lo      ; setzt SDA auf 0
241
  rcall   wait1us    ; Zeitschleife
242
  nop
243
  nop
244
  nop
245
  SCL_Up      ; steigende Flanke von SCL
246
  rcall   wait1us    ; Zeitschleife
247
  SDA_Hi      ; setzt SDA auf 1
248
  rcall   wait1us    ; Zeitschleife
249
  nop
250
  ret

Denke daran, dass hier noch keine Variablen im RAM angelegt sind 
(TEMP_LSB/TEMP_MSB) da es sich hier um eine Include Datei handelt. Den 
kompletten Code findest du hier:
Beitrag "[ASM] RFM02 sendet an RFM01 Sensor Daten"

Gruß Steffen

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.