spi.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "LPC17xx.h" /* LPC17xx definitions */
  2. #include "spi.h"
  3. /* bit definitions for register SSPCR0. */
  4. #define SSPCR0_DSS 0
  5. #define SSPCR0_CPOL 6
  6. #define SSPCR0_CPHA 7
  7. #define SSPCR0_SCR 8
  8. /* bit definitions for register SSPCR1. */
  9. #define SSPCR1_SSE 1
  10. /* bit definitions for register SSPSR. */
  11. #define SSPSR_TFE 0
  12. #define SSPSR_TNF 1
  13. #define SSPSR_RNE 2
  14. #define SSPSR_RFF 3
  15. #define SSPSR_BSY 4
  16. /* Local functions */
  17. static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s);
  18. /* Initialize the SSP0, SSP0_PCLK=CCLK=72MHz */
  19. void LPC17xx_SPI_Init (void)
  20. {
  21. uint32_t dummy;
  22. dummy = dummy; // avoid warning
  23. #if 0
  24. /* Initialize and enable the SSP0 Interface module. */
  25. LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
  26. /* SSEL is GPIO, output set to high. */
  27. LPC_GPIO0->FIODIR |= (1<<16); /* P0.16 is output */
  28. LPC_PINCON->PINSEL1 &= ~(3<<0); /* P0.16 SSEL (used as GPIO) */
  29. LPC17xx_SPI_DeSelect (); /* set P0.16 high (SSEL inactiv) */
  30. /* SCK, MISO, MOSI are SSP pins. */
  31. LPC_PINCON->PINSEL0 &= ~(3UL<<30); /* P0.15 cleared */
  32. LPC_PINCON->PINSEL0 |= (2UL<<30); /* P0.15 SCK0 */
  33. LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4)); /* P0.17, P0.18 cleared */
  34. LPC_PINCON->PINSEL1 |= ((2<<2) | (2<<4)); /* P0.17 MISO0, P0.18 MOSI0 */
  35. #else
  36. LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
  37. /* SSEL is GPIO, output set to high. */
  38. LPC_GPIO1->FIODIR |= (1<<21); /* P1.21 is output */
  39. LPC_GPIO1->FIOPIN |= (1<<21); /* set P1.21 high (SSEL inact.)*/
  40. LPC_PINCON->PINSEL3 &= ~(0<<10); /* P1.21 SSEL (used as GPIO) */
  41. /* P3.26 is SD Card Power Supply Enable Pin */
  42. LPC_GPIO3->FIODIR |= (1<<26); /* P3.26 is output */
  43. LPC_GPIO3->FIOPIN &= ~(1<<26); /* set P3.26 low(enable power) */
  44. /* SCK, MISO, MOSI are SSP pins. */
  45. LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
  46. LPC_PINCON->PINSEL3 |= (3UL<<8); /* P1.20 SCK0 */
  47. LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
  48. LPC_PINCON->PINSEL3 |= ((3<<14) | (3<<16)); /* P1.23 MISO0, P1.24 MOSI0 */
  49. #endif
  50. /* PCLK_SSP0=CCLK */
  51. LPC_SC->PCLKSEL1 &= ~(3<<10); /* PCLKSP0 = CCLK/4 (18MHz) */
  52. LPC_SC->PCLKSEL1 |= (1<<10); /* PCLKSP0 = CCLK (72MHz) */
  53. LPC_SSP0->CR0 = 0x0007; /* 8Bit, CPOL=0, CPHA=0 */
  54. LPC_SSP0->CR1 = 0x0002; /* SSP0 enable, master */
  55. LPC17xx_SPI_SetSpeed (SPI_SPEED_400kHz);
  56. /* wait for busy gone */
  57. while( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
  58. /* drain SPI RX FIFO */
  59. while( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) )
  60. {
  61. dummy = LPC_SSP0->DR;
  62. }
  63. }
  64. /* Close SSP0 */
  65. void LPC17xx_SPI_DeInit( void )
  66. {
  67. // disable SPI
  68. LPC_SSP0->CR1 = 0;
  69. #if 0
  70. // Pins to GPIO
  71. LPC_PINCON->PINSEL0 &= ~(3UL<<30);
  72. LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4));
  73. #else
  74. LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
  75. LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
  76. #endif
  77. // disable SSP power
  78. LPC_SC->PCONP &= ~(1 << 21);
  79. }
  80. /* Set a SSP0 clock speed to desired value. */
  81. void LPC17xx_SPI_SetSpeed (uint8_t speed)
  82. {
  83. speed &= 0xFE;
  84. if ( speed < 2 ) {
  85. speed = 2 ;
  86. }
  87. LPC_SSP0->CPSR = speed;
  88. }
  89. /* SSEL: low */
  90. void LPC17xx_SPI_Select ()
  91. {
  92. #if 0
  93. LPC_GPIO0->FIOPIN &= ~(1<<16);
  94. #else
  95. LPC_GPIO1->FIOPIN &= ~(1<<21); /* SSEL is GPIO, set to high. */
  96. #endif
  97. }
  98. /* SSEL: high */
  99. void LPC17xx_SPI_DeSelect ()
  100. {
  101. #if 0
  102. LPC_GPIO0->FIOPIN |= (1<<16);
  103. #else
  104. LPC_GPIO1->FIOPIN |= (1<<21); /* SSEL is GPIO, set to high. */
  105. #endif
  106. }
  107. /* Send one byte then recv one byte of response. */
  108. static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s)
  109. {
  110. uint8_t byte_r;
  111. LPC_SSP0->DR = byte_s;
  112. while (LPC_SSP0->SR & (1 << SSPSR_BSY) /*BSY*/); /* Wait for transfer to finish */
  113. byte_r = LPC_SSP0->DR;
  114. return byte_r; /* Return received value */
  115. }
  116. /* Send one byte */
  117. void LPC17xx_SPI_SendByte (uint8_t data)
  118. {
  119. LPC17xx_SPI_SendRecvByte (data);
  120. }
  121. /* Recv one byte */
  122. uint8_t LPC17xx_SPI_RecvByte ()
  123. {
  124. return LPC17xx_SPI_SendRecvByte (0xFF);
  125. }
  126. /* Release SSP0 */
  127. void LPC17xx_SPI_Release (void)
  128. {
  129. LPC17xx_SPI_DeSelect ();
  130. LPC17xx_SPI_RecvByte ();
  131. }
  132. #if USE_FIFO
  133. /* on LPC17xx the FIFOs have 8 elements which each can hold up to 16 bits */
  134. #define FIFO_ELEM 8
  135. /* Receive btr (must be multiple of 4) bytes of data and store in buff. */
  136. void LPC17xx_SPI_RecvBlock_FIFO (uint8_t *buff, uint32_t btr)
  137. {
  138. uint32_t hwtr, startcnt, i, rec;
  139. hwtr = btr/2; /* byte number in unit of short */
  140. if ( btr < FIFO_ELEM ) {
  141. startcnt = hwtr;
  142. } else {
  143. startcnt = FIFO_ELEM;
  144. }
  145. LPC_SSP0 -> CR0 |= 0x0f; /* DSS to 16 bit */
  146. for ( i = startcnt; i; i-- ) {
  147. LPC_SSP0 -> DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
  148. }
  149. do {
  150. while ( !(LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) ) {
  151. // wait for data in RX FIFO (RNE set)
  152. }
  153. rec = LPC_SSP0->DR;
  154. if ( i < ( hwtr - startcnt ) ) {
  155. LPC_SSP0->DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
  156. }
  157. *buff++ = (uint8_t)(rec>>8);
  158. *buff++ = (uint8_t)(rec);
  159. i++;
  160. } while ( i < hwtr );
  161. LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
  162. }
  163. /* Send 512 bytes of data block (stored in buff). */
  164. void LPC17xx_SPI_SendBlock_FIFO (const uint8_t *buff)
  165. {
  166. uint32_t cnt;
  167. uint16_t data;
  168. LPC_SSP0->CR0 |= 0x0f; /* DSS to 16 bit */
  169. /* fill the FIFO unless it is full */
  170. for ( cnt = 0; cnt < ( 512 / 2 ); cnt++ )
  171. {
  172. /* wait for TX FIFO not full (TNF) */
  173. while ( !( LPC_SSP0->SR & ( 1 << SSPSR_TNF ) ) );
  174. data = (*buff++) << 8;
  175. data |= *buff++;
  176. LPC_SSP0->DR = data;
  177. }
  178. /* wait for BSY gone */
  179. while ( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
  180. /* drain receive FIFO */
  181. while ( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) {
  182. data = LPC_SSP0->DR;
  183. }
  184. LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
  185. }
  186. #endif /* USE_FIFO */