- /*---------------------------------------------------------------------------------------------------------*/
- /* */
- /* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
- /* */
- /*---------------------------------------------------------------------------------------------------------*/
- #include "includes.h" //包含所需的头文件
- /*************************************************************************************
- ** Function name: main
- ** Descriptions:
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- int main (void)
- {
- uint8_t WriteBuffer[256] = {0};
- uint8_t ReadBuffer[256] = {0};
- uint16_t i, id = 1;
- Set_System(); //封装一些初始化模块
- value = 4;
- for(i=0;i<256;i++) //初始化数组
- {
- WriteBuffer[i] = i;
- }
- SPI_WaitReady(); //W25Q16BV忙状态检查
- SPI_SectorErase(0x0000); //扇区擦除
- SPI_WaitReady(); //W25Q16BV忙状态检查
- SPI_PageProgram(WriteBuffer,0,256); //W25Q16BV按页编程函数
- SPI_WaitReady(); //W25Q16BV忙状态检查
- SPI_ReadData(ReadBuffer,0,256); //W25Q16BV读数据函数
- for(i=0;i<256;i++) //将读出来的数据与写进去的数据进行比较
- {
- if(WriteBuffer[i] != ReadBuffer[i])
- {
- id = 0;
- break;
- }
- }
- if(id ==1)
- value = ReadBuffer[125];
- else
- value = 88;
- while(1)
- {
- }
- }
hw_config函数- #include "includes.h" //包含所需的头文件
- #define Enable_SPI_CS DrvGPIO_ClrBit(E_GPA,14)
- #define DISABLE_SPI_CS DrvGPIO_SetBit(E_GPA,14)
- /*************************************************************************************
- ** Function name: Set_System
- ** Descriptions: 封装一些初始化模块
- ** input parameters: count
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- void Set_System(void)
- {
- RCC_Configuration(); //配置系统时钟
- GPIO_Configuration(); //配置GPIO
- TIMER_Configuration(); //配置TIMER
- SPI_Configuration(); //配置SPI1
- }
- /*************************************************************************************
- ** Function name: RCC_Configuration
- ** Descriptions: 系统时钟源设置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void RCC_Configuration(void)
- {
- UNLOCKREG(); // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
- DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);// 与其 SYSCLK->PWRCON.XTL12M_EN = 1; 等同
- // PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
- // 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
- // 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
- delay_ms(100); // while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
- LOCKREG(); // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
- }
- /*************************************************************************************
- ** Function name: GPIO_Configuration
- ** Descriptions: GPIO配置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void GPIO_Configuration()
- {
- //DrvGPIO_Open( E_GPA, 14, E_IO_OUTPUT );//片选
- DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT );//数码管段选
- DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 6, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 7, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 8, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPA, 9, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPC, 14, E_IO_OUTPUT );//数码管位选
- DrvGPIO_Open( E_GPC, 15, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPC, 6, E_IO_OUTPUT );
- DrvGPIO_Open( E_GPC, 7, E_IO_OUTPUT );
- }
- /*************************************************************************************
- ** Function name: TIMER_Configuration
- ** Descriptions: TIMER配置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void TIMER_Configuration()
- {
- DrvTIMER_Init(); //初始化定时器
- DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0); //使用外设时注意必须设置该外设的时钟 设置TIMER0的时钟源为外部12MHZ
- DrvTIMER_Open(E_TMR0,1000,E_PERIODIC_MODE); //设定定时器timer0的tick周期,并且启动定时器:定时器通道 TMR0 每秒1000次 周期模式
- DrvTIMER_SetTimerEvent(E_TMR0,5,(TIMER_CALLBACK) Timer0_Callback,0); //安装一个定时处理事件到 timer0通道
- DrvTIMER_EnableInt(E_TMR0); //使能定时器中断 //TIMER0->TCSR.IE = 1
- DrvTIMER_Start(E_TMR0); //定时器timer0开始计数 //TIMER0->TCSR.CEN = 1;
- }
- /*************************************************************************************
- ** Function name: Timer0_Callback
- ** Descriptions: 定时处理事件,LED动态扫描
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void Timer0_Callback (void)
- {
- static uint8_t count= 0;
- static uint8_t i,xx[4];
- uint32_t data;
- uint16_t ValueBuff ;
- ValueBuff = value;
- count++;
- if(count >= 5)
- count = 1;
- for(i=0;i<4;i++)
- {
- xx[i] = ValueBuff%10;
- ValueBuff = ValueBuff/10;
- }
- switch(count)
- {
- case 1:
- DrvGPIO_SetBit(E_GPC,14);
- DrvGPIO_ClrBit(E_GPC,15);
- DrvGPIO_ClrBit(E_GPC,6);
- DrvGPIO_ClrBit(E_GPC,7);
- data = Table[xx[0]]<<2;
- GPIOA->DOUT = data;
- break;
- case 2:
- DrvGPIO_SetBit(E_GPC,15);
- DrvGPIO_ClrBit(E_GPC,14);
- DrvGPIO_ClrBit(E_GPC,6);
- DrvGPIO_ClrBit(E_GPC,7);
- data = Table[xx[1]]<<2;
- GPIOA->DOUT = data;
- break;
- case 3:
- DrvGPIO_SetBit(E_GPC,7);
- DrvGPIO_ClrBit(E_GPC,14);
- DrvGPIO_ClrBit(E_GPC,15);
- DrvGPIO_ClrBit(E_GPC,6);
- data = Table[xx[2]]<<2;
- GPIOA->DOUT = data;
- break;
- case 4:
- DrvGPIO_SetBit(E_GPC,6);
- DrvGPIO_ClrBit(E_GPC,14);
- DrvGPIO_ClrBit(E_GPC,15);
- DrvGPIO_ClrBit(E_GPC,7);
- data = Table[xx[3]]<<2;
- GPIOA->DOUT = data;
- //DrvGPIO_ClrBit(E_GPA,9); //显示小数点
- break;
- default:break;
- }
- }
- /*************************************************************************************
- ** Function name: SPI_Configuration
- ** Descriptions: SPI配置
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_Configuration()
- {
- //此功能是用来打开SPI模块。它决定了SPI工作在主或从模式,SPI总线时序 和每传输比特长度
- //指定SPI端口为SPI1 并配置SPI1为主模式 TYPE1总线时序(时钟的空闲状态为低;在串行时钟的下降沿驱动器的数据,在串行时钟上升沿锁存数据) 32位传输
- DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);
- DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST); //配置SPI1传输比特的顺序:优先发送/接收MSB
- DrvSPI_DisableAutoSS(eDRVSPI_PORT1); //禁止自动片选功能
- DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING); //设定从选择线的激活级别:低电平或者下降沿
- DrvSPI_Set2BitTransferMode(eDRVSPI_PORT1, TRUE); //设置2比特串行数据I/O 模式
- DrvSPI_SetClockFreq(eDRVSPI_PORT1, 1000000, 0); //设置SPI的时钟频率为1MHz
- DrvGPIO_Open(E_GPA,14, E_IO_OUTPUT); //SPI_FLAH_CS引脚(即GPA14)为输出
- DISABLE_SPI_CS; //输出低电平 即禁止W25Q16BV 的片选信号
- }
- /*************************************************************************************
- ** Function name: SPI_ReadMidDid
- ** Descriptions: W25Q16BV读制造商ID及设备ID函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- uint32_t SPI_ReadMidDid(void)
- {
- uint32_t au32SourceData;
- uint32_t au32DestinationData;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x90; // send Command: 0x90, Read Manufacturer/Device ID
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送命令到 SPI 总线
- 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; // 禁止W25Q16BV 的片选信号
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1); //从RX寄存器中读取数据 此功能将不会触发SPI数据传输
- return (au32DestinationData & 0xffff); //返回MidDid
- }
- /*************************************************************************************
- ** Function name: SPI_ReadStatusReg1
- ** Descriptions: W25Q16BV读状态寄存器1函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- uint32_t SPI_ReadStatusReg1(void)
- {
- uint32_t au32SourceData;
- uint32_t au32DestinationData;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 16); //配置SPI传输的比特长度:16 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x0500; //send Command: 0x05, Read status register 1
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x0500 (Read status register 1)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1); //从RX寄存器中读取数据 此功能将不会触发SPI数据传输
- return (au32DestinationData & 0xFF);
- }
- /*************************************************************************************
- ** Function name: SPI_WaitReady
- ** Descriptions: W25Q16BV忙状态检查函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_WaitReady(void)
- {
- uint32_t ReturnValue;
- do{
- ReturnValue = SPI_ReadStatusReg1();
- ReturnValue = ReturnValue & 1;
- }while(ReturnValue!=0); //检查从设备状态寄存器1的BUSY位 等待其为0
- }
- /*************************************************************************************
- ** Function name: SPI_ChipErase
- ** Descriptions: W25Q16BV片擦除函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_ChipErase(void)
- {
- uint32_t au32SourceData;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x06;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x06 (Write enable)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0xC7; // send Command: 0xC7, Chip Erase
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0xC7 (Chip Erase)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- }
- /*************************************************************************************
- ** Function name: SPI_ReadData
- ** Descriptions: W25Q16BV读数据函数
- ** input parameters: DataBuffer0,StartAddressByteCount
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_ReadData(uint8_t *DataBuffer, uint32_t StartAddress, uint32_t ByteCount)
- {
- uint32_t au32SourceData;
- uint32_t au32DestinationData;
- uint32_t Counter;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x03;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x03 (Read data)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24); //配置SPI传输的比特长度:24 bits
- au32SourceData = StartAddress;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: StartAddress
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- for(Counter=0; Counter<ByteCount; Counter++)
- {
- au32SourceData = 0x0;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //接收数据;
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);//从RX寄存器中读取数据 此功能将不会触发SPI数据传输
- DataBuffer[Counter] = (uint8_t) au32DestinationData;
- }
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- }
- /*************************************************************************************
- ** Function name: SPI_PageProgram
- ** Descriptions: W25Q16BV按页编程函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_PageProgram(uint8_t *DataBuffer, uint32_t StartAddress, uint32_t ByteCount)
- {
- uint32_t au32SourceData;
- uint32_t Counter;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x06; // send Command: 0x06, Write enable
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x06 (Write enable)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x02;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x02 (Page program)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24); //配置SPI传输的比特长度:24 bits
- au32SourceData = StartAddress;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: StartAddress
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- for(Counter=0; Counter<ByteCount; Counter++)
- {
- au32SourceData = DataBuffer[Counter];
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- }
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- }
- /*************************************************************************************
- ** Function name: SPI_SectorErase
- ** Descriptions: W25Q16BV扇区擦除函数
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *************************************************************************************/
- void SPI_SectorErase(uint32_t StartAddress)
- {
- uint32_t au32SourceData;
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x06;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x06 (Write enable)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 8); //配置SPI传输的比特长度:8 bits
- Enable_SPI_CS; //使能W25Q16BV 的片选信号
- au32SourceData = 0x20;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: 0x20 (Sector Erase)
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DrvSPI_SetBitLength(eDRVSPI_PORT1, 24); //配置SPI传输的比特长度:24 bits
- au32SourceData = StartAddress&0xFFF000;
- DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData); //发送数据到 SPI 总线: StartAddress
- while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {} //等待SPI端口空闲
- DISABLE_SPI_CS; //禁止W25Q16BV 的片选信号
- }
- /*************************************************************************************
- ** Function name: delay_ms
- ** Descriptions: 1ms(晶振为12MHZ)延时子程序
- ** input parameters: count
- ** output parameters: 无
- ** Returned value: 无
- *************************************************************************************/
- void delay_ms(uint32_t count)
- {
- uint32_t i,j;
- for(i=count;i>0;i--)
- for(j=2395;j>0;j--);
- }
hw_config头文件- #ifndef __HW_CONFIG_H__
- #define __HW_CONFIG_H__
- void Set_System(void);
- void RCC_Configuration(void);
- void GPIO_Configuration(void);
- void TIMER_Configuration(void);
- void Timer0_Callback (void);
- void SPI_Configuration(void);
- uint32_t SPI_ReadMidDid(void);
- uint32_t SPI_ReadStatusReg1(void);
- void SPI_WaitReady(void);
- void SPI_ChipErase(void);
- void SPI_ReadData(uint8_t *DataBuffer0, uint32_t StartAddress, uint32_t ByteCount);
- void SPI_PageProgram(uint8_t *DataBuffer, uint32_t StartAddress, uint32_t ByteCount);
- void SPI_SectorErase(uint32_t StartAddress);
- void delay_ms(uint32_t count);
- #endif
已测试通过 OK
工程
芯片资料