Hallo Leute,
so langsam bin ich echt am Verzweifeln. Ich versuche nun seit Stunden
die SPI-Schnittstelle beim Arduino Uno zum laufen zu bekommen, um einen
12-Bit DA-Wandler des Typs MCP4821 anzusprechen. Ich bin mir bei der
Initialisierung der spi eigentlich sehr sicher alles richtig gemacht zu
haben. Nichts desto Trotz möchte ich euch bitten mal kurz drüber zu
schauen:
1
voidspi_Init(){
2
3
4
/** Set the CS-Pins as Output | Set Shutdown Pin output */
5
DDRD|=(1<<DDD6)|(1<<DDD5)|(1<<DDD4);
6
/** Set CS-Pins High --> no communication|shutdown mode off */
7
PORTD|=(1<<CS1)|(1<<CS2)|(1<<PD4);
8
/** Set MOSI, SCK, SS Output */
9
DDRB|=(1<<DDB3)|(1<<DDB5)|(1<<DDB2);
10
/** Enable SPI | Master Mode | prescaler 4 */
11
SPCR|=(1<<SPE)|(1<<MSTR);
12
}
so sieht erst mal die Initialisierung der Schnittstelle aus.
in der main wird nun zum Test einmalig folgendes gemacht:
1
uint16_tval=3000;
2
3
intmain(void)
4
{
5
/** start communication */
6
PORTD&=!(1<<PD5);
7
8
/** send command-bits and high-byte */
9
SPDR=(0x10|highByte(val));
10
while(!(SPSR&(1<<SPIF)));
11
12
/** send low-byte */
13
spi_send(lowByte(val));
14
while(!(SPSR&(1<<SPIF)));
15
16
/** end communication */
17
PORTD|=(1<<PD5);
18
}
die beiden Makros mit highByte und lowByte sind aus der
Arduino-Bibliothek abgeschrieben, ansonsten habe ich aber versucht alles
ohne die Wiring-Funktionen zu lösen. die 0x10h die im ersten Sendelauf
mit dem Spannungswert verodert werden sind commandbits für den DA, dann
folgen 12 bit an Daten.
Was mich nun so verwirrt seht ihr im mitgeliefertern oszi-screenshot:
CH1 - Chip-Select (PD5)
CH2 - MOSI
CH3 - Vout des DA
CH4 - SCK
Die Frequenz der Clock stimmt nicht mit der eingestellten überein und
nach drei Takten kommt kein ClK-Signal mehr raus? Außerdem wird kein
einziges Bit gesendet während der "Übertragung". Hat einer eine Idee was
da schief läuft?
Danke und schon mal Sorry im Voraus falls ich meine Hausaufgaben nicht
gemacht hab.
mfg,
Dennis
Sende doch erstmal einfach ein Byte, z.B. (hex) 55 oder AA, da brauchst
Du Dich um das SPIF nicht zu kümmern und solltest ein MOSI-Signal mit
der halben Frequenz der Clock sehen.
Und lies mal im Datenblatt - vielleicht ist bei SPCR noch mehr
einzustellen.
@Dennis (Gast)
>so langsam bin ich echt am Verzweifeln. Ich versuche nun seit Stunden>die SPI-Schnittstelle beim Arduino Uno zum laufen zu bekommen,
Warum nutzt du nicht die Arduino-Funktionen?
>void spi_Init(){
/** Set CS-Pins High --> no communication|shutdown mode off */
PORTD|= (1<<CS1)|(1<<CS2)|(1<<PD4);
/** Set MOSI, SCK, SS Output */
DDRB |= (1<<DDB3)|(1<<DDB5)|(1<<DDB2);
Beim AVR MUSS das SS-Pin als Ausgang geschaltet werden, sond geht das
nicht! Steht auch in der Arduino-Doku. Ausserdem sit SCLK PB1, nicht
PB5!
https://www.arduino.cc/en/Reference/SPIBegin
Falk B. schrieb:> Beim AVR MUSS das SS-Pin als Ausgang geschaltet werden, sond geht das> nicht!
Das stimmt so nicht ganz. Im Datenblatt des ATmega328P steht dazu:
"Sollte der die SPI im Master Mode konfiguriert sein kann der SS-Pin
frei konfiguriert werden (also als Input oder Output). Ist der SS-Pin
als Input konfiguriert, muss man allerdings dafür sorgen das er High
Pegel hat. Sollte die SPI als Master und der SS-Pin als Input
konfiguriert sein und man bekommt am SS-Pin ein Low Signal so wird die
SPI automatisch in den Slave-Mode zurückgesetzt."
> Steht auch in der Arduino-Doku. Ausserdem sit SCLK PB1, nicht> PB5!
Laut Datenblatt ist PB5 SCK
Hast du irgendwas an der ICSP-Schnittstelle angeschlossen?
Sajuuk schrieb:> Ist der SS-Pin als Input konfiguriert,> muss man allerdings dafür sorgen das er High Pegel hat.
Was macht man mit einem Input-Pin der nur High-Pegel haben darf? :-)
@ Rudolph (Gast)
>> Ist der SS-Pin als Input konfiguriert,>> muss man allerdings dafür sorgen das er High Pegel hat.>Was macht man mit einem Input-Pin der nur High-Pegel haben darf? :-)
Konstantenspeicher!
Neben dem SS-Pin, der wie bereits geschrieben wurde als Ausgang
geschaltet sein muss, ist die Polarität des Signals(Signalbeginn bei
steigender oder fallender Flanke)
Rudolph schrieb:> Was macht man mit einem Input-Pin der nur High-Pegel haben darf? :-)
MM...Gute Frage. Vielleicht ist die Platine ja nur ein Teil eines
Modularen Aufbaus und ich möchte das jedes Modul für sich autark läuft.
Kombiniert man mehrere Module möchte ich ja nur einen Master haben. Ist
der SS-Pin nun als Input geschaltet hat man so natürlich ne einfache
Möglichkeit, dass in der Hirarchie niedrigere Modul in den Slave-Mode zu
zwingen.
Aber wir schweifen glaub ich grad ab... ;-)
Es ist natürlich besser für die Anwendung des OP den SS-Pin im
SPI-Master-Mode als Output zu konfigurieren. Das hat der OP ja auch
getan.
Marco G. schrieb:> Neben dem SS-Pin, der wie bereits geschrieben wurde als Ausgang> geschaltet sein muss, ist die Polarität des Signals(Signalbeginn bei> steigender oder fallender Flanke)
Wenn du dir die Initialisierung anschaust wirst du festellen das die SPI
im Mode 0 ist. Also Bitübertragung bei steigender Flanke. Das passt für
den MCP4821.
Hallo nochmal,
danke schonmal für eure Ideen. Vorweg noch eine kleine Ergänzung zum
code aus meinem ersten Beitrag:
die Pins CS1 und CS2 sind natürlich PD5 und PD6, das hab ich nur wegen
der Handhabung so definiert. Und die Funktion spi_send(value) macht
nichts anderes wie die beiden Zeilen darüber, hab nur vergessen das
abzuändern. Nur falls Verwirrung aufkommen sollte. Nun zu euren
Vorschlägen:
Rainer U. schrieb:
> Sende doch erstmal einfach ein Byte, z.B. (hex) 55 oder AA, da> brauchst> Du Dich um das SPIF nicht zu kümmern und solltest ein MOSI-Signal mit> der halben Frequenz der Clock sehen.
das hab ich ausprobiert, leider kommt das selbe Ergebnis im scope.
Falk B. schrieb:
> Warum nutzt du nicht die Arduino-Funktionen?
Ich hab mir mal die Anleitung in der reference durchgelesen, habs aber
ehrlich gesagt nicht so ganz durchblickt wie die das machen. Und im
Atmel Datenblatt is es ja auch eigentlich wirklich gut erklärt und das
code-beispiel zur Initialisierung kann man ja auch fast abschreiben.
Sajuuk schrieb:
> Wenn du dir die Initialisierung anschaust wirst du festellen das die SPI> im Mode 0 ist. Also Bitübertragung bei steigender Flanke. Das passt für> den MCP4821.
Habe unabhängig davon die SPI-Pins auch direkt am Arduino abgegriffen.
Selbes Ergebnis...
@Dennis (Gast)
>> Warum nutzt du nicht die Arduino-Funktionen?>Ich hab mir mal die Anleitung in der reference durchgelesen, habs aber>ehrlich gesagt nicht so ganz durchblickt wie die das machen.
Bitte? Was kann einfacher sein als ein spi.begin() und spi.transfer()?
Und vor allem, das funktioniert!
In deinem Osziscreenshot sind Kanal 1 und 2 identisch, da stimmt was
nicht.
Kurzschlüsse?
Falk B. schrieb:
>> Bitte? Was kann einfacher sein als ein spi.begin() und spi.transfer()?> Und vor allem, das funktioniert!
Habs probiert mit den Arduino Funktionen --> gleiches Bild wieder
> In deinem Osziscreenshot sind Kanal 1 und 2 identisch, da stimmt was> nicht.> Kurzschlüsse?
Wenn ein Kurzschluss vorliegen sollte, dann eigentlich nur auf dem
Arduino selbst, da ich ja den D/A schon weggehängt hab und immernoch
dieselben Symptome vorliegen. Aber auch da scheint keiner vorzuliegen...
holger schrieb:
>> /** start communication */>> PORTD &= !(1<<PD5);>> PORTD &= ~(1<<PD5);
Oh das hab ich gar nich gesehen ^^. Aber war wohl auch nicht die Ursache
des Übels.
Falk B. schrieb:> In deinem Osziscreenshot sind Kanal 1 und 2 identisch, da stimmt was> nicht.> Kurzschlüsse?
Jetzt wo du es sagst. Was würde denn passieren wenn da ein Kurzschluss
ist?
Das erste Byte ist ja ne 00110000 also 0x30h. Wenn Chipseleckt und Mosi
kurzgeschlossen wären könnte es ja beim dritten Bit nen mehr oder
weniger kurzen High Piek auf der Chipselect Leitung geben. Das wäre
zumindest die bisher beste Erklärung für das Verhalten. Oder?
Du solltest auch mal das SHDN-Signal in deinem Oszi mit überwachen.
Nicht das da was merkwürdiges passiert. Es wäre auch hilfreich wenn du
mal nen Schaltplan von deiner Hardware reinstellst. Eventuell liegt das
Problem dort.
Mir ist auch noch was am Code aufgefallen.
>uint16_t val = 3000;
Das ergiebt doch: 3000 = 0x0BB8 = 00001011/10111000 oder liege ich da
falsch?
>SPDR = (0x10|highByte(val));
Das müsste dann Bitweise Oder von 0x10 und 0x0B = 0x1B sein.
Nun geht meine überlegung weiter.
In deiner initialisierung kann ich nicht sehen das du das du das Bit5
(DORD: Data Order Bit) im SPCR (SPI Control Register) auf High gesetzt
hast. Nun sendest du ja als erstes 0x1B (highByte) Da du das DORD Bit
nicht gesetzt hast wird zuerst das LSB von diesem Byte gesendet. Also
anstatt 00011011 (0x1B) sendest du 11011000. Im Datenblatt des MCP4821
steht aber das,dass erste Bit welches gesendet wird eine 0 sein muss bei
einer 1 wird das Kommando ignoriert.
Der linkt zu dem MCP4821 den du gepostet hast führt übrigens zu einem
veralteten Datenblatt du solltest dir mal ne aktuelle Version anschauen.
https://docs.google.com/viewer?url=https%3A%2F%2Fwww.google.de%2Furl%3Fsa%3Dt%26rct%3Dj%26q%3D%26esrc%3Ds%26source%3Dweb%26cd%3D2%26cad%3Drja%26uact%3D8%26ved%3D0ahUKEwjE7pe3kKvJAhVM7xQKHX-wDX4QFggpMAE%26url%3Dhttp%253A%252F%252Fww1.microchip.com%252Fdownloads%252Fen%252FDeviceDoc%252F22244B.pdf%26usg%3DAFQjCNGD9bco9NeBUc49GCOWDOIg8UYnvQ
Dennis schrieb:> Wenn ein Kurzschluss vorliegen sollte, dann eigentlich nur auf dem> Arduino selbst, da ich ja den D/A schon weggehängt hab und immernoch> dieselben Symptome vorliegen. Aber auch da scheint keiner vorzuliegen...
Also ist aktuell gar nix angeschlossen? Oder hast du noch Irgendwas an
der Programmierschnittstelle dran? Die hängt ja auch an der SPI.
Sajuuk schrieb:> Nun sendest du ja als erstes 0x1B (highByte) Da du das DORD Bit> nicht gesetzt hast wird zuerst das LSB von diesem Byte gesendet.
Das ist so nicht richtig. Lt. Datenblatt:
DORD == 0 --> MSB-first
DORD == 1 --> LSB-first
Dennis schrieb:> das hab ich ausprobiert, leider kommt das selbe Ergebnis im scope.
auch wenn Du das aller-einfachste Arduino-Sample zum senden eines Bytes
per SPI benutzt? Das Senden passiert ja eigentlich mit der SPI-Hardware,
also wenn da ein Byte rausgeht, sollte die Clock 8x "klingeln". Wenn
nicht, würde ich an der Hardware zweifeln.
Oder benutzt Du Software-SPI?
Sajuuk schrieb:
> Der linkt zu dem MCP4821 den du gepostet hast führt übrigens zu einem> veralteten Datenblatt du solltest dir mal ne aktuelle Version anschauen.> https://docs.google.com/viewer?url=https%3A%2F%2Fw...
ehrlich gesagt hab ich da selber gar nichts verlinkt das wurde
automatisch gemacht ^^. Habe die aktuelle Version verwendet.
> Also ist aktuell gar nix angeschlossen? Oder hast du noch Irgendwas an> der Programmierschnittstelle dran? Die hängt ja auch an der SPI.
nein ich gehe momentan direkt mit den tastköpfen auf die Pins vom
Arduino. Dachte mir halt wenn eh nichts gescheites aus der MOSI-Leitung
rauskommt, brauch ich auch nichts anzuschließen. An der ISP hängt nichts
dran.
Habe auch die gesamte SPI Peripherie nochmal auf Kurzschluss geprüft, da
ist definitiv alles IO.
Rainer U. schrieb:
> Dennis schrieb:>> das hab ich ausprobiert, leider kommt das selbe Ergebnis im scope.>> auch wenn Du das aller-einfachste Arduino-Sample zum senden eines Bytes> per SPI benutzt? Das Senden passiert ja eigentlich mit der SPI-Hardware,> also wenn da ein Byte rausgeht, sollte die Clock 8x "klingeln". Wenn> nicht, würde ich an der Hardware zweifeln.>> Oder benutzt Du Software-SPI?
ja eben das verwundert mich ja, dass die clock erstens mal viel später
einsetzt als die fallende flanke vom CS, und dann noch dass nach 3
cycles einfach schluss ist. Ich verwende die normale SPI-Peripherie des
µC.
Sajuuk schrieb:> Dann würde ich mal vorschlagen du nimmst nen zweites Uno und> testest es> mal.
ist in Arbeit. Frag grad rum wer eins hat, hab jez nich grad ne Sammlung
oder so.
Hab auch mal versucht n altes Projekt per ISP mit dem Uno als Programmer
zu flashen. Das geht komischerweise...