stm32 spi flash u盘

ALIENTEK 战舰STM32开发板板载了一个SD卡插槽,可以用来接入SD卡,另外战舰STM32开发板板载了一个8M字节的SPI FLASH芯片,通过STM32的USB接口,我们可以实现一个简单的USB读卡器,来读写SD卡和SPI FLASH。
本章我们还是通过移植官方的USB Mass_Storage例程来实现,该例程在MDK的安装目录下可以找到(..\MDK\ARM\Examples\ST\STM32F10xUSBLib\Demos\Mass_Storage)。
USB Mass Storage类支持两个传输协议:
1)Bulk-Only 传输(BOT)

2)Control/Bulk/Interrupt传输(CBI)

Mass Storage类规范定义了两个类规定的请求:Get_Max_LUN和Mass Storage Reset,所有的Mass Storage类设备都必须支持这两个请求。
Get_Max_LUN(bmRequestType= 10100001b and bRequest= 11111110b)用来确认设备支持的逻辑单元数。Max LUN的值必须是0~15。注意:LUN是从0开始的。主机不能向不存在的LUN发送CBW,本章我们定义Max LUN的值为1,即代表2个逻辑单元。
Mass Storage Reset(bmRequestType=00100001b and bRequest= 11111111b)用来复位Mass Storage设备及其相关接口。
支持BOT传输的Mass Storage设备接口描述符要求如下:
接口类代码bInterfaceClass=08h,表示为Mass Storage设备;
接口类子代码bInterfaceSubClass=06h,表示设备支持SCSI Primary Command-2(SPC-2);
协议代码bInterfaceProtocol有3种:0x00、0x01、0x50,前两种需要使用中断传输,最后一种仅使用批量传输(BOT)。
支持BOT的设备必须支持最少3个endpoint:Control, Bulk-In和Bulk-Out。USB2.0的规范定义了控制端点0。Bulk-In端点用来从设备向主机传送数据(本章用端点1实现)。Bulk-Out端点用来从主机向设备传送数据(本章用端点2实现)。

ST官方的例程是通过USB来读写SD卡(SDIO方式)和NAND FALSH,支持2个逻辑单元,我们在官方例程的基础上,只需要修改SD驱动部分代码(改为SPI),并将对NAND FLASH的操作修改为对SPI FLASH的操作。只要这两步完成了,剩下的就比较简单了,对底层磁盘的读写,都是在mass_mal.c文件实现的,所以我们只需要修改该函数的MAL_Init、MAL_Write、MAL_Read和MAL_GetStatus等4个函数,使之与我们的SD卡和SPI FLASH对应起来即可。

USB时钟频率一定要48Mhz

void Set_USBClock(void)
{
    if (SystemCoreClock == 72000000)
    {
        RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);//USBclk=PLLclk/1.5=48Mhz
    }
    else if (SystemCoreClock == 48000000)
    {
        RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);
    }
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); 
}

初始化时配置好内存大小等参数

Mass_Memory_Size[0]=1024*1024*8;
Mass_Block_Size[0] =512;
Mass_Block_Count[0]=Mass_Memory_Size[0]/Mass_Block_Size[0];
USB_Interrupts_Config();    
Set_USBClock();   
USB_Init();


通过电脑端就可以向spi flash写入数据了,设备想要读取U盘中的文件数据需要移植fatfs文件系统。FATFS文件系统的移植,主要是diskio.c文件。

DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
u8 res=0;    
switch(drv)
{
case SD_CARD:
  break;
case EX_FLASH:
SPI_Flash_Init();
  break;
default:
res=1; 
}  
if(res)return  STA_NOINIT;
else return 0;
}

DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
    u8 res=0; 
    if (!count)return RES_PARERR;//count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó 
   switch(drv)
    {
        case SD_CARD:
            break;

        case EX_FLASH:
            for(;count>0;count--)
            {
               SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
               sector++;
               buff+=FLASH_SECTOR_SIZE;
            }
           res=0;
           break;
       default:
            res=1; 
    }
    if(res==0x00)return RES_OK;  
    else return RES_ERROR;   

#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff,       /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
    u8 res=0;  
     if (!count)return RES_PARERR;//count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó 
    switch(drv)
    {
        case SD_CARD:
            break;
       case EX_FLASH:
            for(;count>0;count--)
            {
               //SPI_Flash_Erase_Sector(sector);
              SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
              sector++;
              buff+=FLASH_SECTOR_SIZE;
            }
            res=0;
            break;
        default:
            res=1; 
    }
    if(res == 0x00)return RES_OK;  
    else return RES_ERROR;  
}
#endif /* _READONLY */

DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
    DRESULT res;      
    if(drv==SD_CARD)
    {
   }

    else if(drv==EX_FLASH)
{
   switch(ctrl)
   {
   case CTRL_SYNC:
res = RES_OK; 
       break;  
   case GET_SECTOR_SIZE:
       *(WORD*)buff = FLASH_SECTOR_SIZE;
       res = RES_OK;
       break;  
   case GET_BLOCK_SIZE:
       *(WORD*)buff = FLASH_BLOCK_SIZE;
       res = RES_OK;
       break;  
   case GET_SECTOR_COUNT:
       *(DWORD*)buff = FLASH_SECTOR_COUNT;
       res = RES_OK;
       break;
   default:
       res = RES_PARERR;
       break;
   }
}
    else res=RES_ERROR;
    
    return res;

通过fatfs读取U盘中的数据

    FRESULT fresult;

    fresult = f_mount(0, fs);
    if (fresult == FR_NO_FILESYSTEM)
    {
        res = f_mkfs(0, 1, 4096);
    }
    if (fresult == FR_OK)
    {
        FIL fil;
        fresult = f_open (&fil, "1.txt", FA_OPEN_EXISTING | FA_READ);
        if (fresult == FR_OK)
        {
            uint8_t buff[8];
            UINT readlen;
            f_read (&fil, buff, 6, &readlen);
        }
    }

你可能感兴趣的:(单片机驱动程序)