Also im Datasheet vom MAX6675 steht geschrieben:
MAX -> AVR
SO MISO
SCK SCK
CS SSB
MISO und SCK ist mir klar. Aber was soll der SSB sein? der SS-Pin am
AVR?
Und wo muss der MOSI Pin am AVR hin?
Wie muss ich den AVR konfigurieren? Als Master nehme ich mal stark an.
Wenn dieser SSB-Pin tatsächlich wie von mir angenommen der SS-Pin vom
AVR sein sol... verstehe ich das dann richtig: Wenn SS auf low gedrückt
wird, fängt der MAX an zu senden und hört erst auf wenn der SS wieder
auf high geht?
Danke schonmal für eure Hilfe.
Wie auch schon in deinem anderen Thread geschrieben solltest du etwas
mehr Zeit mit lesen verbringen. Fragen ist ja nicht schlimm, aber man
kann dir hier auch nicht alles von 0 an beibringen.
Wenn du dir mal überlegt hast was MOSI überhaupt heißt und wer damit was
überträgt wird sich dir Frage schon erledigt haben
SSB ist der SS-Pin
Den MOSI kannst Du unbeschaltet lassen. Du schickst ja keine Daten zum
Temperatursensor. Damit Du Deine Daten aus dem Sensor auslesen kannst,
muss der Master den Takt vorgeben. Dazu schickt man ein Dummy-Byte.
Damit wackelt der Clock. Das Byte ist nicht interessant, ausserdem ist
die Leitung ja nicht angeschlossen. Nimm die Hardware SPI und schieb ein
Byte raus und warte bis es versendet wurde. Dann kannst Du das erste
Byte aus dem Datenregister der SPI lesen. Wenn ich es von Deinem letzten
Thread richtig in Erinnerung habe, erwartet der Sensor 16 Bit. Also
schiebst Du noch ein Dummybyte raus und erhältst nach dem Versenden das
zweite Byte vom Sensor. Du mußt bei der Einstellung der SPI nur auf die
Polarität und die Phasenlage des Clocks aufpassen. Die richtige
Einstellung geht aus dem Datenblatt des Sensors hervor. Zur Not kann man
mit den Einstellungen so lange herumspielen bis es passt, es gibt ja nur
4.
Gruß Matthias
Gut, also ich initialisiere den Controller als Master, schreibe ein Byte
ins SPDR Register, damit versende ich es praktisch. Richtig ?
Nachdem es verschickt wurde, kann ich das erste Byte aus meinem Sensor
aus dem SPDR Register auslesen. Das SPDR Register ist Sende und
Empfangsregister. Richtig ?
Das hier steht im DS vom Controller:
DDR_SPI, DD_MOSI und DD_SCK habe ich durch die Hardwareports ersetzt.
1
voidSPI_MasterInit(void)
2
{
3
/* Set MOSI and SCK output, all others input */
4
DDR_SPI=(1<<DD_MOSI)|(1<<DD_SCK);
5
/* Enable SPI, Master, set clock rate fck/16 */
6
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);
7
}
8
voidSPI_MasterTransmit(charcData)
9
{
10
/* Start transmission */
11
SPDR=cData;
12
/* Wait for transmission complete */
13
while(!(SPSR&(1<<SPIF)))
14
;
15
}
Was genau macht die Zeile
1
while(!(SPSR&(1<<SPIF)))
Kann ich das als eine Art Wartepunkt ansehen? Es geht praktisch erst
weiter wenn das Byte SPIF im SPSR Register auf 0 steht ?
Zum Empfang brauche ich dann das hier? :
1
charSPI_SlaveReceive(void)
2
{
3
/* Wait for reception complete */
4
while(!(SPSR&(1<<SPIF)))
5
;
6
/* Return data register */
7
returnSPDR;
8
}
Also sobald ich ins SPDR was reinschiebe gilt es als versendet?Oder muss
ich da noch irgendwo sagen dass das Byte versendet werden soll?
Wenns versendet ist muss ich SPI_SlaveReceive() aufrufen. Die Funktion
holt dann wiederrum das vom Sensor verschickte Byte wieder aus dem SPDR
Register raus?
Ich brauche ja zwei Byte vom Sensor. Woher weiss denn der Controller
welches Byte er gerade empfangen hat? Ob es Bit 1-7 oder
Bit 8-16 ist?
Man, das ganze hier irritiert mich total ;-) Wäre dankbar wenn ihr mir
etwas auf die Sprünge helfen könntet. Ein Beispielcode würde mir
sicherlich gut weiterhelfen.
Danke schonmal im Voraus.
Konrad
Welches Byte welches ist, kann der Controller nicht wissen. Du mußt die
Bytes laut Datenblatt des Sensors interpretieren. Die SPI ist weiter
nichts wie ein Schieberegister. Mit jedem Bit, das vom Controller
rausgeschoben wird, kommt von Sensor eins zurück. Damit ist die
Zuordnung Deiner Bytes gewährleistet. Du mußt nur noch wissen, welches
Byte der Sensor zuerst rausschickt, bzw. ob er MSB oder LSB zuerst
schickt. Das ist dann reine Interpretationssache und hat mit der
Übertragung an sich nichts zu tun. Ich würde sagen probier es erst mal
aus. Wenn Du zwei Bytes empfangen kannst, die Werte aber nicht passen,
mußt Du die Clock Polarität und Phase noch korrigieren. Das entspricht
dem SPI Modus.
Gruß Matthias
> Woher weiss denn der Controller welches Byte er gerade empfangen hat?
Das erste Byte nachdem CS auf low geht ist das High-byte (bit15-8), das
nächste das low-byte...
>Ein Beispielcode würde mir sicherlich gut weiterhelfen.
wahrscheinlich (genauso wie das Datasheet, das Tutorial etc..) ;)
hth. Jörg
ps.: der Anhang ist für den AVR-GCC/WinAVR gedacht (du hast nirgends
angegeben, welchen Compiler du benutzt)
Danke Jörg für den Code... jetzt versteht ich das Datasheet vom Maxim
erst ;-)
Aber aus irgendeinem Grund bekomme ich trotzdem keine Daten vom Sensor
Das hier ist mein Code:
DDRB|=(1<<PB0)|(1<<PB1)|(1<<PB2);// make MOSI output if necessary
40
PORTB|=(1<<PB0);
41
42
#if CS_PIN != PB0
43
//DESEL_MAX6675();
44
CS_OUTP|=(1<<CS_PIN);
45
CS_DDR|=CS_PIN;
46
#endif
47
/* set to < 4.3MHz; Mode 0 */
48
SPCR=(1<<SPE)|(1<<SPR0);
49
}
50
/* convert the sensor output(0-4095) to sth. readable
51
"0"
52
*/
53
char*temp_to_string(int16_ttemp,char*string)
54
{
55
/* take a look at the article "Fixpointarithmetik"
56
*/
57
uint8_tlen;
58
//convert to tenth
59
temp=(640L*temp)/256;
60
// convert to string
61
itoa(temp,string,10);
62
// insert decimal point
63
len=strlen(string);
64
string[len]=string[len-1];
65
string[len-1]='.';
66
string[len+1]=0;
67
//! TODO: prevent memory corruption for temp < 1 ...
68
returnstring;
69
}
70
71
intmain(void)
72
{
73
DDRA=0xFF;
74
DDRG=0x00;
75
lcd_init();
76
init_spi();
77
78
PORTA|=(1<<PA6);
79
80
int16_ttemperature;
81
while(1){
82
83
// if (PING==30) {
84
85
chartemp[7];// at least sizeof("1023.1\0") bytes
86
temperature=get_max6675_temp();
87
temp_to_string(temperature,temp);
88
//lcd_string(string);
89
lcd_string(temp_to_string(temperature,temp));
90
// }
91
}
92
93
}
Ich bekomme auf dem Display nur ".0" angezeigt.
Die vier defines der Funktionen habe ich jeweils durch den Befehl direkt
ersetzt. So wie es original in deinem Code drin steht kam nicht mal das
.0
im Display.
Die init_spi habe ich auch angepasst wie du siehst. Aber es kommt
einfach nichts raus der der Mühle :-( Bin ich denn wirklich soooo blöd?
Ich habe eben noch den MISO-Pin als Eingang initialisiert und erhalte
jetzt einen Wert von -634.5
Das kann ja auch nicht sein, erst recht nicht bei Raumtemepratur...
ok,
Du kannst noch testen, ob die umwandlung int->string korrekt
funktioniert.
Hier musst du doch entscheiden:
> temp_to_string(temperature, temp);
und das noch einbauen
>> lcd_string(temp);
oder
> lcd_string(temp_to_string(temperature, temp));
obwohl, durch das zweimal-wandeln geht ja nichts kaputt ;)
Aber im MAX-Datasheet sind mir noch zwei 'Kleinigkeiten' aufgefallen:
> t_conv 0.17 bis 0.22 *Sekunden*
das ist lange, vor allem weil es später heißt:
> Forcing CS low immediately stops any conversion process.
.. und es gibt ja kein busy-Signal.
Teste mal
1
//... oben einbauen
2
#include<util/delay.h>
3
//...
4
intmain(void)
5
{
6
chartemp_str[7];
7
uint8_ti;
8
DDRA=0xFF;
9
DDRG=0x00;
10
lcd_init();
11
init_spi();
12
13
PORTA|=(1<<PA6);
14
15
int16_ttemperature;
16
while(1)
17
{
18
temperature=get_max6675_temp();
19
temp_to_string(temperature,temp_str);
20
lcd_string(temp_str);
21
for(i=23;i;i--)
22
{
23
_delay_ms(10);
24
}
25
}
26
}
hth. Jörg
ps.: ich hab da doch tatsächlich was vergessen ;)
Ok, werde ich mal ausprobieren wenn ich Feierabend habe....
Habe schon die nacht deswegen nicht schlafen können weil mir ständig
C-Code vor den Augen hergeflimmert kam ;-)
Ich will ja nicht unhöflich sein aber kann es sein dass die
get_max6675_temp() doch etwas anders aussehen müsste? Ungefähr so
[c]
int16_t get_max6675_temp(void)
{
int16_t act_temp;
SEL_MAX6675();
act_temp = (spi_get_byte() << 8);
DESEL_MAX6675();
SEL_MAX6675();
act_temp |= spi_get_byte();
DESEL_MAX6675();
return act_temp >> 3;
}
Ich muss doch nach jedem übertragegenm Byte CS auf high und gleich
wieder auf low stellen damit ich das zweite Byte vom Sensor bekomme. So
habe ich es zumindest aus dem Datasheet verstanden.
Aber ich werde vorerst deine Lösung ausprobieren, du hast mehr drauf als
ich ;-)
>Ich muss doch nach jedem übertragegenm Byte CS auf high und gleich>wieder auf low stellen damit ich das zweite Byte vom Sensor bekomme.
Nein! Nnachdem CS auf low geht musst du 16 Bit, also 2Bytes auslesen
("Figure 1a"). Dann CS wieder auf high und dem MAXe ab und zu 'ein
bisschen' (für den durchschnittlichen AVR eine halbe Ewigkeit ;) ) Zeit
zum wandeln lassen...
hth. Jörg
SPCR=(1<<SPE)|(1<<SPR0)|(1<<MSTR);/* das master-Bit hat bisher gefehlt
6
- du könntest ruhig auch aufmerksam das Datenblatt lesen ;) */
7
}
Wenn das nicht hilft, probier mal was passiert, wenn du folgendes
machst:
a)
> lcd_string("test123"), statt dem erzeugten string
b)
> temp_to_string(0, temp_str);//(oder andere Zahlen unter 4096)> lcd_string(temp_str);
hth. Jörg
Ich möchte auch einen solchen sensor proggen können, bitte helft mir..
ich baue aus alten backöfen hühnerbrutautomaten.. die letzten eier
wurden hartgekocht..
Also wenn ich mit dem Debugger nachschaue habe ich bei der zeile
act_temp |= spi_get_byte();
einen Wert von 517, nach dem return act_temp >>3; sind es dann -1024.
Das Datenblatt lese ich mehr als genug, aber ich verstehe es ebe nicht
was da steht. Bin zu hohl. Ich versuche im Nachhinein zu verstehen was
der Code mach. Ich übernehme zwar deinen Code, aber was es dann macht
möchte ich trotzdem gerne wissen ;-)
Korrektur :
Beim ersten Programmaufruf habe ich ein act_temp einen wert von 517 drin
stehen. Beim zweiten ändert sich er der Wert allerdings auf -32766 und
bleibt dann unverändert.
und noch was
mit temp_to_string(4069, temp_str) bekomme ich 406.9 , mit
temp_to_string(317, temp_str) 31.7 und mit temp_to_string(0,temp_str)
einfach nur .0
Was ist eigentlich mit dem CPOL und CPHA Bit im SPCR Register? Das gibt
doch auch an wann die Daten gelesen werden sollen...
Ich habe zwar alle vier Möglichkeiten durchprobiert, hat auch nichts
gebracht. Aber ich wollte es mal erwähnt haben.
>Beim ersten Programmaufruf habe ich ein act_temp einen wert von> 517 drin stehen.
bei 517 ist das bit 2 gesetzt:
>517 -> 0b00000010 00000101
was bedeuten würde, dass du KEIN Thermoelement angeschlossen hast.
>>Bit D2 is normally low and goes high when the thermocouple input is open Was
soll der Sensor denn dann für eine Temperatur liefern?
> mit temp_to_string(4069, temp_str) bekomme ich 406.9 , mit> temp_to_string(317, temp_str) 31.7 und
Schön, d.h. die Stringwandlung funktioniert
> mit temp_to_string(0,temp_str) einfach nur .0
Da steht auch ein dickes TODO im Code -- der Code funktioniert nicht
korrekt mit Sensorwerten unter 4 (1.0°C).
> Was ist eigentlich mit dem CPOL und CPHA Bit im SPCR Register? Das gibt> doch auch an wann die Daten gelesen werden sollen...
Das ist richtig...
> Ich habe zwar alle vier Möglichkeiten durchprobiert,
Ist (war) nicht notwendig, der MAX verwendet Mode 0 - Vergleiche mal
"Figure 1b" im Max-datasheet mit den Diagrammen "SPI Transfer format" im
Kapitel "SPI" -> "Data Modes" im Mega128 Datasheet (bei mir Figure 77
und 78, mein Datenblatt ist aber vom 10/06, kann also bei neueren anders
sein).
Um also sinnvolle Ergebnisse zu bekommen, musst du:
- ein Thermoelement (korrekt) anschließen
- zwischen dem auslesen mindestens 170ms warten (besser: länger als
220ms, das sind >1,7Mio Takte bei 8MHz </klugsch>)
hth. Jörg
Naja, ich habe den sensor direkt angelötet. Ist also sehr
unwahrscheinlich dass er "offen" ist. Aber gut, werd gucken dass ichso
einen stecker beibekomme.
Mir ist noch was aufgefallen. Du hast geschrieben dass 517 0b00000010
00000101 ist. Dann steht doch das 2. Bit auf 0. Also ist der Fühler
richtig angeschlossen. Und noch was: Die 517 hatte ich ja auf dem
Display stehen, und da du in deiner Funktion ja nur die 12 Bit für die
Temperatur ausgefiltert hast, wird das Bit für den Temperaturfühler ja
garnicht mit ausgegeben. Oder sehe ich das falsch?
Frohe Ostern wünsche ich dir übrigens :-)
Ok, langsam wirst du konfus, erst heißt es:
>> Also wenn ich mit dem Debugger nachschaue habe ich bei der zeile>> act_temp |= spi_get einen Wert von 517,
Dann wieder
>> Die 517 hatte ich ja auf dem Display stehen,
was denn nun??? (unter Debugger verstehe ich ein JTAG-Interface o.ä.)
Poste nochmal:
- dein aktuelles Programm
- deine tatsächliche Schaltung
- Was Genau passiert und was nicht!
Ebenfalls Frohe Ostern!
hth. Jörg (dem langsam langweilig wird)
ps.: Wie kommst du nur auf die Idee "Bit 2" sei das zweite Bit ? ;)
Ein Byte sieht doch so aus:
1
Bit 7|Bit 6|Bit 5|Bit 4|Bit 3|Bit 2|Bit 1|Bit 0
(wegen 2 hoch 7, etc..), also ist "Bit 2" das dritte :D
Ja Bit zwei ist das dritte, hast recht. Aber ich hatte jetzt das
zweitwärtigste gemeint :-P
Und du hattest Recht, bei dem Debugger hatte ich 517 stehen. Hatte mich
selbst verdacht..... langsam wirds konfus :)
Und ja, ich habe mir schon so gedacht dass es dir bald langweilig werden
müsste...
Deshalb: Ich habe es mittlerweile über die Software-SPI gelöst. Die
erscheint mir irgendwie einfacher als diese ganze
Konfigurationsgeschichte des Hardware SPI. Den Code für die Soft-SPI
habe ich von Tobias Schlegel - http://www.tobias-schlegel.de/ und
ihn ein wenig abgeändert.
Mein Sensor ist also richtig angeschlossen ;)
Merkwürdig, das SPI ist ja schließlich noch eines der einfachsten
Pheripherals.
Aber da der MAX ja ewig für die Wandlung braucht, hast du definitiv Zeit
für Soft-SPI ;)
Schön, dass es geht
hth. Jörg