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

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