Hallo liebe Gemeinde, Ich habe eine kleine Hardware angefertigt, bestehend aus: - einer Platine mit einem LM75-Temperatursensor - einer µC-Platine mit einem PIC16F877A - und einem LC-Display Soweit funktionierte auch alles ganz gut, 1x kann ich die Temperatur korrekt einlesen, auch die Ausgabe am Display geht. Wiederholt sich nun aber die Schleife zum ersten Mal (nach ca. 5 Sekunden Pause) treten schier willkürlich folgende Ergebnisse auf: - der Wert wird weitere ein- oder zweimal eingelesen, danach friert alles ein - der Wert wird noch einmal eingelesen, die Logik friert jedoch schon beim freigeben des Bus ein Mache ich einen Reset über den !MCLR ist kann er den Bus nicht einmal mehr übernehmen. Auch wenn ich die Versorgungsspannung entferne und wieder anlege ergeben sich die zwei oben genannten Zustände. Hat jemand vielleicht schon einmal ein solches oder ähnliches Problem gehabt? (Ich vermute es hat etwas mit dem Freigeben des Bus zu tun, ich bin mir aber nicht sicher.) Ich werde morgen noch meine Routine zum Freigeben posten. Vielen Dank im Voraus, Peter
Viel mehr als (auf) die Routine zu (warten) sehen, würde uns alle das Schaltbild interessieren. I2C ist nicht so ganz ohne. Machst Du es in Software oder in Hardware ? Der uC kann ja beides. Und bei der Hardware-Lösung gibt es einige Fehler, die man machen kann.
>Mache ich einen Reset über den !MCLR ist kann er den Bus nicht einmal >mehr übernehmen. Dann hat der LM75 wohl schon aufgegeben. Pullups an SDA und SCL sind vorhanden?
I2C braucht relativ starke Pullups, so um die 1k können nicht schaden. 3,3 oder 5 Volt ? Die empfohlene I2C Reset Routine ist m.W. ausgeben von mindestens 9 SCL Pulsen bei inaktivem ( high ) SDA, können aber evtl. noch mehr sein.
Ich steuere den Bus harwaremäßig mit den vom µC bereitgestellten Mitteln. Pull-Up's sind vorhanden, allerdings sind es 4k7. Der Sensor ist übrigens ein 5V-Typ. Hier der ganze Code, vielleicht fällt jemandem der Fehler auf?
1 | errorlevel -203 ;These removes unwanted warnings |
2 | errorlevel -205 ;from the compile information listing |
3 | errorlevel -207 |
4 | errorlevel -301 |
5 | errorlevel -302 |
6 | |
7 | __config h'3f39' |
8 | |
9 | list p=16f877 |
10 | include <p16f877.inc> |
11 | include <lcd.inc> |
12 | |
13 | ;----------------------------------------------------------------------------------------- |
14 | ; Deklarationen |
15 | ;----------------------------------------------------------------------------------------- |
16 | TMR1CONF1 equ B'00001101' ;Konfiguration für Timer 1 |
17 | TEMP equ 0x20 ;Hilfsregister |
18 | MSByte equ 0x21 |
19 | LSByte equ 0x22 |
20 | REPEAT equ 0x29 |
21 | LM75ADDRESS equ B'10010001' ;Adresse des LM75 + R/W-Bit |
22 | |
23 | h equ 0x23 |
24 | z equ 0x24 |
25 | e equ 0x25 |
26 | |
27 | TEMPByte equ 0x26 |
28 | TEMPByte1 equ 0x27 |
29 | TEMPByte2 equ 0x28 |
30 | |
31 | COUNT1 equ 0x30 |
32 | COUNT2 equ 0x31 |
33 | |
34 | lcdnumberprefix equ b'00110000' |
35 | gradzeichen equ b'11011111' |
36 | |
37 | ;----------------------------------------------------------------------------------------- |
38 | ; Adresszuteilungen |
39 | ;----------------------------------------------------------------------------------------- |
40 | |
41 | org 0x00 ;Startadresse |
42 | |
43 | ;----------------------------------------------------------------------------------------- |
44 | main ;Hauptprogramm |
45 | ;----------------------------------------------------------------------------------------- |
46 | |
47 | call picinit |
48 | |
49 | call lcdinit |
50 | |
51 | call iicinit |
52 | |
53 | call waitwhilestartup |
54 | |
55 | hauptschleife |
56 | |
57 | movlw LCDDISPLAYCLEAR |
58 | |
59 | call lcdsendinstruction |
60 | |
61 | call iicrepeatbus |
62 | |
63 | call iicsendaddress |
64 | |
65 | call iicreadvalue |
66 | |
67 | call lcdsendtemp |
68 | |
69 | call iicreleasebus |
70 | |
71 | call warte15sekunden |
72 | |
73 | goto hauptschleife |
74 | |
75 | |
76 | ;----------------------------------------------------------------------------------------- |
77 | iicinit ;Initialisierung des IIC-Moduls |
78 | ;----------------------------------------------------------------------------------------- |
79 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
80 | movlw d'9' |
81 | movwf SSPADD ;Teiler für 100kHz bei 4MHz-Takt laden |
82 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
83 | |
84 | movlw B'00001000' |
85 | movwf SSPCON |
86 | |
87 | bsf SSPCON, SSPEN ;MSSP-Modul einschalten |
88 | |
89 | return |
90 | |
91 | ;----------------------------------------------------------------------------------------- |
92 | iicgetbus ;Übernehmen des Busses |
93 | ;----------------------------------------------------------------------------------------- |
94 | bcf PIR1, SSPIF ;SSPIF-Bit löschen |
95 | |
96 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
97 | bsf SSPCON2, SEN ;Bus-Übernahme starten |
98 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
99 | |
100 | iicwait1 |
101 | btfss PIR1, SSPIF ;Prüfe ob Bus übernommen wurde |
102 | goto iicwait1 ;Nein, wiederhole |
103 | bcf PIR1, SSPIF ;Ja, Bus übernommen |
104 | |
105 | return |
106 | |
107 | ;----------------------------------------------------------------------------------------- |
108 | iicrepeatbus ;erneutes Übernehmen des Busses |
109 | ;----------------------------------------------------------------------------------------- |
110 | bcf PIR1, SSPIF ;SSPIF-Bit löschen |
111 | |
112 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
113 | bsf SSPCON2, RSEN ;Bus-Übernahme starten |
114 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
115 | |
116 | iicwait6 |
117 | btfss PIR1, SSPIF ;Prüfe ob Bus übernommen wurde |
118 | goto iicwait6 ;Nein, wiederhole |
119 | bcf PIR1, SSPIF ;Ja, Bus übernommen |
120 | |
121 | return |
122 | |
123 | ;----------------------------------------------------------------------------------------- |
124 | iicsendaddress ;Adresse senden |
125 | ;----------------------------------------------------------------------------------------- |
126 | bcf PIR1, SSPIF |
127 | |
128 | movlw B'10010001' ;Adresse des Sensors + Read-Bit |
129 | movwf SSPBUF ;Adresse in den Sende-Puffer schieben |
130 | |
131 | iicwait2 |
132 | btfss PIR1, SSPIF ;Prüfe ob Acknowledge empfangen wurde |
133 | goto iicwait2 ;Nein, wiederhole |
134 | bcf PIR1, SSPIF ;Ja, Daten sind im Slave |
135 | |
136 | return |
137 | |
138 | ;----------------------------------------------------------------------------------------- |
139 | iicreadvalue ;Temperaturwert auslesen |
140 | ;----------------------------------------------------------------------------------------- |
141 | |
142 | ;MSB einlesen |
143 | |
144 | bcf PIR1, SSPIF |
145 | |
146 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
147 | bsf SSPCON2, RCEN ;Datenempfang einschalten |
148 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
149 | |
150 | iicwait3 |
151 | btfss PIR1, SSPIF ;Daten empfangen? |
152 | goto iicwait3 ;Nein, wiederhole |
153 | bcf PIR1, SSPIF ;Ja, Daten empfangen |
154 | |
155 | movf SSPBUF, 0 |
156 | movwf MSByte |
157 | |
158 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
159 | bsf SSPCON2, ACKEN ;ein Acknowledge senden |
160 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
161 | |
162 | ;LSB einlesen |
163 | |
164 | bcf PIR1, SSPIF |
165 | |
166 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
167 | bsf SSPCON2, RCEN ;Datenempfang einschalten |
168 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
169 | |
170 | iicwait4 |
171 | btfss PIR1, SSPIF ;Daten empfangen? |
172 | goto iicwait4 ;Nein, wiederhole |
173 | bcf PIR1, SSPIF ;Ja, Daten empfangen |
174 | |
175 | movf SSPBUF, 0 |
176 | movwf LSByte |
177 | |
178 | bsf STATUS, RP0 ;Bankumschaltung auf Bank 1 |
179 | bcf SSPCON2, RCEN ;Datenempfang ausschalten |
180 | bcf STATUS, RP0 ;Bankumschaltung auf Bank 0 |
181 | |
182 | return |
183 | |
184 | ;----------------------------------------------------------------------------------------- |
185 | iicreleasebus ;Den Bus wieder freigeben |
186 | ;----------------------------------------------------------------------------------------- |
187 | bcf PIR1, SSPIF |
188 | |
189 | bsf STATUS, RP0 |
190 | ; bsf SSPCON2, ACKDT ;Art des Acknowledges auf NOT umstellen |
191 | ; bsf SSPCON2, ACKEN ;ein Acknowledge senden |
192 | bsf SSPCON2, PEN ;Bus-Freigabe starten |
193 | bcf STATUS, RP0 |
194 | |
195 | iicwait5 |
196 | btfss PIR1, SSPIF |
197 | goto iicwait5 |
198 | bcf PIR1, SSPIF |
199 | |
200 | return |
201 | |
202 | ;----------------------------------------------------------------------------------------- |
203 | picinit ;Initialisierung des µControllers |
204 | ;----------------------------------------------------------------------------------------- |
205 | bsf STATUS,RP0 ;Bankumschaltung auf Bank 1 |
206 | movlw B'00000111' |
207 | movwf ADCON1 ;PORTA als digitale I/O's konfigur. |
208 | movlw B'11111110' |
209 | movwf TRISA ;RA0 als Ausgang definieren (Power-On) |
210 | movlw B'00000000' |
211 | movwf TRISB ;PORTB als Ausgang definieren |
212 | movlw B'00011000' |
213 | movwf TRISC ;PORTC3,4 als Eingang definieren |
214 | movlw B'00000000' |
215 | movwf TRISE ;PORTE als Ausgang definieren |
216 | bcf INTCON,GIE ;Alle Interrupts sperren |
217 | bcf STATUS,RP0 ;Bankumschaltung auf Bank 0 |
218 | bsf POWERONLED,0 ;Power-On Led einschalten |
219 | |
220 | return ;Ruecksprung zum Hauptprogramm |
221 | |
222 | ;----------------------------------------------------------------------------------------- |
223 | lcdinit ;Initialisierung des Displays |
224 | ;----------------------------------------------------------------------------------------- |
225 | movlw LCDFUNCTIONSET ;Datenwort zur Initialisierung, siehe DB. |
226 | call lcdsendinstruction |
227 | movlw LCDFUNCTIONSET ;Datenwort zur Initialisierung, siehe DB. |
228 | call lcdsendinstruction |
229 | movlw LCDFUNCTIONSET ;Datenwort zur Initialisierung, siehe DB. |
230 | call lcdsendinstruction |
231 | movlw LCDDISPLAYFORMAT ;5x8dot-Zeichen |
232 | call lcdsendinstruction |
233 | movlw LCDDISPLAYOFF ;Display ausschalten |
234 | call lcdsendinstruction |
235 | movlw LCDDISPLAYCLEAR ;Gesamten Display löschen |
236 | call lcdsendinstruction |
237 | movlw LCDENTRYMODESET |
238 | call lcdsendinstruction |
239 | movlw LCDDISPLAYON ;Display und blinkenden Cursor einschalten |
240 | call lcdsendinstruction |
241 | |
242 | return |
243 | |
244 | ;----------------------------------------------------------------------------------------- |
245 | lcdapplydata ;Auf dem PORTB liegende Daten durch einen Impuls an der |
246 | ;Enable-Leitung (RE0) an das Display übergeben. |
247 | ;----------------------------------------------------------------------------------------- |
248 | bsf LCDCONTROLPORT,0 ;Enable-Leitung auf H setzen |
249 | nop ;warten... |
250 | nop ;warten... |
251 | nop ;warten... |
252 | bcf LCDCONTROLPORT,0 ;Enable-Leitung auf L setzen |
253 | |
254 | return ;Ruecksprung zum Hauptprogramm |
255 | |
256 | ;----------------------------------------------------------------------------------------- |
257 | lcdsendinstruction ;Einen Befehl an das Display senden |
258 | ;----------------------------------------------------------------------------------------- |
259 | bcf LCDCONTROLPORT,1 ;RS auf L setzen |
260 | bcf LCDCONTROLPORT,2 ;R/W auf L setzen |
261 | movwf LCDDATAPORT ;Daten auf den PORTB legen |
262 | call lcdapplydata ;Daten an das Display übergeben |
263 | call waitwhilebusy ;Busy-Flag überprüfen |
264 | |
265 | return ;Ruecksprung zum Hauptprogramm |
266 | |
267 | ;----------------------------------------------------------------------------------------- |
268 | lcdsenddata ;Ein Zeichen an das Display senden |
269 | ;----------------------------------------------------------------------------------------- |
270 | bsf LCDCONTROLPORT,1 ;RS auf L setzen |
271 | bcf LCDCONTROLPORT,2 ;R/W auf L setzen |
272 | movwf LCDDATAPORT ;Daten auf den PORTB legen |
273 | call lcdapplydata ;Daten an das Display übergeben |
274 | call waitwhilebusy ;Busy-Flag überprüfen |
275 | |
276 | return ;Ruecksprung zum Hauptprogramm |
277 | |
278 | ;----------------------------------------------------------------------------------------- |
279 | waitwhilebusy ;Warte ~5ms |
280 | ;----------------------------------------------------------------------------------------- |
281 | movlw TMR1CONF1 ;Timer 1-Konfiguration |
282 | movwf T1CON ;Konfiguration in Timer 1 laden |
283 | movlw 0xEF |
284 | movwf TMR1H ;MSByte des Timer 1 mit 0x9F laden |
285 | movlw 0xFF |
286 | movwf TMR1L ;LSByte des Timer 1 mit 0xFF laden |
287 | movlw D'1' |
288 | movwf TEMP ;w-Reg. ins TEMP-Reg. |
289 | wait0 |
290 | btfss PIR1,0 ;Teste ob Überlauf aufgetreten ist |
291 | goto wait0 ;Ansonsten bleibe in der Schleife |
292 | bcf PIR1,0 ;lösche das Timer 1-Interrupt Flag |
293 | movlw 0x3F ;0x0A(10) in das w-Reg. |
294 | return ;Ruecksprung zum Hauptprogramm |
295 | |
296 | ;----------------------------------------------------------------------------------------- |
297 | waitwhilestartup ;Warte 100ms |
298 | ;----------------------------------------------------------------------------------------- |
299 | movlw D'4' |
300 | movwf TEMP ;w-Reg. ins TEMP-Reg. |
301 | movlw TMR1CONF1 ;Timer 1-Konfiguration |
302 | movwf T1CON ;Konfiguration in Timer 1 laden |
303 | wait1 |
304 | movlw 0x00 |
305 | movwf TMR1H ;MSByte des Timer 1 mit 0x9F laden |
306 | movlw 0x00 |
307 | movwf TMR1L ;LSByte des Timer 1 mit 0xFF laden |
308 | |
309 | wait2 |
310 | btfss PIR1,0 ;Teste ob Überlauf aufgetreten ist |
311 | goto wait2 ;Ansonsten bleibe in der Schleife |
312 | bcf PIR1,0 ;lösche das Timer 1-Interrupt Flag |
313 | |
314 | decfsz TEMP |
315 | goto wait1 |
316 | |
317 | return ;Ruecksprung zum Hauptprogramm |
318 | |
319 | ;----------------------------------------------------------------------------------------- |
320 | lcdsendtemp ;Temperatur auswerten und an den LCD senden |
321 | ;----------------------------------------------------------------------------------------- |
322 | |
323 | movlw '+' |
324 | |
325 | btfsc MSByte,7 |
326 | movlw '-' |
327 | |
328 | call lcdsenddata |
329 | |
330 | btfsc MSByte,7 |
331 | call negativeZahl |
332 | |
333 | clrf h |
334 | clrf z |
335 | clrf e |
336 | |
337 | movlw d'100' |
338 | |
339 | hunderter |
340 | incf h |
341 | subwf MSByte,1 |
342 | btfsc STATUS,C ;Überprüfe ob Subtraktion 0 ergab |
343 | goto hunderter |
344 | |
345 | bcf STATUS,C |
346 | |
347 | addwf MSByte,1 |
348 | decf h |
349 | |
350 | movlw lcdnumberprefix |
351 | iorwf h,0 |
352 | |
353 | call lcdsenddata |
354 | |
355 | movlw d'10' |
356 | |
357 | zehner |
358 | incf z |
359 | subwf MSByte,1 |
360 | btfsc STATUS,C ;Überprüfe ob Subtraktion 0 ergab |
361 | goto zehner |
362 | |
363 | bcf STATUS,C |
364 | |
365 | addwf MSByte,1 |
366 | decf z |
367 | |
368 | movlw lcdnumberprefix |
369 | iorwf z,0 |
370 | |
371 | call lcdsenddata |
372 | |
373 | movlw d'1' |
374 | |
375 | einer |
376 | incf e |
377 | subwf MSByte,1 |
378 | btfsc STATUS,C ;Überprüfe ob Subtraktion 0 ergab |
379 | goto einer |
380 | |
381 | bcf STATUS,C |
382 | |
383 | addwf MSByte,1 |
384 | decf e |
385 | |
386 | movlw lcdnumberprefix |
387 | iorwf e,0 |
388 | |
389 | call lcdsenddata |
390 | |
391 | movlw '.' |
392 | call lcdsenddata |
393 | |
394 | movlw '0' |
395 | |
396 | btfsc LSByte,7 |
397 | movlw '5' |
398 | |
399 | call lcdsenddata |
400 | |
401 | movlw gradzeichen |
402 | call lcdsenddata |
403 | movlw 'C' |
404 | call lcdsenddata |
405 | |
406 | return |
407 | |
408 | ;----------------------------------------------------------------------------------------- |
409 | negativeZahl |
410 | ;----------------------------------------------------------------------------------------- |
411 | movlw 0xFF |
412 | movwf TEMPByte2 ;255 ins TEMPByte2 |
413 | |
414 | movf MSByte,0 ;Schreibe MSByte ins w-Reg. |
415 | |
416 | subwf TEMPByte2,0 ;Subtrahiere MSByte von 255 |
417 | |
418 | movwf MSByte |
419 | |
420 | incf MSByte,1 |
421 | |
422 | return |
423 | |
424 | ;----------------------------------------------------------------------------------------- |
425 | warte15sekunden |
426 | ;----------------------------------------------------------------------------------------- |
427 | movlw d'255' |
428 | movwf COUNT1 |
429 | movlw d'5' |
430 | movwf COUNT2 |
431 | |
432 | schleife |
433 | warte |
434 | call waitwhilebusy |
435 | decfsz COUNT1 |
436 | goto warte |
437 | decfsz COUNT2 |
438 | goto schleife |
439 | |
440 | return |
441 | |
442 | |
443 | |
444 | |
445 | END ;EOF |
Peter schrieb: > Wie wär's mit einer Antwort die mir hilft? Du hast das Problem nicht verstanden: in 500 Zeilen fremden Assemblersourcecodes sucht niemand freiwillig einen Fehler. In 100 Zeilen C-Code schon eher.
Peter schrieb: Hallo Peter Ich gestehe, dass ich momentan auch zu faul bin, durch den Code zu scannen. Und das hast Du ja sicher schon selbst gelesen: http://ww1.microchip.com/downloads/en/appnotes/00735a.pdf Ein paar allgemeine Fragen hab ich aber noch (see below) > > Soweit funktionierte auch alles ganz gut, 1x kann ich die Temperatur > korrekt einlesen, auch die Ausgabe am Display geht. > > Wiederholt sich nun aber die Schleife zum ersten Mal (nach ca. 5 > Sekunden Pause) treten schier willkürlich folgende Ergebnisse auf: > - der Wert wird weitere ein- oder zweimal eingelesen, danach friert > alles ein Ok, es bilden sich Eisblumen an den Fenstern und ... Was heisst einfrieren ? Läuft die PIC Clock noch ? Hast Du ein Scope ? Dann check mal den I2C Bus ob der noch zuckt. > - der Wert wird noch einmal eingelesen, die Logik friert jedoch schon > beim freigeben des Bus ein Same story again: Woher weisst Du das ? WANN friert der bus ein ? Hat der PIC noch das Adressbyte (oder mehr) gesendet ? Hat der LM75 geantwortet ? Mit der richtigen Länge ? Ist Dein Processing für das LCD auch korrekt, wenn der LM75 totalen Schrott schickt (aka wird der gesamte, evtl. sinnlosse, Wertebereich korrekt gehandelt) ? > > Mache ich einen Reset über den !MCLR ist kann er den Bus nicht einmal > mehr übernehmen. Das !MCLR nur den PIC reseted, nicht den LM75, ist klar ? Woher weisst Du, dass der PIC den I2C nicht "übernehmen" kann ? Ein (mehr als) flüchtiger Blick in den Code sagt mir, dass Du zB ewig wartest, wenn der LM75 Dir kein ACK beim zweiten Zugriff schickt (darum die Fragen zum "Einfrieren"). Vielleicht hängt er ja auch da ? > > Auch wenn ich die Versorgungsspannung entferne und wieder anlege ergeben > sich die zwei oben genannten Zustände. > Das heisst, es wird mindestens ein mal der richtige Wert angezeigt ? > > Hat jemand vielleicht schon einmal ein solches oder ähnliches Problem > gehabt? Einmal ? ;-) Grüße Andreas
Hi Irgendwie kommen mir deine ACKs komisch vor. Wo sagst du deinem PIC, das er nach dem ersten gelesenen Byte ein ACK und nach dem zweiten ein NACK senden soll? MfG Spess
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.