如题,这几天都忙于winces手持机,抽空看了下W25Q16BV的芯片资料,用NUC120SPI1总线“所谓的中断方式"操作。参考BSP例程和三心的程序。谢谢。
SPI总线操作W25Q16BV:
#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;
}
main 函数
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
/*---------------------------------------------------------------------------------------------------------*/
/******************************************************************************
文件名: 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");
}
}
}
}
|