Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

218 строки
6.0 KiB

  1. /*
  2. * wiringPiSPI.c:
  3. * Simplified SPI access routines
  4. * Copyright (c) 2012-2015 Gordon Henderson
  5. ***********************************************************************
  6. * This file is part of wiringPi:
  7. * https://github.com/WiringPi/WiringPi/
  8. *
  9. * wiringPi is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * wiringPi is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with wiringPi.
  21. * If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************
  23. */
  24. #include <stdio.h>
  25. #include <unistd.h>
  26. #include <stdint.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <sys/ioctl.h>
  32. #include <asm/ioctl.h>
  33. #include <linux/spi/spidev.h>
  34. #include "wiringPi.h"
  35. #include "wiringPiSPI.h"
  36. // The SPI bus parameters
  37. // Variables as they need to be passed as pointers later on
  38. //static const char *spiDev0 = "/dev/spidev0.0" ;
  39. //static const char *spiDev1 = "/dev/spidev0.1" ;
  40. static const uint8_t spiBPW = 8 ;
  41. static const uint16_t spiDelay = 0 ;
  42. //https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf
  43. const uint8_t WPI_MaxSPINumbers = 7 ;
  44. const uint8_t WPI_MaxSPIChannels = 3 ;
  45. static uint32_t spiSpeeds [7][3] =
  46. {
  47. {0, 0, 0},
  48. {0, 0, 0},
  49. {0, 0, 0},
  50. {0, 0, 0},
  51. {0, 0, 0},
  52. {0, 0, 0},
  53. {0, 0, 0},
  54. };
  55. static int spiFds [7][3] =
  56. {
  57. {-1, -1, -1},
  58. {-1, -1, -1},
  59. {-1, -1, -1},
  60. {-1, -1, -1},
  61. {-1, -1, -1},
  62. {-1, -1, -1},
  63. {-1, -1, -1},
  64. };
  65. int SPICheckLimits(const int number, const int channel) {
  66. if (channel<0 || channel>=WPI_MaxSPIChannels) {
  67. fprintf (stderr, "wiringPiSPI: Invalid SPI channel (%d, valid range 0-%d)", channel, WPI_MaxSPIChannels-1);
  68. return -EINVAL;
  69. }
  70. if (number<0 || number>=WPI_MaxSPINumbers) {
  71. fprintf (stderr, "wiringPiSPI: Invalid SPI number (%d, valid range 0-%d)", number, WPI_MaxSPINumbers-1);
  72. return -EINVAL;
  73. }
  74. return 0; //sucess
  75. }
  76. #define RETURN_ON_LIMIT_FAIL int ret = SPICheckLimits(number, channel); if(ret!=0) { return ret; };
  77. /*
  78. * wiringPiSPIGetFd:
  79. * Return the file-descriptor for the given channel
  80. *********************************************************************************
  81. */
  82. int wiringPiSPIxGetFd(const int number, int channel)
  83. {
  84. if (SPICheckLimits(number, channel)!=0) {
  85. return -1;
  86. }
  87. return spiFds[number][channel];
  88. }
  89. int wiringPiSPIGetFd(int channel) {
  90. return wiringPiSPIxGetFd(0, channel);
  91. }
  92. /*
  93. * wiringPiSPIDataRW:
  94. * Write and Read a block of data over the SPI bus.
  95. * Note the data ia being read into the transmit buffer, so will
  96. * overwrite it!
  97. * This is also a full-duplex operation.
  98. *********************************************************************************
  99. */
  100. int wiringPiSPIxDataRW (const int number, const int channel, unsigned char *data, const int len)
  101. {
  102. RETURN_ON_LIMIT_FAIL
  103. if (-1==spiFds[number][channel]) {
  104. fprintf (stderr, "wiringPiSPI: Invalid SPI number/channel (need wiringPiSPIxSetupMode before read/write)");
  105. return -EBADF;
  106. }
  107. struct spi_ioc_transfer spi ;
  108. // Mentioned in spidev.h but not used in the original kernel documentation
  109. // test program )-:
  110. memset (&spi, 0, sizeof (spi)) ;
  111. spi.tx_buf = (unsigned long)data ;
  112. spi.rx_buf = (unsigned long)data ;
  113. spi.len = len ;
  114. spi.delay_usecs = spiDelay ;
  115. spi.speed_hz = spiSpeeds [number][channel] ;
  116. spi.bits_per_word = spiBPW ;
  117. return ioctl (spiFds[number][channel], SPI_IOC_MESSAGE(1), &spi) ;
  118. }
  119. int wiringPiSPIDataRW (int channel, unsigned char *data, int len) {
  120. return wiringPiSPIxDataRW(0, channel, data, len);
  121. }
  122. /*
  123. * wiringPiSPISetupMode:
  124. * Open the SPI device, and set it up, with the mode, etc.
  125. *********************************************************************************
  126. */
  127. int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode)
  128. {
  129. int fd ;
  130. char spiDev [32] ;
  131. RETURN_ON_LIMIT_FAIL
  132. if (mode<0 || mode>3) { // Mode is 0, 1, 2 or 3 original
  133. fprintf (stderr, "wiringPiSPI: Invalid mode (%d, valid range 0-%d)", mode, 3);
  134. return -EINVAL;
  135. }
  136. snprintf (spiDev, 31, "/dev/spidev%d.%d", number, channel) ;
  137. if ((fd = open (spiDev, O_RDWR)) < 0) {
  138. return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device %s: %s\n", spiDev, strerror (errno)) ;
  139. }
  140. spiSpeeds [number][channel] = speed ;
  141. spiFds [number][channel] = fd ;
  142. // Set SPI parameters.
  143. if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0)
  144. return wiringPiFailure (WPI_ALMOST, "SPI mode change failure: %s\n", strerror (errno)) ;
  145. if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
  146. return wiringPiFailure (WPI_ALMOST, "SPI BPW change failure: %s\n", strerror (errno)) ;
  147. if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
  148. return wiringPiFailure (WPI_ALMOST, "SPI speed change failure: %s\n", strerror (errno)) ;
  149. return fd ;
  150. }
  151. int wiringPiSPISetupMode (int channel, int speed, int mode) {
  152. return wiringPiSPIxSetupMode (0, channel, speed, mode);
  153. }
  154. /*
  155. * wiringPiSPISetup:
  156. * Open the SPI device, and set it up, etc. in the default MODE 0
  157. *********************************************************************************
  158. */
  159. int wiringPiSPISetup (int channel, int speed) {
  160. return wiringPiSPIxSetupMode(0, channel, speed, 0) ;
  161. }
  162. int wiringPiSPIxClose (const int number, const int channel) {
  163. RETURN_ON_LIMIT_FAIL
  164. if (spiFds[number][channel]>0) {
  165. ret = close(spiFds[number][channel]);
  166. }
  167. spiSpeeds [number][channel] = 0 ;
  168. spiFds [number][channel] = -1 ;
  169. return ret;
  170. }
  171. int wiringPiSPIClose (const int channel) {
  172. return wiringPiSPIxClose (0, channel);
  173. }