[牛人杂谈] 标准SPI,Dual SPI和Qual SPI

[复制链接]
2028|9
 楼主| zhuomuniao110 发表于 2018-12-26 23:42 | 显示全部楼层 |阅读模式

1. 标准SPI

标准SPI通常就称SPI,它是一种串行外设接口规范,有4根引脚信号:clk , cs, mosi, miso

2. Dual SPI

它只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输

3. Qual SPI

与Dual SPI类似,也是针对SPI Flash,Qual SPI Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit

所以对于SPI Flash,有标准spi flash,dual spi , qual spi 三种类型,分别对应3-wire, 4-wire, 6-wire,在相同clock下,线数越多,传输速率越高。

btw:spi flash一般为NOR Flash


 楼主| zhuomuniao110 发表于 2018-12-26 23:43 | 显示全部楼层
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V2.0
  4. * $Revision: 6 $
  5. * $Date: 14/08/05 11:13a $
  6. * @brief
  7. *           Demonstrate how to communicate with an off-chip SPI slave device with Dual I/O mode and FIFO mode.
  8. *           This sample code needs to work with SPI_SlaveDualIOMode sample code.
  9. * @note
  10. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "NUC123.h"


  15. #define TEST_COUNT 16

  16. uint32_t g_au32SourceData[TEST_COUNT];
  17. uint32_t g_au32DestinationData[TEST_COUNT];
  18. volatile uint32_t g_u32TxDataCount;
  19. volatile uint32_t g_u32RxDataCount;

  20. /* Function prototype declaration */
  21. void SYS_Init(void);
  22. void SPI_Init(void);

  23. /* ------------- */
  24. /* Main function */
  25. /* ------------- */
  26. int main(void)
  27. {
  28.     uint32_t u32DataCount;

  29.     /* Unlock protected registers */
  30.     SYS_UnlockReg();

  31.     /* Init System, IP clock and multi-function I/O */
  32.     SYS_Init();

  33.     /* Lock protected registers */
  34.     SYS_LockReg();

  35.     /* Configure UART0: 115200, 8-bit word, no parity bit, 1 stop bit. */
  36.     UART_Open(UART0, 115200);

  37.     /* Init SPI */
  38.     SPI_Init();

  39.     printf("\n\n");
  40.     printf("+--------------------------------------------------------+\n");
  41.     printf("|             SPI Master Mode Sample Code                |\n");
  42.     printf("+--------------------------------------------------------+\n");
  43.     printf("\n");
  44.     printf("Configure SPI0 as a master.\n");
  45.     printf("Bit length of a transaction: 32\n");
  46.     printf("The I/O connection for SPI0:\n");
  47.     printf("    SPI0_SS0 (PC.0)\n    SPI0_CLK (PC.1)\n");
  48.     printf("    SPI0_MISO0 (PC.2)\n    SPI0_MOSI0 (PC.3)\n\n");
  49.     printf("SPI controller will enable Dual I/O mode and FIFO mode, then transfer %d data to a off-chip slave device.\n", TEST_COUNT);
  50.     printf("Afterward the SPI controller will receive %d data from the off-chip slave device.\n", TEST_COUNT);
  51.     printf("After the transfer is done, the %d received data will be printed out.\n", TEST_COUNT);
  52.     printf("The SPI master configuration is ready.\n");

  53.     for(u32DataCount = 0; u32DataCount < TEST_COUNT; u32DataCount++)
  54.     {
  55.         /* Write the initial value to source buffer */
  56.         g_au32SourceData[u32DataCount] = 0x00550000 + u32DataCount;
  57.         /* Clear destination buffer */
  58.         g_au32DestinationData[u32DataCount] = 0;
  59.     }

  60.     printf("Before starting the data transfer, make sure the slave device is ready.\n");
  61.     printf("Press any key to start the Dual I/O output transfer.");
  62.     getchar();
  63.     printf("\n");

  64.     /* Enable Dual I/O output mode */
  65.     SPI_ENABLE_DUAL_OUTPUT_MODE(SPI0);
  66.     /* Enable FIFO mode, set TX FIFO threshold, enable TX FIFO threshold interrupt and RX FIFO time-out interrupt */
  67.     SPI_EnableFIFO(SPI0, 2, 2);
  68.     SPI_EnableInt(SPI0, SPI_FIFO_TX_INT_MASK | SPI_FIFO_TIMEOUT_INT_MASK);
  69.     g_u32TxDataCount = 0;
  70.     g_u32RxDataCount = 0;
  71.     NVIC_EnableIRQ(SPI0_IRQn);

  72.     /* Wait for transfer done */
  73.     while(g_u32RxDataCount < TEST_COUNT);

  74.     /* Enable Dual I/O input mode */
  75.     SPI_ENABLE_DUAL_INPUT_MODE(SPI0);
  76.     printf("Dual I/O output transfer is done. Before starting the Dual I/O input transfer, make sure the slave device is ready.\n");
  77.     printf("Press any key to start the Dual I/O input transfer.");
  78.     getchar();
  79.     printf("\n");
  80.    
  81.     g_u32TxDataCount = 0;
  82.     g_u32RxDataCount = 0;
  83.     SPI_EnableInt(SPI0, SPI_FIFO_TX_INT_MASK | SPI_FIFO_TIMEOUT_INT_MASK);
  84.    
  85.     /* Wait for transfer done */
  86.     while(g_u32RxDataCount < TEST_COUNT);
  87.    
  88.     /* Print the received data */
  89.     printf("Received data:\n");
  90.     for(u32DataCount = 0; u32DataCount < TEST_COUNT; u32DataCount++)
  91.     {
  92.         printf("%d:\t0x%X\n", u32DataCount, g_au32DestinationData[u32DataCount]);
  93.     }
  94.     /* Disable TX FIFO threshold interrupt and RX FIFO time-out interrupt */
  95.     SPI_DisableInt(SPI0, SPI_FIFO_TX_INT_MASK | SPI_FIFO_TIMEOUT_INT_MASK);
  96.     NVIC_DisableIRQ(SPI0_IRQn);
  97.    
  98.     printf("\n\nExit SPI driver sample code.\n");

  99.     /* Disable SPI0 peripheral clock */
  100.     SPI_Close(SPI0);
  101.     while(1);
  102. }

  103. void SYS_Init(void)
  104. {
  105.     /*---------------------------------------------------------------------------------------------------------*/
  106.     /* Init System Clock                                                                                       */
  107.     /*---------------------------------------------------------------------------------------------------------*/

  108.     /* Enable XT1_OUT (PF0) and XT1_IN (PF1) */
  109.     SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;

  110.     /* Enable external 12MHz XTAL */
  111.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  112.     /* Waiting for clock ready */
  113.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  114.     /* Switch HCLK clock source to HXT and HCLK source divide 1 */
  115.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_CLKDIV_HCLK(1));

  116.     /* Select HXT as the clock source of UART0 */
  117.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  118.     /* Select HCLK as the clock source of SPI0 */
  119.     CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL1_SPI0_S_HCLK, MODULE_NoMsk);

  120.     /* Enable UART peripheral clock */
  121.     CLK_EnableModuleClock(UART0_MODULE);
  122.     /* Enable SPI0 peripheral clock */
  123.     CLK_EnableModuleClock(SPI0_MODULE);

  124.     /* Update System Core Clock */
  125.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CyclesPerUs automatically. */
  126.     SystemCoreClockUpdate();

  127.     /*---------------------------------------------------------------------------------------------------------*/
  128.     /* Init I/O Multi-function                                                                                 */
  129.     /*---------------------------------------------------------------------------------------------------------*/
  130.     /* Set PB multi-function pins for UART0 RXD and TXD */
  131.     SYS->GPB_MFP = SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD;

  132.     /* Setup SPI0 multi-function pins */
  133.     SYS->GPC_MFP = SYS_GPC_MFP_PC0_SPI0_SS0 | SYS_GPC_MFP_PC1_SPI0_CLK | SYS_GPC_MFP_PC2_SPI0_MISO0 | SYS_GPC_MFP_PC3_SPI0_MOSI0;
  134.     SYS->ALT_MFP = SYS_ALT_MFP_PC0_SPI0_SS0 | SYS_ALT_MFP_PC1_SPI0_CLK | SYS_ALT_MFP_PC2_SPI0_MISO0 | SYS_ALT_MFP_PC3_SPI0_MOSI0;
  135. }

  136. void SPI_Init(void)
  137. {
  138.     /*---------------------------------------------------------------------------------------------------------*/
  139.     /* Init SPI                                                                                                */
  140.     /*---------------------------------------------------------------------------------------------------------*/
  141.     /* Configure SPI0 as a master, clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
  142.     /* Set IP clock divider. SPI clock rate = 2 MHz */
  143.     SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 32, 2000000);

  144.     /* Enable the automatic hardware slave select function. Select the SPI0_SS0 pin and configure as low-active. */
  145.     SPI_EnableAutoSS(SPI0, SPI_SS0, SPI_SS_ACTIVE_LOW);
  146. }

  147. void SPI0_IRQHandler(void)
  148. {
  149.     /* Check RX EMPTY flag */
  150.     while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0) == 0)
  151.     {
  152.         /* Read RX FIFO */
  153.         g_au32DestinationData[g_u32RxDataCount++] = SPI_READ_RX0(SPI0);
  154.     }
  155.     /* Check TX FULL flag and TX data count */
  156.     while((SPI_GET_TX_FIFO_FULL_FLAG(SPI0) == 0) && (g_u32TxDataCount < TEST_COUNT))
  157.     {
  158.         /* Write to TX FIFO */
  159.         SPI_WRITE_TX0(SPI0, g_au32SourceData[g_u32TxDataCount++]);
  160.     }
  161.     if(g_u32TxDataCount >= TEST_COUNT)
  162.         SPI_DisableInt(SPI0, SPI_FIFO_TX_INT_MASK); /* Disable TX FIFO threshold interrupt */

  163.     /* Check the RX FIFO time-out interrupt flag */
  164.     if(SPI_GetIntFlag(SPI0, SPI_FIFO_TIMEOUT_INT_MASK))
  165.     {
  166.         /* If RX FIFO is not empty, read RX FIFO. */
  167.         while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0) == 0)
  168.             g_au32DestinationData[g_u32RxDataCount++] = SPI_READ_RX0(SPI0);
  169.     }
  170. }


  171. /*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/

 楼主| zhuomuniao110 发表于 2018-12-26 23:43 | 显示全部楼层
  1. /**************************************************************************//**
  2. * @file     main.c
  3. * @version  V2.0
  4. * $Revision: 6 $
  5. * $Date: 14/08/05 11:13a $
  6. * @brief
  7. *           Demonstrate how to communicate with an off-chip SPI master device with Dual I/O mode and FIFO mode.
  8. *           This sample code needs to work with SPI_MasterDualIOMode sample code.
  9. * @note
  10. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include <stdio.h>
  14. #include "NUC123.h"


  15. #define TEST_COUNT 16

  16. uint32_t g_au32SourceData[TEST_COUNT];
  17. uint32_t g_au32DestinationData[TEST_COUNT];
  18. volatile uint32_t g_u32TxDataCount;
  19. volatile uint32_t g_u32RxDataCount;

  20. /* Function prototype declaration */
  21. void SYS_Init(void);
  22. void SPI_Init(void);

  23. /* ------------- */
  24. /* Main function */
  25. /* ------------- */
  26. int main(void)
  27. {
  28.     volatile uint32_t u32TxDataCount, u32RxDataCount;

  29.     /* Unlock protected registers */
  30.     SYS_UnlockReg();

  31.     /* Init System, IP clock and multi-function I/O */
  32.     SYS_Init();

  33.     /* Lock protected registers */
  34.     SYS_LockReg();

  35.     /* Configure UART0: 115200, 8-bit word, no parity bit, 1 stop bit. */
  36.     UART_Open(UART0, 115200);

  37.     /* Init SPI */
  38.     SPI_Init();
  39.     /* Enable Dual I/O input mode */
  40.     SPI_ENABLE_DUAL_INPUT_MODE(SPI0);
  41.     /* Enable FIFO mode and set FIFO threshold. */
  42.     SPI_EnableFIFO(SPI0, 2, 2);

  43.     printf("\n\n");
  44.     printf("+-----------------------------------------------------+\n");
  45.     printf("|           SPI Slave Mode Sample Code                |\n");
  46.     printf("+-----------------------------------------------------+\n");
  47.     printf("\n");
  48.     printf("Configure SPI0 as a slave.\n");
  49.     printf("Bit length of a transaction: 32\n");
  50.     printf("The I/O connection for SPI0:\n");
  51.     printf("    SPI0_SS0 (PC.0)\n    SPI0_CLK (PC.1)\n");
  52.     printf("    SPI0_MISO0 (PC.2)\n    SPI0_MOSI0 (PC.3)\n\n");
  53.     printf("SPI controller will enable Dual I/O mode and FIFO mode.\n");
  54.     printf("In the first stage, the SPI controller will receive %d data from a off-chip master device.\n", TEST_COUNT);
  55.     printf("After the transfer is done, the %d received data will be printed out.\n", TEST_COUNT);
  56.     printf("In the second stage, the SPI controller will transfer %d data to the off-chip master device.\n", TEST_COUNT);
  57.    
  58.     for(u32TxDataCount = 0; u32TxDataCount < TEST_COUNT; u32TxDataCount++)
  59.     {
  60.         /* Write the initial value to source buffer */
  61.         g_au32SourceData[u32TxDataCount] = 0x00AA0000 + u32TxDataCount;
  62.         /* Clear destination buffer */
  63.         g_au32DestinationData[u32TxDataCount] = 0;
  64.     }

  65.     u32RxDataCount = 0;
  66.     printf("< Stage 1 >\n");
  67.     printf("Press any key to start the Dual I/O input transfer if the master device configuration is ready.");
  68.     getchar();
  69.     printf("\n");

  70.     /* Access RX FIFO */
  71.     while(u32RxDataCount < TEST_COUNT)
  72.     {
  73.         /* Check RX EMPTY flag */
  74.         if(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0) == 0)
  75.             g_au32DestinationData[u32RxDataCount++] = SPI_READ_RX0(SPI0); /* Read RX FIFO */
  76.     }

  77.     /* Print the received data */
  78.     printf("Received data:\n");
  79.     for(u32RxDataCount = 0; u32RxDataCount < TEST_COUNT; u32RxDataCount++)
  80.     {
  81.         printf("%d:\t0x%X\n", u32RxDataCount, g_au32DestinationData[u32RxDataCount]);
  82.     }

  83.     /* Enable Dual I/O output mode */
  84.     SPI_ENABLE_DUAL_OUTPUT_MODE(SPI0);
  85.     u32TxDataCount = 0;
  86.     u32RxDataCount = 0;
  87.     printf("< Stage 2 >\n");
  88.     printf("Enable Dual I/O output mode. Slave is ready to transfer.\n");
  89.    
  90.     /* Access TX and RX FIFO */
  91.     while(u32RxDataCount < TEST_COUNT)
  92.     {
  93.         /* Check TX FULL flag and TX data count */
  94.         if((SPI_GET_TX_FIFO_FULL_FLAG(SPI0) == 0) && (u32TxDataCount < TEST_COUNT))
  95.             SPI_WRITE_TX0(SPI0, g_au32SourceData[u32TxDataCount++]); /* Write to TX FIFO */
  96.         /* Check RX EMPTY flag */
  97.         if(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0) == 0)
  98.             g_au32DestinationData[u32RxDataCount++] = SPI_READ_RX0(SPI0); /* Read RX FIFO */
  99.     }
  100.    
  101.    
  102.     printf("\n\nExit SPI driver sample code.\n");

  103.     /* Disable SPI0 peripheral clock */
  104.     SPI_Close(SPI0);
  105.     while(1);
  106. }

  107. void SYS_Init(void)
  108. {
  109.     /*---------------------------------------------------------------------------------------------------------*/
  110.     /* Init System Clock                                                                                       */
  111.     /*---------------------------------------------------------------------------------------------------------*/

  112.     /* Enable XT1_OUT (PF0) and XT1_IN (PF1) */
  113.     SYS->GPF_MFP |= SYS_GPF_MFP_PF0_XT1_OUT | SYS_GPF_MFP_PF1_XT1_IN;

  114.     /* Enable external 12 MHz XTAL */
  115.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  116.     /* Waiting for clock ready */
  117.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  118.     /* Switch HCLK clock source to HXT and HCLK source divide 1 */
  119.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_CLKDIV_HCLK(1));

  120.     /* Select HXT as the clock source of UART0 */
  121.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  122.     /* Select HCLK as the clock source of SPI0 */
  123.     CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL1_SPI0_S_HCLK, MODULE_NoMsk);

  124.     /* Enable UART peripheral clock */
  125.     CLK_EnableModuleClock(UART0_MODULE);
  126.     /* Enable SPI0 peripheral clock */
  127.     CLK_EnableModuleClock(SPI0_MODULE);

  128.     /* Update System Core Clock */
  129.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CyclesPerUs automatically. */
  130.     SystemCoreClockUpdate();

  131.     /*---------------------------------------------------------------------------------------------------------*/
  132.     /* Init I/O Multi-function                                                                                 */
  133.     /*---------------------------------------------------------------------------------------------------------*/
  134.     /* Set PB multi-function pins for UART0 RXD and TXD */
  135.     SYS->GPB_MFP = SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD;

  136.     /* Setup SPI0 multi-function pins */
  137.     SYS->GPC_MFP = SYS_GPC_MFP_PC0_SPI0_SS0 | SYS_GPC_MFP_PC1_SPI0_CLK | SYS_GPC_MFP_PC2_SPI0_MISO0 | SYS_GPC_MFP_PC3_SPI0_MOSI0;
  138.     SYS->ALT_MFP = SYS_ALT_MFP_PC0_SPI0_SS0 | SYS_ALT_MFP_PC1_SPI0_CLK | SYS_ALT_MFP_PC2_SPI0_MISO0 | SYS_ALT_MFP_PC3_SPI0_MOSI0;
  139. }

  140. void SPI_Init(void)
  141. {
  142.     /*---------------------------------------------------------------------------------------------------------*/
  143.     /* Init SPI                                                                                                */
  144.     /*---------------------------------------------------------------------------------------------------------*/
  145.     /* Configure SPI0 as a slave, clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
  146.     /* Configure SPI0 as a low level active device. SPI peripheral clock rate is equal to system clock rate. */
  147.     SPI_Open(SPI0, SPI_SLAVE, SPI_MODE_0, 32, NULL);
  148. }

  149. /*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/


dongliushui 发表于 2018-12-27 11:39 | 显示全部楼层
只用过标准的SPI
幸福小强 发表于 2018-12-27 23:16 | 显示全部楼层
手册好像提过。
598330983 发表于 2018-12-29 23:32 来自手机 | 显示全部楼层
spi好几个形势
xinpian101 发表于 2018-12-30 13:43 | 显示全部楼层
新唐的单片机性能强大,支持多种SPI模式。
观海 发表于 2019-1-8 11:12 | 显示全部楼层
我很少用全双工的
keaibukelian 发表于 2019-1-8 11:31 | 显示全部楼层
非常感谢楼主分享
renzheshengui 发表于 2019-1-8 11:51 | 显示全部楼层
我用三根线的时候很多
您需要登录后才可以回帖 登录 | 注册

本版积分规则

233

主题

3529

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部