C51 单片机与spiflash连接只能读,不能写,麻烦各位看看
程序代码:
#include "REG51.h" #include "intrins.h" #include <stdio.h> #include <string.h> #include "spi.c" #define uchar unsigned char //typedef bit BOOL; //typedef unsigned char BYTE; //typedef unsigned short WORD; //typedef unsigned long DWORD; #define SF_WREN 0x06 //Flash命令 #define SF_WRDI 0x04 #define SF_RDSR 0x05 #define SF_WRSR 0x01 #define SF_READ 0x03 #define SF_FASTREAD 0x0B #define SF_RDID 0x90 #define SF_PAGEPROG 0x02 //#define SF_RDCR 0xA1 //#define SF_WRCR 0xF1 #define SF_SECTORER 0x20 #define SF_BLOCKER1 0x52 //32KB #define SF_BLOCKER2 0xD8 //64KB #define SF_CHIPER 0xC7 //#define NULL 0 //#define FALSE 0 //#define TRUE 1 #define BUFFER_SIZE 256 //缓冲区大小 #define TEST_ADDR 512 //Flash测试地址 uchar idflag; //uchar m=256; uchar g_Buffer[BUFFER_SIZE]; /* void waitsend(); void UART_Initial(); void send_char( uchar ch); void spi_write(unsigned char spi_dat); unsigned char spi_read(); //BYTE SpiShift(BYTE dat); FlashCheckID(); void FlashBusy(); void FlashWriteEnable(); void FlashErase(); void FlashChipErase(); void FlashSectorErase(); void FlashBlockErase(); void FlashRead( addr, size,unsigned char *buffer); void FlashWrite( addr, size,unsigned char *buffer); */ void waitsend() { TI = 0; ES = 0; while(!TI) { }; TI = 0; ES = 1; } void delay(long i) { long j; for(j=0;j<i;j++) { SomeNOP(); SomeNOP(); } } void delay1ms(long i) { long j; for(j=0;j<i;j++) { delay(70); } } // UART void UART_Initial() { SCON = 0x50; //串口方式1,允许接收 TMOD = 0x20; //定时计数器1方式2 TH1 = 0xFD; //9600 波特率 FD TL1 = 0xFD; EA=1; ES=1; TR1 = 1; } //向串口发送一个字符 void send_char( uchar ch) { SBUF=ch; //delay1ms(1); //while (TI==0); //TI=0; } /************************************************ 使用SPI方式与Flash进行数据交换 入口参数: dat : 准备写入的数据 出口参数: 从Flash中读出的数据 ************************************************ BYTE SpiShift(BYTE dat) { SPDAT = dat; //触发SPI发送 while (!(SPSTAT & SPIF)); //等待SPI数据传输完成 SPSTAT = SPIF | WCOL; //清除SPI状态 return SPDAT; } */ /************************************************ 检测FlashID W25Q16:0XEF14 ************************************************/ unsigned char FlashCheckID() { uchar dat1,dat2; uchar flag=0; spi_cs = 0; spi_write(SF_RDID); //发送读取ID命令 spi_write(0x00); //空读3个字节 spi_write(0x00); spi_write(0x00); dat1 = spi_read(); //读取制造商ID1 dat2 = spi_read(); //读取制造商ID2 spi_cs = 1; flag = ((dat1==0xef)&&(dat2==0x14)); return flag; } /************************************************ 检测Flash的忙状态读状态寄存器1 入口参数: 无 出口参数: 0 : Flash处于空闲状态 1 : Flash处于忙状态 ************************************************/ FlashBusy(void) { uchar dat; spi_cs = 0; spi_write(SF_RDSR); //发送读取状态命令 dat = spi_read(); //读取状态 spi_cs = 1; return (dat & 0x01); //状态值的Bit0即为忙标志 } /************************************************ 使能Flash写命令 入口参数: 无 出口参数: 无 ************************************************/ void FlashWriteEnable() { // while (FlashBusy()); //Flash忙检测 spi_cs = 0; spi_write(SF_WREN); //发送写使能命令 spi_cs = 1; //delay1ms(10); } /************************************************ 擦除整片Flash 入口参数: 无 出口参数: 无 ************************************************/ void FlashChipErase() { FlashWriteEnable(); //使能Flash写命令 spi_cs = 0; spi_write(SF_CHIPER); //发送擦除命令 spi_cs = 1; } /************************************************ 擦除扇区Flash 入口参数: addr 出口参数: 无 ************************************************/ void FlashSectorErase(unsigned long addr) { FlashWriteEnable(); //使能Flash写命令 spi_cs = 0; spi_write(SF_SECTORER); //发送擦除命令 spi_write(addr>>16 & 0xff); //设置起始地址 spi_write(addr>>8 & 0xff); spi_write(addr & 0xff); spi_cs = 1; } /************************************************ 擦除BlockFlash(64KB) 入口参数: 无 出口参数: 无 ************************************************/ void FlashBlockErase() { FlashWriteEnable(); //使能Flash写命令 spi_cs = 0; spi_write(SF_BLOCKER2); //发送擦除命令 spi_cs = 1; } /************************************************ 从Flash中读取数据fastread 入口参数: addr : 地址参数 size : 数据块大小 buffer : 缓冲从Flash中读取的数据 出口参数: 无 ************************************************/ void FlashRead(unsigned long addr,unsigned long size, unsigned char *buffer) { while (FlashBusy()); //Flash忙检测 spi_cs = 0; spi_write(SF_FASTREAD); //使用快速读取命令 spi_write(addr>>16 & 0xff); //设置起始地址 spi_write(addr>>8 & 0xff); spi_write(addr & 0xff); spi_write(0x00); //需要空读一个字节 while (size) { *buffer = spi_read(); //自动连续读取并保存 addr++; buffer++; size--; } spi_cs = 1; } /************************************************ 写数据到Flash中 入口参数: addr : 地址参数 size : 数据块大小 buffer : 缓冲需要写入Flash的数据 出口参数: 无 ************************************************/ void FlashWrite( unsigned long addr,unsigned long size, unsigned char *buffer) { //while (FlashBusy()); while (size) { //uchar i; FlashWriteEnable(); //使能Flash写命令 spi_cs = 0; spi_write(SF_PAGEPROG); //发送页编程命令 spi_write(addr>>16 & 0xff); //设置起始地址 spi_write(addr>>8 & 0xff); spi_write(addr & 0xff); //for (i=0; i<0x100; i++) //{ //spi_write(*buffer); //size--; //buffer++; //} while (size) { spi_write(*buffer); //连续页内写 buffer++; addr++; //buffer++; size--; if ((addr & 0xff) == 0) break; } //send_char(addr>>16); //send_char(addr>>8); //send_char(addr); spi_cs = 1; } } void main() { int i; for (i=0; i<BUFFER_SIZE; i++) { g_Buffer[i]=i; } //初始化Flash状态 //g_fFlashOK = FALSE; //初始化串口 UART_Initial(); delay1ms(2); FlashSectorErase(TEST_ADDR); delay1ms(200); while(1) { //for (i=0; i<BUFFER_SIZE; i++) //{ //send_char(g_Buffer[i]),waitsend(); //delay1ms(100); //} //i=0; //检测Flash状态 idflag = FlashCheckID(); send_char(idflag),waitsend(); delay1ms(1000); //send_char(0x01), waitsend(); //将缓冲区的数据写到Flash中 FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer); //send_char(addr); delay1ms(100); //读取测试地址的数据 FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer); delay1ms(100); //发送到串口 for (i=0; i<BUFFER_SIZE; i++) { send_char(g_Buffer[i]),waitsend(); delay1ms(100); } /* //擦除Flash FlashErase(); //读取测试地址的数据 FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer); //发送到串口 for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]); //修改置缓冲区 for (i=0; i<BUFFER_SIZE; i++) g_Buffer[i] = i>>2; //将缓冲区的数据写到Flash中 FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer); //读取测试地址的数据 FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer); //发送到串口 for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]); FlashErase(); //读取测试地址的数据 FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer); //发送到串口 for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]); //修改置缓冲区 for (i=0; i<BUFFER_SIZE; i++) g_Buffer[i]= 255-(i>>2); //将缓冲区的数据写到Flash中 FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer); //读取测试地址的数据 FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer); //发送到串口 for (i=0; i<BUFFER_SIZE; i++) SendUart(g_Buffer[i]); */ } }flash是w25q16