spidev in c
-
Hallo,
ich experimentiere gerade auf dem RaspberryPi mit SPI...
dazu habe ich folgende funktionieren Funktion (steuert ein DIP204 von Electronic Assembly an):
static void lcd_send_byte(int fd,int command,char value) { #define COMMAND 0b00011111 // Command start byte (1f) #define WRITE_DATA 0b01011111 // Write Data start byte (5f) unsigned char cmd=0; if (command) cmd=COMMAND; else cmd=WRITE_DATA; char lowerdata=value & 0x0f; char upperdata=(value & 0xf0) >> 4; cmd=reversebits(cmd); lowerdata=reversebits(lowerdata); upperdata=reversebits(upperdata); char writecommand[3] = {cmd, lowerdata, upperdata, }; struct spi_ioc_transfer message[1] = {0}; //setup spi transfer data structure message[0].tx_buf = (unsigned long)writecommand; //send the write command an$ message[0].rx_buf = (unsigned long)NULL; message[0].len = sizeof(writecommand); //message[0].cs_change = 0; //keep holding chip select state message[0].cs_change = 1; int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &message); //spi check if sent if (ret < 1) pabort("can't send spi message"); usleep(5000); //wait 5ms for write command to c$ }
so jetzt dachte ich, ich kann gleich mehrere Bytes schicken (string):
static void lcd_send_string(int fd,char *value) { #define COMMAND 0b00011111 // Command start byte (1f) #define WRITE_DATA 0b01011111 // Write Data start byte (5f) unsigned char cmd=WRITE_DATA; unsigned int l=strlen(value); char *writecommand=malloc(1+l*2);//1byte for command/write-flag + 2byte per s$ cmd=reversebits(cmd); //LSB_FIRST (RPi does not support it) writecommand[0]=cmd; printf("len: %d (%d)\n",l,sizeof(writecommand*)); int i; for (i=0;i<l;i++) { char v=value[i]; printf("%c (%x)\n", v,v); char lowerdata=v & 0x0f; char upperdata=(v & 0xf0) >> 4; //reversing bits (LSB_FIRST not supported by RPi) lowerdata=reversebits(lowerdata); upperdata=reversebits(upperdata); writecommand[1+i*2]=lowerdata; writecommand[2+i*2]=upperdata; } struct spi_ioc_transfer message[1] = {0}; //setup spi transfer data structure message[0].tx_buf = (unsigned long)writecommand; //send the write command message[0].rx_buf = (unsigned long)NULL; message[0].len = sizeof(writecommand); //message[0].cs_change = 0; //keep holding chip select st$ message[0].cs_change = 1; //chip select needs to be relea$ free(writecommand); int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &message); //spi check if sent if (ret < 1) pabort("can't send spi message"); usleep(5000); //wait 5ms for write command to c$ }
kompiliert super und beim Ausführen kommt kein Fehler....der Text wird aber auch nicht auf dem Display angezeigt. Kann natürlich sein, dass ich trotzdem vor jedem Datenbyte-Paar noch mal das Startbyte senden muss (Datenblatt: www.lcd-module.de/eng/pdf/zubehoer/ks0073.pdf).
auf seite 52 des Datenblattes gibt es eine Ansicht für den "Continuous Write Mode" mit einer "Wait"-Zeit...nur wie realisiert man sowas (einfach ein 0-Byte)?
Deswegen wollte ich mal fragen, ob ich das prinzipiell vom Code her richtig habe (gerade wegen der dynamischen Speicherzuweisung). bevor ich da weiter im Dunkeln stochereGruß Frank
-
struct spi_ioc_transfer message[1] = {0}; // unsinniges Array message[0].tx_buf = (unsigned long)writecommand; message[0].rx_buf = (unsigned long)NULL; message[0].len = sizeof(writecommand); //message[0].cs_change = 0; message[0].cs_change = 1; free(writecommand); // UB weil tx_buf hier jetzt auf undefinierten Speicher zeigt int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &message); // UB wegen Adresse auf struct-Array statt Adresse auf struct
Bist du dir sicher, dass das ganze Reverse-Zeugs wirklich notwenig ist und nichts kaputt macht?
Ohne den Rpi jetzt wirklich zu kennen:
static void lcd_send_string(int fd,char *value) { #define COMMAND 0b00011111 // Command start byte (1f) #define WRITE_DATA 0b01011111 // Write Data start byte (5f) unsigned int len=strlen(value); char rxdummy[128]="",*writecommand=calloc(1,2+len+1); writecommand[0]=WRITE_DATA; strcpy(writecommand+2,value); struct spi_ioc_transfer message = { .tx_buf = (unsigned long)writecommand, .rx_buf = (unsigned long)rxdummy, .len = 2+len, .cs_change = 1, ... // hier sollte doch noch was kommen?! }; int ret = ioctl(fd, SPI_IOC_MESSAGE(1), &message); free(writecommand); // erst NACH Verwendung von message das free! if (ret < 1) pabort("can't send spi message"); usleep(5000); }
-
Danke für deine Nachricht.
Das Reverse-Zeug muss ich machen, da das Display LSB_FIRST erfordert, welches der Pi nicht unterstützt...
Was meinst du mit "UB"?
mit dem Free gebe ich dir absolut Recht...
das mit dem vorinitialisierten message-Array habe ich aus einem Beispiel-Code, wo noch die Indizes 1 und 2 gefüllt wurden...
was sollte noch in dem Message-Array drin sein?