spi.c 5.0 KB

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