STM32CUBEMX(一)USB HOST+W25QXX+FATFS——开始我的旅程

发布于:2022-10-30 ⋅ 阅读:(958) ⋅ 点赞:(0)

使用STM32CUBEMX6.6.1        KEIL5.27

首先打开CUBEMX新建工程:

 确定芯片型号

根据实际外部晶振选择

设置下载调试方法

设置usb 引脚

设置usb主机模式

设置W25QXX的SPI引脚,看资料说W25QXX SPI协议要HIGH+2EDGE,但我尝试通信不正确,改为LOW+1EDGE通信正确,FLASH_CS引脚自己根据引脚连接设置。

 设置FATFS,开启U盘和USER(W25QXX)

频率设置输入168按回车即可

 工程配置,保存位置不要有中文。

最后生成工程;

由于U盘设置只用了俩个引脚会跳出警告无视点yes即可

生成完成后,点击打开工程。

打开工程进入配置界面

 根据自己的下载器选择下载方式

 

 

下载完成,自动开始运行。

在工程保存地址内,新建文件夹来保存自己移植的文件。

 

 

 在KEIL里把创建的文件夹包含进来

 添加分组,与自己的文件

查看U盘状态在

把Appli_state加入DEBUG中,开始后,插入U盘和拔出U盘状态改变。

自定义的FATFS中这俩个函数返回一定要像U盘FATFS改成返回OK,不然挂载不成功

内容为:
#define FLASH_SECTOR_SIZE     4096        //W25QXX一块4k,对擦写友好
#define FLASH_SECTOR_COUNT     256*16    //代表总大小=FLASH_SECTOR_SIZE*256*16=16M
#define FLASH_BLOCK_SIZE       65536             //不太懂        
/* USER CODE END DECL */

/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
#if _USE_WRITE == 1
  DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
  DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
#endif /* _USE_IOCTL == 1 */

Diskio_drvTypeDef  USER_Driver =
{
  USER_initialize,
  USER_status,
  USER_read,
#if  _USE_WRITE
  USER_write,
#endif  /* _USE_WRITE == 1 */
#if  _USE_IOCTL == 1
  USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_initialize (
    BYTE pdrv           /* Physical drive nmuber to identify the drive */
)
{
  /* USER CODE BEGIN INIT */

    return RES_OK;
  /* USER CODE END INIT */
}

/**
  * @brief  Gets Disk Status
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_status (
    BYTE pdrv       /* Physical drive number to identify the drive */
)
{
  /* USER CODE BEGIN STATUS */

    return RES_OK;
  /* USER CODE END STATUS */
}

/**
  * @brief  Reads Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT USER_read (
    BYTE pdrv,      /* Physical drive nmuber to identify the drive */
    BYTE *buff,     /* Data buffer to store read data */
    DWORD sector,   /* Sector address in LBA */
    UINT count      /* Number of sectors to read */
)
{
  /* USER CODE BEGIN READ */
    for(;count>0;count--)
            {
                W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
                sector++;
                buff+=FLASH_SECTOR_SIZE;
            }
    return RES_OK;
  /* USER CODE END READ */
}

/**
  * @brief  Writes Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT USER_write (
    BYTE pdrv,          /* Physical drive nmuber to identify the drive */
    const BYTE *buff,   /* Data to be written */
    DWORD sector,       /* Sector address in LBA */
    UINT count          /* Number of sectors to write */
)
{
  /* USER CODE BEGIN WRITE */
  /* USER CODE HERE */
    if(count<=8)
    {
        W25QXX_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE*count);    //节约时间            
    }
    else
    {
        for(;count>0;count--)
        {                                            
            W25QXX_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
            sector++;
            buff+=FLASH_SECTOR_SIZE;
        }
    }
    return RES_OK;
  /* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */

/**
  * @brief  I/O control operation
  * @param  pdrv: Physical drive number (0..)
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1
DRESULT USER_ioctl (
    BYTE pdrv,      /* Physical drive nmuber (0..) */
    BYTE cmd,       /* Control code */
    void *buff      /* Buffer to send/receive control data */
)
{
  /* USER CODE BEGIN IOCTL */
    DRESULT res = RES_ERROR;
        switch(cmd)
        {
            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 = (WORD)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;
        }
    return res;
  /* USER CODE END IOCTL */
}

 测试时先测试W25QXX读ID是否正确

W25QXX_Init();
    retUSER=f_mount(&USERFatFS,USERPath,1);//挂载w25qxx
    if(retUSER == FR_NO_FILESYSTEM)//没有格式化过
    {
        sprintf(system_state,"w25qxx未格式化");
        retUSER  = f_mkfs(USERPath, 1, 0, work, sizeof(work));//格式化
        if(retUSER  == FR_OK)//格式化成功后重新挂载
        {
                sprintf(system_state,"w25qxx格式化成功");
                /* 格式化后,先取消挂载 */
                retUSER  = f_mount(NULL, USERPath, 1);
                /* 重新挂载 */
                retUSER  = f_mount(&USERFatFS,USERPath, 1);
        }
        else
        {
                sprintf(system_state,"w25qxx格式化失败");
                    while(1);
        }
    }
    else if(retUSER  != FR_OK)
    {
        sprintf(system_state,"w25qxx挂载失败");
        while(1);
    }
    else
    {
            sprintf(system_state,"w25qxx挂载成功");
    }

 retUSER =  f_open(&USERFile, "1:STM32.TXT", FA_OPEN_ALWAYS | FA_WRITE);
            if(retUSER != FR_OK)
            {
                sprintf(system_state,"打开文件失败");
                 while(1);
            }
            else
                sprintf(system_state,"打开文件成功");
            f_lseek(&USERFile,f_size(&USERFile));//应该是开启后可以连续写
            retUSER = f_write(&USERFile, &trigger_time, sizeof(trigger_time),  &bw);
            if(retUSER)
            {
                sprintf(system_state,"写时间失败");
                 while(1);
            }
            else
                    sprintf(system_state,"写时间成功");

retUSER = f_close(&USERFile);//关闭文件

retUSER  = f_mount(NULL, USERPath, 1);//取消挂载

今日先到此。

希望给自己增加一个好习惯。细节之处以后再慢慢积累补全。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到