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.
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
Da habe ich noch gar nicht daran gedacht....Danke.. Hast Du zufälligerweise ein Assembler Beispiel?
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.
Wollte gerade fragen -welcher Tiny hat denn SPI, aber kein TWI?? Mir fällt keiner ein.
Hi
>Hast Du zufälligerweise ein Assembler Beispiel?
Gab mal eine App-Note von Atmel.
MfG Spess
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.