原创 新唐NUC120操作W25Q16BV

2011-8-23 14:20 2915 9 9 分类: MCU/ 嵌入式
如题,用菜农老师的助学板写的。以前俺都习惯用模拟的SPI去解决问题,用这个板子试了下自带的SPI控制器。板子上是用W25Q16BV这款SPI接口的FLASH,这块片子是华邦出的,去DataSheet网上找居然没有,后来去华邦的官网下载了。他由8192个可编程的页组成,每页有256bytes。一次可写256bytes,可以sector、BLOCK、whole chip擦除。具体擦除的指令可以参照其Datasheet,我就不说了。下面附上程序,整个工程见附件:

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyrightp;                         */
/*---------------------------------------------------------------------------------------------------------*/


/******************************************************************************
文件名:    W25Q16BV_Function.c
说  明:    本文件为“NUC120RE3AN用SPI总线主机模式读写W25Q16BV的主函数。UART的波特率为115200。
申明:       本程序参考三心的spi程序和板子自带的BSP例程,运用中断模式。谢谢。
开  始:    2011.8.23
修  改:    V1.0
******************************************************************************/

#include <stdio.h>
#include "NUC1xx.h"
#include "DrvUART.h"
#include "DrvSYS.h"
#include "DrvSPI.h"
#include "global.h"

 
int main()
{
    SYSTEM_Config();
    UART_Config();
    GPIO_Config();
    W25Q16BV_SPI_Init();
 
 

      printf("\n\n");
    printf("+----------------------------------------------------------------------+\n");       
    printf("|                      菜农老师助学板之SPI操作W25Q16BV                 |\n");
    printf("|                                                                      |\n");
    printf("+----------------------------------------------------------------------+\n");
    printf("\n");
    printf("配置SPI1为主机模式.\n");
    printf("SPI1 时钟为: %d Hz\n", DrvSPI_GetClock1Freq(eDRVSPI_PORT1));
   
  
  while(1)
  {
       if(SPI_Start_Flag==TRUE)
     {
        SPI_Start_Flag=FALSE;
        printf("开始操作SPI\n");
        switch(UART_Buffer_Rx)
        {
          case  'R':
          case  'r':
          printf("Read data from W25Q16BV ...\n");
         
          W25Q16BV_SPI_ReadFlash();
          break;


          case 'W':
          case 'w':
          printf("Write data to W25Q16BV ...\n");


          DrvSYS_Delay(1000);
          W25Q16BV_SPI_PageProgram();
          printf("Write Flash Over!\n");
          break;
          default:
        printf("您输入的指令有误!\n");
        }
       
    
     }
 
    }

}







#include <stdio.h>
#include "NUC1xx.h"
#include "DrvUART.h"
#include "DrvSYS.h"
#include "DrvSPI.h"
#include "DrvGPIO.h"
#include "Drive_Function.h"

#define Enable_SPI1_W25Q16BV     DrvGPIO_ClrBit(E_GPA, 14)
#define Disable_SPI1_W25Q16BV    DrvGPIO_SetBit(E_GPA, 14)
//extern  uint32_t  SPI_TX_DATA_Buffer[256];
//extern  uint32_t  SPI_RX_DATA_Buffer[256];
extern  uint32_t  SPI_RX_DATA;
extern  uint32_t Write_Enable;
extern  uint32_t Write_Disable;
extern  uint32_t Read_Status_Register1;
extern  uint32_t Read_DATA;
extern  uint32_t Page_Program;
extern  uint32_t Sector_Erase;
extern  uint32_t Chip_Erase;
extern  uint32_t Read_ID;
extern  uint32_t Addr;


extern uint8_t SPI_DATA_Buffer[256];

extern volatile uint8_t count;
extern volatile uint32_t g_Spi1IntFlag;
extern volatile uint8_t  W25Q16BV_BUSY_Flag;
extern uint32_t u32Tmp;



void W25Q16BV_SPI_Init()

     
    /*开SPI1总线  设置为主机模式,波形1*/
     DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);   
    /*设置为MSP优先传输MSB*/
    DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);           
    /*从机选择线低电平或者下降沿激活*/
    DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
    /*SPI总线的速率设置为1MHZ*/   
    DrvSPI_SetClockFreq(eDRVSPI_PORT1, 1000000, 0);
    /*使能W25Q16BV 的片选信号*/
    Enable_SPI1_W25Q16BV;
    /*开启SPI1总线中断,并且与回调函数SPI1_Callback挂钩*/
    DrvSPI_EnableInt(eDRVSPI_PORT1, SPI1_Callback, 1);
                                 
}




void W25Q16BV_SPI_PageProgram()
{
       uint16_t i;
    uint32_t au32SourceData;
     /*使能SPI1中断,且SPI1_Callback为其回调函数*/
    DrvSPI_EnableInt(eDRVSPI_PORT1, SPI1_Callback, 0);
     /*中断标志清0*/
    g_Spi1IntFlag=0;
 
   /*使能W25Q16BV*/
   Enable_SPI1_W25Q16BV;


   /* Set the bit length of SPI transfer. */ 
   DrvSPI_SetBitLength(eDRVSPI_PORT1,8);

   /*写使能*/
   au32SourceData=0x06;
   printf("发送写能W25Q16BV\n");
   DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
 
   /*等待传输完毕*/
   while(g_Spi1IntFlag==0);
   g_Spi1IntFlag=0;

   printf("写能W25Q16BV指令发送完毕\n");


   /*关闭CS*/
   Disable_SPI1_W25Q16BV;
 

   /*打开CS*/
   Enable_SPI1_W25Q16BV;
  

   printf("Page_Program指令开始发送\n");
   au32SourceData=0x02;
   DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);

    /*等待传输完毕*/
   while(g_Spi1IntFlag==0);
   g_Spi1IntFlag=0;
 

   DrvSPI_SetBitLength(eDRVSPI_PORT1,24);
   au32SourceData=0x0000;
   DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);

    /*等待传输完毕*/
   while(g_Spi1IntFlag==0);
   g_Spi1IntFlag=0;
   printf("Page_Program指令已经发送完毕\n");



   DrvSPI_SetBitLength(eDRVSPI_PORT1,8);


   for(i=0;i<256;i++)
   {
     SPI_DATA_Buffer=0x02;
      au32SourceData=SPI_DATA_Buffer;
     DrvSPI_SingleWrite(eDRVSPI_PORT1,&au32SourceData);
      /*等待传输完毕*/
     while(g_Spi1IntFlag==0);
     g_Spi1IntFlag=0;
     printf("写入的值为: %d\n", SPI_DATA_Buffer);
   }
    Disable_SPI1_W25Q16BV;
}

void W25Q16BV_SPI_ReadFlash()
{   
     uint32_t au32SourceData;
     uint16_t i;

     /*中断标志清0*/
     g_Spi1IntFlag=0;

     /*使能SPI1中断,且SPI1_Callback为其回调函数*/
     DrvSPI_EnableInt(eDRVSPI_PORT1, SPI1_Callback, 0);   
   
     /*设置传输的长度*/
     DrvSPI_SetBitLength(eDRVSPI_PORT1,8);
     /*使能W25Q16BV*/
     Enable_SPI1_W25Q16BV;
  
     /*读操作指令*/
     au32SourceData=0X03;
     /*写入指令*/
     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);

        /*等待传输完毕*/
    printf("开始写读命令字和地址\n");
    while(g_Spi1IntFlag==0);
    g_Spi1IntFlag=0;                 
    printf("写完读命令字和地址\n");

     /*设置传送长度为24位*/
    DrvSPI_SetBitLength(eDRVSPI_PORT1,24);
    /*传送地址*/
    au32SourceData=0X0000;
    DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);

        /*等待传输完毕*/
    while(g_Spi1IntFlag==0);
    g_Spi1IntFlag=0;         
    DrvSPI_SetBitLength(eDRVSPI_PORT1,8);
   
       for(i =0; i<256; i++)
    {
      au32SourceData=0x0;
       
     /*开始接收数据*/
     DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
    /*等待传输完毕*/
     while(g_Spi1IntFlag==0);
     g_Spi1IntFlag=0;   
     /*读取收到的数据*,并且不触发下一次传送*/
     DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &SPI_RX_DATA, 1);
     /*打印收到的数据*/
     SPI_DATA_Buffer=(uint8_t)SPI_RX_DATA;
     printf("0x%X ",SPI_DATA_Buffer);
     if ((i%10)==6)printf("\n");
     }
      printf("所有数据接收完毕\n");
     Disable_SPI1_W25Q16BV;
 }

void W25Q16BV_SPI_ChipErase()
{
  
        /*使能SPI1中断,且SPI1_Callback为其回调函数*/
    DrvSPI_EnableInt(eDRVSPI_PORT1, SPI1_Callback, 0);
    /*中断标志清0*/
   g_Spi1IntFlag=0;
 
   /*使能W25Q16BV*/
   Enable_SPI1_W25Q16BV;

   /* Set the bit length of SPI transfer. */ 
   DrvSPI_SetBitLength(eDRVSPI_PORT1,8);


/* write the first data of source buffer to Tx register of SPI0. And start transmission. */
   DrvSPI_SingleWrite(eDRVSPI_PORT1, &Write_Enable);

   /*等待传输完毕*/
   while(g_Spi1IntFlag==0);
   g_Spi1IntFlag=0;

    /*关闭CS*/
   Disable_SPI1_W25Q16BV;
   DrvSPI_SetBitLength(eDRVSPI_PORT1,8);

   /*打开CS*/
   Enable_SPI1_W25Q16BV;

   DrvSPI_SingleWrite(eDRVSPI_PORT1, &Chip_Erase);

        /*等待传输完毕*/
   while(g_Spi1IntFlag==0);
   g_Spi1IntFlag=0;

   Disable_SPI1_W25Q16BV;

}

void SPI1_Callback(uint32_t u32UserData)
{
    g_Spi1IntFlag = 1;
}



rar.gifNUC120_SPI1_W25Q16BV.rar
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条