drakejest
Posts: 31
Joined: Sun Feb 14, 2021 7:28 pm

simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 4:41 pm

Im looking for a simple example for raspberrypi using the spi communications via spi dev. google has not been kind to me show some results. Most SPI dev examples are python while i need it to be C/C++. I was hoping you could help me show me a code snippet / example as basic as a loopback test. I think that would be enough so i can build what i need down the road. it doesnt even need to have the functions for setting the GPIO as i already have codes for them. just the raw setting of clock speed and sendRecieveByte functions.


Thank you


drakejest
Posts: 31
Joined: Sun Feb 14, 2021 7:28 pm

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 5:22 pm

joan wrote:
Sun Feb 21, 2021 4:54 pm
spi-driver-speed.c at http://abyz.me.uk/rpi/pigpio/faq.html#How_fast_is_SPI
this relies on a daemon running on the background right? would you have to happen to have a example for purely c/c++ just like your minimal examples? or i am misunderstanding how spidev works and inorder to use it inside c/c++ there must be a daemon

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 5:52 pm

No, it does not depend on pigpio. It uses spidev. I use that code to compare spidev's performance with the performance of the pigpio SPI driver.

drakejest
Posts: 31
Joined: Sun Feb 14, 2021 7:28 pm

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 6:30 pm

joan wrote:
Sun Feb 21, 2021 5:52 pm
No, it does not depend on pigpio. It uses spidev. I use that code to compare spidev's performance with the performance of the pigpio SPI driver.
ohh ! if you dont mind me asking why is the spidev so slow? although the spidev performance is within what i need, i am curious as it may become a problem in the future

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 6:44 pm

drakejest wrote:
Sun Feb 21, 2021 6:30 pm
joan wrote:
Sun Feb 21, 2021 5:52 pm
No, it does not depend on pigpio. It uses spidev. I use that code to compare spidev's performance with the performance of the pigpio SPI driver.
ohh ! if you dont mind me asking why is the spidev so slow? although the spidev performance is within what i need, i am curious as it may become a problem in the future
I haven't bothered to find out precisely why as it's outside my control. I'd guess the layoff between userland and the kernel is soaking up the time. pigpio stays in userland for the transaction.

drakejest
Posts: 31
Joined: Sun Feb 14, 2021 7:28 pm

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 8:09 pm

I noticed that when executing the example code (http://abyz.me.uk/rpi/pigpio/code/spi-driver-speed.c) i dont see the signals in my logic analyzer. Is this normal for the test file or something is wrong? I am probing SPI0 and the code is set to SPI0 the bus speed is also 1Mhz which is far from the 24mHz limit of y logic analyzer

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 8:13 pm

The code assumes you have correctly configured the SPI bus, e.g. by enabling it with raspi-config or by adding the correct entries in /boot/config.txt. It also assumes you haven't changed the modes of any GPIO that were configured for SPI.

drakejest
Posts: 31
Joined: Sun Feb 14, 2021 7:28 pm

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 8:38 pm

joan wrote:
Sun Feb 21, 2021 8:13 pm
The code assumes you have correctly configured the SPI bus, e.g. by enabling it with raspi-config or by adding the correct entries in /boot/config.txt. It also assumes you haven't changed the modes of any GPIO that were configured for SPI.
ahhh you are absolutely right i did a reboot and i can see it, only the serial clock though.

Also is it normal for the clock to fluctuate so much 4-12mHz (set to 10Mhz bps) and it would seem i cant puush it to 20Mhz

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Sun Feb 21, 2021 9:08 pm

I would expect the clock to be stable, but it's not something I have ever tested.

User avatar
DougieLawson
Posts: 40821
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: simple examples for C/C++ spi communications using spidev

Mon Feb 22, 2021 7:10 pm

Code: Select all

#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>

#define MAX7219_REG_NOOP 0x00
#define MAX7219_REG_DIGIT0 0x01
#define MAX7219_REG_DIGIT1 0x02
#define MAX7219_REG_DIGIT2 0x03
#define MAX7219_REG_DIGIT3 0x04
#define MAX7219_REG_DIGIT4 0x05
#define MAX7219_REG_DIGIT5 0x06
#define MAX7219_REG_DIGIT6 0x07
#define MAX7219_REG_DIGIT7 0x08
#define MAX7219_REG_DECODEMODE 0x09
#define MAX7219_REG_INTENSITY 0x0A
#define MAX7219_REG_SCANLIMIT 0x0B
#define MAX7219_REG_SHUTDOWN 0x0C
#define MAX7219_REG_DISPLAYTEST 0x0F

#define CMD_WRITE 0x40

typedef struct
{

 int digits[8];

} max7219;


max7219 header;

int spi_fd;
struct sigaction act;
static char *spiDevice = "/dev/spidev0.1";
static uint8_t spiBPW = 8;
static uint32_t spiSpeed = 5000000;
static uint16_t spiDelay = 0;

int spiOpen(char* dev)
{
  if((spi_fd = open(dev, O_RDWR)) < 0)
  {
    printf("error opening %s\n",dev);
    return -1;
  }
  return 0;
}

void writeByte(uint8_t reg, uint8_t data)
{
  uint8_t spiBufTx [3];
  uint8_t spiBufRx [3];
  struct spi_ioc_transfer spi;
  memset (&spi, 0, sizeof(spi));
  spiBufTx [0] = CMD_WRITE;
  spiBufTx [1] = reg;
  spiBufTx [2] = data;
  spi.tx_buf =(unsigned long)spiBufTx;
  spi.rx_buf =(unsigned long)spiBufRx;
  spi.len = 3;
  spi.delay_usecs = spiDelay;
  spi.speed_hz = spiSpeed;
  spi.bits_per_word = spiBPW;
  ioctl(spi_fd, SPI_IOC_MESSAGE(1), &spi);
}

void writeBytes(max7219 *header, int cmd, int data)
{
  if(!header) return;
  writeByte(cmd, data);
}

void setBrightness(max7219 *header, int bright)
{
  if(!header) return;
  if (bright < 0) bright = 0;
  if (bright > 15) bright = 15;

  writeBytes(header, MAX7219_REG_INTENSITY, bright);
}

void initialiseDisplay(max7219 *header)
{
  spiOpen(spiDevice);

  writeBytes(header, MAX7219_REG_SCANLIMIT, 7);
  writeBytes(header, MAX7219_REG_DECODEMODE, 0xff);
  writeBytes(header, MAX7219_REG_SHUTDOWN, 1);
  writeBytes(header, MAX7219_REG_DISPLAYTEST, 0);
  setBrightness(header, 5);
}

void byte_to_binary(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }
    printf("%s", b);
}

void digitDisplay(max7219 *header)
{
  int i;
  if(!header) return;
  for (i=0; i<8; i++)
  {
    writeBytes(header, i+1, header->digits[i]);
  }
}

void clearDisplay(max7219 *header)
{
  int i;
  if(!header) return;
  for (i=0; i<8; i++) {
    header->digits[i] = 0x0F;
  }
  digitDisplay(header);
}

uint8_t asciiToBCD (uint8_t chr)
{
  uint8_t bcd_value;
  bcd_value = (chr - 48);
  return bcd_value;
}

void writeDigits(max7219 *header, char chars[12])
{
  int i,j;
  if (!header) return;
  i = 7;
  j = 0;
  while (j <= 11 && i >= 0)
  {
    switch ((int)chars[j]) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':

      header->digits[i] = asciiToBCD(chars[j]);
      j++;
      i--;
      break;
    case ' ':
      header->digits[i] = 0x0F;
      j++;
      i--;
      break;
    case '-':
      header->digits[i] = 0x0a;
      j++;
      i--;
      break;
    case ':':
      header->digits[i] = 0x8f;
      j++;
      i--;
      break;
    case '.':
      header->digits[i+1] = header->digits[i+1] + 0x80;
      j++;
      break;
    case 0x00:
      j = 12;
      i = -1;
      break;
    default:
      j++;
      break;
    }
  }
  digitDisplay(header);
}

void sig_handler(int signum, siginfo_t *info, void *ptr)
{
  clearDisplay(&header);
  printf("Received signal %d\n", signum);
  printf("Signal originated from process %lu\n",
    (unsigned long)info->si_pid);
  exit(0);
}

int main()
{
  memset(&act, 0, sizeof(act));

  act.sa_sigaction = sig_handler;
  act.sa_flags = SA_SIGINFO;
  sigaction(SIGTERM, &act, NULL);

  char chars[12] = "12:34:56";
  initialiseDisplay(&header);
  clearDisplay(&header);

  while (1)
  {

    clearDisplay(&header);
    writeDigits(&header, chars);
    sleep(1);
  }

  return 0;
}

That one simply sends "12.34.56" to a SPI connected MAX7219 display.
Any language using left-hand whitespace for syntax is ridiculous

Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.

Any requirement to use a crystal ball or mind reading will result in me ignoring your question.

plugwash
Forum Moderator
Forum Moderator
Posts: 3737
Joined: Wed Dec 28, 2011 11:45 pm

Re: simple examples for C/C++ spi communications using spidev

Tue Feb 23, 2021 5:45 am

joan wrote:
Sun Feb 21, 2021 6:44 pm
I haven't bothered to find out precisely why as it's outside my control. I'd guess the layoff between userland and the kernel is soaking up the time. pigpio stays in userland for the transaction.
SPI_IOC_MESSAGE does allow you to send more than one transaction at a time, I wonder how this impacts overall performance.

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Tue Feb 23, 2021 8:38 am

plugwash wrote:
Tue Feb 23, 2021 5:45 am
joan wrote:
Sun Feb 21, 2021 6:44 pm
I haven't bothered to find out precisely why as it's outside my control. I'd guess the layoff between userland and the kernel is soaking up the time. pigpio stays in userland for the transaction.
SPI_IOC_MESSAGE does allow you to send more than one transaction at a time, I wonder how this impacts overall performance.
Pretty dramatically I'd guess. I'll have a look when I get a bit of time.

User avatar
joan
Posts: 15378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: simple examples for C/C++ spi communications using spidev

Tue Feb 23, 2021 11:44 am

Some results. Perhaps not as dramatic as I thought.

Code: Select all

3 byte transfers 1Mbps          IOCS

pi4b:~ $ ./a.out 3 1000000 10000 1
sps=6543.9: 3 bytes @ 1000000 bps iocs 1(loops=10000 time=1.5)
pi4b:~ $ ./a.out 3 1000000 10000 2
sps=7662.8: 3 bytes @ 1000000 bps iocs 2(loops=10000 time=2.6)
pi4b:~ $ ./a.out 3 1000000 10000 3
sps=8031.5: 3 bytes @ 1000000 bps iocs 3(loops=10000 time=3.7)
pi4b:~ $ ./a.out 3 1000000 10000 4
sps=8464.4: 3 bytes @ 1000000 bps iocs 4(loops=10000 time=4.7)
pi4b:~ $ ./a.out 3 1000000 10000 5
sps=8682.2: 3 bytes @ 1000000 bps iocs 5(loops=10000 time=5.8)
pi4b:~ $ ./a.out 3 1000000 10000 6
sps=8779.8: 3 bytes @ 1000000 bps iocs 6(loops=10000 time=6.8)
pi4b:~ $ ./a.out 3 1000000 10000 7
sps=8876.3: 3 bytes @ 1000000 bps iocs 7(loops=10000 time=7.9)
pi4b:~ $ ./a.out 3 1000000 10000 8
sps=8893.4: 3 bytes @ 1000000 bps iocs 8(loops=10000 time=9.0)
pi4b:~ $ ./a.out 3 1000000 10000 9
sps=8985.3: 3 bytes @ 1000000 bps iocs 9(loops=10000 time=10.0)

3 byte transfers 2Mbps          IOCS

pi4b:~ $ ./a.out 3 2000000 10000 1
sps=11121.2: 3 bytes @ 2000000 bps iocs 1(loops=10000 time=0.9)
pi4b:~ $ ./a.out 3 2000000 10000 2
sps=15100.3: 3 bytes @ 2000000 bps iocs 2(loops=10000 time=1.3)
pi4b:~ $ ./a.out 3 2000000 10000 3
sps=18182.5: 3 bytes @ 2000000 bps iocs 3(loops=10000 time=1.6)
pi4b:~ $ ./a.out 3 2000000 10000 4
sps=19189.2: 3 bytes @ 2000000 bps iocs 4(loops=10000 time=2.1)
pi4b:~ $ ./a.out 3 2000000 10000 5
sps=20738.8: 3 bytes @ 2000000 bps iocs 5(loops=10000 time=2.4)
pi4b:~ $ ./a.out 3 2000000 10000 6
sps=21337.6: 3 bytes @ 2000000 bps iocs 6(loops=10000 time=2.8)
pi4b:~ $ ./a.out 3 2000000 10000 7
sps=21841.1: 3 bytes @ 2000000 bps iocs 7(loops=10000 time=3.2)
pi4b:~ $ ./a.out 3 2000000 10000 8
sps=21755.8: 3 bytes @ 2000000 bps iocs 8(loops=10000 time=3.7)

3 byte transfers 4Mbps          IOCS

pi4b:~ $ ./a.out 3 4000000 10000 1
sps=12641.4: 3 bytes @ 4000000 bps iocs 1(loops=10000 time=0.8)
pi4b:~ $ ./a.out 3 4000000 10000 2
sps=20255.9: 3 bytes @ 4000000 bps iocs 2(loops=10000 time=1.0)
pi4b:~ $ ./a.out 3 4000000 10000 3
sps=26284.1: 3 bytes @ 4000000 bps iocs 3(loops=10000 time=1.1)
pi4b:~ $ ./a.out 3 4000000 10000 4
sps=29089.3: 3 bytes @ 4000000 bps iocs 4(loops=10000 time=1.4)
pi4b:~ $ ./a.out 3 4000000 10000 5
sps=31196.7: 3 bytes @ 4000000 bps iocs 5(loops=10000 time=1.6)
pi4b:~ $ ./a.out 3 4000000 10000 6
sps=32592.1: 3 bytes @ 4000000 bps iocs 6(loops=10000 time=1.8)
pi4b:~ $ ./a.out 3 4000000 10000 7
sps=32463.5: 3 bytes @ 4000000 bps iocs 7(loops=10000 time=2.2)
pi4b:~ $ 

Return to “C/C++”