找回密码
 立即注册
楼主: mcu

47-MSC(Mass Storage Class)协议范例-U盘演示程序 ,无法识别到u盘

[复制链接]
已绑定手机

124

主题

5136

回帖

1万

积分

超级版主

无情的代码机器

积分
11478
发表于 2025-11-22 20:01:51 | 显示全部楼层
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

已绑定手机

5

主题

43

回帖

196

积分

注册会员

积分
196
 楼主| 发表于 2025-11-23 09:19:27 | 显示全部楼层
感谢版主,依葫芦画瓢,做个一个mcs cdc,在AI8051试验箱上测试OK。

AI8051_USB_MSC_cdc.rar

391.83 KB, 下载次数: 118

点评

朕亲自尝试,发现可以。  发表于 2026-8-19 06:46
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

已绑定手机

96

主题

7378

回帖

1万

积分

超级版主

积分
14037
发表于 2025-11-23 15:35:27 | 显示全部楼层
mcu 发表于 2025-11-22 19:37
有CDC ,MSC的版本吗?

CDC和MSC同时使用,属于复合设备,需要IAD描述符
回复

使用道具 举报 送花

已绑定手机

5

主题

43

回帖

196

积分

注册会员

积分
196
 楼主| 发表于 2025-11-23 16:24:17 | 显示全部楼层
Debu*** 发表于 2025-11-23 15:35
CDC和MSC同时使用,属于复合设备,需要IAD描述符

已经添加, 上面的例子已经在AI8051U试验箱上验证过。
回复

使用道具 举报 送花

56

主题

392

回帖

486

积分

中级会员

积分
486
发表于 2026-8-19 06:41:26 | 显示全部楼层
mcu 发表于 2025-11-23 09:19
感谢版主,依葫芦画瓢,做个一个mcs cdc,在AI8051试验箱上测试OK。

我之前用这个:https://www.stcaimcu.com/forum.php?mod=viewthread&tid=10542 好像就没有提示格式化什么的,我看里面是 操作 w25qxx 的。查看打印发现提示格式化失败。
回复

使用道具 举报 送花

56

主题

392

回帖

486

积分

中级会员

积分
486
发表于 2026-8-19 09:36:22 | 显示全部楼层
mcu 发表于 2025-11-23 09:19
感谢版主,依葫芦画瓢,做个一个mcs cdc,在AI8051试验箱上测试OK。

大佬,我感觉你这个例子不错,就想移到stc32g12k128 上,可是移过去后,发现不能用。
你这个有  stc32g12k128  的版本吗?
回复

使用道具 举报 送花

56

主题

392

回帖

486

积分

中级会员

积分
486
发表于 2026-8-19 09:45:13 | 显示全部楼层
这个是给AI8051 用的

#include "config.h"
#include "qspi.h"
#include "w25qxx.h"


void W25Q_WriteEnable_06()
{
    QSPI_WRITE_INSTR(0x06);
}

void W25Q_QPI_WriteEnable_06()
{
    QSPI_WRITE_QINSTR(0x06);
}

void W25Q_WriteEnableVSR_50()
{
    QSPI_WRITE_INSTR(0x50);
}

void W25Q_QPI_WriteEnableVSR_50()
{
    QSPI_WRITE_QINSTR(0x50);
}

void W25Q_WriteDisable_04()
{
    QSPI_WRITE_INSTR(0x04);
}

void W25Q_QPI_WriteDisable_04()
{
    QSPI_WRITE_QINSTR(0x04);
}

BYTE W25Q_ReadSR1_05()
{
    BYTE dat;
   
    QSPI_READ_INSTR_SDATA(0x05, (BYTE *)&dat, 1);

    return dat;
}

void W25Q_WaitBusy(int n)       //×Ô¶¯ÂÖѯÖÜÆÚʱ¼äµ¥Î»: us
{
    while (W25Q_ReadSR1_05() & 0x01);

    if (n);
//    QSPI_POLLING_READ_INSTR_SDATA(0x05, 0x01, 0x00, 12*n);
}

BYTE W25Q_QPI_ReadSR1_05()
{
    BYTE dat;
   
    QSPI_READ_QINSTR_QDATA(0x05, (BYTE *)&dat, 1);

    return dat;
}

void W25Q_QPI_WaitBusy(int n)
{
    QSPI_POLLING_READ_QINSTR_QDATA(0x05, 0x01, 0x00, 12*n);
}

BYTE W25Q_ReadSR2_35()
{
    BYTE dat;
   
    QSPI_READ_INSTR_SDATA(0x35, (BYTE *)&dat, 1);

    return dat;
}

BYTE W25Q_QPI_ReadSR2_35()
{
    BYTE dat;
   
    QSPI_READ_QINSTR_QDATA(0x35, (BYTE *)&dat, 1);

    return dat;
}

BYTE W25Q_ReadSR3_15()
{
    BYTE dat;
   
    QSPI_READ_INSTR_SDATA(0x15, (BYTE *)&dat, 1);

    return dat;
}

BYTE W25Q_QPI_ReadSR3_15()
{
    BYTE dat;
   
    QSPI_READ_QINSTR_QDATA(0x15, (BYTE *)&dat, 1);

    return dat;
}

void W25Q_WriteSR1_01(BYTE dat)
{
    QSPI_WRITE_INSTR_SADDR8(0x01, dat);
}

void W25Q_WriteSR12_01(WORD dat)
{
    QSPI_WRITE_INSTR_SADDR16(0x01, dat);    //SR1+SR2ºÏ²¢Îª16λµØÖ·
}

void W25Q_QPI_WriteSR1_01(BYTE dat)
{
    QSPI_WRITE_QINSTR_QADDR8(0x01, dat);
}

void W25Q_WriteSR2_31(BYTE dat)
{
    QSPI_WRITE_INSTR_SADDR8(0x31, dat);
    W25Q_WaitBusy(100);
}

void W25Q_QPI_WriteSR2_31(BYTE dat)
{
    QSPI_WRITE_QINSTR_QADDR8(0x31, dat);
}

void W25Q_WriteSR3_11(BYTE dat)
{
    QSPI_WRITE_INSTR_SADDR8(0x11, dat);
}

void W25Q_QPI_WriteSR3_11(BYTE dat)
{
    QSPI_WRITE_QINSTR_QADDR8(0x11, dat);
}

BYTE W25Q_ReadEAR_C8()
{
    BYTE dat;
   
    QSPI_READ_INSTR_SDATA(0xc8, (BYTE *)&dat, 1);

    return dat;
}

void W25Q_WriteEAR_C5(BYTE dat)
{
    QSPI_WRITE_INSTR_SADDR8(0xc5, dat);
}

void W25Q_EnterAddr32Mode_B7()
{
    QSPI_WRITE_INSTR(0xb7);
}

void W25Q_ExitAddr32Mode_E9()
{
    QSPI_WRITE_INSTR(0xe9);
}

void W25Q_ReadData_03(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_SDATA(0x03, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_ReadData_03(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR24_SDATA(0x03, addr, pdat, datalen);
}

void W25Q_ReadData_Addr32_13(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR32_SDATA(0x13, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_ReadData_Addr32_13(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR32_SDATA(0x13, addr, pdat, datalen);
}

void W25Q_FastRead_0B(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_DUMMY_SDATA(0x0b, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_0B(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR24_DUMMY_SDATA(0x0b, addr, 8, pdat, datalen);
}

void W25Q_QPI_FastRead_0B(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_QINSTR_QADDR24_DUMMY_QDATA(0x0b, addr, 2, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_QPI_DMA_FastRead_0B(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_QINSTR_QADDR24_DUMMY_QDATA(0x0b, addr, 2, pdat, datalen);
}

void W25Q_FastRead_Addr32_0C(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR32_DUMMY_SDATA(0x0C, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_Addr32_0C(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR32_DUMMY_SDATA(0x0C, addr, 8, pdat, datalen);
}

void W25Q_FastRead_3B(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_DUMMY_DDATA(0x3b, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_3B(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR24_DUMMY_DDATA(0x3b, addr, 8, pdat, datalen);
}

void W25Q_FastRead_Addr32_3C(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR32_DUMMY_DDATA(0x3c, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_Addr32_3C(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR32_DUMMY_DDATA(0x3c, addr, 8, pdat, datalen);
}

void W25Q_FastRead_6B(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_DUMMY_QDATA(0x6b, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_6B(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR24_DUMMY_QDATA(0x6b, addr, 8, pdat, datalen);
}

void W25Q_FastRead_Addr32_6C(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR32_DUMMY_QDATA(0x6c, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_Addr32_6C(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_SADDR32_DUMMY_QDATA(0x6c, addr, 8, pdat, datalen);
}

void W25Q_FastRead_BB(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_DADDR24_DALT8_DDATA(0xbb, addr, 0x00, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_BB(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_DADDR24_DALT8_DDATA(0xbb, addr, 0x00, pdat, datalen);
}

void W25Q_FastRead_Addr32_BC(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_DADDR32_DALT8_DDATA(0xbc, addr, 0x00, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_Addr32_BC(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_DADDR32_DALT8_DDATA(0xbc, addr, 0x00, pdat, datalen);
}

void W25Q_FastRead_EB(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xeb, addr, 0x00, 4, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_EB(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xeb, addr, 0x00, 4, pdat, datalen);
}

void W25Q_QPI_FastRead_EB(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_QINSTR_QADDR24_QALT8_DUMMY_QDATA(0xeb, addr, 0x00, 0, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_QPI_DMA_FastRead_EB(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_QINSTR_QADDR24_QALT8_DUMMY_QDATA(0xeb, addr, 0x00, 0, pdat, datalen);
}

void W25Q_FastRead_Addr32_EC(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_QADDR32_QALT8_DUMMY_QDATA(0xec, addr, 0x00, 4, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_FastRead_Addr32_EC(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_QADDR32_QALT8_DUMMY_QDATA(0xec, addr, 0x00, 4, pdat, datalen);
}

void W25Q_WordRead_E7(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xe7, addr, 0x00, 2, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_WordRead_E7(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xe7, addr, 0x00, 2, pdat, datalen);
}

void W25Q_OctalWordRead_E3(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xe3, addr, 0x00, 0, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_DMA_OctalWordRead_E3(DWORD addr, BYTE *pdat, WORD datalen)
{
    QSPI_DMA_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0xe3, addr, 0x00, 0, pdat, datalen);
}

void W25Q_SetBurstWrap_77(BYTE wrap)
{
    QSPI_WRITE_INSTR_QADDR32(0x77, wrap);
}

void W25Q_PageProgram_02(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    W25Q_WriteEnable_06();
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        if (cnt + (addr & 0xff) >= 0x100)
            cnt = 0x100 - (addr & 0xff);
            
        QSPI_WRITE_INSTR_SADDR24_SDATA(0x02, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
        
        if (datalen > 0)
        {
            W25Q_WaitBusy(100);
            W25Q_WriteEnable_06();
        }
    }
    W25Q_WaitBusy(100);
}

void W25Q_DMA_PageProgram_02(DWORD addr, BYTE *pdat, WORD datalen)
{
    W25Q_WriteEnable_06();
    QSPI_DMA_WRITE_INSTR_SADDR24_SDATA(0x02, addr, pdat, datalen);
    W25Q_WaitBusy(100);
}

void W25Q_PageProgram_Addr32_12(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    W25Q_WriteEnable_06();
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        if (cnt + (addr & 0xff) >= 0x100)
            cnt = 0x100 - (addr & 0xff);
            
        QSPI_WRITE_INSTR_SADDR32_SDATA(0x12, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
        
        if (datalen > 0)
        {
            W25Q_WaitBusy(100);
            W25Q_WriteEnable_06();
        }
    }
    W25Q_WaitBusy(100);
}

void W25Q_DMA_PageProgram_Addr32_12(DWORD addr, BYTE *pdat, WORD datalen)
{
    W25Q_WriteEnable_06();
    QSPI_DMA_WRITE_INSTR_SADDR32_SDATA(0x12, addr, pdat, datalen);
    W25Q_WaitBusy(100);
}

void W25Q_PageProgram_32(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    W25Q_WriteEnable_06();
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        if (cnt + (addr & 0xff) >= 0x100)
            cnt = 0x100 - (addr & 0xff);
            
        QSPI_WRITE_INSTR_SADDR24_QDATA(0x32, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
        
        if (datalen > 0)
        {
            W25Q_WaitBusy(100);
            W25Q_WriteEnable_06();
        }
    }
    W25Q_WaitBusy(100);
}

void W25Q_DMA_PageProgram_32(DWORD addr, BYTE *pdat, WORD datalen)
{
    W25Q_WriteEnable_06();
    QSPI_DMA_WRITE_INSTR_SADDR24_QDATA(0x32, addr, pdat, datalen);
    W25Q_WaitBusy(100);
}

void W25Q_PageProgram_Addr32_34(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    W25Q_WriteEnable_06();
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        if (cnt + (addr & 0xff) >= 0x100)
            cnt = 0x100 - (addr & 0xff);
            
        QSPI_WRITE_INSTR_SADDR32_QDATA(0x34, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
        
        if (datalen > 0)
        {
            W25Q_WaitBusy(100);
            W25Q_WriteEnable_06();
        }
    }
    W25Q_WaitBusy(100);
}

void W25Q_DMA_PageProgram_Addr32_34(DWORD addr, BYTE *pdat, WORD datalen)
{
    W25Q_WriteEnable_06();
    QSPI_DMA_WRITE_INSTR_SADDR32_QDATA(0x34, addr, pdat, datalen);
    W25Q_WaitBusy(100);
}

void W25Q_Erase4K_20(DWORD addr, BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR_SADDR24(0x20, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_QPI_Erase4K_20(DWORD addr, BOOL wait)
{
    W25Q_QPI_WriteEnable_06();
    QSPI_WRITE_QINSTR_QADDR24(0x20, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_Erase4K_Addr32_21(DWORD addr, BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR_SADDR32(0x21, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_Erase32K_52(DWORD addr, BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR_SADDR24(0x52, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_QPI_Erase32K_52(DWORD addr, BOOL wait)
{
    W25Q_QPI_WriteEnable_06();
    QSPI_WRITE_QINSTR_QADDR24(0x52, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_Erase64K_D8(DWORD addr, BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR_SADDR24(0xd8, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_QPI_Erase64K_D8(DWORD addr, BOOL wait)
{
    W25Q_QPI_WriteEnable_06();
    QSPI_WRITE_QINSTR_QADDR24(0xd8, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_Erase64K_Addr32_DC(DWORD addr, BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR_SADDR32(0xdc, addr);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_EraseChip_C7(BOOL wait)
{
    W25Q_WriteEnable_06();
    QSPI_WRITE_INSTR(0xc7);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_QPI_EraseChip_C7(BOOL wait)
{
    W25Q_QPI_WriteEnable_06();
    QSPI_WRITE_QINSTR(0xc7);
    W25Q_QPI_WaitBusy(100);
    if (wait)
        W25Q_WaitBusy(100);
}

void W25Q_EraseSuspend_75()
{
    QSPI_WRITE_INSTR(0x75);
}

void W25Q_QPI_EraseSuspend_75()
{
    QSPI_WRITE_QINSTR(0x75);
}

void W25Q_EraseResume_7A()
{
    QSPI_WRITE_INSTR(0x7a);
}

void W25Q_QPI_EraseResume_7A()
{
    QSPI_WRITE_QINSTR(0x7a);
}

void W25Q_ProgramSuspend_75()
{
    W25Q_EraseSuspend_75();
}

void W25Q_QPI_ProgramSuspend_75()
{
    W25Q_QPI_EraseSuspend_75();
}

void W25Q_ProgramResume_7A()
{
    W25Q_EraseResume_7A();
}

void W25Q_QPI_ProgramResume_7A()
{
    W25Q_QPI_EraseResume_7A();
}

void W25Q_PowerDown_B9()
{
    QSPI_WRITE_INSTR(0xb9);
}

void W25Q_QPI_PowerDown_B9()
{
    QSPI_WRITE_QINSTR(0xb9);
}

void W25Q_ReleasePowerDown_AB()
{
    QSPI_WRITE_INSTR(0xab);
}

void W25Q_QPI_ReleasePowerDown_AB()
{
    QSPI_WRITE_QINSTR(0xab);
}

BYTE W25Q_ReadDeviceID_AB()
{
    BYTE dat;

    QSPI_READ_INSTR_SADDR24_SDATA(0xab, 0x000000, &dat, 1);
   
    return dat;
}

BYTE W25Q_QPI_ReadDeviceID_AB()
{
    BYTE dat;

    QSPI_READ_QINSTR_QADDR24_QDATA(0xab, 0x000000, &dat, 1);
   
    return dat;
}

WORD W25Q_ReadID_90()
{
    WORD dat;
   
    QSPI_READ_INSTR_SADDR24_SDATA(0x90, 0x000000, (BYTE *)&dat, 2);

    return dat;
}

WORD W25Q_ReadID_92()
{
    WORD dat;
   
    QSPI_READ_INSTR_DADDR24_DALT8_DDATA(0x92, 0x000000, 0x00, (BYTE *)&dat, 2);

    return dat;
}

WORD W25Q_ReadID_94()
{
    WORD dat;
   
    QSPI_READ_INSTR_QADDR24_QALT8_DUMMY_QDATA(0x94, 0x000000, 0x00, 4, (BYTE *)&dat, 2);

    return dat;
}

void W25Q_ReadUniqueID_4B(BYTE *pdat)
{
    QSPI_READ_INSTR_SADDR32_SDATA(0x4b, 0x00000000, pdat, 8);
}

DWORD W25Q_ReadJEDECID_9F()
{
    DWORD dat;
   
    dat = 0;
    QSPI_READ_INSTR_SDATA(0x9f, (BYTE *)&dat+1, 3);

    return dat;
}

DWORD W25Q_QPI_ReadJEDECID_9F()
{
    DWORD dat;
   
    dat = 0;
    QSPI_READ_QINSTR_QDATA(0x9f, (BYTE *)&dat+1, 3);

    return dat;
}

void W25Q_ReadSFDP_5A(BYTE addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_DUMMY_SDATA(0x5a, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_EraseSecurityReg_44(DWORD addr)
{
    QSPI_WRITE_INSTR_SADDR24(0x44, addr);
}

void W25Q_ProgramSecurityReg_42(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    W25Q_WriteEnable_06();
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_WRITE_INSTR_SADDR24_SDATA(0x42, addr, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
        
        if (datalen > 0)
        {
            W25Q_WaitBusy(100);
            W25Q_WriteEnable_06();
        }
    }
    W25Q_WaitBusy(100);
}

void W25Q_ReadSecurityReg_48(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_INSTR_SADDR24_DUMMY_SDATA(0x48, addr, 8, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_QPI_SetReadParam_C0(BYTE dat)
{
    QSPI_WRITE_QINSTR_QADDR8(0xc0, dat);
}

void W25Q_QPI_BurstReadWithWrap_0C(DWORD addr, BYTE *pdat, WORD datalen)
{
    BYTE cnt;
   
    while (datalen > 0)
    {
        cnt = 32;
        if (datalen < 32)
            cnt = datalen;
            
        QSPI_READ_QINSTR_QADDR24_DUMMY_QDATA(0x0c, addr, 2, pdat, cnt);
        
        datalen -= cnt;
        addr += cnt;
        pdat += cnt;
    }
}

void W25Q_EnterQPIMode_38()
{
    QSPI_WRITE_INSTR(0x38);
}

void W25Q_QPI_ExitQPIMode_FF()
{
    QSPI_WRITE_QINSTR(0xFF);
}

void W25Q_LockSector_36(DWORD addr)
{
    QSPI_WRITE_INSTR_SADDR24(0x36, addr);
}

void W25Q_QPI_LockSector_36(DWORD addr)
{
    QSPI_WRITE_QINSTR_QADDR24(0x36, addr);
}

void W25Q_UnlockSector_39(DWORD addr)
{
    QSPI_WRITE_INSTR_SADDR24(0x39, addr);
}

void W25Q_QPI_UnlockSector_39(DWORD addr)
{
    QSPI_WRITE_QINSTR_QADDR24(0x39, addr);
}

BYTE W25Q_ReadLockSector_3D(DWORD addr)
{
    BYTE dat;

    QSPI_READ_INSTR_SADDR24_SDATA(0x3d, addr, &dat, 1);
   
    return dat;
}

BYTE W25Q_QPI_ReadLockSector_3D(DWORD addr)
{
    BYTE dat;

    QSPI_READ_QINSTR_QADDR24_QDATA(0x3d, addr, &dat, 1);
   
    return dat;
}

void W25Q_LockGlobal_7E()
{
    QSPI_WRITE_INSTR(0x7e);
}

void W25Q_QPI_LockGlobal_7E()
{
    QSPI_WRITE_QINSTR(0x7e);
}

void W25Q_UnlockGlobal_98()
{
    QSPI_WRITE_INSTR(0x98);
}

void W25Q_QPI_UnlockGlobal_98()
{
    QSPI_WRITE_QINSTR(0x98);
}

void W25Q_ResetDevice_66_99()
{
    QSPI_WRITE_INSTR(0x66);
    QSPI_WRITE_INSTR(0x99);
}

void W25Q_QPI_ResetDevice_66_99()
{
    QSPI_WRITE_QINSTR(0x66);
    QSPI_WRITE_QINSTR(0x99);
}

void W25Q_Enable_QE()
{
    if ((W25Q_ReadJEDECID_9F() & 0xffff00) == 0xef4000)
    {
        if ((W25Q_ReadSR2_35() & 0x02) == 0)
        {
            W25Q_WriteEnableVSR_50();
            if ((W25Q_ReadJEDECID_9F() & 0xffff) == 0x4014)
            {
                W25Q_WriteSR12_01(0x0002);
            }
            else
            {
                W25Q_WriteSR2_31(0x02);
            }
        }
    }
}
回复

使用道具 举报 送花

56

主题

392

回帖

486

积分

中级会员

积分
486
发表于 2026-8-19 09:46:27 | 显示全部楼层
这个是STC32G12k128 上用的 。这个我在实验箱上试过,可以用。

/*---------------------------------------------------------
w25qxx.c
----------------------------------------------------------*/

#include "w25qxx.h"


/******************* 串行Flash命令集 ************************/
#define SFC_RDJID       0x9F                //读ID
#define SFC_RDID        0xAB                //读ID
#define SFC_WRSR        0x01                //写状态寄存器
#define SFC_PAGEPROG    0x02                //写数据
#define SFC_READ        0x03                //读数据
#define SFC_WRDI        0x04                //写禁止
#define SFC_RDSR        0x05                //读状态寄存器
#define SFC_WREN        0x06                //写使能
#define SFC_SECTORER    0x20                //扇区擦除
#define SFC_CHIPER      0xC7                //整片擦除


static u32         Cache_addr;      //缓冲区数据对应的扇区地址
static u8 xdata    CacheBufS[4096]; //缓存区
static u8 xdata    CacheBufP[256];  //缓存区
static u8          Cache_Flag;      //1表示缓存内有未写入的数据


/*---------------------------------------------------------
返回ID
----------------------------------------------------------*/
u8 W25QXX_Get_ID(void)
{
    u8 a;
    SPI_CS=0;
    SPI_shift(SFC_RDID);
    SPI_shift(0);
    SPI_shift(0);
    SPI_shift(0);
    a=SPI_shift(0);
    SPI_CS=1;
    return a;
}

/*---------------------------------------------------------
返回 MemorySize
----------------------------------------------------------*/
u32 W25QXX_Get_MemorySize(void)
{
    u8 id, jid;
   
    id = W25QXX_Get_ID();
   
    if ( (id<0x10) || (id>0x17) ) return 0;  //限制 128KB 至 16MB 之间的型号有效

    SPI_CS=0;
    SPI_shift(SFC_RDJID);
    SPI_shift(0);
    SPI_shift(0);
    jid=SPI_shift(0);
    SPI_CS=1;
   
    if ( jid != (id+1) ) return 0;          //JID 总是比 ID 大1
   
    return 1ul << jid;
}


/*---------------------------------------------------------
//忙检
----------------------------------------------------------*/
static void Busy_Wait(void)
{
    u8 state;
    while(1){
        SPI_CS=0;
        SPI_shift(SFC_RDSR);
        state=SPI_shift(0);
        SPI_CS=1;
        if(!state)break;
        OSTimeDly(1);
    }
}

/*---------------------------------------------------------
写使能
----------------------------------------------------------*/
static void WriteEnable(void)
{
    Busy_Wait();        //忙检
    SPI_CS=0;
    SPI_shift(SFC_WREN);
    SPI_CS=1;
}

/*---------------------------------------------------------
写扇区
----------------------------------------------------------*/
static void Write_Sector(u32 addr, u8 *buf)
{
    u8 i;
   
    WriteEnable();              //写使能
    SPI_CS=0;
    SPI_shift(SFC_SECTORER);       //扇区擦除命令
    SPI_shift((u8)(addr>>16));
    SPI_shift((u8)(addr>>8 ));
    SPI_shift((u8)(addr>>0 ));
    SPI_CS=1;
   
    for(i=0;i<16;i++){
        WriteEnable();                  //写使能
        SPI_CS=0;
        SPI_shift(SFC_PAGEPROG);           //页编程命令
        SPI_shift((u8)(addr>>16));
        SPI_shift((u8)(addr>>8 ));
        SPI_shift((u8)(addr>>0 ));
        SPI_DMA_Write(buf,256);
        buf+=256;
        addr+=256;
        SPI_CS=1;
    }
}

/*---------------------------------------------------------
读Flash
----------------------------------------------------------*/
static void Read_Flash(u32 addr, u8 *buf, u16 Size)
{
    Busy_Wait();        //忙检
    SPI_CS=0;
    SPI_shift(SFC_READ);         
    SPI_shift((u8)(addr>>16));
    SPI_shift((u8)(addr>>8 ));
    SPI_shift((u8)(addr>>0 ));
    SPI_DMA_Read(buf,Size);
    SPI_CS=1;
}


/*---------------------------------------------------------
//读数据,分扇区
----------------------------------------------------------*/
void W25QXX_Read(u32 addr, u8 *buf, u32 Size)
{
    u32 sector,addr1;
    u16 number;

    while(Size){
        sector = addr&~4095;    //扇区地址
        if(sector == Cache_addr){
            addr1 = addr&4095;          //扇区内偏移
            number = 4096-addr1;        //当前扇区剩余空间
            if(number>Size)number=Size; //实际操作数量
            memcpy(buf,&CacheBufS[addr1],number);
        }else{
            addr1 = addr&255;           //页内偏移
            number = 256-addr1;         //当前页剩余空间
            if(number>Size)number=Size; //实际操作数量
            Read_Flash(addr,CacheBufP,number);  //
            memcpy(buf,CacheBufP,number);
        }
        addr+=number;
        buf+=number;
        Size-=number;
    }
}

/*---------------------------------------------------------
//为了减小内存使用量和提升小批量数据写入效率, 写入使了一级缓存延迟写入, 当所有对W25QXX的操作都完成后, 应调用一次本函数, 使缓存立即写入
----------------------------------------------------------*/
void W25QXX_WriteCache(void)
{
    if(Cache_Flag){
        Write_Sector(Cache_addr,CacheBufS); //缓存写入FLASH
        Cache_Flag=0;           //0表示缓存内没有未写入的数据
    }
}

/*---------------------------------------------------------
//写数据,分扇区
----------------------------------------------------------*/
void W25QXX_Write(u32 addr, u8 *buf, u32 Size)
{
    u32 sector,addr1;
    u16 number;
   
    while(Size){
        sector = addr&~4095;        //扇区地址   
        if(sector != Cache_addr){
            if(Cache_Flag){
                Write_Sector(Cache_addr,CacheBufS); //缓存写入FLASH
                Cache_Flag=0;       //0表示缓存内没有未写入的数据
            }
            Read_Flash(sector,CacheBufS,4096);  //重载缓存
            Cache_addr = sector;
        }
        addr1 = addr&4095;          //扇区内偏移
        number = 4096-addr1;        //当前扇区剩余空间
        if(number>Size)number=Size; //实际操作数量
        memcpy(&CacheBufS[addr1],buf,number);
        addr+=number;
        buf+=number;
        Size-=number;
        Cache_Flag=1;               //1表示缓存内有未写入的数据
    }
}

static bit FlashOK = 0;
/*------------------------------------------------------------------------------
//初始化W25QXX, 返回值为 MemorySize, 如果未能识别型号, 则返回 0
------------------------------------------------------------------------------*/
u32 W25QXX_INIT(void)
{
    u32 MemorySize;
   
    if ( FlashOK ) return W25QXX_Get_MemorySize();
        
    SPI_init();
   
    MemorySize = W25QXX_Get_MemorySize();
   
    if( MemorySize ) {
        FlashOK = 1;
        Cache_addr=0;                               //当前缓存对应的扇区
        Cache_Flag=0;                               //0表示缓存内没有未写入的数据
        Read_Flash(Cache_addr,CacheBufS,4096);      //填充缓存
    }
   
    return MemorySize;
}




回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-9 11:28 , Processed in 0.073749 second(s), 85 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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