预备知识
>>W25Q128是16M spi flash,一共有256个block ,每个Block 64KB。
>>一个Block可以分割为16个扇区(small sector),每个扇区4096字节
步骤 | 步骤讲解与结果截图 |
---|---|
步骤1:创建STM32CUBEIDE工程(根据自己的开发板,配置RCC,选择最低版本固件库) | ![]() ![]() |
2:查看FLASH与自己板子的接线图 | ![]() ![]() ![]() |
3:根据FLASH时序特点,这个芯片采用MSB先行,一般采用模式0(初始低电平,采集第一个边沿)与模式3(初始高电平,采集第二个边沿)的时钟,SPI采用的摩托罗拉的设计,所以我们将SPI配置如下 | ![]() |
4:调整引脚 | 由于我们发现系统配置的SPI1的引脚与我们开发板的引脚标号PB3,PB4,PB5不一致,所以我们要对SPI1进行调整引脚![]() ![]() |
5:配置NSS脚 | 由于NSS片选引脚需要我们用软件配置,所以我们将原理图上的PG6的NSS脚,配置为GPIO的输出模式,方便控制FLASH芯片的工作接入与否![]() |
6:由于FLASH的传输机制与EEPROM不同,读写数据前需要发送对应编码的指令,所以FLASH的指令众多,功能众多,所以要学会移植FLASH的驱动(移植!=抄,要读懂驱动代码,移植才比较快,否则你要移植很久,可能还是会失败),而且今后移植驱动也是家常便饭的事情 | 1:将厂商给我们的BSP驱动程序复制到我们的项目(需要提前把待移植的代码保存为GB2312编码,再移植到我们项目,并且把我们的项目编码也设置为GB2312,才不会出现移植的文件中文乱码的情况) 2:)为了验证我们是否移植成功,我们还需要将mian函数里面的测试代码给移植过来![]() ![]() |
7:串口使能 | 在移植过程中,我们发现需要用到上位机进行显示,所以我们将串口配置好,串口的配置很简单,只需要选择异步模式就ok![]() |
8:移植过程介绍 | 技巧:有时需要批量替换一个单词可以选中单词,右键点击Refactor重建,然后选择Rename 1)移植过程主要是移植![]() ![]() ![]() ![]() |
9:移植验证 | ![]() |
10:阅读支持包驱动代码 | 移植完后,不要就不管了,一定要看FLASH厂商给的驱动流程 |
进阶内容:串行FLASH文件系统FatFs
步骤 | 截图/讲解 |
---|---|
步骤1:在上个SPI读写FLASH基础上配置FATFS | 我的FLASH一个扇区sector为4096字节,所以将扇区大小设置为4096最大;因为需要读取的文件是中文的,所以要配置为中文,然后为以后可能还有别的存储器预留空位,所以配置VOLUMES为其他![]() |
步骤2:修改project setting里面的stack大小 | ![]() 生成的项目结构中的fatfs的在中间件里面的第三方支持里面 ![]() 同时stm32cubemx在源文件里面为我们生成了user_diskio的源文件 注意:修改#define SPI_FLASH 0 ![]() |
步骤3:将stm32cubemx提供给我们的user_diskio文件写入自己的接口 | 直接将野火的相同函数部分复制到user_diskio文件中就ok![]() |
步骤4:测试 | 在mian.c里面测试文件系统 |
/*******************************************************有文件系统测试****************************************************/
/* 配置串口1为:115200 8-N-1 */
printf("\r\n这是一个16M串行flash(W25Q128)实验(QSPI驱动) \r\n");
/* 16M串行flash W25Q128初始化 */
/* 获取 Flash Device ID */
printf("****** 这是一个SPI FLASH 文件系统实验 ******\r\n");
//在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化
retUSER = f_mount(&USERFatFS,"0:",1);
/*----------------------- 格式化测试 ---------------------------*/
/* 如果没有文件系统就格式化创建创建文件系统 */
if(retUSER == FR_NO_FILESYSTEM)
{
printf("》FLASH还没有文件系统,即将进行格式化...\r\n");
/* 格式化 */
retUSER=f_mkfs("0:",FM_ANY, 0, ReadBuffer, sizeof(ReadBuffer));
if(retUSER == FR_OK)
{
printf("》FLASH已成功格式化文件系统。\r\n");
/* 格式化后,先取消挂载 */
retUSER = f_mount(NULL,"0:",1);
/* 重新挂载 */
retUSER = f_mount(&USERFatFS,"0:",1);
}
else
{
printf("《《格式化失败。》》\r\n");
while(1);
}
}
else if(retUSER!=FR_OK)
{
printf("!!外部Flash挂载文件系统失败。(%d)\r\n",retUSER);
printf("!!可能原因:SPI Flash初始化不成功。\r\n");
while(1);
}
else
{
printf("》文件系统挂载成功,可以进行读写测试\r\n");
}
/*----------------------- 文件系统测试:写测试 -----------------------------*/
/* 打开文件,如果文件不存在则创建它 */
printf("\r\n****** 即将进行文件写入测试... ******\r\n");
retUSER = f_open(&USERFile, "0:FatUSERFatFS读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );
// LOG_ERROR(retUSER);
if ( retUSER == FR_OK )
{
printf("》打开/创建FatUSERFatFS读写测试文件.txt文件成功,向文件写入数据。\r\n");
/* 将指定存储区内容写入到文件内 */
retUSER=f_write(&USERFile,WriteBuffer,sizeof(WriteBuffer),&fnum);
if(retUSER==FR_OK)
{
printf("》文件写入成功,写入字节数据:%d\n",fnum);
printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
}
else
{
printf("!!文件写入失败:(%d)\n",retUSER);
}
/* 不再读写,关闭文件 */
f_close(&USERFile);
}
else
{
printf("!!打开/创建文件失败。\r\n");
}
/*------------------- 文件系统测试:读测试 ------------------------------------*/
printf("****** 即将进行文件读取测试... ******\r\n");
retUSER = f_open(&USERFile, "0:FatUSERFatFS读写测试文件.txt", FA_OPEN_EXISTING | FA_READ);
if(retUSER == FR_OK)
{
printf("》打开文件成功。\r\n");
retUSER = f_read(&USERFile, ReadBuffer, sizeof(ReadBuffer), &fnum);
if(retUSER==FR_OK)
{
printf("》文件读取成功,读到字节数据:%d\r\n",fnum);
printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer);
}
else
{
printf("!!文件读取失败:(%d)\n",retUSER);
}
}
else
{
printf("!!打开文件失败。\r\n");
}
/* 不再读写,关闭文件 */
f_close(&USERFile);
/* 不再使用文件系统,取消挂载文件系统 */
f_mount(NULL,"0:",1);
/* 操作完成,停机 */