收藏 分享(赏)

STM32 FLASH实验-SPI.pdf

上传人:精品资料 文档编号:8818512 上传时间:2019-07-13 格式:PDF 页数:12 大小:384.64KB
下载 相关 举报
STM32 FLASH实验-SPI.pdf_第1页
第1页 / 共12页
STM32 FLASH实验-SPI.pdf_第2页
第2页 / 共12页
STM32 FLASH实验-SPI.pdf_第3页
第3页 / 共12页
STM32 FLASH实验-SPI.pdf_第4页
第4页 / 共12页
STM32 FLASH实验-SPI.pdf_第5页
第5页 / 共12页
点击查看更多>>
资源描述

1、 FLASH实验-SPI 学习目标: 1、学会STM32硬件SPI 2、学会对EN25Q64进行读写操作 10.1 EN25Q64简介 EN25Q64 是华邦公司推出的大容量 SPI FLASH 产品,EN25Q64 的容量为64M比特,也就是说有8M字节。EN25Q64将8M的容量分为 128个块(Block),每个块大小为 64K字节,每个块又分为 16个扇区(Sector),每个扇区 4K 个字节。EN25Q64 的最少擦除单位为一个扇区,也就是每次必须擦除 4K个字节。 EN25Q64 支持标准的 SPI,还支持双输出/四输出的 SPI,最大 SPI 时钟可以到 80Mhz(双输出时相

2、当于 160Mhz,四输出时相当于 320M),更多的 EN25Q64 的介绍,请参考 EN25Q64 的DATASHEET。 10.2 SPI简介 从上面的简介我们知道,EN25Q64是使用SPI来通信的。那什么是SPI呢? SPI 是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口,SPI接口主要用四根线进行通信: 1、MISO:主设备数据输入,从设备数据输出。 2、MOSI:主设备数据输出,从设备数据输入。 3、SCLK:时钟信号,由主设备产生。 4、CS:从设备片选信号,由主设备控制。 而通常意义上,SPI 的通信只用三根线就可以了,一

3、根时钟线、一根输出、一根输入。 为了更好理解SPI的传输原理,我们来看一下SPI的内部结构: 从图上可以有知道,SPI 数据的传输过程其实是通过一个移位寄存器来完成的,主机将自己的移位寄存器的数据移出,同时从机的移位寄存器数据移入,同时将自己的数据移出。简单的来理解,就像将两个寄存器贴在一起,然后进行循环左移或者循环右移(SPI的传输可以选择先发送高位还是先发送低位。),直到两个寄存器的数据交换为止。而时钟信号SCLK就是控制传输速率的。 STM32内部是给我们提供了一个SPI的外设的,那么我们就可以使用单片机的内部的SPI来控制EN25Q64了。 10.3 EN25Q64的原理图 从上面的原

4、理图,我们发现,其实EN25Q64是使用了STM32单片机的SPI2的接口(我们开发板上面使用的单片机是拥有两个 SPI 外设的。),而 EN25Q64的片选控制端使用的是PG13。 10.4 SPI库函数介绍 我们知道了 EN25Q64 的用途和通信方式,那么接下来我们就看下怎么对EN25Q64进行读写呢? 1、打开时钟使能。 我们要使用GPIOB、GPIOG和SPI所以要打开三个时钟。 代码为: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,

5、 ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); 2、配置GPIO口的模式。 这这里我们要打开GPIOG和GPIOB的时钟,然后将片选端PG13设置为推挽输出,然后设置SPI使用的GPIO口,将PB13、PB14和PB15设置为复用推挽输入。大家可能疑惑为什么 PB14 也设置为输出呢?它不是应该输入吗?在这里它是作为复用端口了,所以设置为复用推挽输出就是跟外设连接,要外设自己来决定输入输出了。 那么我们要使用的库函数大家都很熟悉了,就不详细介绍了。 代码为: /* flash_cs的IO口设置 PG13 */ GPI

6、O_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOG, /* SPI的IO口设置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init

7、Structure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, 3、设置SPI参数。 1) SPI_Init ()函数 这个函数可以用来初始化SPI外设。它有两个参数: 第一个参数:选择你要设置的 SPI,我们要使用 SPI2 所以设置为:SPI2。 第二个参数:传递一个结构体,用于设置 SPI 的参数。它一共有 9个成员: SPI_Direction:表示SPI的方向,我们要使用的是双线双向全双工,所以我们设置为:SPI_Direction_2Lines_FullDuplex。 SPI_Mode:表示SPI的模式,我们使用主机模式,所以设置

8、为:SPI_Mode_Master。 SPI_DataSize:表示传输数据的长度,我们使用8位数据传输,所以设置为:SPI_DataSize_8b。 SPI_CPOL:表示在空闲的时候时钟线是高电平还是低电平。我们选择高:SPI_CPOL_High。 SPI_CPHA:选择采样延迟。我们选择从第二个时钟开始采样,所以设置为:SPI_CPHA_2Edge。 SPI_NSS:表示是否用硬件控制片选端。我们的片选另外使用的PG13,所以不用。所以设置为软件控制:SPI_NSS_Soft。 SPI_BaudRatePrescaler:表示时钟波特率的分频,用来设置 SPI的速度。我们设置为256分频

9、:SPI_BaudRatePrescaler_256。 SPI_FirstBit:表示SPI的第一位,我们使用先发送高位,所以设置为:SPI_FirstBit_MSB。 SPI_CRCPolynomial:表示CRC效验的设置,我们使用7位CRC,所以设置为:7。 所以代码为: SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;/选择全双工SPI模式 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; /主机模式 SPI_InitStructure.SPI_DataSize

10、 = SPI_DataSize_8b; /8位SPI SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /时钟悬空高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; /在第二个时钟采集数据 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /Nss使用软件控制 /* 选择波特率预分频为256 */ SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_

11、FirstBit = SPI_FirstBit_MSB;/从最高位开始传输 SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, 2) 打开SPI的使能。 我们可以使用SPI_Cmd()函数。它有两个参数: 第一个参数选择要设置的SPI,我们选择SPI2。 第二个参数用来设置SPI的状态,我们选择ANABLE。 4、使用SPI读写。 从上面 SPI 的简介我们知道,SPI 发送的同时,也接收数据。所以我们使用SPI读写的时候,发送的同时也接收。 1) SPI_I2S_SendData()函数。 这个函数用来发送数据的,它有两个参数: 第

12、一个参数选择要使用的SPI,我们选择SPI2。 第二个参数用来传递我们要发送的8位数据。 2) SPI_I2S_GetFlagStatus()函数 这个函数用来检测SPI的状态,一般在发送和接收之前都要检测SPI的状态,发送时要检测 SPI的发送缓冲器是否为空,接收时检测接收缓冲器是否为非空。 这个函数有两个参数: 第一个参数选择要检测的SPI,我们选择SPI2。 第二个参数用来传递我们要检测的状态。检测发送缓冲器为空的时候设置为:SPI_I2S_FLAG_TXE;检测接收缓冲器是否为非空的时候设置为:SPI_I2S_FLAG_RXNE。 同时它返回一个状态值,状态出现返回:SET(非零);否

13、者返回:RESET(0)。 所以使用SPI读写我们可以写为: uint8_t SPI2_WriteReadData(uint8_t dat) uint16_t i = 0; /* 当发送缓冲器空 */ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) = RESET) i+; if(i 10000) eturn 0xFF; /* 发送数据 */ SPI_I2S_SendData(SPI2, dat); /* 等待接收缓冲器为非空 */ while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)

14、= RESET); /* 将读取到的数值返回 */ return SPI_I2S_ReceiveData(SPI2); 10.5 EN25Q64操作 我们在进行EN25Q64操作的时候,需要用到EN24Q64的命令。它的命令表如下: 1. EN25Q64读取ID操作 我们知道了,怎么跟 EN25Q64 通信之后,我们首先要对 EN25Q64 进行初始化,一般来说EN25Q64是不需要什么初始化的,不过我们为了确定芯片,我们先来读取一次芯片的ID。 从上面的命令表,我们知道读取芯片ID的命令是90H,命令发送的第1个字节是命令字节,然后第2、3、4字节是要么是伪字节要么是无用字节,在第 5 个字

15、节返回生产商 ID(即 M7-M0),第 6 个字节返回器件 ID(即ID7-ID0),我们使用的是EN25Q64,生产商ID是0x1C,器件ID是0x16,合起来的ID就是0x1C16读取芯片的操作步骤如下: 1) 把CS引脚拉低,选择片选。 2) 把指令90H发送到芯片。 3) 发送3个无用字节。 4) 读取生产商ID 5) 读取器件ID 6) 把CS引脚拉高,取消片选。 代码我们可以写为: uint16_t FLASH_ReadID(void) uint16_t id = 0; FLASH_CS_CLR; /打开片选 SPI2_WriteReadData(0x90);/发送读取ID命令

16、SPI2_WriteReadData(0x00); SPI2_WriteReadData(0x00); SPI2_WriteReadData(0x00); id |= SPI2_WriteReadData(0xFF) 0xEFFFFFFF) /等待超时 return 0xFF; FLASH_CS_CLR; /使能器件 SPI2_WriteReadData(EN25X_ReadStatusReg); /发送读取状态寄存器命令 statusValue = SPI2_WriteReadData(0xFF); /读取一个字节 FLASH_CS_SET; /取消片选 while(statusValue

17、/ 等待BUSY位清空 return 0; 2) 选择片选 3) 发送读取命令0x03 4) 发送三个字节的地址 5) 读取n个字节 6) 取消片选 程序实现如下: void FLASH_ReadData(uint8_t *readBuff, uint32_t readAddr, uint16_t readByteNum) SPI2_SetSpeed(SPI_BaudRatePrescaler_2); FLASH_CS_CLR; /打开片选 /* 写读取命令 */ SPI2_WriteReadData(EN25X_ReadData); /* 发送24位读取地址 */ SPI2_WriteRea

18、dData(readAddr 16); SPI2_WriteReadData(readAddr 8); SPI2_WriteReadData(readAddr); /* 读取数据 */ while(readByteNum-) *readBuff = SPI2_WriteReadData(0xFF); readBuff+; FLASH_CS_SET; /关闭片选 3. EN25Q64写入数据 对于EN25Q64的写入操作比较复杂,它只能页编辑,也就是必须一次性写入256个字节的数据,而且在进行页编辑的时候,必须保证写入区域位都为 1,就是说如果有数据必须要擦除掉,所以一般每次写入都要先擦除数据才

19、能写入。而写入数据的操作步骤为: 1) 注意要保证:要写入的区域,是空的,否则要先擦除。 2) 检测器件是否处于忙状态。 3) 开启写入使能。 在命令表中,写使能命令是0x06。每次执行编辑和擦除操作的时候,都需要器件开启写使能。开启的操作为: a) 选择片选 b) 写入一个字节的写使能命令0x06。 c) 取消片选 程序实现为: static void FLASH_WriteEnable(void) FLASH_CS_CLR; /使能器件 SPI2_WriteReadData(EN25X_WriteEnable); /发送写使能 FLASH_CS_SET; /取消片选 4) 选择片选 5)

20、发送1个字节的页编辑命令0x02。 6) 发送写入3个字节的写入地址。 7) 写入256个字节 8) 取消片选 例程中的程序实现如下: static void FLASH_WritePage(uint8_t *writeBuff, uint32_t writeAddr, uint16_t writeByteNum) uint16_t byteNum, i; byteNum = writeAddr % 256; byteNum = 256 - byteNum; /求出首页剩余地址 if(writeByteNum 16); /发送24位读取地址 SPI2_WriteReadData(writeAd

21、dr 8); SPI2_WriteReadData(writeAddr); for(i=0; i= 256) /如果剩余字节数大于256,那么一次写入一页 byteNum = 256; else /如果剩余字节数小于256,那么一次全部写完 byteNum = writeByteNum; 4. EN25Q64擦除操作 因为EN25Q64的写入的时候都要保证写入位置都没有数据,所以每次写入数据的时候,总会伴随着擦除操作。器件擦除命令有三种,第一种是“块擦除”,一次擦除64K字节数据,即256页。第二种是“扇区擦除”,一次擦除4K字节数据,即:16页。第三种是“芯片擦除”,一次性擦除整块芯片。我们

22、这里就讲述“扇区擦除”,其实擦除操作方式都差不多,操作步骤为: 1) 检测器件是否未处于忙状态 2) 开启写使能。 3) 选择片选。 4) 发送1个字节的“扇区擦除”命令。 5) 发送3个字节的扇区擦除地址。 6) 取消片选。 程序实现如下: static void FLASH_SectorErase(uint32_t eraseAddr) FLASH_CheckBusy(); /确定FLASH是否处于忙状态 FLASH_WriteEnable(); /开启写使能 FLASH_CS_CLR; /使能器件 SPI2_WriteReadData(EN25X_SectorErase); /发送命令

23、SPI2_WriteReadData(eraseAddr 16); /发送24位地址 SPI2_WriteReadData(eraseAddr 8); SPI2_WriteReadData(eraseAddr); FLASH_CS_SET; /取消片选 10.6 例程主函数 const u8 TEXT_Buffer19=“FLASH SPI TEST OK!“; #define SIZE (19-1) int main(void) uint8_t buffSIZE, showCharSIZE + 1, j, keyValue, ledState = 0; uint32_t i; /* 初始化

24、*/ TFT_Init(); KEY_Config(); FLASH_Init(); LED_Config(); /* 显示初始化 */ TFT_ClearScreen(BLACK); while(FLASH_ReadID() != EN25Q64) GUI_Show12Char(75, 0, “FLASH Init ERROR!“, RED, BLACK); TFT_ClearScreen(BLACK); GUI_Show12Char(75, 0, “FLASH Init OK! “, RED, BLACK); GUI_Show12Char(0, 32, “KEY_UP: write KEY

25、_DOWN:read“, RED, BLACK); while(1) keyValue = KEY_Scan(); /* 根据按键做出反应 */ switch(keyValue) case(KEY_UP): /按上键将“FLASH SPI test OK!“从FLASH地址0开始写入 FLASH_WriteData(u8*)TEXT_Buffer, 0, SIZE); GUI_Show12Char(0, 48, “wirte OK! “, RED, BLACK); break; case(KEY_DOWN): /按下键将从 FLASH 地址 0 开始读取 18位数,将读取到的显示 FLASH_ReadData(buff, 0, SIZE); for(j=0; j 0x5FFFF) i = 0; if(ledState = 0xFE) ledState = 0xFF; else ledState = 0xFE; LED_SetState(ledState); 程序效果是,按KEY_UP写入“FLASH SPI TEST OK!”到EN25Q64中,KEY_DOWN,读取写入的数据,并显示到LCD彩屏上面。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报