第22章 W25Q64存储小数和整数
第二十二章 W25Q64存储小数和整数
1. 硬件设计
参考上一章SPI读写实验
2. 软件设计
主要程序设计我们在上一章就见识过了,这个实验主要就是改下主函数就行了
#include "led.h"
#include "spi_flash.h"
#include "usart.h"
__IO uint32_t DeviceID = 0;
__IO uint32_t FlashID = 0;
void Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
int main(void)
{
uint8_t flag = 0;
uint8_t k;
long double doule_buffer[7] = {0}; // 小数数组缓冲区
int long_buffer[7] = {0}; // 长整型数组缓冲区
LED_Init();
LED_BLUE();
SPI_FLASH_Init();
USART_Config();
printf("SPI FLASH Test Program\r\n");
DeviceID = SPI_FLASH_ReadDeviceID(); // 读取设备ID
Delay(200);
FlashID = SPI_FLASH_ReadID(); // 读取Flash ID
printf("Device ID: 0x%X\r\n", DeviceID);
printf("Flash ID: 0x%X\r\n", FlashID);
if(FlashID == sFLASH_ID)
{
LED_GREEN();
printf("检测到W25Q64\r\n");
SPI_FLASH_BufferRead(&flag, SPI_FLASH_PageSize*0, 1);
if(flag == 0xCD) // 检测数据标志
{
printf("之前已经写入数据\r\n");
// 读取小数数据
SPI_FLASH_BufferRead((void*)doule_buffer, SPI_FLASH_PageSize*1, sizeof(doule_buffer));
// 读取长整型数据
SPI_FLASH_BufferRead((void*)long_buffer, SPI_FLASH_PageSize*2, sizeof(long_buffer));
printf("\r\n 从芯片读到的数据为: \r\n");
for(k = 0; k < 7; k++)
{
printf("小数 = %LF \r\n", doule_buffer[k]);
printf("长整型 = %d \r\n", long_buffer[k]);
}
}
else // 未写入数据
{
printf("未写入数据, 准备写入数据\r\n");
flag = 0xCD; // 数据标志
SPI_FLASH_SectorErase(0); // 擦除第0页
SPI_FLASH_BufferWrite(&flag, SPI_FLASH_PageSize*0, 1); // 写入数据标志
for(k = 0; k < 7; k++)
{
doule_buffer[k] = k +0.01; // 写入小数数据
long_buffer[k] = k + 1000000000; // 写入长整型数据
}
SPI_FLASH_BufferWrite((void*)doule_buffer, SPI_FLASH_PageSize*1, sizeof(doule_buffer));
SPI_FLASH_BufferWrite((void*)long_buffer, SPI_FLASH_PageSize*2, sizeof(long_buffer));
printf("向芯片写入的数据为: \r\n");
for(k = 0; k < 7; k++)
{
printf("小数 = %LF \r\n", doule_buffer[k]);
printf("长整型 = %d \r\n", long_buffer[k]);
}
printf("\r\n 复位开发板,进行数据效验 \r\n");
}
}
else
{
LED_RED();
printf("未检测到W25Q64\r\n");
}
while(1)
{}
}
唯一的区别就是加了读写小数的功能,我们可以简单分析一下:
-
前面定义缓存区,各项外设初始化
-
获取Flash、SPI的ID,并且打印
-
之后就可以获取标志位,如果没有获取到,进行写入小数操作:擦除->写入标志位第0页->写入小数到第一页
-
之后复位开发板,这时应该能成功获取到标志位,于是通过for循环打印出我们写入的数据
3. 小结
下面整体概括一下:
3.1 头文件引入
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h"
#include "./flash/bsp_spi_flash.h"
这些头文件包含了不同模块所需的函数和宏定义。例如,stm32f10x.h
提供了STM32F10系列芯片的基础功能,而其他头文件则提供了LED、串口、Flash操作的具体实现。
举一反三:如果你在使用其他外设,比如定时器或ADC,你需要包含相应的头文件,如stm32f4xx_tim.h
或stm32f4xx_adc.h
。
3.2 全局变量
__IO uint32_t DeviceID = 0;
__IO uint32_t FlashID = 0;
这些全局变量用来存储设备ID和Flash ID,__IO
修饰符用于表示这些变量可能会被硬件或中断改变。
举一反三:类似地,如果你需要存储其他硬件相关的信息,可以使用类似的全局变量。
3.3 函数原型声明
void Delay(__IO uint32_t nCount);
声明了一个延时函数,用于在程序中创建延时。
举一反三:如果需要其他功能的延时(例如基于定时器的延时),你可以声明并实现新的延时函数。
3.4 主函数
int main(void)
{
uint8_t cal_flag = 0;
uint8_t k;
long double double_buffer[7] = {0};
int int_bufffer[7] = {0};
主函数中初始化了数据标志位、循环变量以及两个数据缓冲区:double_buffer
用于存储小数,int_bufffer
用于存储整数。
举一反三:如果需要处理更多的数据,可以增加更多的数组或缓冲区。例如,你可以增加一个float_buffer
来存储浮点数数据。
3.5 外设初始化
LED_GPIO_Config();
LED_BLUE;
USART_Config();
配置LED和串口的初始化函数,并点亮蓝色LED作为开始的指示。
举一反三:类似地,你可以配置其他外设,如定时器或DAC,通过相应的初始化函数。
3.6 Flash ID读取和验证
DeviceID = SPI_FLASH_ReadDeviceID();
FlashID = SPI_FLASH_ReadID();
从SPI Flash中读取设备ID和Flash ID,并打印出来进行验证。
举一反三:对于其他外设的ID读取和验证,流程类似。比如读取传感器ID,你也会用相应的函数读取数据并验证。
3.7 数据读取和写入
if(cal_flag == 0xCD)
{
SPI_FLASH_BufferRead((void*)double_buffer, SPI_FLASH_PageSize*1, sizeof(double_buffer));
SPI_FLASH_BufferRead((void*)int_bufffer, SPI_FLASH_PageSize*2, sizeof(int_bufffer));
}
else
{
SPI_FLASH_SectorErase(0);
SPI_FLASH_BufferWrite((void*)double_buffer, SPI_FLASH_PageSize*1, sizeof(double_buffer));
SPI_FLASH_BufferWrite((void*)int_bufffer, SPI_FLASH_PageSize*2, sizeof(int_bufffer));
}
检查标志位,如果数据已存在则读取数据,否则进行写入操作。
举一反三:类似的操作可以应用于其他存储设备,比如EEPROM或SD卡的读写。只需替换为对应的读写函数即可。
2025.1.22 修订部分内容
本文作者:hazy1k
本文链接:https://www.cnblogs.com/hazy1k/p/18398612
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步