// Rapsberry Pi: SPI in C - Versione 0.56 - Luglio 2013 // Copyright (c) 2013, Vincenzo Villa (https://www.vincenzov.net) // Creative Commons | Attribuzione-Condividi allo stesso modo 3.0 Unported. // Creative Commons | Attribution-Share Alike 3.0 Unported // https://www.vincenzov.net/tutorial/elettronica-di-base/RaspberryPi/spi-c.htm // Compile: gcc max146.c -std=c99 -o max146 // Run as user with R&W right on /dev/spidev0.* (NOT ROOT!) // vv@vvrpi ~ $ ./max146 4 // Using MAX146 - Read a single voltage #include #include #include #include #include #include #include #include #include #define SPI_SPEED 2000000 // SPI frequency clock #define VREF 2.500 // MAX146 voltage reference #define MAX146_CONTROL_BYTE 0x8F // 1000 1111 = Unipolar, single ended, external clock (see datasheet) static const char *device = "/dev/spidev0.0"; // MAX146 CS to RPi CE0 static uint8_t mode = SPI_MODE_0; // Set SPI mode static void exit_on_error (const char *s) // Exit and print error code { perror(s); abort(); } int main(int argc, char *argv[]) { int fd; double volt; uint16_t data; uint8_t rx[3]; // RX buffer (3 byte) uint8_t tx[3]; // TX buffer (3 byte) struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = 3, .delay_usecs = 0, .speed_hz = SPI_SPEED, .bits_per_word = 8, .cs_change = 0, }; if (argc != 2) { printf ( "Usage: \n rpi ~ $ ./max146 CH\n CH is channel number, from 0 to 7\n\n"); exit(-1); } switch(argv[1][0]) // See data sheet { case '0': tx[0] = MAX146_CONTROL_BYTE | 0x00; break; case '1': tx[0] = MAX146_CONTROL_BYTE | 0x40; break; case '2': tx[0] = MAX146_CONTROL_BYTE | 0x10; break; case '3': tx[0] = MAX146_CONTROL_BYTE | 0x50; break; case '4': tx[0] = MAX146_CONTROL_BYTE | 0x20; break; case '5': tx[0] = MAX146_CONTROL_BYTE | 0x60; break; case '6': tx[0] = MAX146_CONTROL_BYTE | 0x30; break; case '7': tx[0] = MAX146_CONTROL_BYTE | 0x70; break; default: printf ( "Usage: \n rpi ~ $ ./max146 CH\n CH is channel number, from 0 to 7\n\n"); exit(-2); } tx[1]=0; tx[2]=0; // Open SPI device if ((fd = open(device, O_RDWR)) < 0) exit_on_error ("Can't open SPI device"); // Set SPI mode if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) exit_on_error ("Can't set SPI mode"); // Read data if (ioctl(fd, SPI_IOC_MESSAGE(1), &tr) < 1) exit_on_error ("Can't send SPI message"); // Adjust bit order from buffer (see datasheet) data = rx[1]; data = data << 5; data = data | (rx[2] >> 3); // Convert to voltage volt = VREF * data / 4096; printf("Rapsberry Pi: SPI in C - Versione 0.56 - Luglio 2013\n"); printf("Copyright (c) 2013, Vincenzo Villa (https://www.vincenzov.net)\n"); printf("Creative Commons | Attribuzione-Condividi allo stesso modo 3.0 Unported.\n"); printf("Creative Commons | Attribution-Share Alike 3.0 Unported\n"); printf("https://www.vincenzov.net/tutorial/elettronica-di-base/RaspberryPi/spi-c.htm\n\n"); printf("Reading data from MAX146 on %s\n\n", device); printf("Control byte sent to MAX146: 0x%X\n", tx[0]); printf("Raw data recived from MAX146: 0x%02X 0x%02X\n\n", rx[1], rx[2] ); printf("Voltage applied to CH%s = %f V\n\n", argv[1], volt); close(fd); return (0); }