您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* Arduino SdSpi Library
  2. * Copyright (C) 2013 by William Greiman
  3. *
  4. * This file is part of the Arduino SdSpi Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdSpi Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file
  22. * \brief SdSpi class for V2 SD/SDHC cards
  23. */
  24. #ifndef SdSpi_h
  25. #define SdSpi_h
  26. #include <Arduino.h>
  27. #include "SdFatConfig.h"
  28. //------------------------------------------------------------------------------
  29. /**
  30. * \class SdSpiBase
  31. * \brief Virtual SPI class for access to SD and SDHC flash memory cards.
  32. */
  33. class SdSpiBase {
  34. public:
  35. /** Initialize the SPI bus */
  36. virtual void begin() = 0;
  37. /** Set SPI options for access to SD/SDHC cards.
  38. *
  39. * \param[in] divisor SCK clock divider relative to the system clock.
  40. */
  41. virtual void init(uint8_t divisor);
  42. /** Receive a byte.
  43. *
  44. * \return The byte.
  45. */
  46. virtual uint8_t receive() = 0;
  47. /** Receive multiple bytes.
  48. *
  49. * \param[out] buf Buffer to receive the data.
  50. * \param[in] n Number of bytes to receive.
  51. *
  52. * \return Zero for no error or nonzero error code.
  53. */
  54. virtual uint8_t receive(uint8_t* buf, size_t n) = 0;
  55. /** Send a byte.
  56. *
  57. * \param[in] data Byte to send
  58. */
  59. virtual void send(uint8_t data) = 0;
  60. /** Send multiple bytes.
  61. *
  62. * \param[in] buf Buffer for data to be sent.
  63. * \param[in] n Number of bytes to send.
  64. */
  65. virtual void send(const uint8_t* buf, size_t n) = 0;
  66. /** \return true if hardware SPI else false */
  67. virtual bool useSpiTransactions() = 0;
  68. };
  69. //------------------------------------------------------------------------------
  70. /**
  71. * \class SdSpi
  72. * \brief SPI class for access to SD and SDHC flash memory cards.
  73. */
  74. #if SD_SPI_CONFIGURATION >= 3
  75. class SdSpi : public SdSpiBase {
  76. #else // SD_SPI_CONFIGURATION >= 3
  77. class SdSpi {
  78. #endif // SD_SPI_CONFIGURATION >= 3
  79. public:
  80. /** Initialize the SPI bus */
  81. void begin();
  82. /** Set SPI options for access to SD/SDHC cards.
  83. *
  84. * \param[in] divisor SCK clock divider relative to the system clock.
  85. */
  86. void init(uint8_t divisor);
  87. /** Receive a byte.
  88. *
  89. * \return The byte.
  90. */
  91. uint8_t receive();
  92. /** Receive multiple bytes.
  93. *
  94. * \param[out] buf Buffer to receive the data.
  95. * \param[in] n Number of bytes to receive.
  96. *
  97. * \return Zero for no error or nonzero error code.
  98. */
  99. uint8_t receive(uint8_t* buf, size_t n);
  100. /** Send a byte.
  101. *
  102. * \param[in] data Byte to send
  103. */
  104. void send(uint8_t data);
  105. /** Send multiple bytes.
  106. *
  107. * \param[in] buf Buffer for data to be sent.
  108. * \param[in] n Number of bytes to send.
  109. */
  110. void send(const uint8_t* buf, size_t n);
  111. /** \return true - uses SPI transactions */
  112. bool useSpiTransactions() {
  113. return true;
  114. }
  115. };
  116. //------------------------------------------------------------------------------
  117. /**
  118. * \class SdSpiLib
  119. * \brief Arduino SPI library class for access to SD and SDHC flash
  120. * memory cards.
  121. */
  122. #if SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 || defined(DOXYGEN)
  123. #include <SPI.h>
  124. #if SD_SPI_CONFIGURATION >= 3
  125. class SdSpiLib : public SdSpiBase {
  126. #else // SD_SPI_CONFIGURATION >= 3
  127. class SdSpiLib {
  128. #endif // SD_SPI_CONFIGURATION >= 3
  129. public:
  130. /**
  131. * Initialize SPI pins.
  132. */
  133. void begin() {
  134. SPI.begin();
  135. }
  136. /** Set SPI options for access to SD/SDHC cards.
  137. *
  138. * \param[in] divisor SCK clock divider relative to the system clock.
  139. */
  140. void init(uint8_t divisor) {
  141. SPI.setBitOrder(MSBFIRST);
  142. SPI.setDataMode(SPI_MODE0);
  143. #ifndef SPI_CLOCK_DIV128
  144. SPI.setClockDivider(divisor);
  145. #else // SPI_CLOCK_DIV128
  146. int v;
  147. if (divisor <= 2) {
  148. v = SPI_CLOCK_DIV2;
  149. } else if (divisor <= 4) {
  150. v = SPI_CLOCK_DIV4;
  151. } else if (divisor <= 8) {
  152. v = SPI_CLOCK_DIV8;
  153. } else if (divisor <= 16) {
  154. v = SPI_CLOCK_DIV16;
  155. } else if (divisor <= 32) {
  156. v = SPI_CLOCK_DIV32;
  157. } else if (divisor <= 64) {
  158. v = SPI_CLOCK_DIV64;
  159. } else {
  160. v = SPI_CLOCK_DIV128;
  161. }
  162. SPI.setClockDivider(v);
  163. #endif // SPI_CLOCK_DIV128
  164. }
  165. /** Receive a byte.
  166. *
  167. * \return The byte.
  168. */
  169. uint8_t receive() {
  170. return SPI.transfer(0XFF);
  171. }
  172. /** Receive multiple bytes.
  173. *
  174. * \param[out] buf Buffer to receive the data.
  175. * \param[in] n Number of bytes to receive.
  176. *
  177. * \return Zero for no error or nonzero error code.
  178. */
  179. uint8_t receive(uint8_t* buf, size_t n) {
  180. for (size_t i = 0; i < n; i++) {
  181. buf[i] = SPI.transfer(0XFF);
  182. }
  183. return 0;
  184. }
  185. /** Send a byte.
  186. *
  187. * \param[in] b Byte to send
  188. */
  189. void send(uint8_t b) {
  190. SPI.transfer(b);
  191. }
  192. /** Send multiple bytes.
  193. *
  194. * \param[in] buf Buffer for data to be sent.
  195. * \param[in] n Number of bytes to send.
  196. */
  197. void send(const uint8_t* buf , size_t n) {
  198. for (size_t i = 0; i < n; i++) {
  199. SPI.transfer(buf[i]);
  200. }
  201. }
  202. /** \return true - uses SPI transactions */
  203. bool useSpiTransactions() {
  204. return true;
  205. }
  206. };
  207. #endif // SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1
  208. //------------------------------------------------------------------------------
  209. #if SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
  210. #include "utility/SoftSPI.h"
  211. /**
  212. * \class SdSpiSoft
  213. * \brief Software SPI class for access to SD and SDHC flash memory cards.
  214. */
  215. template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
  216. class SdSpiSoft : public SdSpiBase {
  217. public:
  218. /**
  219. * initialize SPI pins
  220. */
  221. void begin() {
  222. m_spi.begin();
  223. }
  224. /**
  225. * Initialize hardware SPI - dummy for soft SPI
  226. * \param[in] divisor SCK divisor - ignored.
  227. */
  228. void init(uint8_t divisor) {}
  229. /** Receive a byte.
  230. *
  231. * \return The byte.
  232. */
  233. uint8_t receive() {
  234. return m_spi.receive();
  235. }
  236. /** Receive multiple bytes.
  237. *
  238. * \param[out] buf Buffer to receive the data.
  239. * \param[in] n Number of bytes to receive.
  240. *
  241. * \return Zero for no error or nonzero error code.
  242. */
  243. uint8_t receive(uint8_t* buf, size_t n) {
  244. for (size_t i = 0; i < n; i++) {
  245. buf[i] = receive();
  246. }
  247. return 0;
  248. }
  249. /** Send a byte.
  250. *
  251. * \param[in] data Byte to send
  252. */
  253. void send(uint8_t data) {
  254. m_spi.send(data);
  255. }
  256. /** Send multiple bytes.
  257. *
  258. * \param[in] buf Buffer for data to be sent.
  259. * \param[in] n Number of bytes to send.
  260. */
  261. void send(const uint8_t* buf , size_t n) {
  262. for (size_t i = 0; i < n; i++) {
  263. send(buf[i]);
  264. }
  265. }
  266. /** \return false - no SPI transactions */
  267. bool useSpiTransactions() {
  268. return false;
  269. }
  270. private:
  271. SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
  272. };
  273. #endif // SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
  274. //------------------------------------------------------------------------------
  275. #if SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  276. /** Default is custom fast SPI. */
  277. typedef SdSpi SpiDefault_t;
  278. #elif SD_SPI_CONFIGURATION == 1
  279. /** Default is Arduino library SPI. */
  280. typedef SdSpiLib SpiDefault_t;
  281. #elif SD_SPI_CONFIGURATION == 2
  282. /** Default is software SPI. */
  283. typedef SdSpiSoft<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN>
  284. SpiDefault_t;
  285. #else // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  286. #error bad SD_SPI_CONFIGURATION
  287. #endif // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  288. //------------------------------------------------------------------------------
  289. // Use of in-line for AVR to save flash.
  290. #ifdef __AVR__
  291. //------------------------------------------------------------------------------
  292. inline void SdSpi::begin() {
  293. #ifdef __AVR_ATmega328P__
  294. // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi.
  295. PORTB |= 1 << 2; // SS high
  296. DDRB |= 1 << 2; // SS output mode
  297. DDRB |= 1 << 3; // MOSI output mode
  298. DDRB |= 1 << 5; // SCK output mode
  299. #else // __AVR_ATmega328P__
  300. // set SS high - may be chip select for another SPI device
  301. digitalWrite(SS, HIGH);
  302. // SS must be in output mode even it is not chip select
  303. pinMode(SS, OUTPUT);
  304. pinMode(MOSI, OUTPUT);
  305. pinMode(SCK, OUTPUT);
  306. #endif // __AVR_ATmega328P__
  307. }
  308. //------------------------------------------------------------------------------
  309. inline void SdSpi::init(uint8_t divisor) {
  310. uint8_t b = 2;
  311. uint8_t r = 0;
  312. // See AVR processor documentation.
  313. for (; divisor > b && r < 7; b <<= 1, r += r < 5 ? 1 : 2) {}
  314. SPCR = (1 << SPE) | (1 << MSTR) | (r >> 1);
  315. SPSR = r & 1 ? 0 : 1 << SPI2X;
  316. }
  317. //------------------------------------------------------------------------------
  318. inline uint8_t SdSpi::receive() {
  319. SPDR = 0XFF;
  320. while (!(SPSR & (1 << SPIF))) {}
  321. return SPDR;
  322. }
  323. //------------------------------------------------------------------------------
  324. inline uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
  325. if (n-- == 0) {
  326. return 0;
  327. }
  328. SPDR = 0XFF;
  329. for (size_t i = 0; i < n; i++) {
  330. while (!(SPSR & (1 << SPIF))) {}
  331. uint8_t b = SPDR;
  332. SPDR = 0XFF;
  333. buf[i] = b;
  334. }
  335. while (!(SPSR & (1 << SPIF))) {}
  336. buf[n] = SPDR;
  337. return 0;
  338. }
  339. //------------------------------------------------------------------------------
  340. inline void SdSpi::send(uint8_t data) {
  341. SPDR = data;
  342. while (!(SPSR & (1 << SPIF))) {}
  343. }
  344. //------------------------------------------------------------------------------
  345. inline void SdSpi::send(const uint8_t* buf , size_t n) {
  346. if (n == 0) {
  347. return;
  348. }
  349. SPDR = buf[0];
  350. if (n > 1) {
  351. uint8_t b = buf[1];
  352. size_t i = 2;
  353. while (1) {
  354. while (!(SPSR & (1 << SPIF))) {}
  355. SPDR = b;
  356. if (i == n) {
  357. break;
  358. }
  359. b = buf[i++];
  360. }
  361. }
  362. while (!(SPSR & (1 << SPIF))) {}
  363. }
  364. #endif // __AVR__
  365. #endif // SdSpi_h