前提提要spi概念
目录
- stm32用spi开发W25Q128(Flash闪存芯片)
- W25Q128(Flash闪存芯片)介绍
- 内存分布
- 引脚说明
- 指令介绍
- (1) 写使能指令 0x06
- (2) 读状态寄存器 0x35
- (3) 写失能指令 0x04
- (4) 擦除扇区指令 0x20
- (5) 读取厂商和设备ID 0x90
- 代码
- W25Q128(Flash闪存芯片)介绍
stm32用spi开发W25Q128(Flash闪存芯片)
W25Q128(Flash闪存芯片)介绍
串行Flash芯片,型号是W25Q128,容量是128Mbit,该存储IC采用SPI接口进行通信。
* 可编程块>扇区>可编程页
* 1个扇区 == 16个可编程页== 4KB
* 1个可编程块 == 16个扇区==64KB
* 该存储IC由65536个可编程页组成,每个可编程页的大小是256字节,所以存储IC的容量是16MB
* 一次最多可以编程256字节
内存分布
1个可编程块是由16个可编程扇区组成
该存储IC一共有256个可编程块,一个可编程块是64KB
引脚说明
指令介绍
(1) 写使能指令 0x06
折叠重要但又不重要的图片
(2) 读状态寄存器 0x35
折叠重要但又不重要的图片
(3) 写失能指令 0x04
折叠重要但又不重要的图片
(4) 擦除扇区指令 0x20
折叠重要但又不重要的图片
(5) 读取厂商和设备ID 0x90
折叠重要但又不重要的图片
代码
点击查看代码
void W25Q128_Config(void)
{SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;//打开SPI1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//打开GPIOB端口的时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//选择IO口的复用功能GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1); //SCKGPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1); //MISOGPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1); //MOSIGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;GPIO_Init(GPIOB, &GPIO_InitStructure);//配置CS片选引脚 输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOB, &GPIO_InitStructure);//片选引脚,空闲状态为高电平W25Q128_CS(1);//配置SPI1 W25Q128存储IC支持模式0和模式3SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8bit数据位SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟极性 1SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //时钟相位 1 11 --模式3SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件控制CS片选 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //高位先出SPI_Init(SPI1, &SPI_InitStructure);//使能SPI1SPI_Cmd(SPI1, ENABLE);}//发送一个字节,并且会得到一个字节
uint8_t W25Q128_SendByte(uint8_t byte)
{/*!< Loop while DR register in not emplty */while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);/*!< Send byte through the SPI1 peripheral */SPI_I2S_SendData(SPI1, byte);/*!< Wait to receive a byte */while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);/*!< Return the byte read from the SPI bus */return SPI_I2S_ReceiveData(SPI1);
}//读取设备ID 0x17
uint8_t W25Q128_ReadDeviceID(void)
{uint8_t device_id = 0;//1.把片选引脚拉低W25Q128_CS(0);//2.MCU发送指令 0x90W25Q128_SendByte(0x90);//3.MCU发送地址W25Q128_SendByte(0x00);W25Q128_SendByte(0x00);W25Q128_SendByte(0x00);//4.MCU提供脉冲,得到厂商ID W25Q128_SendByte(0xFF);//5.MCU提供脉冲,得到设备IDdevice_id = W25Q128_SendByte(0xFF);//6.把片选引脚拉高W25Q128_CS(1);return device_id;
}int main()
{uint8_t buf[128] = {0};//1.硬件的初始化USART1_Config(9600);W25Q128_Config();//2.读取W25Q128的设备IDsprintf((char *)buf,"Device ID = %#X\r\n",W25Q128_ReadDeviceID());USART1_SendString((char *)buf);while(1){}
}
重要:模拟spi可以看上篇文章,主要是将端口初始化修改还有传输数据修改即可
** #define W25Q128_CS(n) (n) ? GPIO_SetBits(GPIOB,GPIO_Pin_14) : GPIO_ResetBits(GPIOB,GPIO_Pin_14) **
参考李明轩老师笔记