mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit mehr als 8 Bit rausschreiben


Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Hab ein Problem mit meinem Mikrocontroller.
Ich kann ganz normal 8 Bit rausschreiben über die SPI, hab das Ganze 
über einen Logikanalysator aufgenommen und ausgewertet.
Bei dem Versuch, 16 Bit über die SPI rauszuschreiben, schreibt der 
Mikrocontroller trotzdem nur 8 Bit raus.
Wo liegt mein Fehler?

µC: PIC18F452, mit CCS Compiler



#fuses HS, NOWDT, NOBROWNOUT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
#use standard_io(d)
#use spi(FORCE_HW, BITS=16, MSB_FIRST)


unsigned int8 i=0;
unsigned int8 j=0;

#define CS PIN_E0



void main()
  {

  enable_interrupts(GLOBAL);
  setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
  delay_ms(100);

  while (1)
  {
  for(i = 200; i <=255; i++)
    {
      for(j=0;j<=50;j++)
      {
           printf("\n\r j=%lu",j);
           output_low(CS);
           spi_write(0xaa);
           //spi_write(0xaaaa);  //-->GEHT NICHT!
           output_high(CS);
           delay_ms(10);
      }
      delay_ms(100);
    }
  }
}

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>            //spi_write(0xaaaa);  //-->GEHT NICHT!


Wie ist denn "spi_write" deklariert? Was macht die Funktion? Und kann 
die SPI-Hardware Deines µCs überhaupt 16-Bit-Zugriffe ausführen?

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denk mal, weil spi_write (wie auch immer das definiert ist) nur 8 
Bit haben will. Einfach 2x 8 Bit schicken oder die Funktion ändern.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann spi_write nicht nur 8-Bit (char,uchar), oder wie sieht der Prototyp 
aus. Ansonsten machst halt
spi_write(0xaa);
spi_write(0xaa);

EDIT: Verdammt, zu langsam. Immerhin alle die gleiche Idee.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spi_write wird halt nur 1 Byte übertragen.
UNd wenn du versuchst dort 1 Mb hineinzustopfen, wird es trotzdem nur 1 
Byte übertragen.

Aber man kann spi_write ja auch 2 mal aufrufen. Einmal mit dem High-Byte 
und einmal mit dem Low-Byte. Oder auch umgekehrt: Zuerst Low-Byte, dann 
High-Byte. Je nachdem wie es die Gegenstelle haben will.

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:
>>            //spi_write(0xaaaa);  //-->GEHT NICHT!
>
>
> Wie ist denn "spi_write" deklariert? Was macht die Funktion? Und kann
> die SPI-Hardware Deines µCs überhaupt 16-Bit-Zugriffe ausführen?

spi_write ist ein Standardbefehl des CCS. Die Funktion schreibt den Wert 
raus,welchen man ihr angibt. Ob das die Hardware kann,weiß ich jetzt 
nicht,aber ich bin auf nen andren weg gekommen,ich glaub,dass es die 
Software nicht zulässt mehr rauszuschreiben, da der spi_write Befehl 
angeblich nur ein Byte rausschreiben soll.

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MeinerEiner schrieb:
> Ich denk mal, weil spi_write (wie auch immer das definiert ist) nur 8
> Bit haben will. Einfach 2x 8 Bit schicken oder die Funktion ändern.

Danke, ist richtig!

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timmo H. schrieb:
> kann spi_write nicht nur 8-Bit (char,uchar), oder wie sieht der Prototyp
> aus. Ansonsten machst halt
> spi_write(0xaa);
> spi_write(0xaa);
>
> EDIT: Verdammt, zu langsam. Immerhin alle die gleiche Idee.

Danke,
aber da stellt sich bei mir nur die nächste Frage:
Macht es dem Baustein etwas aus? Oder achtet der Baustein nur darauf ob 
SS auf High oder Low ist?
Der Baustein der angesprochen werden soll ist der 25LC320 (EEPROM) von 
Microchip.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja wie oben schon geschrieben: spi_write(x) schreibt nur 8-Bit über SPI.

Möglichkeit:
void spi_writeBytes(unsigned int8 u8Anzahl, unsigned int8 *pu8Bytes)
{
 unsigned int8 u8Index;

 for(u8Index = 0; u8Index < u8Anzahl; u8Index++)
 {
  spi_write(*(pu8Bytes+u8Anzahl));
 }
}


Nicht getestet !

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dem chip ist es egal. Nu musst nur das Chip Select richtig setzen.

Also:

setze Chipselect;
spi_write(0xaa);
spi_write(0xaa);
lösche Chipselet;

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Dem chip ist es egal. Nu musst nur das Chip Select richtig setzen.
>
> Also:
>
> setze Chipselect;
> spi_write(0xaa);
> spi_write(0xaa);
> lösche Chipselet;

Ja genau, so habe ich es auch gemeint :-)
Dankeschön für die Hilfe.


Wo ich aber jetzt schon im Forum aktiv bin, hätte ich die nächste Frage:
Einen Baustein zu beschreiben, der 11 Bit verlangt, wird wohl für mich 
nur zu Fuß möglich sein oder?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um welchen Baustein handelt es sich denn?

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Um welchen Baustein handelt es sich denn?

Es handelt sich um den AD5292, und Korrektur: 10 Bits.
Zuerst werden 6 Steuerbits (Ersten zwei sind nutzlos,also 4 Steuerbits) 
rausgeschrieben, danach zehn Datenbits.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Dtaenblatt eben überflogen:
Der wird mit 16-Bit gefüttert. Die ersten 2 Bits haben dabei keine 
Funktion.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag:

Zitat aus dem Datenblatt: "The AD5291/AD5292 shift register is 16 bits 
wide (see Figure 2). The 16-bit input word consists of two unused bits 
(set to 0),
followed by four control bits, and 10 RDAC data bits."

Autor: Heinz Wichtelmann (heinz_wichtelmann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Hab das Dtaenblatt eben überflogen:
> Der wird mit 16-Bit gefüttert. Die ersten 2 Bits haben dabei keine
> Funktion.

JA
Mit 10 Bits mein ich nur die Datenbits, hab mich etwas umständlich 
artikuliert.
Natürlich sind es insgesamt 16 Bit. Wird aber nur zu Fuß möglich sein, 
oder habt ihr eine Idee?

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber du hast doch oben schon 16Bit geschrieben?
Wo liegt denn jetzt das Problem?

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach wie vor:

> setze Chipselect;
> spi_write(0xaa);
> spi_write(0xaa);
> lösche Chipselet;

Du musst nur den ersten und zweiten Wert entsprechend vorbereiten, ist 
easy.
Nimm eine uint16_t variable, und setze sie auf zu übertragenden wert (10 
Bit).
Das ganze shiftest du 6 bits nach links, verORst das mit deinen 
Controlbits, und gut. Anschliessend macht du spi_writes() für das lo und 
und hi byte.

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht falsch verstehen, der obrige Quellcode hat mit dem AD5292 nichts 
zu tun!!!
Das ist ein ganz unabhängiges Thema!

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also so, dass zum Beispiel im Higher Byte schon ein Teil der Daten 
steht. D.h. zwei Datenbits werden schon im ersten Byte mitgesendet?
2 aussagelose Bits + 4 Steuerbits + 2 Datenbits = 1 Byte
Rest im Lower Byte?

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja.

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Puh...
Da stellt sich mir schon die nächste Frage.
Ich möchte die zehn Datenbits aber als Dezimalwert rausschreiben.
Jetzt stellt sich ja die Frage, wie kann ich den Dezimalwert in einen 
Binärwert umwandeln, sodass ich die Bits shiften kann?
Versteht Ihr was ich meine?
Wie würde so eine Realisierung aussehen?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz Wichtelmann (heinz_wichtelmann) schrieb:

> Versteht Ihr was ich meine?

nein...im µC sind alle Zahlen binär, was anderes gibt es nicht

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja OK, aber, möchte ich zum Beispiel den Wert "126d", also 1111110b 
rausschreiben, wie realisiere ich dann das shiften? Sodass eben die zwei 
MSB schon mit dem Higher Byte gesendet werden?

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...gleichzeitig sind alles zahlen hexadezimal, was anderes gibt es 
nicht!
und sie sind auch "dezimal", was anderes gibt es nicht!

ok..was damit gesagt werden soll, ist: nur die DARSTELLUNG entscheidet, 
ob bei du der AUSGABE einer Zahl ihre Binäre, Dezimale, oder 
Hexadezimale oder wasauchimmer REPRESENTATION siehst.


Aber das sind absolutes Bascis.. bevor du irgendwas mit Programmierung 
anfängst, noch dazu in C solltest du dich zumindest ein bischen 
einlesen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t  Wert = 328;

uint8_t HighByte = ( Wert >> 8 );
uint8_t LowByte  = Wert;

Bist du sicher, dass du vorher nicht ein wenig Basics am PC üben 
solltest?

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t a = 126; // = 1111110b

inhalt von a : 000000001111110b

um 6 stellen shiften:

a = (a<<6); // 001111110000000b

jetzt noch die control-bits um 2 verschoben verORen

//controlbits = 0101b

a = a | (0b0101 << 2);

ergebnis:

0b001111110010100

oder anders ausgedrückt :
00111111 0010100
^hi      ^lo

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
huch...wenn du meinen fehler findest, hast du's verstanden ;-)

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein warum?
Ich bin mir dessen bewusst, dass die Zahlenformate in jeglicher Form 
implementiert werden können. Hab nur gedacht, zum shiften muss man es 
vielleicht in eine Art umwandeln etc.
Dass wenn ich einen Int16 verwende die Dezimalzahl immer "16" Bit hat, 
ist mir bewusst!
Ich dachte nicht, dass mein so "einfach" shiften kann, aber DANKE für 
die Information!!

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Passt irgendwie nicht ganz mit der Bitanzahl zusammen?

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t a = 126; // = 1111110b

inhalt von a : 00000000001111110b

um 6 stellen shiften:

a = (a<<3); // 0000011111100000b

jetzt noch die control-bits verschieben

//controlbits = 0101b

a = a | (0b0101 << 13);

ergebnis:

0b0001010001111110

oder anders ausgedrückt :
00010100 01111110
^hi      ^lo

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz Wichtelmann (heinz_wichtelmann) schrieb:
> uint16_t a = 126; // = 1111110b
>
> inhalt von a : 00000000001111110b
>
> um 6 stellen shiften:
>
> a = (a<<3); // 0000011111100000b

Genau. Drum schreibt man 3, wenn man um 6 Stellen schieben muss :-)
(Geschenkt, ist nur ein Tippfehler)

>
> jetzt noch die control-bits verschieben
>
> //controlbits = 0101b
>
> a = a | (0b0101 << 13);

Warum 13?
Du hast 10 Datenbits. Wenn die Kontrollbits links von diesen 10 Bits 
sein sollen, dann wird man wohl um 10 Bits verschieben.

> ergebnis:
>
> 0b0001010001111110

Aber nur wenn du vom Originalen a ausgehst :-)

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t a = 126; // = 1111110b

inhalt von a : 0000000001111110b

um 3 stellen shiften:

a = (a<<3); // 0000001111110000b

jetzt noch die control-bits verschieben

//controlbits = 0101b

a = a | (0b0101 << 10);

ergebnis:

0b0001011111110000b

oder anders ausgedrückt :
00010111 11110000
^hi      ^lo

Jetzt hab ich mal genau nachgezählt^^

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja sorry sorry sorry, aber ich hab mich verzählt :-D

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bleibt nur noch die Frage, warum du a (welches ja offenbar den Wert 
darstellt) überhaupt verschiebst :-)

Dein Datenblattt fordert von dir das du sendest

   00ccccdddddddddd

c  Controlbits
d  Datenbits
0  0-Bits

gesendet in 2 Paketen (aka Bytes)

  00ccccdd    dddddddd


Die komplette 16 Bit Zahl entsteht also durch

    total = ( control << 10 ) | Daten;

  und die Bytes kriegst du

     HighByte = total >> 8;
     LowByte  = total;

(Noch die richtigen Datentypen eingesetzt und ev. sollte man bei den 
Datenwerten noch dafür sorgen, dass da nicht zufällig noch ein 1-Bit 
über dem 10. Datenbit existiert. Aber das wars dann)

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, hier stellt sich die Frage warum überhaupt verschieben? Es würde 
so ganz gut klappen.
Und jetzt habe ich mir noch etwas überlegt, wozu das Ganze?
Ich kann ja ganz einfach den Higher Byte rausschreiben und die zwei MSB 
mit Null ergänzen (Gut, dann hab ich nichtmehr so viel Bit für Daten zur 
Verfügung, aber das ist mir egal!)
In das restliche Lower Byte schreibe ich meinen Wert ganz einfach als 
unsigned int8 und fertig.
Ist meine Überlegung richtig oder?


Blöd wäre es nur, würde ich die vollen 10 Bit wollen.
Denn was wäre, wenn ich eine Zahl eingebe, wo die letzten MSB 1 sind? 
Z.B.: 1000000000b = 512d.
Dann müsste ich eine Abfrage dazuprogrammieren, bei welchen Zahlen die 
MSB eins sind, und diese dann verarbeiten.
Ist aber auch irgendwie blöd oder?

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder so gehts natürlich auch, wie du das beschrieben hast!!
Super, danke für die Hilfe! :-)

Autor: Dispschalter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
öh... ok,ich nehm alles zurück, ich hab das Datenblatt nämlich nicht 
gelesen und ging von einer anderer Reihenfolge aus.

Entschuldigung.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz Wichtelmann (heinz_wichtelmann) schrieb:

> Und jetzt habe ich mir noch etwas überlegt, wozu das Ganze?
> Ich kann ja ganz einfach den Higher Byte rausschreiben und die zwei MSB
> mit Null ergänzen (Gut, dann hab ich nichtmehr so viel Bit für Daten zur
> Verfügung, aber das ist mir egal!)
> In das restliche Lower Byte schreibe ich meinen Wert ganz einfach als
> unsigned int8 und fertig.
> Ist meine Überlegung richtig oder?

Wenn du nach 6 Stunden einen derartigen Vorschlag bringst, sollte man 
eigentlich als Helfer einen Schreikrampf bekommen.

6 Stunden!
Für einen 3-Zeiler!
Bei dem der Compiler die meiste Arbeit macht!


Aaaaaaargh

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das war natürlich nur eine ironische Ergänzung ;-D

Autor: Heinz Wichtelmann (heinz_wichtelmann) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber Spaß beiseite, danke für die Hilfe!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.