Hallo,
ich versuche einen LM75 Temperatursensor über meine druckerschnittstelle
auszulesen. Leider bin ich blutiger Anfänger was programmieren angeht.
Ein Lauflicht in c++ über die Druckerschnittstelle ist mein bisherige
Highlight.
Bitte nicht zu doll schimpfen aber hier ist mein bischen Quelltext. Ist
übrigens ein Mix aus zusammengegoogelten Code
dabei interessiert mich vorallem ob ich die ganze Kommunikation nicht
vereinfachen kann. Meine jetzige Version beinhaltet viel zu viele
fehlermöglichkeiten. Ich hoffe das es irgen eine andere Methode gibt an
den LM75 Einzen und Nullen zu senden - und zu empfangen.
1
#include<stdio.h>
2
#include<conio.h>
3
#include<windows.h>
4
#include<math.h>
5
//#include <iostream.h>
6
7
//using namesapce std;
8
9
#define lpt 0x378
10
11
//#define D_IN 64 //Byte for SDA -> ACKNOWLEDGE high
12
#define oo 0 //SDA -> low / SCL -> low
13
#define oi 1 //SDA -> low / SCL -> high
14
#define io 2 //SDA -> high / SCL -> low
15
#define ii 3 //SDA -> high / SCL -> high
16
17
18
//void funktion();
19
voidfunc_stop()
20
{
21
outp(lpt,ii);
22
Sleep(10);
23
}
24
25
voidfunc_start()
26
{
27
outp(lpt,oi);
28
Sleep(10);
29
outp(lpt,oo);
30
Sleep(10);
31
}
32
33
voidfunc_send_adress_byte()
34
{
35
intcounter;
36
37
outp(lpt,ii);//1
38
Sleep(10);
39
outp(lpt,oo);
40
Sleep(10);
41
outp(lpt,oi);//0
42
Sleep(10);
43
outp(lpt,oo);
44
Sleep(10);
45
outp(lpt,oi);//0
46
Sleep(10);
47
outp(lpt,oi);
48
Sleep(10);
49
outp(lpt,ii);//1
50
Sleep(10);
51
outp(lpt,oo);
52
Sleep(10);
53
outp(lpt,oi);//0
54
Sleep(10);
55
outp(lpt,oo);
56
Sleep(10);
57
outp(lpt,oi);//0
58
Sleep(10);
59
outp(lpt,oo);
60
Sleep(10);
61
outp(lpt,oi);//0
62
Sleep(10);
63
outp(lpt,oo);
64
Sleep(10);
65
outp(lpt,ii);//1
66
Sleep(10);
67
68
69
70
voidfunc_slave_acknowledge()
71
{
72
outp(lpt,oi);
73
Sleep(10);
74
inp(lpt,0x04);//SDA abhorchen: for SDA low - > weiter machen -> else stop und wieder von vorne und fehler melden
75
Sleep(10);
76
}
77
intfunc_slave_send_data_ganzzahl()//ganzzahligen Anteil der Temperatur abholden
78
{
79
intnachkomma;
80
outp(lpt,oo);
81
Sleep(10);
82
//irgend wie die abgehorcheten Bits in Variablen a,b,c,d,e,f,g,h speichern?! - Bsp Ergebniss 10011010 = 128 + 16 + 8 + 2= -26°C
Rocco schrieb:
> dabei interessiert mich vorallem ob ich die ganze Kommunikation nicht> vereinfachen kann. Meine jetzige Version beinhaltet viel zu viele> fehlermöglichkeiten. Ich hoffe das es irgen eine andere Methode gibt an> den LM75 Einzen und Nullen zu senden - und zu empfangen.
Na ja, bei der Kommunikation passiert doch immer wieder das selbe,
nämlich beim Senden von Daten an den LM75 in Etwa sowas:
- Datenbit (0 oder 1) auf Datenleitung ausgeben
- Möglicherweise kurz warten
- Clockleitung 0->1
- Möglicherweise kurz warten
- Clock 1 -> 0, damit die CLK-Leitung nicht auf einem Pegel festsitzt
Aus diesem Schema kannst Du Dir zunächst eine Funktion zusammenbasteln,
die ein einzelnes Bit an den LM75 sendet, in Pseudocode also etwa:
function send_bit(bit) {
set_data_signal(bit);
short_delay();
set_clock_signal(1);
short_delay();
set_clock_signal(0);
short_delay();
}
Um ein einzelnes Byte zu senden macht man dann sowas:
function send_byte(value) {
for (i = 0; i < 8; i++) { /* One Byte = 8 bits */
bit = Nth_bit(value, i);
send_bit(bit);
}
}
Soviel zum Prinzip. In der Praxis muss dann ja noch die Startbedingung
auf dem Bus richtig ausgegeben werden und das einlesen der Daten muss ja
auch noch irgendwie erfolgen, und und und...
Das was Du gemacht hast, ist ja nicht verkehrt, es ist halt nur sehr
viel langweilige "Prosa" im Code. Versuche als erstes, die sich
wiederholenden Strukturen im Code zu Funktionen zusammenzufassen. So wie
oben angedeutet kann man das Problem ja leicht auf mehrere Ebenen
zerlegen:
- Bit-Ebene = Unterste Ebene: Einzelne Bits senden oder einlesen
- Byte-Ebene = Mittlere Ebene: Ganze Bytes (oder beliebig lange Gruppen
von Bits) senden oder einlesen, im einfachsten Fall z.B. Funktionen, die
z.B. ein Byte = 8 Bits gleichzeitig einlesen oder schreiben
- Protokoll-Ebene = Oberste Ebene: Hier stehen Funktionen wie "lese
Temperatur aus" oder "programmiere Chip so um, dass er statt der
Temperatur die Luftfeuchtigkeit misst" (nur als abstraktes Beispiel)
- Funktionale Ebene = Allerhöchste Ebene: Nach Programmstart wird alle
10 Sekunden ein Temperaturmesswert ermittelt und in eine Datei
geschrieben
Viel Spaß und Erfolg beim Bitbanging,
Stephan
Hallo,
cooler Tip - genau das habe ich erst mal gebraucht.
ich würde also vom PC an den SCL Eingang des LM75 in einer for Schleife
ein dauerndes high low - wechselndes Signal schicken. und wärend dessn
zum richtigen Zeitpunkt SDA beschreiben oder auslesen.
Oben im Bild sieht man doch die wie die Adresse des LM75 angesprochen
wird. dazu sendet der PC volgendes Bitmuster 10010001 an den SDA Eingang
des Chips.
Während dessen "Tickt" an Scl der Tackt.
also wird follgendes vom PC an den LM75 gesendet:
PC -> SCL 1010101010101010
PC -> SDA 1 0 0 1 0 0 0 1
das wäre dann so etwas wie:
1
for(i=0;i<8;i++){/* scl Takt erzeugen 8x an und aus */
2
outp(lpt,0x01);//nur Pin D0 am LPT Port ein
3
Sleep(10);
4
outp(lpt,0x00);//alle Pins am LPT Port aus
5
Sleep(10);
6
}
Was ich dabei nicht kapiere - wie schreibe ich wärend dessen den Pin D1
ansteuere, an dem SDA vom LM 75 hängt?!
fG Rocco
>for(i=0;i<8;i++){/* scl Takt erzeugen 8x an und aus */
2
>outp(lpt,0x01);//nur Pin D0 am LPT Port ein
3
>Sleep(10);
4
>outp(lpt,0x00);//alle Pins am LPT Port aus
5
>Sleep(10);
6
>}
7
>
>> Was ich dabei nicht kapiere - wie schreibe ich wärend dessen den Pin D1> ansteuere, an dem SDA vom LM 75 hängt?!
SDA hängt doch an der D1-Leitung der Druckerschnittstelle, oder? Also
wie wäre es z.B. hiermit:
Pseudocode:
function send_bit(bit) { /* bit must be either 0 or 1 */
bit <<= 1; // Now bit is either 0 or 2
// One could use 'bit *= 2;', too :-)
// Emit bit value, CLK is left in LOW state
outp(lpt, bit);
Sleep(10);
// Clk LOW -> HIGH
outp(lpt, bit | 1);
Sleep(10);
// Clk HIGH -> LOW
outp(lpt, bit);
Sleep(10);
};
Stephan
Rocco schrieb:
> mal schauen ob ich das richtig kapiere - bin wie gesagt Anfänger - also> etwas Mitleid ;-)
Neee, Mitleid is nicht ;-)
> [...]> Warscheinlich schnall ich es einfach nicht - aber wie meinst du kann ich> wärend dessen über D1 follgendes ausgeben 10010001?
Die Funktion wie ich sie geschrieben habe, sendet ja nur ein einzelnes
Bit, und zwar wie folgt in drei Schritten:
outp(lpt, bit); -> CLK=0, SDA=bit
outp(lpt, bit | 1); -> CLK=1, SDA=bit
outp(lpt, bit); -> CLK=0, SDA=bit
Um 90 Grad gedreht gibt das folgenden Ablauf:
Zeit T T+1 T+2
-------------------------
SCL 0 1 0
SDA B B B
(B = Wert des Bits, 0 oder 1) -> Bei T+1 liegt das Datenbit an SDA und
eine Steigende CLK-Flanke kommt. Das sollte doch zum Senden eines Bits
reichen, oder?
Nun zum Senden von Bytes: Ein Byte 0x11000101 sendet man nun halt als
Folge von 8 Bits. Achtung: Reihenfolge beachten - MSB oder LSB zuerst?!
Ich mach das mal mit MSB zuerst:
send_bit(1);
send_bit(1);
send_bit(0);
send_bit(0);
send_bit(0);
send_bit(1);
send_bit(0);
send_bit(1);
Oder, um die viele Schreibarbeit zu vereinfachen, halt in einer Schleife
und das ganze dann noch in einer Funktion:
void send_byte(int byte) {
for (int i = 7; i > -1; i--) {
int bit = ((byte >> i) & 1);
send_bit(bit);
};
};
Dann sehen die 8 Zeilen send_bit() von oben so aus:
send_byte(0xC5);
Stephan
ok, ich komme soweit mit - aber das hier kapier ich nicht:
outp(lpt, bit); -> CLK=0, SDA=bit
outp(lpt, bit | 1); -> CLK=1, SDA=bit
outp(lpt, bit); -> CLK=0, SDA=bit
vorallem kann ich" bit | 1 " nicht interpretieren
ich weis das wenn ich follgendes sende nur der D0 pin an ist:
outp( lpt, 0x01 );
sende ich das hier sind D0 und D1 an:
outp( lpt, 0x03 );
das ist doch bestimmt das selbe was auch Dein Quelltext macht - nur das
Du das binär und ich es hexadezimal mache - oder?
fG Rocco
Rocco schrieb:
> [...]> vorallem kann ich" bit | 1 " nicht interpretieren> [...]> das ist doch bestimmt das selbe was auch Dein Quelltext macht - nur das> Du das binär und ich es hexadezimal mache - oder?
Egal wie man eine Zahl im Quelltext hinschreibt - dezimal, binär, oktal,
hexadezimal, ... - der Computer verwurstet alles zu Folgen von Nullen
und Einsen.
"|" ist ein binäres Oder. Auf die Schnelle hab ich dazu folgendes
gefunden:
http://www.cprogramming.com/tutorial/bitwise_operators.html
Ich bin ehrlich gesagt geneigt, Dir zu empfehlen, mal 2-3 Tage den Kopf
von diesem speziellen Problem freizumachen und ein wenig
C/C++-Grundlagen zu lernen. Wenn das einigermassen sitzt, dann versuche
das Problem nochmal neu aufzurollen. Das soll jetzt keine Ablehnung von
Hilfe sein, aber ich seh im Moment für mich keine andere Wahl, als Dir
das Programm zu schreiben, womit Du Null Lerneffekt hast.
Liebe Grüße,
Stephan
Nein, ich nehme dir das nicht übel. Im Gegenteil, ich bin Dir für deine
Hilfe sehr dankbar.
Ich bastel z.Z. eigentlich an einem Thermocycler für unser Labor.
Es soll also ein Progie entstehen mit dem man - über ein Relais - eine
Heizung für eine betimmte Zeit eingeschaltet werden soll. Der Plan ist
das mann 10 Temperaturen wählen kann die dann jeweils für eine bestimmte
Zeit gehalten werden sollen.
Also wenn du ein zwei gute Tutorials kennst die mir da weiter helfen....
fG Rocco
Ach, noch ein Nachtrag: Ich hab glaub ich die Rollen der Datenleitung
und die der Clockleitung (d.h. die Rollen von D0 und D1) vertauscht.
Möglicherweise liegt da auch ein Teil Deines "Verständnisproblems" für
das was ich geschrieben habe. Sorry, ich wollte eigentlich nicht für
Verwirrung sorgen.
Nicht desto trotz, wenn Du den Code verbessern möchtest, solltest Du die
Sprache, in der er geschrieben ist, mindestens 'ein bisschen'
beherrschen.
Ein erster Schritt wäre doch: Schreib doch mal zwei Funktionen, eine für
das Senden einer Null und eine für das Senden einer Eins. Das Senden der
ersten 4 Bit der Addresse wären dann nur noch 4 Funktionsaufrufe:
send_bit_1();
send_bit_0();
send_bit_0();
send_bit_1();
Wenn Du das machst, dann schau Dir die beiden Funktionen mal genau an
(oder poste sie hier) und vergleiche die beiden Funktionen miteinander.
Stephan