linux SPI 与 mbed OS 通信

本实验测试 sysfs 方式的linux SPI 。主板是全志H6 模块构成的设备,从机是nucleo STM32F429 开发板,运行Arm Mbed OS 

确认SPI 的驱动

检查Linux 的dev/spi1.0 是否存在,如果不存在,表示SPI 驱动没有很好地被安装。

Linux 程序

将SPI 封装为一个类SPIConnection。相关程序如下:

SPIConnection.cpp

#include "SPIConnection.hpp"
#include      // Needed for SPI port
#include  // Needed for SPI port
#include      // linux errors
#include     // sleep()
#include 
#include 
#include     // for  uint8_t,  uint16_t etc
#include 
#include 
#include 

using namespace std;

SPIConnection::SPIConnection()
{}

SPIConnection::~SPIConnection()
{
  if (fd > 0) {
    close(fd);
  }
}

int SPIConnection::init(const std::string device,
                        const uint8_t     mode,
                        const uint8_t     bitsParam,
                        const uint8_t     LSB,
                        const uint32_t    speed,
                        const std::string nameParam)
{
  name     = nameParam;
  frequency = speed;
  bits     = bitsParam;

  // filedecriptor which will be given back
  int ret;

  /* open device */

  if ((fd = open(device.c_str(), O_RDWR)) < 0)
  {
    perror("Error Open Device");
    return -1;
  }

  /* set mode */
  ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);

  if (ret < 0)
  {
    perror("Error Set SPI-Mode");
    return -2;
  }


  // /* check mode */
  ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);

  if (ret < 0)
  {
    perror("Error Get SPI-Mode");
    return -3;
  }



  ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &LSB);

  if (ret < 0)
  {
    perror("Error Set LSB-Mode");
    return -2;
  }


  /* set word length*/
  ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);

  if (ret < 0)
  {
    perror("Error Set wordlength");
    return -4;
  }

  // /* check word length */
  ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);

  if (ret < 0)
  {
    perror("Error Get wordlength");
    return -5;
  }

  /* set datarate */
  ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);

  if (ret < 0)
  {
    perror("Error Set Speed");
    return -6;
  }

  // /* check datarate */
  ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);

  if (ret < 0)
  {
    perror("Error Get Speed");
    return -7;
  }

  /* Print */

  printf("SPI-Connection.: %s\n",             name.c_str());
  printf("SPI-Device.....: %s\n",             device.c_str());
  printf("SPI-Mode.......: %d\n",             mode);
  printf("Wordlength.....: %d\n",             bits);
  printf("Speed..........: %d Hz (%d kHz)\n", speed, speed / 1000);
  printf("Filehandle.....: %d\n",             fd);


  return 0;
}



int SPIConnection::transfer(uint8_t *data, int length) {

  int ret;

  uint8_t rx[length];

  //clear memory
  memset(rx, 0, sizeof(uint8_t) * length);
  memset(&spi, 0, sizeof(spi));

  spi.tx_buf        = (unsigned long)data;
  spi.rx_buf        = (unsigned long)rx;
  spi.len           = length;
  spi.delay_usecs   = 0;
  spi.speed_hz      = frequency;
  spi.bits_per_word = bits;
  spi.cs_change     = 0;


  // lets go
  ret = ioctl(fd, SPI_IOC_MESSAGE(1), &spi);

 if (ret < 0)
  {
        if (errno == EBADF) {
          std::cout << "ERROR: fd is not a valid file descriptor." << std::endl;
        } else if (errno == EFAULT) {
          std::cout << "ERROR: argp references an inaccessible memory area" <<
            std::endl;
        }
        else if (errno == EINVAL) {
          std::cout << "ERROR: request or argp is not valid" << std::endl;
        }
        else if (errno == ENOTTY) {
          std::cout <<
            "ERROR: fd is not associated with a character special device" <<
            std::endl;
        }
        else if (errno == ENOTTY) {
          std::cout <<
            "ERROR: The specified request does not apply to the kind of object that the file descriptor fd references."
                    << std::endl;
        }

        perror("Error on I/O - ioctl");
        return -1;
  }

  //copy to output
  memcpy(data, rx, sizeof(uint8_t) * length);

  return 0;
}

SPIConnection.hpp

#ifndef SPIVERBINDUNGHPP3456
#define SPIVERBINDUNGHPP3456
#include  // spi_ioc_transfer u.a
#include 
#include  // for  uint8_t,  uint16_t etc


class SPIConnection {
private:

  int fd;
  struct spi_ioc_transfer spi;
  int frequency;
  std::string name;
  uint8_t bits;

public:

  SPIConnection();
  virtual ~SPIConnection();

  /**
   * Init's the SPI Connection
   * @method init
   * --------------------
   * @param  device    the Path to the SPI file
   * @param  mode      spi mode
   * @param  bits      bits per word
   * @param  LSB       lsb or msb
   * @param  speed     speed in herz
   * @param  nameParam human readable name of spi conn
   * @return           file descriptor if successfull
   */
  int init(std::string device,
           uint8_t     mode,
           uint8_t     bits,
           uint8_t     LSB,
           uint32_t    speed,
           std::string nameParam);

  /**
   * Transfers data
   * @method transfer
   * --------------------
   * @param  data     pointer to send buffer, will be overwritten with 
     received data
   * @param  length   number of bytes to be sned
   * @return          0 if successfull
   */
  int transfer(uint8_t *data,
               int      length);
};


#endif /* end of include guard: SPIVERBINDUNGHPP3456
        */

main.cpp

#include "SPIConnection.hpp"

int main(int argc, char const *argv[]) {
  /**
   * Example usage
   */

  SPIConnection spi_conn;

  spi_conn.init("/dev/spidev1.0",
                SPI_CPOL | !SPI_CPHA,
                8,
                0,
                16000,
                "MX11060");

  uint8_t data[10] = "Hello SPI";
  spi_conn.transfer(data, 10);

  return 0;
}

Mbed 程序

#include "mbed.h"

SPISlave device(PF_9,PF_8,PF_7,PF_6); // mosi, miso, sclk, ssel
Serial pc(USBTX, USBRX);
int main() {
  uint8_t rxbuf[10];
  int i;
  pc.baud(115200);
  printf("Linux SPI Test\n");
  i=0;
   while(1) {
       if(device.receive()) {
           uint8_t v = device.read();   // Read byte from master
          rxbuf[i++]=v;
          if (i==10){
              rxbuf[9]=0x0d;
              for (i=0;i<10;i++)
                pc.putc(rxbuf[i]);
                pc.putc(0x0a);
                i=0;
                }
       }
   }
}

 

你可能感兴趣的:(linux,C++)