- #include
- #include "NUC1xx.h"
- #include "Driver\DrvGPIO.h"
- #include "Driver\DrvSYS.h"
- #include "Driver\DrvUART.h"
- #include "Driver\DrvSPI.h"
- volatile uint8_t IsStart = FALSE;
- volatile uint8_t Receive_Data = 0;
- /* PA14(38脚)接的SPI_Flash_CS */
- #define SPI_CS_PORT E_GPA
- #define SPI_CS_PORT_NUM 14
- #define Enable_SPI_CS DrvGPIO_ClrBit(SPI_CS_PORT,SPI_CS_PORT_NUM)
- #define DISABLE_SPI_CS DrvGPIO_SetBit(SPI_CS_PORT,SPI_CS_PORT_NUM)
- /**************************************************************************************
- ** Name: SPI_ReadStatusReg1
- ** Function: W25Q16BV读状态寄存器1函数
- ***************************************************************************************/
- uint32_t SPI_ReadStatusReg1(void)
- {
- /*
- Status Register - 1
- S7 S6 S5 S4 S3 S2 S1 S0
- SRP0 SEC TB BP2 BP1 BP0 WEL BUSY
- Status Register - 2
- S15 S14 S13 S12 S11 S10 S9 S8
- Suspend Status (R) (R) (R) (R) (R) CE SRP1
- */
- uint32_t ByteCode; //相当于命令
- uint32_t ReceiveData; //接收
-
- /* 配置SPI传输的比特长度:16 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
- Enable_SPI_CS;
- /* 发送数据到 SPI 总线: 0x0500 (Read status register 1) */
- ByteCode = 0x0500;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
-
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- DISABLE_SPI_CS;
- /*
- 从接收寄存器读数据. 但是不触发下一次数据传输.
- uint32_t DrvSPI_DumpRxRegister(eSpiPort,*pu32Buf,DataCount)
- (SPI端口,缓存指针,用来存放从接收器收到的数据,要收的数据笔数,不能超过2笔)
- */
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &ReceiveData, 1);
- return (ReceiveData & 0xFF);
- }
- /*****************************************************************************************
- ** Name: SPI_WaitReady
- ** Function: W25Q16BV忙状态检查函数
- *******************************************************************************************/
- void SPI_WaitReady(void)
- {
- uint32_t BusyFlag;
- /*
- S7 S6 S5 S4 S3 S2 S1 S0
- SRP0 SEC TB BP2 BP1 BP0 WEL BUSY
- 检查从设备状态寄存器1的BUSY位 等待其为0
- */
- do
- {
- BusyFlag = SPI_ReadStatusReg1();
- BusyFlag &= 0x01;
- }while( BusyFlag != 0 );
- }
- /**********************************************************************************
- ** Name: SPI_PageProgram
- ** Function: W25Q16BV按页编程函数
- *********************************************************************************/
- void SPI_PageProgram(uint8_t *DataBuffer,uint32_t StartAddress,uint32_t ByteCount)
- {
- uint32_t ByteCode;
- uint32_t Counter;
- /*
- DrvSPI_SetBitLength(E_DRVSPI_PORT eSpiPort,BitLength)
- 这里选择配置SPI传输的比特长度:8 bits
- */
- DrvSPI_SetBitLength(eDRVSPI_PORT1,8);
- /*
- 激活/配置从设备片选信号
- */
- Enable_SPI_CS;
- /* Enable Write(06H) From DataSheet */
- ByteCode = 0x06;
- /*
- BOOL DrvSPI_SingleWrite( eSpiPort,*pu32Data )
- 发送数据到SPI总线
- */
- DrvSPI_SingleWrite( eDRVSPI_PORT1,&ByteCode);
- while( DrvSPI_IsBusy(eDRVSPI_PORT1) ){}
- DISABLE_SPI_CS;
- Enable_SPI_CS;
- /*
- 由手册可知
- Page Program Instruction Sequence Diagram
- FIRST: Instrustion 02H
- Second: 24-Bit Address
- Third: Data Byte1
- Data Byte2
- …………………………
- Data Byte256
- */
- /* Page Program(02H) From DataSheet
- 发送数据到 SPI 总线: 0x02 */
- ByteCode = 0x02;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- /* 配置SPI传输的比特长度:24 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
-
- /* BIT- Address */
- ByteCode = StartAddress;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
-
- /* DATABIT 8位 */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
- for(Counter=0; Counter<ByteCount; Counter++)
- {
- ByteCode = DataBuffer[Counter];
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- }
-
- DISABLE_SPI_CS;
- }
- /****************************************************************************************
- ** Name: SPI_ChipErase
- ** Function: W25Q16BV片擦除函数
- *****************************************************************************************/
- void SPI_ChipErase(void)
- {
-
- uint32_t ByteCode;
- /* 配置SPI传输的比特长度:8 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
- Enable_SPI_CS;
- /* 发送数据到 SPI 总线: 0x06 (Write enable) */
- ByteCode = 0x06;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- DISABLE_SPI_CS;
- Enable_SPI_CS;
- /* 发送数据到 SPI 总线: 0xC7 (Chip Erase) */
- ByteCode = 0xC7;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- DISABLE_SPI_CS;
- }
- /*****************************
- ** Name: SPI_ReadData
- ** Function: W25Q16BV读数据函数
- ***********************************/
- void SPI_ReadData(uint8_t *DataBuffer, uint32_t StartAddress, uint32_t ByteCount)
- {
- uint32_t ByteCode;
- uint32_t ReceiveData;
- uint32_t Counter;
- /* 配置SPI传输的比特长度:8 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
- Enable_SPI_CS;
- /* 发送数据到 SPI 总线: 0x03 (Read data) */
- ByteCode = 0x03;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
- /* 配置SPI传输的比特长度:24 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
- /* 发送数据到 SPI 总线: StartAddress */
- ByteCode = StartAddress;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
- /* 配置SPI传输的比特长度:8 bits */
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
-
- for(Counter=0; Counter<ByteCount; Counter++)
- {
- ByteCode = 0x0;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &ByteCode);
-
- while (DrvSPI_IsBusy(eDRVSPI_PORT1));
-
- /* 从接收寄存器读数据. 但是不触发下一次数据传输. */
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &ReceiveData, 1);
-
- DataBuffer[Counter] = (uint8_t) ReceiveData;
- }
- DISABLE_SPI_CS;
- }
- /******************************************************************************************
- ** Name: UART_INT_HANDLE
- ** Function: UART Callback function
- *******************************************************************************************/
- void UART_INT_HANDLE(uint32_t u32IntStatus)
- {
- uint8_t bInChar[1]={0xFF};
- if(u32IntStatus & DRVUART_RDAINT)
- {
- /* Get all the input characters */
- while(UART0->ISR.RDA_IF==1)
- {
- /* Get the character from UART Buffer */
- DrvUART_Read(UART_PORT0,bInChar,1);
- if (IsStart!=TRUE)
- {
- IsStart = TRUE;
- Receive_Data = bInChar[0];
- }
- }
- }
- }
- /*******************************************************************************************
- ** Name: Init_System
- ** Function: 系统初始化函数
- *******************************************************************************************/
- void Init_System(void)
- {
- /* Unlock the locked registers before access */
- UNLOCKREG(x); //寄存器锁定键地址寄存器(RegLockAddr) :有些系统控制寄存器需要被保护起来,以防止误操作而影响芯片运行,
- //这些寄存器在上电复位到用户解锁定之前是锁定的。用户可以连续依次写入“59h”, “16h” “88h”到0x5000_0100解锁定.
- /* Enable the 12MHz oscillator oscillation */
- DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); //SYSCLK->PWRCON.XTL12M_EN = 1;
- /* Waiting for 12M Xtal stable */
- //while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1); //SYSCLK->CLKSTATUS.XTL12M_STB
- /*eClkSrc - [in] E_SYS_XTL12M / E_SYS_XTL32K / E_SYS_OSC22M / E_SYS_OSC10K / E_SYS_PLL */
- // Note: Only some of NuMicro NUC100 Series support this function.
- DrvSYS_Delay(5000);
- LOCKREG(x);
- //向“0x5000_0100”写入任何值,就可以重锁保护寄存器
- }
- void Init_Uart(void)
- {
- STR_UART_T param;
- /*
- 声明 UART设置的结构体 位于DRVUART.H
- 结构体如下
- typedef struct DRVUART_STRUCT
- {
- uint32_t u32BaudRate;
- E_DATABITS_SETTINS u8cDataBits;
- E_STOPBITS_SETTINS u8cStopBits;
- E_PARITY_SETTINS u8cParity;
- E_FIFO_SETTINGS u8cRxTriggerLevel;
- uint8_t u8TimeOut ;
- }STR_UART_T;
- */
- DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0); //使能UART时钟
- //SYSCLK->CLKSEL1.UART_S = 0; //UART时钟源选择. 00 =外部12MHz 晶振 01 = PLL 1x =内部 22MHz 振荡器
- DrvGPIO_InitFunction(E_FUNC_UART0); //GPB_MFP0-1-2-3置位 GPIO使能UART功能
- //outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) | (0xF<<0));
- param.u32BaudRate = 115200; // 波特率
- param.u8cDataBits = DRVUART_DATABITS_8; // 数据位
- param.u8cStopBits = DRVUART_STOPBITS_1; // 停止位
- param.u8cParity = DRVUART_PARITY_NONE; // 校验位
- param.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES; // FIFO存储深度 1 字节
- param.u8TimeOut = 0; // FIFO超时设定
- /* Set UART Configuration */
- if(DrvUART_Open(UART_PORT0,¶m) != E_SUCCESS) // 串口开启、结构体整体赋值
- printf("UART0 open failed\n");
- /* u32Port -[in] UART Channel: UART_PORT0 / UART_PORT1 /UART_PORT2 */
- /* sParam -[in] the struct parameter to configure UART */
- /* Enable Interrupt and install the call back function */
- DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);
- /*u32Port -[in] UART Channel: UART_PORT0 / UART_PORT1 / UART_PORT2 */
- /*u32InterruptFlag -[in] DRVUART_LININT/DRVUART_WAKEUPINT/DRVUART_BUFERRINT/DRVUART_RLSINT */
- /* DRVUART_MOSINT/DRVUART_THREINT/DRVUART_RDAINT/DRVUART_TOUTINT */
- /*pfncallback -[in] A function pointer for callback function */
- }
- /*****************************************************************************************
- ** Name: Init_SPI
- ** Function: SPI初始化函数
- *****************************************************************************************/
- void Init_SPI(void)
- {
- /*
- DrvSPI_Open(eSpiPort,eMode,eType,i32BitLength)
- 打开SPI功能
- 配置SPI工作在主/从模式,SPI总线时序和每笔传输的长度
- 这里与手册略有差别
- DrvSPI_Open(E_DRVSPI_PORT eSpiPort, E_DRVSPI_MODE eMode,
- E_DRVSPI_TRANS_TYPE eType, int32_t i32BitLength, uint8_t bQFN36PIN)
- */
- /* 配置SPI1为主模式 TYPE1波形 32位传输 */
- DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);
- /* 配置传输比特的顺序:优先发送/接收MSB */
- DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
-
- /* 这里与手册不同
- DrvSPI_DisableAutoCS( eSpiPort )
- 这个函数用来关闭自动片选功能,如果在多次传输过程中需要一直保持高/低
- 用户应该关闭自动片选功能,改为手动控制,只用于NUC1xx是主模式
- */
- DrvSPI_DisableAutoSS(eDRVSPI_PORT1);
-
- /*
- 设定从选择线的激活级别:
- DrvSPI_SetSlaveSelectActiveLevel
- (eSpiPort,eSSActType)
- Type: eDRVSPI_ACTIVE_LOW _FALLING:从片选择信号低/下降沿激活
- eDRVSPI_ACTIVE_HIGH_RISING :从片选择信号高/上升沿激活
- */
- DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
-
- /* 与手册不同
- DrvSPI_Set2BitSerialDataIOMode( eSpiPort,bEnable )
- 设置2比串行数据IO模式 TRUE(使能)/关闭
- */
- DrvSPI_Set2BitTransferMode(eDRVSPI_PORT1, TRUE);
- /* 与手册不同 设置SPI时钟1MHZ
- DrvSPI_SetClock( eSpinPort,Clock1,Clock2 )
- 在固定时钟频率模式下,Clock1是SPI的基本时钟频率,在可变模式下,他是可变时钟1
- CLOCK2,他是可变时钟2
- */
- DrvSPI_SetClockFreq(eDRVSPI_PORT1, 1000000, 0);
- DrvGPIO_Open(SPI_CS_PORT,SPI_CS_PORT_NUM, E_IO_OUTPUT); //SPI_FLAH_CS
- DISABLE_SPI_CS;
- }
- /******************************************************************************************
- ** Name: SPI_ReadMidDid
- ** Function: W25Q16BV读制造商ID及设备ID函数:
- *******************************************************************************************/
- uint32_t SPI_ReadMidDid(void)
- {
- uint32_t au32SourceData;
- uint32_t au32DestinationData;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
- //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS;
- //激活/配置从设备片选信号
-
- au32SourceData = 0x90;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
- //发送数据到 SPI 总线: 0x90 (Read Manufacturer/Device ID)
-
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
- //等待SPI端口空闲
-
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
- //配置SPI传输的比特长度:24 bits
- au32SourceData = 0x0;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
- //发送数据到 SPI 总线: 0x00 (24-bit Address)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
- //等待SPI端口空闲
-
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
- //配置SPI传输的比特长度:16 bits
- au32SourceData = 0x0;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
- //接收数据
-
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
- //等待SPI端口空闲
-
- DISABLE_SPI_CS;
- //从设备片选信号取消激活
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);
- //从接收寄存器读数据. 但是不触发下一次数据传输.
- return (au32DestinationData & 0xffff);
- }
- int main(void)
- {
- uint8_t test = 250;
- uint32_t Tmp = 0;
- uint8_t DataBuffer[256];
- Init_System();
- Init_Uart();
- Init_SPI();
- DrvGPIO_Open(E_GPA,14,E_IO_OUTPUT);//程序运行指示灯
- DrvGPIO_ClrBit( E_GPA,14 );
- printf("\n");
- printf("======菜农 %d 助学计划======\n", test);
- printf("========NUC120助学板========\n");
- printf("======程序模仿三心爱意0322例程======\n");
- printf("=======2011年05月26日=======\n");
- printf("=======SPI(查询方式)=====\n");
- /* WINBOND W25Q16BV Page 0 初始化 */
- SPI_WaitReady();
- Tmp = SPI_ReadMidDid();
- printf("W25Q16BV制造商ID及设备ID为:0x%X\n",Tmp);
- SPI_WaitReady();
- SPI_ReadData( DataBuffer,0x1000,1 );
- if( DataBuffer[0] != 0xff)
- {
- DataBuffer[0] = 0xff;
- SPI_WaitReady();
- SPI_ChipErase();
- SPI_WaitReady();
- SPI_PageProgram( DataBuffer,0x1000,1 );
- for( Tmp=0;Tmp<256;Tmp++)DataBuffer[Tmp] = Tmp;
- SPI_PageProgram( DataBuffer,0,256 );
- }
- /* WINBOND W25Q16BV Page 0 读取 */
- printf("Read Flash (Page 0) ...\n");
- SPI_WaitReady();
- SPI_ReadData(DataBuffer,0,256);
- for (Tmp=0;Tmp<256;Tmp++)
- {
- printf("0x%X ",DataBuffer[Tmp]);
- if ((Tmp%16)==15)printf("\n");
- }
- printf("Read Flash (Page 0) done!\n");
- printf("'R/r'为读指令、'U/u'为Page 0加1并存储指令、'D/d'为Page 0减1并存储指令\n");
- printf("====请输入字符开始测试!===\n");
- printf("==========================*/\n");
- while(1)
- {
- if (IsStart)
- {
- switch (Receive_Data)
- {
- case 'R':
- case 'r':
- printf("Read Flash (Page 0) ...\n");
- SPI_WaitReady();
- SPI_ReadData(DataBuffer,0,256);
- for (Tmp=0;Tmp<256;Tmp++)
- {
- printf("0x%X ",DataBuffer[Tmp]);
- if ((Tmp%16)==15)printf("\n");
- }
- printf("Read Flash (Page 0) done!\n");
- break;
- case 'U':
- case 'u':
- printf("Program Flash (Page 0)[Add 1] ...\n");
- SPI_WaitReady();
- SPI_ReadData(DataBuffer,0,256);
- for (Tmp=0;Tmp<256;Tmp++)
- {
- DataBuffer[Tmp] += 1;
- }
- SPI_WaitReady();
- SPI_PageProgram(DataBuffer,0,256);
- printf("Program Flash (Page 0)[Add 1] done!\n");
- break;
- case 'D':
- case 'd':
- printf("Program Flash (Page 0)[Minus 1] ...\n");
- SPI_WaitReady();
- SPI_ReadData(DataBuffer,0,256);
- for (Tmp=0;Tmp<256;Tmp++)
- {
- DataBuffer[Tmp] -= 1;
- }
- SPI_WaitReady();
- SPI_PageProgram(DataBuffer,0,256);
- printf("Program Flash (Page 0)[Minus 1] done!\n");
- break;
- default:
- printf("请确认您输入的指令是否合法!\n");
-
- }
- IsStart = FALSE;
- }
- }
- }