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


von Heinz W. (heinz_wichtelmann)


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);
    }
  }
}

von Rufus Τ. F. (rufus) Benutzerseite


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?

von MeinerEiner (Gast)


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.

von Timmo H. (masterfx)


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.

von Karl H. (kbuchegg)


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.

von Heinz W. (heinz_wichtelmann)


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.

von Heinz W. (heinz_wichtelmann)


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!

von Heinz W. (heinz_wichtelmann)


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.

von Gast (Gast)


Lesenswert?

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

Möglichkeit:
1
void spi_writeBytes(unsigned int8 u8Anzahl, unsigned int8 *pu8Bytes)
2
{
3
 unsigned int8 u8Index;
4
5
 for(u8Index = 0; u8Index < u8Anzahl; u8Index++)
6
 {
7
  spi_write(*(pu8Bytes+u8Anzahl));
8
 }
9
}

Nicht getestet !

von Gast (Gast)


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;

von Heinz W. (heinz_wichtelmann)


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?

von Gast (Gast)


Lesenswert?

Um welchen Baustein handelt es sich denn?

von Heinz W. (heinz_wichtelmann)


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.

von Gast (Gast)


Lesenswert?

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

von Gast (Gast)


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."

von Heinz W. (heinz_wichtelmann)


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?

von ozo (Gast)


Lesenswert?

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

von Dispschalter (Gast)


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.

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

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

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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?

von Dispschalter (Gast)


Lesenswert?

Ja.

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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?

von Justus S. (jussa)


Lesenswert?

Heinz Wichtelmann (heinz_wichtelmann) schrieb:

> Versteht Ihr was ich meine?

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

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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?

von Dispschalter (Gast)


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.

von Karl H. (kbuchegg)


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?

von Dispschalter (Gast)


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

von Dispschalter (Gast)


Lesenswert?

huch...wenn du meinen fehler findest, hast du's verstanden ;-)

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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!!

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

Passt irgendwie nicht ganz mit der Bitanzahl zusammen?

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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

von Karl H. (kbuchegg)


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 :-)

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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^^

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

Ja sorry sorry sorry, aber ich hab mich verzählt :-D

von Karl H. (kbuchegg)


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)

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


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?

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

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

von Dispschalter (Gast)


Lesenswert?

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

Entschuldigung.

von Karl H. (kbuchegg)


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

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

Das war natürlich nur eine ironische Ergänzung ;-D

von Heinz Wichtelmann (heinz_wichtelmann) (Gast)


Lesenswert?

Aber Spaß beiseite, danke für die Hilfe!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.