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
|