1 2 Previous Next 16 Replies Latest reply on Nov 15, 2016 11:27 PM by PRB

    Using The SPI Port Without the mraa Library Problems

    mikemoy

      Using the Edison with the mini breakout board. I am trying to get the fastest possible SPI speeds i can.

      I have a 7" capacitive touch LCD connected to the board through level shifters and using the mraa lib i have it working.

      But its to slow for real use. The cause is that there is a significant delay between CS to CS in writing the data out, and it's not that the SPI clock speed is to slow.

      I have this same LCD on the RPI CM, and works just fine there. The CS to CS delays on the RPI are very minimal.

      mraa has now been fixed to send 16bit, which helped but now the delays are nagging.

       

      So i though i would skip the mraa lib, and go direct. In doing so i found a very strange issue with multiple writes.

      The reason i say this is because i have tried the exact same following code on the Edison, RPI, Arietta G25, & ODROID-U3. The only change between boards was made was

      " mcp3008Spi a2d("/dev/spidev5.1", SPI_MODE_0, 100000, 8); " as the location is different for each them.

       

      Using the scope on the RPI, Arietta G25, & ODROID-U3 board i see that 3 bytes are sent out.

      When i try the Edison only one gets sent. Moreover the printf reports back that 3 were sent, which were not.

       

      Here is the code used that was used:

       

       

      #include <signal.h>

      #include <stdlib.h>

      #include <string.h>

      #include <stdint.h>

      #include <unistd.h>

      #include <stdio.h>

      #include <fcntl.h>

      #include <sys/ioctl.h>

      #include <linux/types.h>

      #include <linux/spi/spidev.h>

      #include <iostream>

      #include <errno.h>

       

      #include "mraa.h"

       

      class mcp3008Spi{

       

      public:

          mcp3008Spi();

          mcp3008Spi(std::string devspi, unsigned char spiMode, unsigned int spiSpeed, unsigned char spibitsPerWord);

          ~mcp3008Spi();

          int spiWriteRead( unsigned char *data, int length);

       

      private:

          unsigned char mode;

          unsigned char bitsPerWord;

          unsigned int speed;

          int spifd;

       

          int spiOpen(std::string devspi);

          int spiClose();

       

      };

       

      using namespace std;

      /**********************************************************

      * spiOpen() :function is called by the constructor.

      * It is responsible for opening the spidev device

      * "devspi" and then setting up the spidev interface.

      * private member variables are used to configure spidev.

      * They must be set appropriately by constructor before calling

      * this function.

      * *********************************************************/

      int mcp3008Spi::spiOpen(std::string devspi){

          int statusVal = -1;

          this->spifd = open(devspi.c_str(), O_RDWR);

          if(this->spifd < 0){

              perror("could not open SPI device");

              exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_WR_MODE, &(this->mode));

          if(statusVal < 0){

              perror("Could not set SPIMode (WR)...ioctl fail");

              exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_RD_MODE, &(this->mode));

          if(statusVal < 0) {

            perror("Could not set SPIMode (RD)...ioctl fail");

            exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_WR_BITS_PER_WORD, &(this->bitsPerWord));

          if(statusVal < 0) {

            perror("Could not set SPI bitsPerWord (WR)...ioctl fail");

            exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_RD_BITS_PER_WORD, &(this->bitsPerWord));

          if(statusVal < 0) {

            perror("Could not set SPI bitsPerWord(RD)...ioctl fail");

            exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_WR_MAX_SPEED_HZ, &(this->speed));

          if(statusVal < 0) {

            perror("Could not set SPI speed (WR)...ioctl fail");

            exit(1);

          }

       

          statusVal = ioctl (this->spifd, SPI_IOC_RD_MAX_SPEED_HZ, &(this->speed));

          if(statusVal < 0) {

            perror("Could not set SPI speed (RD)...ioctl fail");

            exit(1);

          }

          return statusVal;

      }

      /***********************************************************

      * spiClose(): Responsible for closing the spidev interface.

      * Called in destructor

      * *********************************************************/

       

      int mcp3008Spi::spiClose(){

          int statusVal = -1;

          statusVal = close(this->spifd);

              if(statusVal < 0) {

            perror("Could not close SPI device");

            exit(1);

          }

          return statusVal;

      }

      /********************************************************************

      * This function writes data "data" of length "length" to the spidev

      * device. Data shifted in from the spidev device is saved back into

      * "data".

      * ******************************************************************/

      int mcp3008Spi::spiWriteRead( unsigned char *data, int length){

       

        struct spi_ioc_transfer spi[length];

        int i = 0;

        int retVal = -1;

       

      // one spi transfer for each byte

       

        for (i = 0 ; i < length ; i++){

       

          spi[i].tx_buf        = (unsigned long)(data + i); // transmit from "data"

          spi[i].rx_buf        = (unsigned long)(data + i) ; // receive into "data"

          spi[i].len           = sizeof(*(data + i)) ;

          spi[i].delay_usecs   = 0 ;

          spi[i].speed_hz      = this->speed ;

          spi[i].bits_per_word = this->bitsPerWord ;

          spi[i].cs_change = 0;

      }

       

      retVal = ioctl (this->spifd, SPI_IOC_MESSAGE(length), &spi);

       

        if(retVal < 0){

          perror("Problem transmitting spi data..ioctl");

          exit(1);

      }

       

      return retVal;

       

      }

      /*************************************************

      * Default constructor. Set member variables to

      * default values and then call spiOpen()

      * ***********************************************/

       

      mcp3008Spi::mcp3008Spi(){

          this->mode = SPI_MODE_0 ;

          this->bitsPerWord = 8;

          this->speed = 1000000;

          this->spifd = -1;

       

          this->spiOpen(std::string("/dev/spidev0.0"));

       

          }

       

      /*************************************************

      * overloaded constructor. let user set member variables to

      * and then call spiOpen()

      * ***********************************************/

      mcp3008Spi::mcp3008Spi(std::string devspi, unsigned char spiMode, unsigned int spiSpeed, unsigned char spibitsPerWord){

          this->mode = spiMode ;

          this->bitsPerWord = spibitsPerWord;

          this->speed = spiSpeed;

          this->spifd = -1;

       

          this->spiOpen(devspi);

       

      }

       

      /**********************************************

      * Destructor: calls spiClose()

      * ********************************************/

      mcp3008Spi::~mcp3008Spi(){

          this->spiClose();

      }

       

       

      //*********************************************************************

      //***********************  SPI WRITE WORD  ****************************

      //*********************************************************************

      int main (void)

      {

          // Init the SPI pins

          mraa_init();

       

          // Init the SPI pins

          mraa_spi_init(0);

       

       

          mcp3008Spi a2d("/dev/spidev5.1", SPI_MODE_0, 400000, 8);

       

       

          unsigned char data[3];

       

          data[0] = 1;

          data[1] = 2;

          data[2] = 3;

       

          int ret = a2d.spiWriteRead(data, sizeof(data) );

          printf("Bytes Sent=%d\r\n", ret);

       

       

       

       

           printf("We are done\r\n");

       

          return 0;

      }

        1 2 Previous Next