STM32驱动SPI接口FLASH文档格式.docx
- 文档编号:21709396
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:14
- 大小:55.95KB
STM32驱动SPI接口FLASH文档格式.docx
《STM32驱动SPI接口FLASH文档格式.docx》由会员分享,可在线阅读,更多相关《STM32驱动SPI接口FLASH文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
<
SPI_FLASH_SPI
Periph
clock
enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,
ENABLE);
/*将PA5(CLK)配置成复用推挽输出
GPIO_InitStructure.GPIO_Pin
=
GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed
GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode
GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,
&
GPIO_InitStructure);
/*将PA6(DO)设置成浮空输入
GPIO_Pin_6;
/*将PA7(DIO)设为浮空输入*/
GPIO_Pin_7;
/*将PA4(CS)设为推挽输出*/
GPIO_Pin_4;
GPIO_Mode_Out_PP;
/*拉高CS,失能芯片,该语句是宏定义,就是置高PA4*/
SPI_FLASH_CS_HIGH();
SPI配置/
//
W25X16:
data
input
on
the
DIO
pin
is
sampled
rising
edge
of
CLK.
Data
DO
pins
are
clocked
out
falling
CLK.
/*将SPI设为全双工模式*/
SPI_InitStructure.SPI_Direction
SPI_Direction_2Lines_FullDuplex;
/*将SPI设为主模式*/
SPI_InitStructure.SPI_Mode
SPI_Mode_Master;
/*将SPI通信的数据大小设为8位*/
SPI_InitStructure.SPI_DataSize
SPI_DataSize_8b;
/*将CLK的高电平设为空闲*/
SPI_InitStructure.SPI_CPOL
SPI_CPOL_High;
/*设置在第二个时钟沿捕获数据*/
SPI_InitStructure.SPI_CPHA
SPI_CPHA_2Edge;
/*指定NSS信号由软件管理*/
SPI_InitStructure.SPI_NSS
SPI_NSS_Soft;
/*SPI_BaudRatePrescaler用来定义波特率预分频的值,这个值用以设置发送和接收的SCK时钟*/
SPI_InitStructure.SPI_BaudRatePrescaler
SPI_BaudRatePrescaler_4;
/*SPI_FirstBit指定了数据传输从高位还是低位开始*/
SPI_InitStructure.SPI_FirstBit
SPI_FirstBit_MSB;
/*SPI_CRCPolynomial定义了用于CRC值计算的多项式*/
SPI_InitStructure.SPI_CRCPolynomial
7;
SPI_Init(SPI1,
SPI_InitStructure);
/*
SPI_Cmd(SPI1,
}
(2)获取器件地址1
因为SPI总线上可以挂很多的器件,所以首先要获得器件的地址。
获得器件地址的步骤是:
拉低CS——>
向器件发送获得地址的命令——>
连续发送三个任意数据——>
在发送第四个任意数据时在DO口上读出器件地址。
注意,发送完读地址后,从机会将数据自动传给主机的SPI数据寄存器中,用户只要到该寄存器中取数就可以了。
好的,既然用到写命令那么我们写来写这两个最基础的程序。
写数据函数:
/*******************************************************************************
*
Function
Name
:
SPI_FLASH_SendByte
Description
通过SPI总线发送一字节数据,再通过SPI总线返回
一字节数据
Input
byte
——要发送的数据
Output
从机返回的数据
被SPI_FLASH_ReadDeviceID调用
*******************************************************************************/
u8
SPI_FLASH_SendByte(u8
byte)
等待SPI发送寄存器里的数据发送结束
while(SPI_I2S_GetFlagStatus(SPI1,
SPI_I2S_FLAG_TXE)
==
RESET);
发送数据*/
SPI_I2S_SendData(SPI1,
byte);
等待接收完一字节数据
while
(SPI_I2S_GetFlagStatus(SPI1,
SPI_I2S_FLAG_RXNE)
返回接收到的数据
return
SPI_I2S_ReceiveData(SPI1);
现在我们再来看看读器件地址函数:
SPI_FLASH_ReadDeviceID(void)
读器件地址1
返回
:
器件地址
:
u32
Temp
0;
SPI_FLASH_CS_LOW(),是一个宏定义,就是拉低CS(PA4)
SPI_FLASH_CS_LOW();
/*W25X_DeviceID=0XAB,是读器件地址的命令,发送完该命令后连续发三个任意数字,在发第五个任意数后可以读出地址
SPI_FLASH_SendByte(0XAB);
SPI_FLASH_SendByte(0XFF);
Read
a
from
FLASH
*/
Temp
SPI_FLASH_SendByte(0XFF);
失能芯片*/
SPI_FLASH_CS_HIGH();
/*返回器件地址*/
return
Temp;
像温度传感器一样,WX25X16也有很多的命令,具体的命令看下图:
(4)擦除扇区
WX25X16是2M的字节,共分为8页,每页是256个字节的大小。
可以采用页写入的方式写入数据。
这里需要注意的是,采用页写入时,每写入一个字节的数据地址会自动加1,当写满一页后会从该页的起始位置写起,即覆盖掉已写的数据。
如果想写完一页后进入下一页继续写入数据那么就要在写入数据的起始地址上加上256(页的大小就是256),比如我是从0开始写的,写到255时一页写完,那么要在第二页开始写,那么要将写入的地址变成(0+256),这一点大家一定要注意。
在写入数据前先要对芯片进行擦除。
芯片的擦除主要有一下几个步骤:
发送写使能命令——>
等待写使能命令执行结束——>
选中芯片——>
发送擦除命令——>
发送要擦除的起始地址——>
释放芯片——>
等待擦除命令执行结束
这里要注意的是,并不是发送任何命令都需要等待命令执行结束的,WX25X16手册规定以下几个操作要等待命令执行结束:
1.数据擦除
2.对状态寄存器写的操作(例如数据写入失能结会改
变状态寄存器中的BUSY位)
首先看发送写使能命令:
SPI_FLASH_WriteEnable
允许想芯片内写入数据
None
Return
被SPI_FLASH_SectorErase调用
SPI_FLASH_WriteEnable(void)
Select
FLASH:
Chip
low
Send
"
Write
Enable"
instruction
SPI_FLASH_SendByte(0X06);
Deselect
high
等待命令执行结束
SPI_FLASH_WaitForWriteEnd
执行写使能会值位状态寄存器中的BUSY位,只有
BUSY位变为0时说明写使能命令执行完成
*调用
SPI_FLASH_WaitForWriteEnd(void)
FLASH_Status
Status
Register"
SPI_FLASH_SendByte(0X05);
Loop
as
long
memory
busy
with
write
cycle
do{
dummy
to
generate
needed
by
put
value
status
register
in
variable
SPI_FLASH_SendByte(Dummy_Byte);
while
((FLASH_Status
0X01)
SET);
progress
下面看看数据擦除函数
SPI_FLASH_SectorErase
Erases
specified
sector.
SectorAddr:
address
sector
erase.
SPI_FLASH_WriteEnable()
SPI_FLASH_WaitForWriteEnd()
SPI_FLASH_SendByte()
SPI_FLASH_SectorErase(u32
SectorAddr)
发送使能写命令
SPI_FLASH_WriteEnable();
/*使能写命令是一个写状态寄存器的命令,所以要等待该命令执行完,才能写其他命令*/
SPI_FLASH_WaitForWriteEnd();
发送擦除扇区命令
SPI_FLASH_SendByte(0X20);
发送要擦除的起始地址
SPI_FLASH_SendByte((SectorAddr
0xFF0000)
>
16);
SectorAddr
medium
nibble
0xFF00)
8);
SPI_FLASH_SendByte(SectorAddr
0xFF);
从机的数据手册规定(12页)规定,对于写擦除命令,要等待命令执行完才能执行下一命令*/
这里要注意,发送擦除地址时要发送三个8位的地址。
(5)写入数据
由于我们是选择的的页写入的方式,所以这里的程序又点小复杂,大家慢慢看,好好理解。
SPI_FLASH_BufferWrite
Writes
block
FLASH.
In
this
function,
the
number
WRITE
cycles
reduced,
using
Page
WRITEsequence.
-
pBuffer
pointer
buffer
containing
be
written
FLASH.
WriteAddr
FLASH'
s
internal
to.
NumByteToWrite
bytes
SPI_FLASH_BufferWrite(u8
*pBuffer,u32
WriteAddr,u16NumByteToWrite)
NumOfPage
=0,NumOfSingl
=0,Addr
=0,count
=0,temp
=0;
/*Addr记录的数据是用来判断写入的数据是否从页的起始地址开始写,如果Addr
=0,则表示从起始地址开始写
,SPI_FLASH_PageSize=256*/
Addr
=WriteAddr
%
SPI_FLASH_PageSize;
/*count记录的是从开始写的地址到该页结束处共有多少字节*/
count
=SPI_FLASH_PageSize
-Addr;
/*NumOfPage指示要写的数据要占几个整页*/
NumOfPage
=NumByteToWrite
/
/*NumOfSingl指示的是要写的数据在写完整页后还剩下的部分*/
NumOfSingl
/*判断是否从页的起始处开始写起,Addr=0说明从起始处写起*/
if(Addr
==0)
{
if(NumOfPage
==0)
//说明要写的数据的大小不足1页
SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumByteToWrite);
else
//要写的数据大于1页
while(NumOfPage--)
//将整页的数据写完
SPI_FLASH_PageWrite(pBuffer,WriteAddr,SPI_FLASH_PageSize);
WriteAddr
+=SPI_FLASH_PageSize;
pBuffer
}
SPI_FLASH_PageWrite(pBuffer,WriteAddr,NumOfSingl);
//不是从起始地址开始写
{
//要写的数据小于一页
if(NumOfSingl
count)
//要写入的数据大于从开始写处到页结束之间的空间大小
temp
NumOfSingl
count;
/*先写完该页*/
SPI_FLASH_PageWrite(pBuffer,WriteAddr,count);
/*多余的数据转到下页写*/
+=
SPI_FLASH_PageWrite(pBuffer,
WriteAddr,
temp);
//要写的数据小于从开始写处到页结束之间的空间大小
NumByteToWrite);
}
//要写的数据大于一页
NumByteToWrite
-=count;
count);
(NumOfPage--)
SPI_FLASH_PageSize);
if
(NumOfSingl
!
0)
NumOfSingl);
上面的函数用到了
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- STM32 驱动 SPI 接口 FLASH