0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32入门学习笔记之外置FLASH读写实验(下)

jf_78858299 来源:滑小稽笔记 作者:电子技术园地 2023-02-16 14:13 次阅读

(2)创建w25q128.c并输入以下代码。

/*********************************************************************************************************
                FLASH    驱    动    程    序
*********************************************************************************************************/
#include "w25q128.h" 
#include "delay.h"
/***************************************************
Name    :SPI2_SetSpeed
Function  :SPI2速度设置函数
Paramater  :
      SpeedSet:0~7
Return    :None
***************************************************/
void SPI2_SetSpeed( u8 SpeedSet )
{
  SpeedSet &= 0x07 ;                                          //限制范围
  SPI2->CR1 &= 0xFFC7 ;
  SPI2->CR1 |= SpeedSet<<3 ;                                      //设置SPI2速度
  SPI2->CR1 |= 1<<6 ;                                          //SPI设备使能
}
/***************************************************
Name    :SPI2_ReadWriteByte
Function  :SPI2读写一个字节
Paramater  :
      TxData:要写入的字节
Return    :读取到的字节
***************************************************/
u8 SPI2_ReadWriteByte( u8 TxData )
{
  u16 retry=0;
  //等待发送区空
  while( ( SPI2->SR&0x02 )==0 )
  {
    retry ++ ;
    //超时退出
    if( retry>=0xFFFE )
      return 0 ;
  }
  SPI2->DR = TxData ;                                          //发送一个byte
  //等待接收完一个byte
  retry = 0 ;
  while( ( SPI2->SR&0x01 )==0 )
  {
    retry ++ ;
    //超时退出
    if( retry>=0xFFFE )
      return 0 ;
  }
  return SPI2->DR ;                                          //返回收到的数据
}
/***************************************************
Name    :W25QXX_Init
Function  :初始化W25Q128芯片
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Init()
{ 
  RCC->APB2ENR |= 1<<3 ;                                        //PORTB时钟使能     
  GPIOB->CRH &= 0x0000FFFF ;
  GPIOB->CRH |= 0xBBB30000 ;                                      //PB12推挽输出+PB13/14/15复用
  GPIOB->ODR |= 0x7<<13 ;                                        //PB13/14/15上拉
  W25QXX_CS = 1 ;                                            //SPI FLASH不选中
  //初始化SPI
  RCC->APB1ENR |= 1<<14 ;                                        //SPI2时钟使能
  SPI2->CR1 |= 0<<10 ;                                        //全双工模式
  SPI2->CR1 |= 1<<9 ;                                          //软件nss管理
  SPI2->CR1 |= 1<<8 ;
  SPI2->CR1 |= 1<<2 ;                                          //SPI主机
  SPI2->CR1 |= 0<<11 ;                                        //8bit数据格式
  SPI2->CR1 |= 1<<1 ;                                          //空闲模式下SCK为1 CPOL=1
  SPI2->CR1 |= 1<<0 ;                                          //数据采样从第二个时间边沿开始,CPHA=1
  //对SPI2属于APB1的外设.时钟频率最大为36M
  SPI2->CR1 |= 3<<3 ;                                          //Fsck=Fpclk1/256
  SPI2->CR1 |= 0<<7 ;                                          //MSBfirst
  SPI2->CR1 |= 1<<6 ;                                          //SPI设备使能
  SPI2_ReadWriteByte( 0xFF ) ;                                    //启动传输
  SPI2_SetSpeed( SPI_SPEED_2 ) ;                                    //设置为18M时钟,高速模式
}
/***************************************************
Name    :W25QXX_Wait_Busy
Function  :等待空闲
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Wait_Busy()   
{
  u8 byte=0 ;
  // 等待BUSY位清空
  do
  {
    W25QXX_CS = 0 ;                                          //使能器件
    SPI2_ReadWriteByte( W25X_ReadStatusReg ) ;                            //发送读取状态寄存器命令
    byte = SPI2_ReadWriteByte( 0xFF ) ;                                //读取一个字节
    W25QXX_CS = 1 ;                                          //取消片选
  }while( ( byte&0x01 )==0x01 ) ;
}
/***************************************************
Name    :W25QXX_Erase_Chip
Function  :擦除整个芯片
Paramater  :None
Return    :None
***************************************************/
void W25QXX_Erase_Chip()
{
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_WriteEnable ) ;                              //发送写使能
  W25QXX_CS = 1 ;                                            //取消片选
    W25QXX_Wait_Busy() ;   
    W25QXX_CS=0 ;                                            //使能器件   
    SPI2_ReadWriteByte( W25X_ChipErase ) ;                                //发送片擦除命令  
  W25QXX_CS = 1 ;                                            //取消片选             
  W25QXX_Wait_Busy() ;                                        //等待芯片擦除结束
}
/***************************************************
Name    :W25QXX_Erase_Sector
Function  :擦除一个扇区
Paramater  :
      Address:扇区地址
Return    :None
***************************************************/
void W25QXX_Erase_Sector( u32 Address )
{
   Address *= 4096 ;
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_WriteEnable ) ;                              //发送写使能
  W25QXX_CS = 1 ;                                            //取消片选
    W25QXX_Wait_Busy();   
    W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_SectorErase ) ;                              //发送扇区擦除指令
    SPI2_ReadWriteByte( ( u8 )( Address>>16 ) ) ;                            //发送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address ) ;
  W25QXX_CS = 1 ;                                            //取消片选
    W25QXX_Wait_Busy() ;                                        //等待擦除完成
}
/***************************************************
Name    :W25QXX_Read
Function  :在指定地址开始读取指定长度的数据
Paramater  :
      pBuffer:数据存储区
      Address:开始读取的地址
      Len:要读取的字节数
Return    :None
***************************************************/
void W25QXX_Read( u8 *pBuffer, u32 Address, u16 Len )
{ 
   u16 i ;                           
  W25QXX_CS = 0 ;                                            //使能器件
    SPI2_ReadWriteByte( W25X_ReadData ) ;                                //发送读取命令
    SPI2_ReadWriteByte( ( u8 )( Address>>16 ) ) ;                            //发送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address );
    for( i=0; i>16 ) ) ;                            //发送24bit地址
    SPI2_ReadWriteByte( ( u8 )( Address>>8 ) ) ;
    SPI2_ReadWriteByte( ( u8 )Address ) ;
    for( i=0; ipageremain
     else
    {
      pBuffer += pageremain ;
      Address += pageremain ;
      Len -= pageremain ;                                      //减去已经写入了的字节数
      //一次可以写入256个字节
      if( Len>256 )
        pageremain = 256 ;
      //不够256个字节了
      else
        pageremain = Len ;
    }
  }
}
/***************************************************
Name    :W25QXX_Write_NoCheck
Function  :在指定地址开始写入指定长度的数据
Paramater  :
      pBuffer:数据存储区
      Address:开始写入的地址
      Len:要写入的字节数
Return    :None
***************************************************/
u8 W25QXX_BUFFER[ 4096 ] ;
void W25QXX_Write( u8 *pBuffer, u32 Address, u16 Len )
{
  u32 secpos ;
  u16 secoff ;
  u16 secremain ;
   u16 i ;
  u8 *W25QXX_BUF ;
     W25QXX_BUF = W25QXX_BUFFER ;
   secpos = Address/4096 ;                                        //扇区地址
  secoff = Address%4096 ;                                        //在扇区内的偏移
  secremain = 4096-secoff ;                                      //扇区剩余空间大小
  //不大于4096个字节
   if( Len<=secremain )
    secremain = Len ;
  while( 1 )
  {
    W25QXX_Read( W25QXX_BUF, secpos*4096, 4096 ) ;                          //读出整个扇区的内容
    //校验数据
    for( i=0; 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, Address, secremain ) ;                    //写已经擦除了的,直接写入扇区剩余区间
    //写入结束了
    if( Len==secremain )
      break ;
    //写入未结束
    else
    {
      secpos ++ ;                                          //扇区地址增1
      secoff = 0 ;                                        //偏移位置为0
         pBuffer += secremain ;                                    //指针偏移
      Address += secremain ;                                    //写地址偏移
         Len -= secremain ;                                      //字节数递减
      //下一个扇区还是写不完
      if( Len>4096 )
        secremain = 4096 ;
      //下一个扇区可以写完了
      else
        secremain = Len ;
    }
  }
}

(3)在1.c文件中输入以下代码。

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "w25q128.h"


const u8 TEXT_Buffer[] = { "WarShip STM32F1 SPI TEST" } ;
#define SIZE sizeof( TEXT_Buffer )


int main()
{
  u8 datatemp[ SIZE ] ;
  u32 FLASH_SIZE ;
  STM32_Clock_Init( 9 ) ;                                        //STM32时钟初始化
  SysTick_Init( 72 ) ;                                        //SysTick初始化
  USART1_Init( 72, 115200 ) ;                                      //初始化串口1波特率115200
  LCD_Init() ;                                            //LCD初始化
  W25QXX_Init() ;                                            //W25QXX初始化
   POINT_COLOR = RED ;                                          //设置字体为红色
  FLASH_SIZE = 128*1024*1024 ;                                    //FLASH 大小为16M字节
  W25QXX_Write( (u8*)TEXT_Buffer, FLASH_SIZE-100, SIZE ) ;                      //从倒数第100个地址处开始,写入SIZE长度的数据
  W25QXX_Read( datatemp, FLASH_SIZE-100, SIZE ) ;                            //从倒数第100个地址处开始,读出SIZE个字节
  LCD_ShowString( 0, 0, datatemp ) ;                                  //显示读到的字符串
  while( 1 )
  {

  }
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 闪存
    +关注

    关注

    16

    文章

    1776

    浏览量

    114805
  • FlaSh
    +关注

    关注

    10

    文章

    1621

    浏览量

    147738
  • ROM
    ROM
    +关注

    关注

    4

    文章

    562

    浏览量

    85668
  • STM32
    +关注

    关注

    2266

    文章

    10870

    浏览量

    354759
  • EEPROM
    +关注

    关注

    9

    文章

    1010

    浏览量

    81400
收藏 人收藏

    评论

    相关推荐

    STM32入门学习笔记之外置FLASH读写实验(上)

    Flash,全名叫做Flash EEPROM Memory,即平时所说的“闪存”,它结合了ROM和RAM的长处,不仅可以反复擦除,还可以快速读取数据,STM32运行的程序其实就是存放在Flas
    的头像 发表于 02-16 14:10 8864次阅读
    <b class='flag-5'>STM32</b><b class='flag-5'>入门</b><b class='flag-5'>学习</b><b class='flag-5'>笔记</b><b class='flag-5'>之外置</b><b class='flag-5'>FLASH</b><b class='flag-5'>读写实验</b>(上)

    【GD32F470紫藤派开发板使用手册】第十二讲 SDIO-SD卡读写实验

    通过本实验主要学习以下内容: •SDIO操作原理 •SD卡读写实
    的头像 发表于 05-18 09:36 1300次阅读
    【GD32F470紫藤派开发板使用手册】第十二讲 SDIO-SD卡<b class='flag-5'>读写实验</b>

    如何对扩展存储器进行读写实验

    扩展存储器读写实验的目的是什么?怎样去设计一种扩展存储器读写的电路?扩展存储器读写实验的流程有哪些?
    发表于 07-14 07:04

    如何通过对flash读写实stm32的编程操作?

    如何通过对flash读写实stm32的编程操作?
    发表于 10-29 06:19

    接触式IC卡读写实验

    接触式IC卡读写实验 一. 实验目的了解接触式IC 卡的知识,
    发表于 09-22 17:20 4698次阅读
    接触式IC卡<b class='flag-5'>读写实验</b>

    AVR内部EEPROM读写实验

    片内EEPROM读写实险。 1、用内部EEPROM记录CPU启动次数,并在PB口上显示出来。 2、内部1 M晶振,程序采用单任务方式,软件延时。 3、进行此实验
    发表于 06-30 11:25 2539次阅读

    STM32_ SPI读写Flash

    STM32_SPI读写Flash
    的头像 发表于 04-08 10:26 5481次阅读
    <b class='flag-5'>STM32</b>_ SPI<b class='flag-5'>读写</b><b class='flag-5'>Flash</b>

    单片机实验汇编--扩展存储器读写实验

    扩展存储器读写实验一.实验要求编制简单程序,对实验板上提供的外部存贮器(62256)进行读写操作。二.实验目的1.
    发表于 11-23 09:51 19次下载
    单片机<b class='flag-5'>实验</b>汇编--扩展存储器<b class='flag-5'>读写实验</b>

    STM32内部Flash读写问题

    STM32Flash读写Flash调试技巧文章目录先熟悉所用MCU的Flash存储大小以及扇区地址Flsah写之前为什么要先擦除Flash
    发表于 12-01 20:21 20次下载
    <b class='flag-5'>STM32</b>内部<b class='flag-5'>Flash</b><b class='flag-5'>读写</b>问题

    STM32F103学习笔记——SPI读写Flash(一)

    STM32F103学习笔记——SPI读写Flash(一)  此系列文章是小白学习
    发表于 12-02 12:06 19次下载
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>——SPI<b class='flag-5'>读写</b><b class='flag-5'>Flash</b>(一)

    STM32F103学习笔记——SPI读写Flash(三)

      此系列文章是小白学习STM32的一些学习笔记。小白第一次写笔记文章,有不足或是错误之处,请多体谅和交流!目录1.
    发表于 12-22 19:29 11次下载
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>——SPI<b class='flag-5'>读写</b><b class='flag-5'>Flash</b>(三)

    STM32F103学习笔记——SPI读写Flash(二)

      此系列文章是小白学习STM32的一些学习笔记。小白第一次写笔记文章,有不足或是错误之处,请多体谅和交流!目录1.软件设计流程2.SPI初
    发表于 12-22 19:30 10次下载
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>——SPI<b class='flag-5'>读写</b><b class='flag-5'>Flash</b>(二)

    STM32F103学习笔记——SPI读写Flash(四)

      此系列文章是小白学习STM32的一些学习笔记。小白第一次写笔记文章,有不足或是错误之处,请多体谅和交流!目录1.main函数编写2.下载
    发表于 12-22 19:32 6次下载
    <b class='flag-5'>STM32</b>F103<b class='flag-5'>学习</b><b class='flag-5'>笔记</b>——SPI<b class='flag-5'>读写</b><b class='flag-5'>Flash</b>(四)

    外置FLASH读写实验

    Flash,全名叫做Flash EEPROM Memory,即平时所说的“闪存”,它结合了ROM和RAM的长处,不仅可以反复擦除,还可以快速读取数据,STM32运行的程序其实就是存放在Flas
    的头像 发表于 03-01 14:56 4821次阅读

    【GD32F303红枫派开发板使用手册】第二十三讲 SDIO-SD卡读写实验

    通过本实验主要学习以下内容: •SDIO操作原理 •SD卡读写实
    的头像 发表于 06-23 10:49 544次阅读
    【GD32F303红枫派开发板使用手册】第二十三讲 SDIO-SD卡<b class='flag-5'>读写实验</b>