Nabend
Ich habe ein kleines Problem. Und zwar habe ich an einem Mega16 sowohl
UART und I2C in benutztung, als ist auch noch ein LCD dran.
Programmiert wird das ganze in C, benutzt werden die Peter Fleury
libarys.
Nun zu meinem Problem:
Ich kann nicht den I2C-Bus ansteuern, und in der gleichen while dann
noch das LCD ansteuern. Sobald ich also z.B. die I2C geschichte
auskommentiere geht dann das LCD, ohne das aber nicht. Der I2C bus wird
aber auch vor dem Ansteuern des LCDs relased und die Stop-Condition ist
auch vorhanden.
Ich kann mir das nur so vorstellen, dass es irgend wo Interrupt Probleme
gibt. Ich bin echt ratlos. Wie kann ich das Problem lösen?
Vielen dank im Voraus.
JeyBee66
So steht jetzt nur die ganze Zeit "Bereit" auf dem LCD. Wenn ich die
ganze I2C sache direkt nach der While(1) auskommenitere und
"lcd_puts(temp);" durch "lcd_puts("temp");" ändere, steht dann auch
"temp" auf dem LCD. -> Das LCD geht.
mfg JeyBee
Hast du die Möglichkeit, irgendwie ne LED anzuschließen? Ist für
Debugzwecke immer ganz hilfreich, wenn du das so in deinen Code
einbaust:
1
while(1)
2
{
3
toggleLED;
4
5
i2c_start(Dev24C02+I2C_WRITE);
6
temp=i2c_readNak();
7
i2c_stop();
8
9
lcd_clrscr();
10
lcd_home();
11
lcd_puts(temp);
12
_delay_ms(300);
13
14
}
toggleLED musst du natürlich irgendwie implementieren, als Funktion,
Macro, oder wie auch immer.
Aber dann siehst du ob deine Schleife durchlaufen wird.
Wie kommst du eigentlich auf diese Slave-Adresse? Laut Datenblatt des
LM75 ist diese nämlich 0x90, sofern A0-A2 an GND liegen. 24C02 und LM75
unterscheiden sich in Bit4+5 der Adresse! Könntest also auch beide an
den Bus anschließen.
Hi,
Die LED blinkt, wenn ich das I2C raus nehme. Wenn ich das I2C und das
LCD drinn habe, dann leuchtet sie dauernt durch (Sie ist zwischen uC und
GND)
Mfg JeyBee66
F. Reiling schrieb:
> Wie kommst du eigentlich auf diese Slave-Adresse? Laut Datenblatt des> LM75 ist diese nämlich 0x90, sofern A0-A2 an GND liegen. 24C02 und LM75> unterscheiden sich in Bit4+5 der Adresse!
Änder mal die Adresse.
nimm mal: i2c_start(LM75+I2C_READ);
Du willst ja den Sensor auslesen. Hab ich total übersehen. Und als
Adresse 0x90. Ich kenn zwar den LM75 nicht, aber dann sollte es
funktionieren.
mfg
Die adresse 0x90 muss stimmen, da ich die drei Pins auch auf Masse habe
und 1001 ja die ersten 4 Adressbits sind.
Aber auch so weiterhin eine leuchtende LED und ein LCD, das "Bereit"
anzeigt.
Ratlos^2
hier nochmal der Code:
JeyBee66 schrieb:
> while(1)> {> PORTD ^=(1<<PD3);>> i2c_start(Dev24C02+I2C_READ);> temp = i2c_readNak();> i2c_stop();>> lcd_clrscr();> lcd_home();> lcd_puts(temp);> _delay_ms(300);> }
Ist das der aktuelle Code? Und du hast den LM75 angeschlossen? Dann kann
das nicht funktionieren, wenn du den 24C02 ansprechen willst. Da sich ja
kein Gerät am Bus angesprochen fühlt mit der angegebenen Adresse.
Du solltest folgende Zeile korrigieren:
Jetzt fällt mir auch nix mehr ein. Ganz blöde Frage: Ist der Sensor auch
korrekt angeschlossen? Mit Pullups am Bus, ich glaube typischerweise
werden 4k7 verwendet. Ist das ganze auf nem Breadboard? Liegen die drei
Adressbits wirklich auf Masse? Hast du mal eine niedrigere
I2C-Geschwindigkeit probiert, falls nicht sowieso schon verwendet? Kurze
Verbindungen zwischen AVR und LM75? Da du am Anfang den Verdacht von
irgendwelchen Interrupts geäußert hast, dann deaktiviere sie doch
testweise mal. Denn eigentlich werden sie ja in diesem Fall nicht
benötigt.
Ich muss mal nachschauen, ich hab irgendwann mal eine Funktion
geschrieben, die den Bus scannt und die erste gefundene Slave-Adresse
zurückgibt. Bedingung: Es ist überhaupt ein Gerät angeschlossen. Ich
schau mal ob ich die finde.
Das ganze ist auf einer Lochrasterplatine. Pullups sind vorhanden,
Sensor ist korrekt mit dem uC verbunden, Sensor wurde schon
ausgetauscht. Das Deaktivieren der Interrupts brauchte kein Ergebnis, es
ist alles so, wie es ssein sollte....
Ich weiss nicht weiter.
Mfg JeyBee66
Ich hab die Funktion gefunden. Hatte ich mal geschrieben, da ich ein
Gerät hatte, von dem ich die Adresse nicht wusste.
1
/* Sucht nach nächstem Slave der antwortet.
2
Rückgabe: Adresse des ersten gefundenen Slaves
3
0 = kein Gerät gefunden
4
*/
5
unsignedchari2c_findSlave(unsignedcharstartAdr)
6
{
7
charfTrue=1;// 0 -> Gerät gefunden
8
9
while(fTrue&&startAdr<256)
10
{
11
fTrue=i2c_start(startAdr);
12
if(!fTrue)
13
{
14
i2c_stop();// Stop I2C
15
returnstartAdr;
16
}
17
else
18
{
19
startAdr++;
20
}
21
}
22
return0;
23
}
Den Rückgabewert kannst du ja in ein lesbares Format auf deinem Display
ausgeben lassen. Ich hab die Funktion damals mit mehreren Devices
getestet und hatte auch zuverlässig funktioniert. Vielleicht bringt dich
das weiter.
mfg
Was für ein Display hast du angeschlossen? Und da würde ich mal
vermuten, wenn du das
1
lcd_puts(temp);
ausführt, passiert was merkwürdiges, da die Funktion lcd_puts einen
String erwartet und keinen Integer. Du musst die Zahl in einen
ASCII-String umwandeln, geht mit itoa() und diesen dann auf dein Display
ausgeben. Wie z.b. aus dem Tutorial
(http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung):
1
...
2
intvariable=42;
3
4
lcd_init();
5
6
// Ausgabe des Zeichens dessen ASCII-Code gleich dem Variablenwert ist
7
// (Im Beispiel entspricht der ASCII-Code 42 dem Zeichen *)
8
// http://www.code-knacker.de/ascii.htm
9
lcd_data(variable);
10
11
set_cursor(0,2);
12
13
// Ausgabe der Variable als Text in dezimaler Schreibweise
14
{
15
// ... umwandeln siehe FAQ Artikel bei www.mikrocontroller.net
16
// WinAVR hat eine itoa()-Funktion, das erfordert obiges #include <stdlib.h>
Interessant:
Wenn ich den Aufruf deiner Funktion auskommentiere, und einen normalen
String auf dem LCD (zur kontrolle) ausgeben lassen will, gehts nicht.
Wenn ich deinen Funktionsaufruf jedoch auskomentiere, gehts wieder...
hier der Aktuelle code
Wie gesagt, meine Funktion funktioniert nur, wenn der Bus korrekt
funktioniert und auch ein Gerät angeschlossen ist, anderweitig hängt
sich die Funktion aus der Bibliothek auf, da kein Timeout standardmäßig
implementiert ist.
Weitere Fragen: welchen Compiler/Entwicklungsumgebung verwendest du?
Ich hab so langsam echt keine Ahnung mehr, woran es noch liegen könnte.
Ich kann heute abend mal mein Breadboard rauskramen und versuchen,
nachzubauen. Hab jetzt aber keine Möglichkeit dazu.
mfg
Hallo,
bin gestern abend nicht mehr zum schreiben gekommen. Allerdings habe ich
mal wieder mein Breadboard rausgekramt und getestet. Seltsamerweise hat
bei mir die lcd bibliothek (p.fleury) nicht richtig funktioniert, i2c
schon. Auch die Funktion zum Scannen des Busses hat problemlos
funktioniert. Mit der LCD-Bibliothek aus dem GCC-Tutorial hatte ich
keine Probleme mehr.
Grml...
Kannst du mir mal deinen gesammten Code posten? Also der der
Funktioniert (mit slaveadresse rausfinden). Das würde mir als sehr
hilfreich erscheinen.
Viele Dank für deine Hilfe
JeyBee66
Gute Neuigkeiten, es funktioniert jetzt..
Wenn du mich nun töten willst, nur zu, ansonsten mach ich es selbst....
Ich hatte den PullUp am SCL leider als Pulldown :/
Vielen dank für deine bemühungen, ich bin dir was schuldig.
P.S. krieg ich dann deinen Code trotzdem noch?
Mfg JeyBee66
ich hab mir jetzt funktionen geschrieben, um ein Byte in ein externe I2C
EEprom zu schreiben und auch wieder auszulesen. Das selbe, um dem LM75
auszulesen.
Wenn ich in der main den Funktionsaufruf drin habe, um den LM75
auszulesen, gehts nix, die LED blinkt nicht, das LCD bleibt leer, wenn
ich NUR diese eine Funktion auskommentiere, gehts prima. Woran kann denn
dass nun liegen?
1
#include<stdlib.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<avr/signal.h>
5
#include<avr/pgmspace.h>
6
#include<util/delay.h>
7
#include<string.h>
8
#include"i2cmaster.h"
9
#include"lcd.h"
10
11
#ifndef F_CPU
12
#define F_CPU 16000000UL
13
#endif
14
15
#define M24C02 0xA0 // Device Adresse des EEproms (10100000)
16
#define LM75 0x90 // Device Adresse des LM75 (10010000)
17
#define DS1307 0xD0 // Device Adresse des DS2307 (11010000)
18
19
unsignedchareeprom_adresse;// Speicheradresse
20
unsignedchareeprom_output;// Byte aus EEprom lesen
21
unsignedchareeprom_input;// Byte in EEprom schreiben
Hallo, probier mal in der Funktion getTemp(): anstatt i2c_start_wait die
Funktion i2c_start zu verwenden.
Und hier mein Code:
1
#include<stdlib.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<avr/interrupt.h>
5
#include<avr/pgmspace.h>
6
#include<util/delay.h>
7
#include"i2cmaster.h"
8
#include"lcd_routines.h"
9
10
#define F_CPU 20000000UL
11
12
#define Dev24C02 0xA0
13
#define LM75 0x90
14
15
16
unsignedchari2c_findSlave(unsignedcharstartAdr)
17
{
18
charfTrue=1;// 0 -> Gerät gefunden
19
20
while(fTrue&&startAdr<128)
21
{
22
fTrue=i2c_start(startAdr*2);
23
if(!fTrue)
24
{
25
i2c_stop();// Stop I2C
26
returnstartAdr*2;
27
}
28
else
29
{
30
i2c_stop();
31
startAdr++;
32
}
33
}
34
return0;
35
}
36
37
38
intmain(void)
39
{
40
uint8_ttemp;
41
charbuffer[10];
42
DDRB=0xFF;
43
PORTB=0x00;
44
i2c_init();
45
temp=i2c_findSlave(0x00);
46
lcd_init();
47
lcd_clear();
48
lcd_home();
49
lcd_string("Bereit...");
50
set_cursor(0,2);
51
lcd_string("I2C-Slave: 0x");
52
lcd_string(itoa(temp,buffer,16));
53
54
while(1)
55
{
56
PORTB^=(1<<PB0);
57
i2c_start(temp);
58
i2c_write(0x40);
59
i2c_stop();
60
61
_delay_ms(300);
62
}
63
64
}
Das Programm scannt den I2C-Bus, gibt die Adresse in Hex-Form auf dem
Display aus. Ausserdem blinkt eine LED an PB0 und es wird dauerhaft der
Wert 0x40 über I2C an das Gerät 0x58 geschickt. Habe da einen
I2c-Motorcontroller dranhängen. der lag grad so hier rum.
achja, die lcd-Routinen sind die hier aus dem tutorial
mfg