Probleme mit mehr als 8 Bit rausschreiben

OP #1488648
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);
    }
  }
}
#1488659
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.
OP #1488738
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.
OP #1488745
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.
Gast #1488752
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 !
OP #1488760
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?
OP #1488785
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?
Gast #1488793
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.
Gast #1489077
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?
Gast #1489121
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?
Gast #1489133
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?
Gast #1489138
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.
Gast #1489146
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
Gast #1489154
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!!
Gast #1489186
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
#1489191
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 :-)
Gast #1489201
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^^
#1489207
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)
Gast #1489228
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?
#1489243
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren