1、STM32cube配置
RCC和SYS不再赘述
时钟配置
由于有USB,必须设置USB时钟48Mhz
SPI配置
由于USB时钟问题 ,Prescaler 没法设置为2 CPOL和CPHA W25QXX应该是 00 和11 都行,我只试了00,中断不开也行
USB设置
这一篇我主要是是为了记录USB的
选上FS Device 勾选中断 settings部分默认就行,也不会改
USB DEVICE设置
这一节USB保持512 只把 MSC改4096也可以
这里主要就是搞USB的4K 因为USB默认数据是512 而flash是4096的,把数据对齐 类型选择MSC setting里他们都没管这个数,但是在这里改了的话就不用再在源码的usbd_conf.h里改了,不然的话需要把usbd_conf.h改成
#define USBD_MAX_NUM_INTERFACES 2
#define USBD_MAX_NUM_CONFIGURATION 2
#define USBD_MAX_STR_DESC_SIZ 4096
#define USBD_DEBUG_LEVEL 3
#define USBD_SELF_POWERED 1
#define MSC_MEDIA_PACKET 4096
其他设置
这个改大
其他的就不用管了,最后是源码
源码
改变量
usbd_conf.h
要改的有两个h一个C 之前配置中已经提到 usbd_conf.h 也可以直接在配置中改
#define USBD_MAX_NUM_INTERFACES 1
#define USBD_MAX_NUM_CONFIGURATION 1
#define USBD_MAX_STR_DESC_SIZ 4096
#define USBD_DEBUG_LEVEL 0
#define USBD_SELF_POWERED 1
#define MSC_MEDIA_PACKET 4096
usb_msc.h
* MSC Class Config */
#ifndef MSC_MEDIA_PACKET
#define MSC_MEDIA_PACKET 4096
#endif
#define MSC_MAX_FS_PACKET 0x40U
#define MSC_MAX_HS_PACKET 4096
#define BOT_GET_MAX_LUN 0xFE
#define BOT_RESET 0xFF
#define USB_MSC_CONFIG_DESC_SIZ 32
#define MSC_EPIN_ADDR 0x81U
#define MSC_EPOUT_ADDR 0x01U
usb_storage.c
这个文件两个变量,另外这里面还有关于硬件的接口函数 这里只看变量
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x2000
#define STORAGE_BLK_SIZ 0x1000
避免每次更改设置后要重新设置变量
除去usbd_conf.h内变量可以在配置中设置 另外两个每次设置都会重新定义,这里利用 #undef取消宏定义再重新定义
usb_storage.c
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x2000
#define STORAGE_BLK_SIZ 0x1000
#ifdef STORAGE_BLK_NBR
#undef STORAGE_BLK_NBR
#define STORAGE_BLK_NBR 0x2000
#else
#define STORAGE_BLK_NBR 0x2000
#endif
#ifdef STORAGE_BLK_SIZ
#undef STORAGE_BLK_SIZ
#define STORAGE_BLK_SIZ 0x1000
#else
#define STORAGE_BLK_SIZ 0x1000
#endif
usb_msc.h 这里要在main.c里处理,这个文件没有留自定义代码位置
#ifdef MSC_MEDIA_PACKET
#undef MSC_MEDIA_PACKET
#define MSC_MEDIA_PACKET 4096U
#else
#define MSC_MEDIA_PACKET 4096U
#endif
#ifdef MSC_MAX_HS_PACKET
#undef MSC_MAX_HS_PACKET
#define MSC_MAX_HS_PACKET 0x1000U
#else
#define MSC_MAX_HS_PACKET 0x1000U
#endif
先说flash硬件接口接入USB的部分,也就是usb_storage.c
自定义驱动名称
const int8_t STORAGE_Inquirydata_FS[] = {
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ',
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ',
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1'
};
后续接口,这里我是参考 https://blog.csdn.net/Roomen0/article/details/122963305
int8_t STORAGE_Init_FS(uint8_t lun)
{
W25QXX_Init();
if(((W25QXX_TYPE&0xFF00)>>8)==0xEF)
return (USBD_OK);
else
return USBD_FAIL;
}
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
}
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
return W25QXX_ReadSR(1);
}
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
return (USBD_OK);
}
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
W25QXX_Read(buf,blk_addr*W25Q64_SECTOR_SIZE,blk_len*W25Q64_SECTOR_SIZE);
return (USBD_OK);
}
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
W25QXX_Write(buf,blk_addr*W25Q64_SECTOR_SIZE,blk_len*W25Q64_SECTOR_SIZE);
return (USBD_OK);
}
int8_t STORAGE_GetMaxLun_FS(void)
{
return (STORAGE_LUN_NBR - 1);
}
最后是根据原子例程改写的WQ驱动函数 H文件
#ifndef W25XX_H_
#define W25XX_H_
#include "main.h"
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25Q256 0XEF18
#define W25Q64_SECTOR_NBR 0x2000
#define W25Q64_SECTOR_SIZE 0x1000
extern uint16_t W25QXX_TYPE;
#define W25QXX_CS PAout(4)
void SPI1_Init(void);
void SPI1_SetSpeed(uint8_t SPI_BaudRatePrescaler);
uint8_t SPI1_ReadWriteByte(uint8_t TxData);
#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
void W25QXX_Init(void);
uint16_t W25QXX_ReadID(void);
uint8_t W25QXX_ReadSR(uint8_t regno);
void W25QXX_4ByteAddr_Enable(void);
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);
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
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
C文件
#include "W25XX.h"
extern SPI_HandleTypeDef hspi1;
uint16_t W25QXX_TYPE;
void W25QXX_Init(void)
{
uint8_t temp;
W25QXX_CS=1;
W25QXX_TYPE=W25QXX_ReadID();
if(W25QXX_TYPE==W25Q32)
{
temp=W25QXX_ReadSR(3);
printf("W25Q32 %X\r\n",temp);
if((temp&0X01)==0)
{
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_Enable4ByteAddr);
printf("4ByteAddr\r\n");
W25QXX_CS=1;
}
}
}
uint16_t W25QXX_ReadID(void)
{
uint16_t Temp = 0;
W25QXX_CS=0;
SPI1_ReadWriteByte(0x90);
SPI1_ReadWriteByte(0x00);
SPI1_ReadWriteByte(0x00);
SPI1_ReadWriteByte(0x00);
Temp|=SPI1_ReadWriteByte(0xFF)<<8;
Temp|=SPI1_ReadWriteByte(0xFF);
W25QXX_TYPE=Temp;
W25QXX_CS=1;
return Temp;
}
uint8_t W25QXX_ReadSR(uint8_t regno)
{
uint8_t byte=0,command=0;
switch(regno)
{
case 1:
command=W25X_ReadStatusReg1;
break;
case 2:
command=W25X_ReadStatusReg2;
break;
case 3:
command=W25X_ReadStatusReg3;
break;
default:
command=W25X_ReadStatusReg1;
break;
}
W25QXX_CS=0;
SPI1_ReadWriteByte(command);
byte=SPI1_ReadWriteByte(0Xff);
W25QXX_CS=1;
return byte;
}
void W25QXX_Write_SR(uint8_t regno,uint8_t sr)
{
uint8_t command=0;
switch(regno)
{
case 1:
command=W25X_WriteStatusReg1;
break;
case 2:
command=W25X_WriteStatusReg2;
break;
case 3:
command=W25X_WriteStatusReg3;
break;
default:
command=W25X_WriteStatusReg1;
break;
}
W25QXX_CS=0;
SPI1_ReadWriteByte(command);
SPI1_ReadWriteByte(sr);
W25QXX_CS=1;
}
void W25QXX_Write_Enable(void)
{
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_WriteEnable);
W25QXX_CS=1;
}
void W25QXX_Write_Disable(void)
{
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_WriteDisable);
W25QXX_CS=1;
}
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
uint16_t i;
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_ReadData);
if(W25QXX_TYPE==W25Q256)
{
SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>24));
}
SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>16));
SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>8));
SPI1_ReadWriteByte((uint8_t)ReadAddr);
for(i=0;i<NumByteToRead;i++)
{
pBuffer[i]=SPI1_ReadWriteByte(0XFF);
}
W25QXX_CS=1;
}
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t i;
W25QXX_Write_Enable();
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_PageProgram);
if(W25QXX_TYPE==W25Q256)
{
SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>24));
}
SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>16));
SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>8));
SPI1_ReadWriteByte((uint8_t)WriteAddr);
for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer[i]);
W25QXX_CS=1;
W25QXX_Wait_Busy();
}
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;
while(1)
{
W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
if(NumByteToWrite==pageremain)break;
else
{
pBuffer+=pageremain;
WriteAddr+=pageremain;
NumByteToWrite-=pageremain;
if(NumByteToWrite>256)pageremain=256;
else pageremain=NumByteToWrite;
}
};
}
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;
if(NumByteToWrite<=secremain)secremain=NumByteToWrite;
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[i];
}
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);
if(NumByteToWrite==secremain)break;
else
{
secpos++;
secoff=0;
pBuffer+=secremain;
WriteAddr+=secremain;
NumByteToWrite-=secremain;
if(NumByteToWrite>4096)secremain=4096;
else secremain=NumByteToWrite;
}
};
}
void W25QXX_Erase_Chip(void)
{
W25QXX_Write_Enable();
W25QXX_Wait_Busy();
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_ChipErase);
W25QXX_CS=1;
W25QXX_Wait_Busy();
}
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{
Dst_Addr*=4096;
W25QXX_Write_Enable();
W25QXX_Wait_Busy();
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_SectorErase);
if(W25QXX_TYPE==W25Q256)
{
SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>24));
}
SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>16));
SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>8));
SPI1_ReadWriteByte((uint8_t)Dst_Addr);
W25QXX_CS=1;
W25QXX_Wait_Busy();
}
void W25QXX_Wait_Busy(void)
{
while((W25QXX_ReadSR(1)&0x01)==0x01);
}
void W25QXX_PowerDown(void)
{
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_PowerDown);
W25QXX_CS=1;
delay_us(3);
}
void W25QXX_WAKEUP(void)
{
W25QXX_CS=0;
SPI1_ReadWriteByte(W25X_ReleasePowerDown);
W25QXX_CS=1;
delay_us(3);
}
void SPI1_Init(void)
{
hspi1.Instance=SPI1;
hspi1.Init.Mode=SPI_MODE_MASTER;
hspi1.Init.Direction=SPI_DIRECTION_2LINES;
hspi1.Init.DataSize=SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity=SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase=SPI_PHASE_2EDGE;
hspi1.Init.NSS=SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit=SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode=SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial=7;
HAL_SPI_Init(&hspi1);
__HAL_SPI_ENABLE(&hspi1);
SPI1_ReadWriteByte(0Xff);
}
void SPI1_SetSpeed(uint8_t SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
__HAL_SPI_DISABLE(&hspi1);
hspi1.Instance->CR1&=0XFFC7;
hspi1.Instance->CR1|=SPI_BaudRatePrescaler;
__HAL_SPI_ENABLE(&hspi1);
}
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi1,&TxData,&Rxdata,1, 1000);
return Rxdata;
}
注意 W25QXX_Init中W25QXX_ReadID之后对比的flash型号对应自己的大小
完成的例程参考 https://download.csdn.net/download/qq_27620407/85193715
|