基于STM32实现W25Q16读写操作(spi)

这篇具有很好参考价值的文章主要介绍了基于STM32实现W25Q16读写操作(spi)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

在之前我们学习了flash闪存,这个更多的是内部数据存储,容量也是会比较小。这次我们来学习一下更多的存储单元w25q16,顺便了解spi———串行外围设备接口。

一、W25Q16

1.介绍

在我们的核心板子上基本都会有这么一块芯片,只是有的容量会计较大,大家可以查看板子的原理图,如图所示:
w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
有的板子可能是w25q32或者其他,后面的数字代表的是容量,用法都是一样的,从图中或者产品手册我们可以看到芯片是spi协议通信的。

2.SPI

2.1. 简介

串行外设接口 (SPI) 可与外部器件进行半双工/全双工的同步串行通信。该接口可配置为主模式,在这种情况下,它可为外部从器件提供通信时钟 (SCK)。该接口还能够在多主模式配置 下工作。

它可用于多种用途,包括基于双线的单工同步传输,其中一条可作为双向数据线,或使用CRC 校验实现可靠通信。

2.2. 特性

● 基于三条线的全双工同步传输
● 基于双线的单工同步传输,其中一条可作为双向数据线
● 8 位或 16 位传输帧格式选择
● 主模式或从模式操作
● 多主模式功能
● 8 个主模式波特率预分频器(最大值为 fPCLK/2)
● 从模式频率(最大值为 fPCLK/2)
● 对于主模式和从模式都可实现更快的通信
● 对于主模式和从模式都可通过硬件或软件进行 NSS 管理:动态切换主/从操作
● 可编程的时钟极性和相位
● 可编程的数据顺序,最先移位 MSB 或 LSB
● 可触发中断的专用发送和接收标志
● SPI 总线忙状态标志
● SPI TI 模式
● 用于确保可靠通信的硬件 CRC 功能:
— 在发送模式下可将 CRC 值作为最后一个字节发送
— 根据收到的最后一个字节自动进行 CRC 错误校验
● 可触发中断的主模式故障、上溢和 CRC 错误标志
● 具有 DMA 功能的 1 字节发送和接收缓冲器:发送和接收请求

2.3. 功能说明

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
通常,SPI 通过 4 个引脚与外部器件连接:

● MISO:主输入/从输出数据。此引脚可用于在从模式下发送数据和在主模式下接收数据。
● MOSI:主输出/从输入数据。此引脚可用于在主模式下发送数据和在从模式下接收数据。
● SCK:用于 SPI 主器件的串行时钟输出以及 SPI 从器件的串行时钟输入。
● NSS:从器件选择。这是用于选择从器件的可选引脚。

2.4. 工作模式

SPI总线有四种工作方式,其中使用的最为广泛的是模式0和模式3方式。

CPOL(Clock Polarity):时钟极性选择,为0时SPI总线空闲时,时钟线为低电平 ;为1时SPI总线空闲时,时钟线为高电平。

CPHA(Clock Phase):时钟相位选择,为0时在SCLK第一个跳变沿,主机对MISO引脚电平采样;为1时在SCLK第二个跳变沿,主机对MISO引脚电平采样。
w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网

2.5. 引脚说明

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网

二、代码开发

1.SPI初始化

在原理图中我们可以看到板子上直接是使用了PB3、4、5、14引脚,接下来我们进行初始化。

void w25qxx_init(void)
{
	//PB硬件时钟使能	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	
	//配置PB3 PB5 PB14为输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5|GPIO_Pin_14;		//第3 4 5根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;	//输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻

	GPIO_Init(GPIOB,&GPIO_InitStructure);	
	
	//看时序图,工作在模式3,时钟线引脚PB3,初始电平为高电平
	PBout(3)=1;
	
	//看时序图,片选引脚PB14,初始电平为高电平	
	PBout(14)=1;	
	
	
	//PB4配置输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;		//第4根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN;		//输入模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻
	GPIO_Init(GPIOB,&GPIO_InitStructure);		
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;						//主机模式
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;				//8位数据位
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;						//SPI FLASH可以设置为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;					//MISO在第二边沿采样数据
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;						//片选引脚由代码控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //clk=84MHZ/8=10.5MHz
	
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		//以最高有效位发送
	
	
	SPI_Init(SPI1, &SPI_InitStructure);
	
	SPI_Cmd(SPI1, ENABLE);
	
}

2.读取厂商ID

我们需要根据产品手册来进行这以操作,我们可以看到这样一张图(如下图),这可能看起来有点复杂,不知道从哪里下手,我们需要一点一点慢慢来。
w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
我们将上下两张图拼接起来,其实是一张图,如下图:

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
这里可以把它分为7各部分。

2.1.读写字节

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
这里我们使用的是模式3,从图中可以看出需要从高位先写入,每次8位,读取也是一样的。

uint8_t spi1_send_byte(uint8_t byte)
{
	
	int32_t i=0;
	uint8_t d=0;
	
	
	for(i=7; i>=0; i--)
	{
		//对byte每个bit进行判断
		if(byte & (1<<i))
		{
			//MOSI引脚输出高电平
			PBout(5)=1;
		}
		else
		{
		
			//MOSI引脚输出低电平
			PBout(5)=0;		
		
		}
		
		//时钟线输出低电平
		PBout(3)=0;
		
		//延时一会,MOSI引脚已经发送到对方
		delay_us(1);
		
	
		//时钟线输出高电平
		PBout(3)=1;
		
		//延时一会
		delay_us(1);	
	
		//读取MISO引脚电平
		if(PBin(4))
			d|=1<<i;
	
	}
	
	
	return d;
}

2.2.读取ID

按照时序图的说明我们编写出一下代码

void w25qxx_read_id(uint8_t *m_id,uint8_t *d_id)
{
	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x90);

	//发送24bit地址,该数值全为0
	spi1_send_byte(0x00);
	spi1_send_byte(0x00);
	spi1_send_byte(0x00);	
	
	//传递任意参数,读取厂商id
	*m_id=spi1_send_byte(0xFF);
	
	//传递任意参数,读取设备id
	*d_id=spi1_send_byte(0xFF);	
	
	//片选引脚输出高电平
	PBout(14)=1;	
}

3.其他的一些操作

w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网
在产品手册里有很多不同指令操作,这里不一一介绍,但是都和上面读取ID的操做差不多,如果有兴趣可以根据产品手册编写代码,下面会给出完整的代码,包括一些常见的操作。

4.完整代码

#include "stm32f4xx.h"
#include "sys.h"
#include <stdio.h>


static GPIO_InitTypeDef 		GPIO_InitStructure;
static NVIC_InitTypeDef 		NVIC_InitStructure;
static USART_InitTypeDef 		USART_InitStructure;
static SPI_InitTypeDef  		SPI_InitStructure;

#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f) {
	
	USART_SendData(USART1,ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	USART_ClearFlag(USART1,USART_FLAG_TXE);
	
	
	return ch;
}
void _sys_exit(int return_code) {

}

void delay_us(uint32_t n)
{
	SysTick->CTRL = 0; 			// Disable SysTick,关闭系统定时器
	SysTick->LOAD = (168*n)-1; // 配置计数值(168*n)-1 ~ 0
	SysTick->VAL  = 0; 		// Clear current value as well as count flag
	SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
	while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	SysTick->CTRL = 0; 		// Disable SysTick	
}

void delay_ms(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; 				// Disable SysTick,关闭系统定时器
		SysTick->LOAD = (168000)-1; 	// 配置计数值(168000)-1 ~ 0
		SysTick->VAL  = 0; 		// Clear current value as well as count flag
		SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; 		// Disable SysTick	

}

void usart1_init(uint32_t baud)
{
	
	//打开PA硬件时钟	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	

	//打开串口1硬件时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	//配置PA9和PA10为复用功能模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;		//第9 10根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF;	//多功能模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻

	GPIO_Init(GPIOA,&GPIO_InitStructure);


	//将PA9和PA10引脚连接到串口1的硬件
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);	
	
	
	
	//配置串口1相关参数:波特率、无校验位、8位数据位、1个停止位......
	USART_InitStructure.USART_BaudRate = baud;										//波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//8位数据位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							//1个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;								//无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					//允许收发数据
	USART_Init(USART1, &USART_InitStructure);
	
	
	//配置串口1的中断触发方法:接收一个字节触发中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	
	//配置串口1的中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	
	//使能串口1工作
	USART_Cmd(USART1, ENABLE);
}

void w25qxx_init(void)
{
	//PB硬件时钟使能	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	
	//配置PB3 PB5 PB14为输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5|GPIO_Pin_14;		//第3 4 5根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;	//输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻

	GPIO_Init(GPIOB,&GPIO_InitStructure);	
	
	//看时序图,工作在模式3,时钟线引脚PB3,初始电平为高电平
	PBout(3)=1;
	
	//看时序图,片选引脚PB14,初始电平为高电平	
	PBout(14)=1;	
	
	
	//PB4配置输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;		//第4根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN;		//输入模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻
	GPIO_Init(GPIOB,&GPIO_InitStructure);		
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;						//主机模式
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;				//8位数据位
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;						//SPI FLASH可以设置为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;					//MISO在第二边沿采样数据
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;						//片选引脚由代码控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //clk=84MHZ/8=10.5MHz
	
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		//以最高有效位发送
	
	
	SPI_Init(SPI1, &SPI_InitStructure);
	
	SPI_Cmd(SPI1, ENABLE);
	
}


uint8_t spi1_send_byte(uint8_t byte)
{
	
	int32_t i=0;
	uint8_t d=0;
	
	
	for(i=7; i>=0; i--)
	{
		//对byte每个bit进行判断
		if(byte & (1<<i))
		{
			//MOSI引脚输出高电平
			PBout(5)=1;
		}
		else
		{
		
			//MOSI引脚输出低电平
			PBout(5)=0;		
		
		}
		
		//时钟线输出低电平
		PBout(3)=0;
		
		//延时一会,MOSI引脚已经发送到对方
		delay_us(1);
		
	
		//时钟线输出高电平
		PBout(3)=1;
		
		//延时一会
		delay_us(1);	
	
		//读取MISO引脚电平
		if(PBin(4))
			d|=1<<i;
	
	}
	
	
	return d;
}



//读取w25qxxState Regist(状态寄存器)值
uint8_t w25qxx_read_SR()
{
	uint8_t RS1 = 0;


	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x05);
	
	//接收指定字节数据
	RS1=spi1_send_byte(0xFF);

	//片选引脚输出高电平
	PBout(14)=1;
	
	return RS1;
}



//w25qxx读取数据
void w25qxx_read_data(uint8_t *data,uint32_t dataaddr,uint32_t size)
{
	int8_t i=0;
	
	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x03);

	//发送24bit地址,该数值全为0
	//例如发送地址:0x123456
	spi1_send_byte((uint8_t)(dataaddr>>16));
	spi1_send_byte((uint8_t)(dataaddr>>8));
	spi1_send_byte((uint8_t)dataaddr);	
	
	
	//接收指定字节数据
	for(i=0;i<size;i++)
		//传递任意参数,读取数据
		data[i]=spi1_send_byte(0xFF);
	
	
	//片选引脚输出高电平
	PBout(14)=1;	
}

//w25qxx写使能
void w25qxx_write_enable()
{
	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x06);
	

	//片选引脚输出高电平
	PBout(14)=1;
		
}

//w25qxx写使不能
void w25qxx_write_disable()
{
	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x04);
	

	//片选引脚输出高电平
	PBout(14)=1;


}


//扇区擦除
void w25qxx_erase_sector(uint32_t sectoraddr)
{

	w25qxx_write_enable();
	
	PBout(14) = 0;
	
	//等待BUSY位清空
	//while(w25qxx_read_SR()&0x01 == 0x01);
	
	//发送扇区擦除命令
	spi1_send_byte(0x20);

	//发送24bit地址,该数值全为0
	spi1_send_byte((uint8_t)(sectoraddr>>16));
	spi1_send_byte((uint8_t)(sectoraddr>>8));
	spi1_send_byte((uint8_t)sectoraddr);


	PBout(14) = 1;	
	
	//等待BUSY位清空
	while(w25qxx_read_SR()&0x01 == 0x01);
	


}


void w25qxx_page_write(uint8_t *data,uint32_t dataaddr,uint16_t size)
{
	uint16_t i=0;
	
	//写使能
	w25qxx_write_enable();
	
	PBout(14) = 0;
	
	//发送页存储指令
	spi1_send_byte(0x02);
	
	//发送存储地址
	spi1_send_byte((uint8_t)(dataaddr>>16));
	spi1_send_byte((uint8_t)(dataaddr>>8));
	spi1_send_byte(dataaddr);
	
	//循环发送数据
	for(i=0;i<size;i++)
		spi1_send_byte(data[i]);
	

	PBout(14) = 1;
	
	//等待BUSY位清空
	while(w25qxx_read_SR()&0x01 == 0x01);	
	
	//添加写保护
	w25qxx_write_disable();
	
}

void w25qxx_read_id(uint8_t *m_id,uint8_t *d_id)
{
	//片选引脚输出低电平
	PBout(14)=0;

	//发送90h命令
	spi1_send_byte(0x90);

	//发送24bit地址,该数值全为0
	spi1_send_byte(0x00);
	spi1_send_byte(0x00);
	spi1_send_byte(0x00);	
	
	//传递任意参数,读取厂商id
	*m_id=spi1_send_byte(0xFF);
	
	//传递任意参数,读取设备id
	*d_id=spi1_send_byte(0xFF);	
	
	//片选引脚输出高电平
	PBout(14)=1;	
}


int main(void)
{
	int32_t i=0;
	uint8_t m_id,d_id;
	uint8_t data[256] = {0};
	
	//使能(打开)端口F的硬件时钟,就是对端口F供电
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	//串口1波特率:115200bps
	usart1_init(115200);	

	//初始化GPIO引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;		//第9根引脚
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT;	//输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//推挽输出,增加输出电流能力。
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//没有使能上下拉电阻

	GPIO_Init(GPIOF,&GPIO_InitStructure);
	
	PFout(9)=1;
	
	//初始化SPI1连接的w25qxx
	w25qxx_init();
	w25qxx_read_id(&m_id,&d_id);
	
	
	printf("m_id=%x,d_id=%x\r\n",m_id,d_id);
	
	printf("read data at addr 0:\r\n");
	w25qxx_read_data(data,0,64);
	for(i=0;i<64;i++)
		printf("%02X ",data[i]);
	
	//扇区擦除
	printf("\r\nerase sector 0:\r\n");	
	w25qxx_erase_sector(0);
	
	printf("read data at addr 0:\r\n");	
	w25qxx_read_data(data,0,64);
	for(i=0;i<64;i++)
		printf("%02X ",data[i]);
	
	
	
	//页写入
	printf("write data at addr 0:\r\n");		
	for(i=0;i<256;i++)
		data[i]=0x88;
	w25qxx_page_write(data,0,256);
	
	
	printf("read data at addr 0:\r\n");	
	w25qxx_read_data(data,0,256);
	for(i=0;i<256;i++)
		printf("%02X ",data[i]);
		
	
	

		
	printf("\r\n");
	
	while(1)
	{
		
		
	}
}



void USART1_IRQHandler(void)
{
	uint8_t d;
	
	//检测标志位
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
	{
		//接收数据
		d=USART_ReceiveData(USART1);
		
		
	
		//清空标志位
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}

}

三、效果演示

这里还是使用串口来调试看我们做出来的效果,如下图所示:
w25q16,STM32F4开发学习,stm32,单片机,嵌入式硬件,arm,物联网文章来源地址https://www.toymoban.com/news/detail-803607.html

到了这里,关于基于STM32实现W25Q16读写操作(spi)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32(SPI读写W25Q18)

    SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种 高速的,全双工,同步 的通信总 线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提 供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 A

    2024年02月16日
    浏览(54)
  • STM32驱动W25Q64读写数据

    1.采用串行Nor flash外扩存储芯片 2.支持SPI接口 3.工作电压:2.7~3.6V 4.容量: 32Mbit(W25Q32) 64Mbit(W25Q64) 128Mbit(W25Q128) 此处使用硬件SPI 引脚 功能 CS(NSS) 片选,低电平有效 SCK 时钟信号引脚 MISO/DO 模块数据输出引脚 MOSI/DI 模块数据输入引脚 W25Q64模块 STM32F103C8T6 VCC 3.3V SPI_CS GPIO

    2023年04月08日
    浏览(47)
  • 2023版 STM32实战11 SPI总线读写W25Q

    英文全称:Serial peripheral Interface 串行外设接口 -1- 串行(逐bit传输) -2- 同步(共用时钟线) -3- 全双工(收发可同时进行) -4- 通信只能由主机发起(一主,多从机) -1- CS片选一般配置为软件控制 -2- 片选低电平有效,从器件CS引脚可直接连接GND -3- 从机不能主动给主机发数据 -4- 主机想要

    2024年02月08日
    浏览(35)
  • 【STM32】软件SPI读写W25Q64芯片

    目录 W25Q64模块 W25Q64芯片简介 硬件电路 W25Q64框图 Flash操作注意事项 状态寄存器 ​编辑 指令集 INSTRUCTIONS​编辑 ​编辑 SPI读写W25Q64代码 硬件接线图 MySPI.c MySPI.h W25Q64 W25Q64.c W25Q64.h W25Q64_Ins.h main.c 测试 SPI通信(W25Q64芯片简介,使用SPI读写W25Q64存储器芯片)  SPI通信文章:【

    2024年02月19日
    浏览(43)
  • 【STM32】STM32学习笔记-软件SPI读写W25Q64(38)

    在大容量产品和互联型产品上,SPI接口可以配置为支持SPI协议或者支持I 2 S音频协议。SPI接口默认工作在SPI方式,可以通过软件把功能从SPI模式切换到I2S模式。 在小容量和中容量产品上,不支持I 2 S音频协议。 串行外设接口(SPI)允许芯片与外部设备以半/全双工、同步、串行方

    2024年01月24日
    浏览(46)
  • 【STM32】STM32学习笔记-硬件SPI读写W25Q64(40)

    在大容量产品和互联型产品上,SPI接口可以配置为支持SPI协议或者支持I2S音频协议。SPI接口默认工作在SPI方式,可以通过软件把功能从SPI模式切换到I2S模式。 在小容量和中容量产品上,不支持I2S音频协议。 串行外设接口(SPI)允许芯片与外部设备以半/全双工、同步、串行方式

    2024年02月19日
    浏览(68)
  • STM32-SPI通信(W25Q64芯片简介,使用SPI读写W25Q64存储器芯片)

    ​  SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)。 ​SPI通信具有以下特点: 同步,全双工; 支持总线挂载多设备(SPI仅支持一主多从); 在不

    2024年02月08日
    浏览(44)
  • 【STM32】SPI初步使用 读写FLASH W25Q64

    (1) SS( Slave Select):从设备选择信号线,常称为片选信号线,每个从设备都有独立的这一条 NSS 信号线,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI通讯。所以 SPI通讯以 NSS 线置低电

    2024年02月10日
    浏览(52)
  • STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 使用FatFs中间件通过SPI通信协议对W25Q128芯片进行读写等操作 关于STM32F407使用SPI通信协议对W25Q128 FLASH芯片读写

    2024年02月19日
    浏览(52)
  • STM32—SPI详解入门(使用SPI通讯读写W25Q128模块)

    目录 一、SPI是什么 二、SPI物理架构 三、SPI工作原理 四、SPI工作模式 五、SPI相关寄存器介绍 六、SPI用到的结构体与函数 1.结构体 2.函数 七、W25Q128芯片 1.W25Q128介绍 2.W25Q128存储架构 3.W25Q128常用指令 4.W25Q128状态寄存器 5.W25Q128常见操作流程 八、实验(使用SPI通讯读写W25Q128模块

    2024年02月14日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包