查看: 1666|回复: 2

[分享] 【LPC824lite】之SPI FLASH W25XXX

[复制链接]
  • TA的每日心情

    2024-2-5 12:06
  • 签到天数: 627 天

    [LV.9]以坛为家II

    94

    主题

    1628

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    4429

    热心会员

    最后登录
    2024-2-5
    发表于 2020-10-17 22:45:31 | 显示全部楼层 |阅读模式
    本帖最后由 胤幻1988 于 2020-10-17 22:49 编辑

    今天调了下LPC824的SPI ,测试板载的W23Q32芯片。NXP的片子算不错了,而且SPI0可以配置有4个从机设备的硬件CS选通引脚,这个再其他MCU上面并不多见。
    加上其邮局SWM开关矩阵选择的机制,我们几乎可以选择所以的IO进行配置。
    当然这样我们就无需像其他单片那样不用固定定义的CS引脚,而需要软件定义CS引脚了。
    妈妈再也不用担心我的引脚画反了
    SPI0硬件支持4个从机CS引脚,当然如果不够,我们仍可用软件选择配置的方式。
    spi.JPG
    除了PIO0_10 ,PIO0_11,应为它两是真开漏结果,要用的话,得外接上拉电阻。
    SPI2.png
    相关配的寄存器如下:
    JCQ1.png
    JCQ2.png

    这里我们选择软件控制CS引脚高低电平,因为我还是喜欢用软件控制CS引脚,觉得好用。
    这里使用查询的方式,来控制SPI。在实际项目中,对我而言,我几乎没用过中断方式。        
    SPI0代码配置如下:
    1. void SPI0_Init(void)
    2. {
    3.         //在SYSCON中开启SPI0和SWM的时钟
    4.         LPC_SYSCON->SYSAHBCLKCTRL |= (GPIO | SPI0 | SWM);
    5.         
    6.         //SWM把SPI0的信号映射到引脚上
    7.         ConfigSWM(SPI0_SCK, P0_24);
    8.         ConfigSWM(SPI0_MOSI, P0_26);
    9.         ConfigSWM(SPI0_MISO, P0_25);
    10.         //不配置CS引脚 硬件配置CS
    11.         //ConfigSWM(SPI0_SSEL0, P0_15);
    12.         
    13.         //在SYSCON中对SPI0执行复位
    14.         LPC_SYSCON->PRESETCTRL &= (SPI0_RST_N);
    15.         LPC_SYSCON->PRESETCTRL |= ~(SPI0_RST_N);
    16.         //使能SPI0,SPI0配置为:主机模式,MSB在前,模式0,无回环,SSEL低有效。
    17.         // Enable=true, master, no LSB first, CPHA=0, CPOL=0, no loop-back, SSEL active low
    18.         LPC_SPI0->DIV = (300-1);//300分频,那么当前时钟就是30M/300=100K
    19.         LPC_SPI0->CFG = CFG_ENABLE | CFG_MASTER;
    20.         // Configure the master SPI delay register (DLY), slave's value meaningless.
    21.         // Pre-delay = 0 clocks, post-delay = 0 clocks, frame-delay = 0 clocks, transfer-delay = 0 clocks
    22.         LPC_SPI0->DLY = 0x0000;

    23.         
    24.         // Configure the SPI control registers
    25.         // Master: End-of-frame true, LEN = 8 bits. Slave: LEN = 8 bits
    26.         LPC_SPI0->TXCTL = CTL_EOF | CTL_LEN(8);
    27.         
    28.        // LPC_SPI0->INTENSET = RXRDYEN;                    // Master interrupt only on received data
    29.       //  NVIC_EnableIRQ(SPI0_IRQn);
    30. }
    复制代码


    定义读写一个字节的函数:
    1. #define WaitForSPI0txRdy while((LPC_SPI0->STAT & STAT_TXRDY) == 0) // 等待发送寄存器就绪
    2. #define WaitForSPI0rxRdy while((LPC_SPI0->STAT & STAT_RXRDY) == 0) // 等待接收数据就绪

    3. uint8_t SPI0_ReadWriteByte(uint8_t TxData)
    4. {
    5.         uint8_t Rxdata;
    6.         
    7.         WaitForSPI0txRdy;
    8.         LPC_SPI0->TXDAT= TxData;//发送一个任意数值的字符,然后等待接收
    9.         WaitForSPI0rxRdy;
    10.         Rxdata = LPC_SPI0->RXDAT;//读出收到的第1个字符,对于W25Q32BV,应该是0xEF  
    11.         
    12.         return Rxdata;                              //返回收到的数据               
    13. }
    复制代码


    这样好了后,我们就可以对W25XXX进行控制了。
    W25XXX.c 文件:#include "w25xxx.h"


    uint16_t W25QXX_TYPE=W25Q32;        //默认是W25Q32

    //初始化SPI FLASH的IO口
    void W25xxx_Init(void)
    {
    //这里CS不要自动匹配的选通信号引脚
            //在SYSCON中开启SPI0和SWM的时钟
            LPC_SYSCON->SYSAHBCLKCTRL |= GPIO ;
            //不使用自动CS,使用手动CS
            //设置为输出模式
            LPC_GPIO_PORT->DIR0 |= W25QXX_CS_PIN;           // Make those bits outputs
            //设置初始值H
            LPC_GPIO_PORT->SET0  = W25QXX_CS_PIN;
            //SPI 初始化
            SPI0_Init();

    }

    //读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器
    //状态寄存器1:
    //BIT7  6   5   4   3   2   1   0
    //SPR   RV  TB BP2 BP1 BP0 WEL BUSY
    //SPR:默认0,状态寄存器保护位,配合WP使用
    //TB,BP2,BP1,BP0:FLASH区域写保护设置
    //WEL:写使能锁定
    //BUSY:忙标记位(1,忙;0,空闲)
    //默认:0x00
    //状态寄存器2:
    //BIT7  6   5   4   3   2   1   0
    //SUS   CMP LB3 LB2 LB1 (R) QE  SRP1
    //状态寄存器3:
    //BIT7      6    5    4   3   2   1   0
    //HOLD/RST  DRV1 DRV0 (R) (R) WPS ADP ADS
    //regno:状态寄存器号,范:1~3
    //返回值:状态寄存器值
    uint8_t W25QXX_ReadSR(uint8_t regno)   
    {  
            uint8_t byte=0,command=0;
            switch(regno)
            {
                            case 1:
                                            command=W25X_ReadStatusReg1;    //读状态寄存器1指令
                                            break;
                            case 2:
                                            command=W25X_ReadStatusReg2;    //读状态寄存器2指令
                                            break;
                            case 3:
                                            command=W25X_ReadStatusReg3;    //读状态寄存器3指令
                                            break;
                            default:
                                            command=W25X_ReadStatusReg1;   
                                            break;
            }   
            W25QXX_CS(0);                            //使能器件   
            delay_us(2);
            SPI0_ReadWriteByte(command);            //发送读取状态寄存器命令   
            byte=SPI0_ReadWriteByte(0Xff);          //读取一个字节  
            W25QXX_CS(1);   
            delay_us(2);        //取消片选     
            return byte;   
    }
    //写W25QXX状态寄存器
    void W25QXX_Write_SR(uint8_t regno,uint8_t sr)   
    {   
            uint8_t command=0;
            switch(regno)
            {
                    case 1:
                                    command=W25X_WriteStatusReg1;    //写状态寄存器1指令
                                    break;
                    case 2:
                                    command=W25X_WriteStatusReg2;    //写状态寄存器2指令
                                    break;
                    case 3:
                                    command=W25X_WriteStatusReg3;    //写状态寄存器3指令
                                    break;
                    default:
                                    command=W25X_WriteStatusReg1;   
                                    break;
            }   
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(command);            //发送写取状态寄存器命令   
            SPI0_ReadWriteByte(sr);                 //写入一个字节  
            W25QXX_CS(1);                            //取消片选                  
    }   
    //W25QXX写使能       
    //将WEL置位   
    void W25QXX_Write_Enable(void)   
    {
            W25QXX_CS(0);                            //使能器件   
      SPI0_ReadWriteByte(W25X_WriteEnable);   //发送写使能  
            W25QXX_CS(1);                            //取消片选                  
    }
    //W25QXX写禁止       
    //将WEL清零  
    void W25QXX_Write_Disable(void)   
    {  
            W25QXX_CS(0);                            //使能器件   
      SPI0_ReadWriteByte(W25X_WriteDisable);  //发送写禁止指令   
            W25QXX_CS(1);                            //取消片选                  
    }

    //读取芯片ID
    //返回值如下:                                  
    //0XEF13,表示芯片型号为W25Q80  
    //0XEF14,表示芯片型号为W25Q16   
    //0XEF15,表示芯片型号为W25Q32  
    //0XEF16,表示芯片型号为W25Q64
    //0XEF17,表示芯片型号为W25Q128           
    //0XEF18,表示芯片型号为W25Q256
    uint16_t W25QXX_ReadID(void)
    {
            uint16_t Temp = 0;          
            W25QXX_CS(0);                       
            delay_us(10);       
            SPI0_ReadWriteByte(0x90);//发送读取ID命令            
            SPI0_ReadWriteByte(0xFF);             
            SPI0_ReadWriteByte(0xFF);             
            SPI0_ReadWriteByte(0x00);                                    
            Temp|=SPI0_ReadWriteByte(0xFF)<<8;  
            Temp|=SPI0_ReadWriteByte(0xFF);               
            W25QXX_CS(1);       
            delay_us(10);               
            return Temp;
    }

    //读取SPI FLASH  
    //在指定地址开始读取指定长度的数据
    //pBuffer:数据存储区
    //ReadAddr:开始读取的地址(24bit)
    //NumByteToRead:要读取的字节数(最大65535)
    void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)   
    {
            uint16_t i;                                                                                       
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(W25X_ReadData);      //发送读取命令  
            if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
            {
                    SPI0_ReadWriteByte((uint8_t)((ReadAddr)>>24));   
            }
            SPI0_ReadWriteByte((uint8_t)((ReadAddr)>>16));   //发送24bit地址   
            SPI0_ReadWriteByte((uint8_t)((ReadAddr)>>8));   
            SPI0_ReadWriteByte((uint8_t)ReadAddr);   
            for(i=0;i<NumByteToRead;i++)
            {
                    pBuffer=SPI0_ReadWriteByte(0XFF);    //循环读数  
            }
            W25QXX_CS(1);                                                   
    }  
    //SPI在一页(0~65535)内写入少于256个字节的数据
    //在指定地址开始写入最大256字节的数据
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)
    //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!         
    void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
    {
            uint16_t i;  
            W25QXX_Write_Enable();                  //SET WEL
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(W25X_PageProgram);   //发送写页命令   
            if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
            {
                    SPI0_ReadWriteByte((uint8_t)((WriteAddr)>>24));
            }
            SPI0_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址   
            SPI0_ReadWriteByte((uint8_t)((WriteAddr)>>8));   
            SPI0_ReadWriteByte((uint8_t)WriteAddr);   
            for(i=0;i<NumByteToWrite;i++)SPI0_ReadWriteByte(pBuffer);//循环写数  
            W25QXX_CS(1);                            //取消片选
            W25QXX_Wait_Busy();                                           //等待写入结束
    }
    //无检验写SPI FLASH
    //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
    //具有自动换页功能
    //在指定地址开始写入指定长度的数据,但是要确保地址不越界!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)
    //NumByteToWrite:要写入的字节数(最大65535)
    //CHECK OK
    void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
    {                                           
            uint16_t pageremain;          
            pageremain=256-WriteAddr%256; //单页剩余的字节数                             
            if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
            while(1)
            {          
                    W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
                    if(NumByteToWrite==pageremain)break;//写入结束了
                     else //NumByteToWrite>pageremain
                    {
                            pBuffer+=pageremain;
                            WriteAddr+=pageremain;       

                            NumByteToWrite-=pageremain;                          //减去已经写入了的字节数
                            if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
                            else pageremain=NumByteToWrite;           //不够256个字节了
                    }
            }            
    }
    //写SPI FLASH  
    //在指定地址开始写入指定长度的数据
    //该函数带擦除操作!
    //pBuffer:数据存储区
    //WriteAddr:开始写入的地址(24bit)                                               
    //NumByteToWrite:要写入的字节数(最大65535)   
    uint8_t W25QXX_BUFFER[4096];                 
    void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
    {
            uint32_t secpos;
            uint16_t secoff;
            uint16_t secremain;          
            uint16_t i;   
            uint8_t * W25QXX_BUF;          
      W25QXX_BUF=W25QXX_BUFFER;             
            secpos=WriteAddr/4096;//扇区地址  
            secoff=WriteAddr%4096;//在扇区内的偏移
            secremain=4096-secoff;//扇区剩余空间大小   
            //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
            if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
            while(1)
            {       
                    W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
                    for(i=0;i<secremain;i++)//校验数据
                    {
                            if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除            
                    }
                    if(i<secremain)//需要擦除
                    {
                            W25QXX_Erase_Sector(secpos);//擦除这个扇区
                            for(i=0;i<secremain;i++)           //复制
                            {
                                    W25QXX_BUF[i+secoff]=pBuffer;          
                            }
                            W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  

                    }else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                   
                    if(NumByteToWrite==secremain)break;//写入结束了
                    else//写入未结束
                    {
                            secpos++;//扇区地址增1
                            secoff=0;//偏移位置为0          

                            pBuffer+=secremain;  //指针偏移
                            WriteAddr+=secremain;//写地址偏移          
                            NumByteToWrite-=secremain;                                //字节数递减
                            if(NumByteToWrite>4096)secremain=4096;        //下一个扇区还是写不完
                            else secremain=NumByteToWrite;                        //下一个扇区可以写完了
                    }         
            };         
    }
    //擦除整个芯片                  
    //等待时间超长...
    void W25QXX_Erase_Chip(void)   
    {                                   
            W25QXX_Write_Enable();                  //SET WEL
            W25QXX_Wait_Busy();   
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(W25X_ChipErase);        //发送片擦除命令  
            W25QXX_CS(1);                            //取消片选                  
            W25QXX_Wait_Busy();                                      //等待芯片擦除结束
    }   
    //擦除一个扇区
    //Dst_Addr:扇区地址 根据实际容量设置
    //擦除一个扇区的最少时间:150ms
    void W25QXX_Erase_Sector(uint32_t Dst_Addr)   
    {  
            //监视falsh擦除情况,测试用   
            //printf("fe:%x\r\n",Dst_Addr);          
            Dst_Addr*=4096;
            W25QXX_Write_Enable();                  //SET WEL          
            W25QXX_Wait_Busy();   
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(W25X_SectorErase);   //发送扇区擦除指令
            if(W25QXX_TYPE==W25Q256)                //如果是W25Q256的话地址为4字节的,要发送最高8位
            {
                    SPI0_ReadWriteByte((uint8_t)((Dst_Addr)>>24));
            }
            SPI0_ReadWriteByte((uint8_t)((Dst_Addr)>>16));  //发送24bit地址   
            SPI0_ReadWriteByte((uint8_t)((Dst_Addr)>>8));   
            SPI0_ReadWriteByte((uint8_t)Dst_Addr);  
            W25QXX_CS(1);                            //取消片选                  
            W25QXX_Wait_Busy();                                       //等待擦除完成
    }  
    //等待空闲
    void W25QXX_Wait_Busy(void)   
    {   
            while((W25QXX_ReadSR(1)&0x01)==0x01);   // 等待BUSY位清空
    }  
    //进入掉电模式
    void W25QXX_PowerDown(void)   
    {
            W25QXX_CS(0);                            //使能器件   
            SPI0_ReadWriteByte(W25X_PowerDown);     //发送掉电命令  
            W25QXX_CS(1);                            //取消片选                  
            delay_us(3);                            //等待TPD  
    }   
    //唤醒
    void W25QXX_WAKEUP(void)   
    {  
            W25QXX_CS(0);                                //使能器件   
            SPI0_ReadWriteByte(W25X_ReleasePowerDown);  //  send W25X_PowerDown command 0xAB   
            W25QXX_CS(1);                                //取消片选                  
            delay_us(3);                                //等待TRES1
    }









    //原来自动CS的例程,保留参考
    uint16_t Vendor_ID;
    uint16_t Memory_Type;
    uint16_t Capacity_ID;
    uint16_t Device_ID;
    //读取W25XXX SPI FLASH 制造商ID和存储器容量的轮询函数
    void Read_JEDEC_ID(void)
    {
            WaitForSPI0txRdy;
            LPC_SPI0->TXDATCTL = OUT_CTL | 0x9F;//首先输出命令字
            WaitForSPI0txRdy;
            LPC_SPI0->TXDATCTL = IN_DATA | 0xAA;//发送一个任意数值的字符,然后等待接收
            WaitForSPI0rxRdy;
            Vendor_ID = LPC_SPI0->RXDAT;//读出收到的第1个字符,对于W25Q32BV,应该是0xEF
            LPC_SPI0->TXDATCTL = IN_DATA | 0xAA;//再发送一个字符,等待接收第2个数据。
            WaitForSPI0rxRdy;
            Memory_Type = LPC_SPI0->RXDAT;//读出收到的第2个字符,对于W25Q32BV,应该是0x40。
            LPC_SPI0->TXDATCTL = IN_DATA | 0xAA | CTL_EOT;//发送最后一个字符。配置EOT位,当发送结束后恢复SSEL输出为高
            WaitForSPI0rxRdy;
            Capacity_ID = LPC_SPI0->RXDAT;//读出收到的第3个字符,对于W25Q32BV,应该是0x16
    }

    ////////////////////////////保留  自动CS
    //读取制造商ID和设备ID的轮询函数
    void Read_Device_ID(void)
    {
            LPC_SPI0->TXCTL = OUT_CTL;  //首先设置发送控制位
            WaitForSPI0txRdy;
            LPC_SPI0->TXDAT = 0x90; //输出命令字
            WaitForSPI0txRdy;
            LPC_SPI0->TXDAT = 0xFF;//任意输出一个字符
            WaitForSPI0txRdy;
            LPC_SPI0->TXDAT = 0xFF;//任意输出一个字符
            WaitForSPI0txRdy;
            LPC_SPI0->TXDAT = 0x00;//输出一个字符0x00
            WaitForSPI0txRdy;
            LPC_SPI0->TXDATCTL = IN_DATA | 0xFF;//读出制造商ID,对于W25Q32BV,应该是0xEF
            WaitForSPI0rxRdy;
            Vendor_ID = LPC_SPI0->RXDAT;
            LPC_SPI0->TXDATCTL = IN_DATA | 0xFF | CTL_EOT;//最后一个字符,设置EOT=1
            WaitForSPI0rxRdy;
            Device_ID = LPC_SPI0->RXDAT;//读出设备ID,对于W25Q32BV,应该是0x15

    }

    W25XXX.h文件:
    #ifndef __W25XXX_H_
    #define __W25XXX_H_

    #include "spi0.h"
    #include "delay.h"

    //型号ID定义
    #define W25Q80         0XEF13        
    #define W25Q16         0XEF14
    #define W25Q32         0XEF15
    #define W25Q64         0XEF16
    #define W25Q128        0XEF17
    #define W25Q256 0XEF18

    //指令表
    #define W25X_WriteEnable                0x06
    #define W25X_WriteDisable                0x04
    #define W25X_ReadStatusReg1                0x05
    #define W25X_ReadStatusReg2                0x35
    #define W25X_ReadStatusReg3                0x15
    #define W25X_WriteStatusReg1    0x01
    #define W25X_WriteStatusReg2    0x31
    #define W25X_WriteStatusReg3    0x11
    #define W25X_ReadData                        0x03
    #define W25X_FastReadData                0x0B
    #define W25X_FastReadDual                0x3B
    #define W25X_PageProgram                0x02
    #define W25X_BlockErase                        0xD8
    #define W25X_SectorErase                0x20
    #define W25X_ChipErase                        0xC7
    #define W25X_PowerDown                        0xB9
    #define W25X_ReleasePowerDown        0xAB
    #define W25X_DeviceID                        0xAB
    #define W25X_ManufactDeviceID        0x90
    #define W25X_JedecDeviceID                0x9F
    #define W25X_Enable4ByteAddr    0xB7
    #define W25X_Exit4ByteAddr      0xE9

    extern uint16_t W25QXX_TYPE;                                        //定义W25QXX芯片型号

    //W25XXX的片选信号
    #define W25QXX_CS_PIN    (1<<15)
    #define W25QXX_CS_PORT   P0_15
    #define W25QXX_CS(x)  (x>0)?(LPC_GPIO_PORT->SET0 = W25QXX_CS_PIN)LPC_GPIO_PORT->CLR0 = W25QXX_CS_PIN)

    //#define W25QXX_CS(x) __NOP()

    //原来自动CS的例程,保留参考
    extern uint16_t Vendor_ID;
    extern uint16_t Memory_Type;
    extern uint16_t Capacity_ID;
    extern uint16_t Device_ID;

    void Read_JEDEC_ID(void);
    void Read_Device_ID(void);
    /////////////////////////////
    //手动设置PIN为CS的
    void             W25xxx_Init(void);
    uint16_t         W25QXX_ReadID(void);
    uint8_t         W25QXX_ReadSR(uint8_t regno);             //读取状态寄存器
    void W25QXX_4ByteAddr_Enable(void);     //使能4字节地址模式
    void W25QXX_Write_SR(uint8_t regno,uint8_t sr);   //写状态寄存器
    void W25QXX_Write_Enable(void);                  //写使能
    void W25QXX_Write_Disable(void);                //写保护
    void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
    void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);   //读取flash
    void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);//写入flash
    void W25QXX_Erase_Chip(void);                      //整片擦除
    void W25QXX_Erase_Sector(uint32_t Dst_Addr);        //扇区擦除
    void W25QXX_Wait_Busy(void);                   //等待空闲
    void W25QXX_PowerDown(void);                //进入掉电模式
    void W25QXX_WAKEUP(void);                                //唤醒


    #endif

    main函数里面的调用:
    //要写入到W25QXX的字符串数组
    const uint8_t TEXT_Buffer[]={"LPC824 Lite SPI TEST By JaclsonQiu!"};
    #define SIZE sizeof(TEXT_Buffer)


    W25xxx_Init();

    while(W25QXX_ReadID()!=W25Q32)                                                                //检测不到W25Q80
    {
            printf("the FLASH ID IS :%d \r\n",W25QXX_ReadID());
            printf("\r\n W25Q32 Check Failed!\r\n");
            printf("\r\n Please Check! \r\n ");
            LEDS_TOG(LED7);                //DS0闪烁
            delay_ms(500);
    }
    //输出读出的序列号
    printf("the ID IS :0x%x \r\n",W25QXX_ReadID());
    printf("\r\n W25Q32 Ready! \r\n");

    FLASH_SIZE=32*1024*1024;        //FLASH 大小为4M字节

    printf("Start Write W25Q32....\r\n");
    W25QXX_Write((uint8_t*)TEXT_Buffer,FLASH_SIZE-100,SIZE);//从倒数第100个地址处开始,写入SIZE长度的数据
    printf("W25Q32 Write Finished!\r\n");        //提示传送完成

    printf("Start Read W25Q32.... \r\n");
    W25QXX_Read(datatemp,FLASH_SIZE-100,SIZE);                                        //从倒数第100个地址处开始,读出SIZE个字节
    printf("The Data Readed Is: %s \r\n",datatemp);        //提示传送完成 显示读到的字符串

    编译下载,查看串口输出:
    QQQ.png






    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2016-12-2 08:40
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    97

    主题

    836

    帖子

    7

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    3967
    最后登录
    2024-4-16
    发表于 2020-10-18 11:22:02 | 显示全部楼层
    SWM赛高
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    新手上路

    Rank: 1

    积分
    17
    最后登录
    2024-1-4
    发表于 2023-12-14 11:03:55 | 显示全部楼层
    大咖厉害,这个完整代码能否发我一份?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-19 11:55 , Processed in 0.121360 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表