[DemoCode下载] N76E885的SPI Flash用法

[复制链接]
1724|12
 楼主| yiyigirl2014 发表于 2017-2-17 21:10 | 显示全部楼层 |阅读模式
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*                                                                                                         */
  3. /* Copyright(c) 2015 Nuvoton Technology Corp. All rights reserved.                                         */
  4. /*                                                                                                         */
  5. /*---------------------------------------------------------------------------------------------------------*/

  6. //***********************************************************************************************************
  7. //  Nuvoton Technoledge Corp.
  8. //  Website: http://www.nuvoton.com
  9. //  E-Mail : MicroC-8bit@nuvoton.com
  10. //  Date   : Apr/21/2015
  11. //***********************************************************************************************************

  12. //***********************************************************************************************************
  13. //  File Function: N76E885 Access SPI Flash (W25Q16BV) demo code
  14. //***********************************************************************************************************

  15. #include <stdio.h>
  16. #include <intrins.h>
  17. #include <string.h>
  18. #include "N76E885.h"
  19. #include "Version.h"
  20. #include "Typedef.h"
  21. #include "Define.h"
  22. #include "SFR_Macro.h"
  23. #include "Common.h"
  24. #include "Delay.h"

  25. /*
  26. //-------- <<< Use Configuration Wizard in Context Menu >>> ------------
  27. //
  28. //<e0> System Clock Source Configuration
  29. // <o1> System Clock Source Selection
  30. //      <0=> 2~25MHz    XTAL
  31. //      <1=> 32.768KHz  XTAL
  32. //      <2=> 22.1184MHz Internal
  33. //      <3=> 10KHz      Internal
  34. //      <4=> OSC-In     External
  35. //</e>
  36. //
  37. //<e2> Clock Divider Configuration
  38. //     <o3.0..7>  System Clock Source Devider <1-255>
  39. //                     <i> Fsys = (System Clock Source) / (2 * Devider)
  40. //</e>
  41. //
  42. // <o4> SPI Clock Rate Selection (11.0592MHz System Clock)
  43. //                  <0=>  2.7648MHz, Fosc/4
  44. //                  <1=>  1.3824MHz, Fosc/8
  45. //                  <2=>  0.6912MHz, Fosc/16
  46. //                  <3=>  0.3456MHz, Fosc/32
  47. //-------- <<< end of configuration section >>> ------------------------------
  48. */

  49. #define SYS_CLK_EN      0
  50. #define SYS_SEL         2
  51. #define SYS_DIV_EN      0                   //0: Fsys=Fosc, 1: Fsys = Fosc/(2*CKDIV)
  52. #define SYS_DIV         1
  53. #define SPI_CLOCK       0

  54. #define SS_PIN          P04
  55. #define WRITE_ENABLE    0x06
  56. #define WRITE_DISABLE   0x04
  57. #define READ_DATA       0x03
  58. #define PAGE_PROGRAM    0x02
  59. #define CHIP_ERASE      0xC7
  60. #define READ_STATUS1    0x05
  61. bit BIT_TMP;
  62. //-----------------------------------------------------------------------------------------------------------
  63. void SPI_Error(void)
  64. {
  65.     printf ("\n*  SPI Error, please check the connection between MCU and SPI Flash");
  66.     while(1);
  67. }
  68. //-----------------------------------------------------------------------------------------------------------
  69. void SPI_Initial(void)
  70. {
  71.     #if   SPI_CLOCK == 0
  72.             clr_SPR1;
  73.             clr_SPR0;
  74.     #elif SPI_CLOCK == 1
  75.             clr_SPR1;
  76.             set_SPR0;
  77.     #elif SPI_CLOCK == 2
  78.             set_SPR1;  
  79.             clr_SPR0;
  80.     #elif SPI_CLOCK == 3
  81.             set_SPR1;
  82.             set_SPR0;
  83.     #endif

  84.     /* /SS General purpose I/O ( No Mode Fault ) */
  85.     set_DISMODF;
  86.     clr_SSOE;

  87.     /* SPI in Master mode */
  88.     set_MSTR;

  89.     /* MSB first */
  90.     clr_LSBFE;

  91.     clr_CPOL;
  92.     clr_CPHA;
  93.    
  94.     /* Enable SPI function */
  95.     set_SPIEN;
  96. }
  97. //-----------------------------------------------------------------------------------------------------------
  98. void Read_MID_DID(UINT8 *pu8MID,UINT8 *pu8DID)
  99. {
  100.     SS_PIN = 0;
  101.     SPDR = 0x90;
  102.     while((SPSR&0x80)==0x00);
  103.     clr_SPIF;

  104.     SPDR = 0x00;
  105.     while((SPSR&0x80)==0x00);
  106.     clr_SPIF;

  107.     SPDR = 0x00;
  108.     while((SPSR&0x80)==0x00);
  109.     clr_SPIF;

  110.     SPDR = 0x00;
  111.     while((SPSR&0x80)==0x00);
  112.     clr_SPIF;

  113.     SPDR = 0xFF;
  114.     while((SPSR&0x80)==0x00);
  115.     *pu8MID = SPDR;
  116.     clr_SPIF;

  117.     SPDR = 0xFF;
  118.     while((SPSR&0x80)==0x00);
  119.     *pu8DID = SPDR;
  120.     clr_SPIF;
  121.     SS_PIN = 1;   
  122. }
  123. //-----------------------------------------------------------------------------------------------------------
  124. void Flash_Write_Enable(void)
  125. {
  126.     SS_PIN = 0;
  127.     SPDR = WRITE_ENABLE;
  128.     while((SPSR&0x80)==0x00);
  129.     clr_SPIF;
  130.     SS_PIN = 1;   
  131. }
  132. //-----------------------------------------------------------------------------------------------------------
  133. void Flash_Write_Disable(void)
  134. {
  135.     SS_PIN = 0;
  136.     SPDR = WRITE_DISABLE;
  137.     while((SPSR&0x80)==0x00);
  138.     clr_SPIF;
  139.     SS_PIN = 1;   
  140. }
  141. //-----------------------------------------------------------------------------------------------------------
  142. void Flash_Chip_Erase(void)
  143. {
  144.     SS_PIN = 0;
  145.     SPDR = CHIP_ERASE;
  146.     while((SPSR&0x80)==0x00);
  147.     clr_SPIF;
  148.     SS_PIN = 1;   
  149. }
  150. //-----------------------------------------------------------------------------------------------------------
  151. void Flash_Read_Status(void)
  152. {
  153.     UINT8 u8Status;

  154.     SS_PIN = 0;
  155.     do{
  156.         SPDR = READ_STATUS1;
  157.         while((SPSR&0x80)==0x00);
  158.         clr_SPIF;
  159.    
  160.         SPDR = 0xFF;
  161.         while((SPSR&0x80)==0x00);
  162.         u8Status = SPDR;
  163.         clr_SPIF;
  164.     }while((u8Status&0x01)==0x01);
  165.     SS_PIN = 1;   
  166. }
  167. //-----------------------------------------------------------------------------------------------------------
  168. void Flash_Erase_Verify(void)
  169. {
  170.     UINT16 u16CNT;   
  171.     UINT8  u8Data;

  172.     SS_PIN = 0;

  173.     SPDR = READ_DATA;
  174.     while((SPSR&0x80)==0x00);
  175.     clr_SPIF;

  176.     /* 24-bit Address */
  177.     SPDR = 0x00;
  178.     while((SPSR&0x80)==0x00);
  179.     clr_SPIF;

  180.     SPDR = 0x00;
  181.     while((SPSR&0x80)==0x00);
  182.     clr_SPIF;

  183.     SPDR = 0x00;
  184.     while((SPSR&0x80)==0x00);
  185.     clr_SPIF;

  186.     for(u16CNT=0;u16CNT<256;u16CNT++)
  187.     {
  188.         SPDR = 0x00;
  189.         while((SPSR&0x80)==0x00);
  190.         u8Data = SPDR;
  191.         clr_SPIF;
  192.         if(u8Data != 0xFF)
  193.         {
  194.             SPI_Error();
  195.         }
  196.     }

  197.     SS_PIN = 1;
  198. }
  199. //-----------------------------------------------------------------------------------------------------------
  200. void Flash_Program(void)
  201. {
  202.     UINT16 u16CNT;
  203.    
  204.     SS_PIN = 0;

  205.     SPDR = PAGE_PROGRAM;
  206.     while((SPSR&0x80)==0x00);
  207.     clr_SPIF;

  208.     /* 24-bit Address */
  209.     SPDR = 0x00;
  210.     while((SPSR&0x80)==0x00);
  211.     clr_SPIF;

  212.     SPDR = 0x00;
  213.     while((SPSR&0x80)==0x00);
  214.     clr_SPIF;

  215.     SPDR = 0x00;
  216.     while((SPSR&0x80)==0x00);
  217.     clr_SPIF;

  218.     /* Send the data to SPI_Flash buffer */
  219.     for(u16CNT=0;u16CNT<256;u16CNT++)
  220.     {
  221.         SPDR = (UINT8)u16CNT;
  222.         while((SPSR&0x80)==0x00);
  223.         clr_SPIF;
  224.     }
  225.    
  226.     SS_PIN = 1;   
  227. }
  228. //-----------------------------------------------------------------------------------------------------------
  229. void Flash_Program_Verify(void)
  230. {
  231.     UINT16 u16CNT;   
  232.     UINT8  u8Data;

  233.     SS_PIN = 0;

  234.     SPDR = READ_DATA;
  235.     while((SPSR&0x80)==0x00);
  236.     clr_SPIF;

  237.     /* 24-bit Address */
  238.     SPDR = 0x00;
  239.     while((SPSR&0x80)==0x00);
  240.     clr_SPIF;

  241.     SPDR = 0x00;
  242.     while((SPSR&0x80)==0x00);
  243.     clr_SPIF;

  244.     SPDR = 0x00;
  245.     while((SPSR&0x80)==0x00);
  246.     clr_SPIF;

  247.     for(u16CNT=0;u16CNT<256;u16CNT++)
  248.     {
  249.         SPDR = 0x00;
  250.         while((SPSR&0x80)==0x00);
  251.         u8Data = SPDR;
  252.         clr_SPIF;
  253.         if(u8Data != (UINT8)u16CNT)
  254.         {
  255.             SPI_Error();
  256.         }
  257.     }

  258.     SS_PIN = 1;
  259. }
  260. //-----------------------------------------------------------------------------------------------------------
  261. void main(void)
  262. {      
  263.     UINT8 u8MID,u8DID;

  264.     /* Note
  265.        MCU power on system clock is HIRC (22.1184MHz), so Fsys = 22.1184MHz
  266.     */
  267.    
  268.     Set_All_GPIO_Quasi_Mode();
  269.     InitialUART0_Timer1_Type1(9600);             /* 9600 Baud Rate*/

  270.     Show_FW_Version_Number_To_PC();
  271.    
  272.     printf ("\n*===================================================================");
  273.     printf ("\n*  Name: N76E885 SPI Demo Code, MCU <--> W25Q16BV");
  274.     printf ("\n*===================================================================\n");
  275.    
  276.     /* Change system closk source */
  277.     #if SYS_CLK_EN == 1
  278.         #if   SYS_SEL == 0
  279.             System_Clock_Select(E_HXTEN);   //Fosc = 2~25MHz XTAL
  280.         #elif SYS_SEL == 1
  281.             System_Clock_Select(E_LXTEN);   //Fosc = 32.768KHz XTAL
  282.         #elif SYS_SEL == 2
  283.             System_Clock_Select(E_HIRCEN);  //Fosc = 22.1184MHz Internal RC
  284.         #elif SYS_SEL == 3
  285.             System_Clock_Select(E_LIRCEN);  //Fosc = 10KHz Internal RC
  286.         #elif SYS_SEL == 4
  287.             System_Clock_Select(E_OSCEN);   //Fosc = OSC-In External OSC
  288.         #endif
  289.     #endif
  290.    
  291.     #if SYS_DIV_EN == 1
  292.         CKDIV = SYS_DIV;                    //Fsys = Fosc / (2* CLKDIV) = Fcpu
  293.     #endif

  294.     SPI_Initial();

  295.     Read_MID_DID(&u8MID,&u8DID);

  296.     printf ("\n*  MID value of W25Q16BV = 0x%X",(UINT16)u8MID);
  297.     printf ("\n*  DID value of W25Q16BV = 0x%X",(UINT16)u8DID);

  298.     if((u8MID != 0xEF)&&(u8DID != 0x17))
  299.     {
  300.         SPI_Error();
  301.     }

  302.     /* The procedure of SPI Flash at erase mode */
  303.     Flash_Write_Enable();
  304.     Flash_Chip_Erase();
  305.     Flash_Read_Status();
  306.     Flash_Write_Disable();
  307.    
  308.     Flash_Erase_Verify();

  309.     /* The procedure of SPI Flash at program mode */
  310.     Flash_Write_Enable();
  311.     Flash_Program();
  312.     Flash_Read_Status();
  313.     Flash_Write_Disable();

  314.     /* Program verify */
  315.     Flash_Program_Verify();

  316.     printf("\nFinished the SPI Demo Code and test pass!!!\n");
  317.     while(1);
  318. }
  319. //-----------------------------------------------------------------------------------------------------------


 楼主| yiyigirl2014 发表于 2017-2-17 21:11 | 显示全部楼层
官方封装了很多头文件了,里面有很多可以使用的函数。
 楼主| yiyigirl2014 发表于 2017-2-17 21:15 | 显示全部楼层
下面是这个SPI芯片的图。
QQ截图20170217211217.png
玛尼玛尼哄 发表于 2017-2-17 21:20 | 显示全部楼层
SPI的初始化用了不少的预编译。
598330983 发表于 2017-2-19 19:26 | 显示全部楼层
对于外部SPI的应用和Flash应用的组合历程。
heisexingqisi 发表于 2017-2-19 23:22 | 显示全部楼层
按页面进行擦写,能否按位呢。
gejigeji521 发表于 2017-2-20 00:00 | 显示全部楼层
  clr_SPIF;
        if(u8Data != 0xFF)
        {
            SPI_Error();
        }
清理后,如果对应的位置不为空,这里清理后应该就是都写1了。就该调用错误处理函数了。
 楼主| yiyigirl2014 发表于 2017-2-20 00:11 | 显示全部楼层
SPI Clock Rate Selection (11.0592MHz System Clock)
//                  <0=>  2.7648MHz, Fosc/4
//                  <1=>  1.3824MHz, Fosc/8
//                  <2=>  0.6912MHz, Fosc/16
//                  <3=>  0.3456MHz, Fosc/32
这也给出了分频的方式。
mintspring 发表于 2017-2-20 00:17 | 显示全部楼层
运用do while的地方,就是不管对错都要执行一次。
zhuomuniao110 发表于 2017-2-21 19:24 | 显示全部楼层
初始化的配置尤为重要。弄不对了,就后面没法玩了。
huangcunxiake 发表于 2017-2-21 19:59 | 显示全部楼层
  while((SPSR&0x80)==0x00);
    clr_SPIF;
通过这个来判断,然后清除标志位。
wahahaheihei 发表于 2017-2-21 20:12 | 显示全部楼层
这个例子也可以看出来while在判断上的重要性
TomLinTon 发表于 2019-11-26 11:38 | 显示全部楼层
请问是否有NUC121/125的SPI例程,我按照官网那个去跑,跑不起来
您需要登录后才可以回帖 登录 | 注册

本版积分规则

230

主题

3676

帖子

10

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