您的位置:首页 > 新闻 > 热点要闻 > app定制公司靠谱吗_电子商务网络营销方式有哪些_刷关键词的平台_品牌软文营销案例

app定制公司靠谱吗_电子商务网络营销方式有哪些_刷关键词的平台_品牌软文营销案例

2025/2/24 18:15:14 来源:https://blog.csdn.net/2301_80127410/article/details/145664108  浏览:    关键词:app定制公司靠谱吗_电子商务网络营销方式有哪些_刷关键词的平台_品牌软文营销案例
app定制公司靠谱吗_电子商务网络营销方式有哪些_刷关键词的平台_品牌软文营销案例

常用 STM32 存储器芯片介绍和应用

STM32 微控制器通常与多种存储器芯片一起工作,以下是几种常见的存储器类型及其应用:

1. 闪存(Flash Memory)

STM32 内部的 闪存 是一种非易失性存储器,广泛用于存储程序代码和常驻数据。

  • 存储特性
    • 具有快速读取速度和较长的寿命(一般可以写入数千到数百万次)。
    • 需要通过 编程操作 将数据写入闪存,通常使用 EEPROM 模拟 技术进行写入。
  • 应用
    • 程序存储:程序代码一般存储在闪存中,STM32 会在复位后从闪存中加载代码。
    • 数据存储:用于存储一些不常更改的数据,如设备的配置信息。

2. SRAM(静态随机存取存储器)

SRAM 是一种内部的存储器,具有更快的访问速度,但需要不断供电,属于易失性存储器。

  • 存储特性
    • 读取速度非常快,并且可以随时写入。
    • 不像闪存那样需要特殊的编程方式,直接写入即可。
  • 应用
    • 数据缓存:通常用于存储临时数据,如计算过程中的中间结果。
    • 堆栈空间:作为栈存储器,处理程序的堆栈和局部变量。
    • DMA(直接内存访问):用于数据传输时作为数据缓冲区。

3. EEPROM(电可擦可编程只读存储器)

STM32 支持通过模拟使用 内部 EEPROM 或外部 EEPROM 存储数据。EEPROM 是一种 非易失性存储器,允许对单个字节进行多次读写操作。

  • 存储特性

    • 适合存储少量的数据。
    • 写入操作较慢,写入次数有限。
  • 应用

    • 配置数据存储:用于存储用户配置、校准数据或偏好设置。
    • 存储日志信息:可用于存储事件日志或传感器数据。

4. 外部存储器(如 SPI Flash, NAND Flash)

在 STM32 系列中,外部存储器通常通过 SPI 或 QSPI 接口 与微控制器连接,广泛用于扩展存储空间。

  • SPI Flash

    • 存储器通过 SPI 接口与 STM32 连接,支持快速读取数据。
    • 主要用于存储大量数据,如应用程序、文件系统等。
  • NAND Flash

    • 用于存储大量的程序和数据,通常用于较大容量存储要求的场景。
    • 常与文件系统(如 FAT 文件系统)配合使用,适用于存储图像、日志、音频等大数据。
  • 应用

    • 固件存储:用于存储操作系统或应用程序的固件。
    • 数据记录:在嵌入式系统中,使用外部存储器存储大数据量,例如传感器数据。

5. SD 卡

STM32 还可以通过 SDIO 接口 与外部 SD 卡 连接,这是一种 大容量存储 设备,广泛用于数据存储和文件系统。

  • 存储特性

    • 支持 FAT32 文件系统,适合存储各种类型的文件。
    • 提供 较高的数据读取速度大容量(如 4GB、32GB 等)。
  • 应用

    • 数据日志记录:如环境监测设备记录温湿度数据。
    • 音频和视频存储:用于存储音频、视频等大数据量文件。

6. 外部 SRAM / DRAM

在一些高级应用中,STM32 也可以连接外部 SRAMDRAM 存储器来提供更大的数据存储空间。

  • 存储特性

    • 外部 SRAM 通常连接到 FSMC(外部存储器控制器),以扩展系统内存。
    • 外部 DRAM 提供更高的存储容量,适用于大数据缓存和视频处理。
  • 应用

    • 大数据缓存:用于高速缓存处理大数据或复杂计算。
    • 图形存储:用于显示处理和图形存储,尤其在显示应用中
    • AT24C02 存储器介绍

    • AT24C02Atmel(现为 Microchip) 生产的一款 2Kbit EEPROM 存储器芯片。它基于 I2C 总线协议,适用于需要小容量存储的嵌入式应用中。

      主要特点:
    • 存储容量:2Kbit,等于 256 字节,可以分为 32 页,每页 8 字节
    • I2C 接口:使用 I2C 总线 进行数据读写,支持 快速模式(400 kHz)标准模式(100 kHz)
    • 写保护:可以通过硬件引脚进行写保护,防止不小心擦写重要数据。
    • 电源电压:一般工作电压为 2.7V 到 5.5V,适配不同的系统需求。
    • 写入时间:一次写入操作通常需要 5ms,读取速度较快。
    • 引脚定义:
    • VCC:电源引脚,通常为 3.3V 或 5V。
    • GND:地引脚。
    • SDA:数据线,I2C 总线的数据传输线。
    • SCL:时钟线,I2C 总线的时钟信号线。
    • WP(写保护):硬件写保护引脚,可用于防止写操作。
    • 工作原理:
    • 写操作

      • 通过 I2C 总线的 发送地址写数据 来向存储器中写入数据。
      • 每个写操作都有一个 字节地址,每次写操作可以写入 1 到 8 字节,这由 页(page) 决定。
    • 读操作

      • 通过发送 设备地址字节地址,然后读取从存储器返回的数据。
      • 读取操作是 顺序读取 的,可以根据需要读取多个字节。
    • AT24C02 常见应用:
    • 存储配置数据:用于存储设备的配置信息、校准数据等。
    • 设备序列号存储:用于嵌入式设备中存储唯一的序列号或标识符。
    • 小型数据记录器:如传感器数据记录和日志存储。
    • MCU 存储扩展:在存储空间有限的情况下,为微控制器提供额外的存储空间。
    • AT24C02 的 I2C 使用示例:
      #include "stm32f10x.h"#define AT24C02_I2C_ADDRESS 0xA0  // AT24C02 的 I2C 地址void I2C_Init(void) {// 配置 I2C 外设
      }void AT24C02_Write(uint8_t address, uint8_t data) {// 向 AT24C02 写入一个字节的数据I2C_Start();  // 启动 I2CI2C_Write(AT24C02_I2C_ADDRESS);  // 发送设备地址I2C_Write(address);  // 发送写地址I2C_Write(data);  // 写入数据I2C_Stop();  // 停止 I2C
      }uint8_t AT24C02_Read(uint8_t address) {// 从 AT24C02 读取一个字节的数据uint8_t data;I2C_Start();  // 启动 I2CI2C_Write(AT24C02_I2C_ADDRESS);  // 发送设备地址I2C_Write(address);  // 发送读取地址I2C_Start();  // 重启 I2CI2C_Write(AT24C02_I2C_ADDRESS | 0x01);  // 发送读取地址data = I2C_Read_Nack();  // 读取数据I2C_Stop();  // 停止 I2Creturn data;
      }int main(void) {// 初始化 I2CI2C_Init();// 写入数据AT24C02_Write(0x00, 0x55);  // 向 AT24C02 地址 0x00 写入数据 0x55// 读取数据uint8_t data = AT24C02_Read(0x00);  // 从 AT24C02 地址 0x00 读取数据
      }
      

      总结

    • AT24C02 是一种非常适合低容量存储需求的 EEPROM 存储器,特别适用于通过 I2C 总线 与微控制器进行通信的场景。
    • 它的应用非常广泛,尤其是在需要存储少量非易失性数据的嵌入式系统中,如配置信息、序列号等。

项目:

利用IIC通信对AT24C02芯片进行数据写入,同时读取数据通过串口显示在上位机上面

代码介绍:

#include "stm32f10x.h"                  // Device header
#include   "iic.h"
void iic_GPIO_Config()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );GPIO_InitTypeDef  iic_GPIO_Initsturt;//配置SDA数据线iic_GPIO_Initsturt.GPIO_Mode =  GPIO_Mode_AF_OD ;iic_GPIO_Initsturt.GPIO_Pin =SCL_PIN;   //PB7iic_GPIO_Initsturt.GPIO_Speed =GPIO_Speed_50MHz;GPIO_Init(IIC_PORT  , &iic_GPIO_Initsturt);//配置SCL时钟线iic_GPIO_Initsturt.GPIO_Mode = GPIO_Mode_AF_OD ;iic_GPIO_Initsturt.GPIO_Pin =SDA_PIN;    //PB6iic_GPIO_Initsturt.GPIO_Speed =GPIO_Speed_50MHz;GPIO_Init(IIC_PORT , &iic_GPIO_Initsturt);}void iic_Init_Config()
{//初始化iic的时钟,配置IIC1的结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);I2C_InitTypeDef  iic_initsturt;iic_initsturt.I2C_Ack =I2C_Ack_Enable;iic_initsturt.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit; //配置七位寻从机址 ;iic_initsturt.I2C_ClockSpeed =IIC_Speed ;//速度设置为最大40kbpsiic_initsturt.I2C_DutyCycle =I2C_DutyCycle_2;iic_initsturt.I2C_Mode =I2C_Mode_I2C;iic_initsturt.I2C_OwnAddress1 =OwnAddress;//设置主机地址为0I2C_Init( I2C1, &iic_initsturt);I2C_Cmd( I2C1, ENABLE );}//配置printf函数的usart串口通信
void  usart_GPIO_Config()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );GPIO_InitTypeDef   usart_GPIO_Initurt;//配置usart的TX通信引脚usart_GPIO_Initurt.GPIO_Mode =  GPIO_Mode_AF_PP;usart_GPIO_Initurt.GPIO_Pin =usart_TXpin;  usart_GPIO_Initurt.GPIO_Speed =GPIO_Speed_50MHz;	//PA9       GPIO_Init(USART_PORT  , &	usart_GPIO_Initurt);//配置usart的RX通信引脚usart_GPIO_Initurt.GPIO_Mode =   GPIO_Mode_IN_FLOATING;usart_GPIO_Initurt.GPIO_Pin =usart_RXpin;       //PA10          GPIO_Init(USART_PORT  , &	usart_GPIO_Initurt);}
//配置usart通信结构体USART1,为printf函数做准备
void  usart_Config()
{RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE );USART_InitTypeDef usart_Initsturt;usart_Initsturt.USART_BaudRate =9600;usart_Initsturt.USART_HardwareFlowControl =USART_HardwareFlowControl_None ;   usart_Initsturt.USART_Mode =USART_Mode_Rx |USART_Mode_Tx ; usart_Initsturt.USART_Parity = USART_Parity_No;  usart_Initsturt.USART_StopBits =USART_StopBits_1  ;usart_Initsturt.USART_WordLength =USART_WordLength_8b  ;USART_Init(USART1 , &usart_Initsturt);USART_Cmd(USART1 , ENABLE );
}
//重定向printf函数,使用fputc找到串口
int fputc(int ch,FILE *f)
{USART_SendData(USART1,(uint8_t)ch);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==RESET);return ch;
}//重定向scanf函数,使用fgetc找到串口
int fgetc(FILE *f)
{while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==RESET); return (int) USART_ReceiveData(USART1 );}
//配置一个超时反馈函数用于反馈信号
static  uint32_t  iic_timeout_usercallback(uint8_t errocode)
{printf("IIC等待超时!errocode=%d",errocode);return 0;}
//进行iic通信发送数据uint32_t iic_WriteData(uint8_t buff, uint8_t WriteAddr)
{//产生起始信号I2C_GenerateSTART(I2C1, ENABLE);//设置等待时间uint32_t  iictimer= TIMEOUT_flag;//检测EV5事件while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT )==RESET ){if((iictimer--)==0){return  iic_timeout_usercallback(0);}}//发送地址进行寻址I2C_Send7bitAddress(I2C1,  EEPROM_ADDREE  ,  I2C_Direction_Transmitter);//检测EV6事件iictimer= TIMEOUT_flag;while(I2C_CheckEvent(I2C1,	I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==RESET ){if((iictimer--)==0){return  iic_timeout_usercallback(0);}}
//发送数据可以寻内部地址,也可进行数据操作
I2C_SendData(I2C1,WriteAddr);//检测EV8事件iictimer= TIMEOUT_flag;
while(I2C_CheckEvent(I2C1,	 I2C_EVENT_MASTER_BYTE_TRANSMITTING  )==RESET )
{if((iictimer--)==0){return  iic_timeout_usercallback(0);}}
//发送要写入的数据
I2C_SendData(I2C1,buff);
//检测EV8事件iictimer= TIMEOUT_flag;
while(I2C_CheckEvent(I2C1,	 I2C_EVENT_MASTER_BYTE_TRANSMITTING  )==RESET )
{if((iictimer--)==0){return  iic_timeout_usercallback(0);}
}I2C_GenerateSTOP(I2C1, ENABLE);
return 1;
}
//对ATC02进行读数据
//第一次产生起始信号,对读的地址进行写操作uint32_t iic_ReadData(uint8_t ADDress, uint8_t *Data,uint8_t number )
{I2C_GenerateSTART(I2C1, ENABLE);uint32_t  iictimer= TIMEOUT_flag;while(I2C_CheckEvent( I2C1,I2C_EVENT_MASTER_MODE_SELECT )==RESET ){if((iictimer--)==0){iic_timeout_usercallback(0);}}I2C_Send7bitAddress(I2C1,EEPROM_ADDREE , I2C_Direction_Transmitter);iictimer= TIMEOUT_flag;while(I2C_CheckEvent( I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )==RESET){if((iictimer--)==0){iic_timeout_usercallback(0);}}I2C_SendData(I2C1,ADDress);iictimer= TIMEOUT_flag;while(I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING )==RESET){if((iictimer--)==0){iic_timeout_usercallback(0);}}//第二次产生起始信号进行读数据操作I2C_GenerateSTART(I2C1, ENABLE);iictimer= TIMEOUT_flag;while(I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT  )==RESET){if((iictimer--)==0){iic_timeout_usercallback(0);}}I2C_Send7bitAddress(I2C1, EEPROM_ADDREE, I2C_Direction_Receiver);iictimer= TIMEOUT_flag;while(I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED   )==RESET){if((iictimer--)==0){iic_timeout_usercallback(0);}}while(number--){*Data= I2C_ReceiveData(I2C1);Data++;   }I2C_GenerateSTOP( I2C1, ENABLE );return 1;
}

这里初始化了usart同时重定向了输入输出函数(scanf,printf)便于打印在上位机,同时对对寻址,读写输入以及起始终止信号进行了时间限制,若运行超时则反馈失败信号在上位机,寻址地址选择的是0xA0写入地址是0x11

#include "main.h"
#include "stm32f10x.h"                  // Device header
#include   "led.h"
#include    "Delay.h"
#include  "iic.h"
#include "pwm.h"
#include  "pwmplus.h"
uint8_t data[10];extern TIM_ICUserValue   TIM_CaptureSturt;
int  main()
{iic_GPIO_Config();iic_Init_Config(); printf("这是一个iic通信实验");iic_WriteData(2, 11);delay_ms(100);iic_ReadData(11, data,1);delay_ms(100);printf("%d",data[0]);

W25Q 系列芯片介绍

W25Q 系列芯片Winbond 生产的 SPI 接口 Flash 存储器,广泛应用于嵌入式系统、物联网设备、计算机外设等领域。该系列芯片具有较高的读写速度,较低的功耗,并且支持 标准 SPI、双 SPI 和四 SPI 模式,可以为不同应用提供灵活的存储解决方案。

W25Q 系列的主要特点
  • 存储容量:从 1 Mbit128 Mbit 不等,适用于不同的应用需求。
  • 接口类型:支持 SPI 接口,包括标准 SPI、双 SPI 和四 SPI 模式,可以提供更高的数据传输速率。
  • 工作电压:大多数 W25Q 系列 芯片支持 2.7V 至 3.6V 的电压范围。
  • 数据传输速度:支持高速数据传输,某些版本可以达到 104 MHz 的 SPI 时钟速率。
  • 工作温度范围:-40°C 至 85°C,适合工业环境和消费类电子设备。
  • 擦写周期:大多数芯片提供 100 万次擦写周期,适用于频繁数据写入的应用。
W25Q 系列芯片的常见型号
  • W25Q80:8 Mbit (1MB) 存储,适用于较小存储需求的嵌入式系统。
  • W25Q64:64 Mbit (8MB) 存储,常用于较大数据存储和图像存储应用。
  • W25Q128:128 Mbit (16MB) 存储,适用于需要更大存储的应用场景,如图像显示、固件存储等。
主要功能和命令
  • 读取命令
    • 0x03:读取数据命令,适用于从 Flash 中读取数据。
    • 0x0B:高速读取命令,支持更高的读取速度。
    • 0x02:页写命令,写入数据到指定页。
  • 擦除命令
    • 0xC7:全片擦除命令,擦除整个存储器。
    • 0x20:扇区擦除,擦除一个 64 KB 的扇区。
    • 0xD8:块擦除,擦除一个 32 KB 的块。
  • 写入命令
    • 0x06:写使能命令,使能写操作。
    • 0x02:页面写命令,写入数据到指定地址。
W25Q 系列的应用场景
  1. 嵌入式系统:广泛应用于微控制器、单片机、FPGA 等设备中,用于存储程序、配置数据、校准数据等。
  2. 图像存储:在需要存储大尺寸图像的设备中,W25Q64 和 W25Q128 等高容量型号非常适合存储图像数据。
  3. 物联网设备:用于存储传感器数据、配置文件、固件升级包等。
  4. 音频播放设备:如 MP3 播放器、音响系统等,通过 Flash 存储音频文件。
如何使用 W25Q 系列芯片

使用 W25Q 系列芯片,通常需要通过 SPI 接口 进行数据的读写操作。STM32 微控制器等设备通过 SPI 与 W25Q 芯片连接,可以执行以下基本操作:

  1. 初始化 SPI:配置 SPI 接口,设置合适的时序和速度。
  2. 发送命令:通过 SPI 发送控制命令(如读取、写入、擦除命令)。
  3. 数据传输:通过 SPI 发送或接收数据,以实现 Flash 存储器的数据读写。
  4. 擦除和写入:通过特定命令擦除存储区域,并使用页写命令写入数据。
这里w25Q64芯片进行讲解:

W25Q64 是 Winbond 公司生产的一款 串行 Flash 存储器,它属于 W25Q 系列,主要应用于需要高密度存储并且对速度要求较高的嵌入式系统中。它通过 SPI 接口(Serial Peripheral Interface)与微控制器或其他主机设备进行通信。

W25Q64 的主要特性

  1. 存储容量:64 Mbit (8 MB)
  2. 接口类型:SPI(支持标准 SPI、双 SPI 和四 SPI 模式)
  3. 工作电压:2.7V 至 3.6V
  4. 速度
    • 支持最高 104 MHzSPI 时钟速率
    • 支持 数据传输速率
  5. 工作温度范围:-40°C 至 85°C
  6. 存储类型
    • 单一芯片存储,不依赖复杂的外部存储器控制器。
    • 提供 扇区擦除页编程读取 等基本功能。
  7. 数据擦除与写入
    • 提供 扇区擦除(64 KB)块擦除(32 KB) 以及 页写入(256 字节) 等操作。
    • 支持 写保护,可以通过软件控制来限制特定区域的写入。
  8. 特殊功能
    • 四 SPI 模式(高速模式)提供更高的速度。
    • 支持 写保护功能,可以保护数据免受意外写入或修改。

W25Q64 的引脚定义

W25Q64 通过 SPI 接口与主设备进行通信。它的常见引脚包括:

  • CS (Chip Select):选择芯片进行操作,低电平时有效。
  • MISO (Master In Slave Out):主机输入从机输出数据线。
  • MOSI (Master Out Slave In):主机输出从机输入数据线。
  • SCK (Serial Clock):时钟信号,用于同步数据传输。
  • WP (Write Protect):写保护引脚,通常接地以启用写操作。
  • HOLD (Hold):暂停 SPI 总线操作,通常接地。

常用命令

W25Q64 芯片通过 SPI 接口发送命令来进行各种操作。以下是一些常用的命令:

  1. 读取数据命令

    • 0x03:读取数据。
    • 0x0B:高速读取。
    • 0x02:页写命令,写入数据到指定地址。
  2. 写入命令

    • 0x06:写使能,允许进行数据写入操作。
    • 0x02:页面写入命令,支持写入 256 字节数据。
  3. 擦除命令

    • 0xC7:全片擦除。
    • 0x20:扇区擦除,擦除 64 KB 的数据块。
    • 0xD8:块擦除,擦除 32 KB 的数据块。
  4. 其他命令

    • 0x05:读取状态寄存器。
    • 0x35:读取扩展状态寄存器。

如何使用 W25Q64

W25Q64 通常通过 SPI 与 STM32 或其他微控制器进行通信。以下是使用 STM32 微控制器与 W25Q64 进行基本通信的步骤:

  1. 配置 SPI 接口: 使用 STM32 的 SPI 外设来与 W25Q64 进行通信,首先需要配置 SPI 接口。假设我们使用 SPI1,需要配置 MOSIMISOSCKCS 引脚。
void SPI_Config(void) {SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;// 使能 SPI 和 GPIO 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置 SPI 引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  // SCK, MISO, MOSIGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 SPI1SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);
}
  1. 发送命令和数据: 要向 W25Q64 发送命令,首先使能写操作,然后通过 SPI 发送命令和数据。
// 发送命令
void W25Q64_SendCommand(uint8_t command) {GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // 选择 W25Q64 (CS 低电平)SPI_I2S_SendData(SPI1, command);  // 发送命令while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));  // 等待 SPI 完成GPIO_SetBits(GPIOA, GPIO_Pin_4);  // 取消选择 W25Q64 (CS 高电平)
}// 发送数据
void W25Q64_SendData(uint8_t data) {GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // 选择 W25Q64 (CS 低电平)SPI_I2S_SendData(SPI1, data);  // 发送数据while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));  // 等待 SPI 完成GPIO_SetBits(GPIOA, GPIO_Pin_4);  // 取消选择 W25Q64 (CS 高电平)
}
  1. 读取数据: 读取数据时,首先发送读取命令,然后接收数据。
uint8_t W25Q64_ReadData(void) {uint8_t received_data = 0;GPIO_ResetBits(GPIOA, GPIO_Pin_4);  // 选择 W25Q64 (CS 低电平)SPI_I2S_SendData(SPI1, 0x00);  // 发送占位数据以启动 SPI 接收while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));  // 等待 SPI 完成received_data = SPI_I2S_ReceiveData(SPI1);  // 读取数据GPIO_SetBits(GPIOA, GPIO_Pin_4);  // 取消选择 W25Q64 (CS 高电平)return received_data;
}

项目:利用SPI通信对W25Q64芯片进行数据读写,读出来的数据显示在OLED屏上

spi初始化配置:

#include "stm32f10x.h"                  // Device header
#include "spi.h"
void MySPI_Init(){RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE );RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SPI1,ENABLE );GPIO_InitTypeDef  GPIOinitsturt;//配置关于GPIO的NSS输出引脚GPIOinitsturt .GPIO_Mode =GPIO_Mode_Out_PP;GPIOinitsturt .GPIO_Pin =GPIO_Pin_4;GPIOinitsturt .GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init (GPIOA ,&GPIOinitsturt);//配置关于GPIO的CLK和MOSI引脚输出GPIOinitsturt .GPIO_Mode =GPIO_Mode_AF_PP ;GPIOinitsturt .GPIO_Pin =GPIO_Pin_5|GPIO_Pin_7;GPIOinitsturt .GPIO_Speed =GPIO_Speed_50MHz;GPIO_Init (GPIOA,&GPIOinitsturt);//配置关于GPIO的MISO引脚输出GPIOinitsturt .GPIO_Mode = GPIO_Mode_IPU ;GPIOinitsturt .GPIO_Pin =GPIO_Pin_6;GPIOinitsturt .GPIO_Speed =GPIO_Speed_50MHz;GPIO_Init (GPIOA,&GPIOinitsturt);//初始化SPI外设SPI_InitTypeDef   spi_initsturt;spi_initsturt.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_128 ;spi_initsturt.SPI_CPHA =SPI_CPHA_1Edge ; spi_initsturt.SPI_CPOL =SPI_CPOL_Low;spi_initsturt.SPI_CRCPolynomial =7;spi_initsturt.SPI_DataSize =SPI_DataSize_8b ;spi_initsturt.SPI_Direction =SPI_Direction_2Lines_FullDuplex ;spi_initsturt.SPI_FirstBit =SPI_FirstBit_MSB; spi_initsturt.SPI_Mode =SPI_Mode_Master ;spi_initsturt.SPI_NSS =SPI_NSS_Soft ;SPI_Init (SPI1,&spi_initsturt);SPI_Cmd(SPI1,ENABLE );myspi_w_ss(1);}
void myspi_w_ss(uint8_t BitValue)
{GPIO_WriteBit(GPIOA ,  GPIO_Pin_4, (BitAction) BitValue);}
void myspi_w_sck(uint8_t BitValue)
{GPIO_WriteBit(GPIOA ,  GPIO_Pin_5, (BitAction) BitValue);}void myspi_w_mosi(uint8_t BitValue)
{GPIO_WriteBit(GPIOA ,  GPIO_Pin_7, (BitAction) BitValue);}void MySPI_Start(void){myspi_w_ss(0);}
void MySPI_Stop(void ){myspi_w_ss(1);}uint8_t  MySPI_SwapByte(uint8_t  byesent){while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET);SPI_I2S_SendData(SPI1, byesent);while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);return  SPI_I2S_ReceiveData(SPI1);}

对W25Q64芯片进行数据读写配置:

#include "w25q64.h"
void W25Q64_Init(void)
{MySPI_Init();
}void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{MySPI_Start();MySPI_SwapByte(W25Q64_JEDEC_ID);*MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID <<= 8;*DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);MySPI_Stop();
}void W25Q64_WriteEnable(void)
{MySPI_Start();MySPI_SwapByte(W25Q64_WRITE_ENABLE);MySPI_Stop();
}void W25Q64_WaitBusy(void)
{uint32_t Timeout;MySPI_Start();MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);Timeout = 100000;while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01){Timeout --;if (Timeout == 0){break;}}MySPI_Stop();
}void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{uint16_t i;W25Q64_WriteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_PAGE_PROGRAM);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);MySPI_SwapByte(Address);for (i = 0; i < Count; i ++){MySPI_SwapByte(DataArray[i]);}MySPI_Stop();W25Q64_WaitBusy();
}void W25Q64_SectorErase(uint32_t Address)
{W25Q64_WriteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);MySPI_SwapByte(Address);MySPI_Stop();W25Q64_WaitBusy();
}void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READ_DATA);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);MySPI_SwapByte(Address);for (i = 0; i < Count; i ++){DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop();
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com