苏州企业建设网站服务,购物网站的后台做哪些东西,网站图片加alt标签,好看的网站排版提示#xff1a;文章写完后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、cubemx配置二、keil中文件修改与配置三、几个重要函数的说明四、DMA方式传输#xff08;待写#xff09;总结 前言
W25Q128 容量为128位 128/8 16 也就… 提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档 文章目录 前言一、cubemx配置二、keil中文件修改与配置三、几个重要函数的说明四、DMA方式传输待写总结 前言
W25Q128 容量为128位 128/8 16 也就是16M 擦除之前必须写使能 写数据的存储单元必须是被擦除过的也就是必须是0XFF不过不是则写入无效。 此图来源于 一、cubemx配置
全双工SPI 不使用硬件NSS w25q虽然数据手册写可以达到30mbit/s但是还是建议用10以下的高了偶尔会出错。
这里参考b站的视频 视频中用的spi3模式我用的1模式 spi配置 片选引脚配置 初始化为high 保证上电以后未被片选
二、keil中文件修改与配置
使用到的代码为b站视频中的链接1 链接2
.h文件这里进行了修改 这里注意 前两个 值对任意W25Q都是一样的不需要修改4096 也并未用到目前暂时不修改
//Flash存储芯片W25Q128的存储容量参数
#define FLASH_PAGE_SIZE 256 //一个Page是256字节
#define FLASH_SECTOR_SIZE 4096 //一个Sector是4096字节
#define FLASH_SECTOR_COUNT 4096 //总共4096个 Sector三、几个重要函数的说明
w25q必须以页为单位来写入写入前必须要擦除擦除必须以扇区进行擦除 如果写入前没有擦除虽然不会报错但是写入是无效的。 重要函数 Flash_EraseChip();//擦除整个芯片大概20多秒 Flash_EraseBlock64K(globalAddr);//擦除一个块 Flash_EraseSector(memAddress1);//擦除一个扇区 这个是擦除的最单位了 Flash_Addr_byBlockSectorPage(uint8_t BlockNo, uint8_t SubSectorNo, uint8_t SubPageNo) 这个函数是用来得到 块 扇区 页 的那个绝对地址的。
举例 擦除一个扇区 uint32_t memAddress1 Flash_Addr_byBlockSectorPage(0, 0, 1);Flash_EraseSector(memAddress1);向两个页分别写数据
void Flash_TestWrite() {uint8_t BlockNo 0;uint8_t SubSectorNo 0;uint8_t SubPageNo 0;uint32_t memAddress 0;memAddress Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t bufStr1[30] Hello222444;Flash_WriteInPage(memAddress, bufStr1, strlen(bufStr1) 1);printf(Write in Page0:0\n);printf( %s,bufStr1);uint8_t bufStr2[30] Hello111333;Flash_WriteInPage(memAddress 100, bufStr2, strlen(bufStr2) 1);printf( Write in Page0:100\n);printf( %s, bufStr2);uint8_t bufPage[FLASH_PAGE_SIZE];for (uint16_t i 0; i FLASH_PAGE_SIZE; i) {bufPage[i] 0;}SubPageNo 1;memAddress Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);Flash_WriteInPage(memAddress, bufPage, FLASH_PAGE_SIZE);printf(Write 0~255 in Page1);
}向两个页分别读数据
void Flash_TestRead() {uint8_t BlockNo 0;uint8_t SubSectorNo 0;uint8_t SubPageNo 0;uint32_t memAddress Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t bufStr[50];Flash_ReadBytes(memAddress, bufStr, 50);printf( Read in Page0:0 );printf( %s, bufStr);Flash_ReadBytes(memAddress 100, bufStr, 50);printf( Read in Page0:100 );printf( %s, bufStr);SubPageNo 1;memAddress Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t randData12 Flash_ReadOneByte(memAddress 12);uint8_t randData136 Flash_ReadOneByte(memAddress 136);uint8_t randData210 Flash_ReadOneByte(memAddress 210);uint8_t tempStrRandData[30];sprintf(tempStrRandData, Page1[12]%d,[136]%d,[210]%d,randData12, randData136, randData210);printf( %s, tempStrRandData);
}有了 上面两个函数我们就可以做一些小实验了。 第一次使用的时候先对芯片进行整体的擦除 让后调用Flash_TestWrite();函数此时调用Flash_TestRead() ;函数来读取是正常的 修改代码不对w25q进行任何擦除直接把Flash_TestWrite();中的bufPage[i] 0;写成bufPage[i] i; 这时候读取函数读到的值就是上一次的说明虽然没有报错但是并未写入成功 如果对芯片进行该扇区的擦除再写入即可在读取中获取新的写入。记住写入是按照页来写擦除是按照扇区擦一个扇区里面有16个页。 在使用 W25Q 系列的 SPI Flash 存储器时确实存在写入操作以页为单位通常为256字节而擦除操作以扇区为单位通常为4KB的限制。这意味着如果你只想修改某个页的数据而不影响同一扇区内的其他数据必须采取一些策略来避免丢失扇区中其他页的数据。 解决方法 通常有两种常见的解决方案来应对这个问题 1扇区读出、修改和写回 步骤 读出整个扇区在你需要修改某一页的数据时先读取整个扇区的数据到内存中。 修改页数据在内存中修改目标页的数据。 擦除扇区执行扇区擦除操作。 写回数据将修改后的数据重新写回该扇区包括未修改的页数据和修改后的页数据 2使用缓存缓存区 步骤 在内存中保留一个缓冲区该缓冲区的大小等同于一个扇区大小。 管理缓存每次写入时先更新缓存区中的数据然后定期或在缓存区满时写回 SPI Flash。 擦除与写回当要写入到 Flash 时执行上述 “扇区读出、修改和写回” 的操作。 优点可以减少对 Flash 的擦写次数延长 Flash 的寿命。 总结 无论选择哪种方式主要思想都是避免直接修改 Flash 中的数据而是通过在内存中暂存整个扇区的数据再进行更新和写回操作。这种方式能够有效避免因为写入新数据而导致同一扇区内其他数据的丢失问题。 1扇区读出、修改和写回参考代码
#define SECTOR_SIZE 4096 // W25Q扇区大小
#define PAGE_SIZE 256 // W25Q页大小uint8_t sectorBuffer[SECTOR_SIZE];void updatePageInSector(uint32_t sectorAddr, uint16_t pageOffset, uint8_t* data, uint16_t length) {// 1. 读出整个扇区W25Q_Read(sectorBuffer, sectorAddr, SECTOR_SIZE);// 2. 修改指定页的数据memcpy(sectorBuffer[pageOffset * PAGE_SIZE], data, length);// 3. 擦除扇区W25Q_EraseSector(sectorAddr);// 4. 将修改后的数据写回整个扇区W25Q_Write(sectorBuffer, sectorAddr, SECTOR_SIZE);
}注意W25Q_Read 和 W25Q_Write 是 SPI Flash 的读写函数W25Q_EraseSector 是擦除扇区的函数。这里假设你要修改的页在 sectorAddr 的偏移量为 pageOffset 页。
四、DMA方式传输待写 总结
提示这里对文章进行总结 例如以上就是今天要讲的内容本文仅仅简单介绍了pandas的使用而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。