当前位置: 首页 > wzjs >正文

建设企业网站需要注意的问题快照网站

建设企业网站需要注意的问题,快照网站,独一无二的logo图,页面设计软件教程STM32外设SPI FLASH应用实例 1. 前言1.1 硬件准备1.2 软件准备 2. 硬件连接3. 软件实现3.1 SPI 初始化3.2 QW128 SPI FLASH 驱动3.3 乒乓存储实现 4. 测试与验证4.1 数据备份测试4.2 数据恢复测试 5 实例5.1 参数结构体定义5.2 存储参数到 SPI FLASH5.3 从 SPI FLASH 读取参数5…

STM32外设SPI FLASH应用实例

  • 1. 前言
    • 1.1 硬件准备
    • 1.2 软件准备
  • 2. 硬件连接
  • 3. 软件实现
    • 3.1 SPI 初始化
    • 3.2 QW128 SPI FLASH 驱动
    • 3.3 乒乓存储实现
  • 4. 测试与验证
    • 4.1 数据备份测试
    • 4.2 数据恢复测试
  • 5 实例
    • 5.1 参数结构体定义
    • 5.2 存储参数到 SPI FLASH
    • 5.3 从 SPI FLASH 读取参数
    • 5.4 示例:存储和读取参数
    • 5.6 注意事项
  • 6. 总结

1. 前言

在嵌入式系统中,数据的存储和备份是一个非常重要的功能。SPI FLASH 是一种常见的非易失性存储器,具有容量大、速度快、接口简单等优点。本文将介绍如何在 STM32F103 上使用 SPI 接口操作 QW128 SPI FLASH,并通过乒乓存储的方式实现数据备份。

1.1 硬件准备

  • STM32F103 开发板
  • QW128 SPI FLASH 模块
  • 杜邦线若干

1.2 软件准备

  • Keil MDK 或 STM32CubeIDE
  • STM32 HAL 库

2. 硬件连接

将 QW128 SPI FLASH 模块与 STM32F103 开发板连接,具体连接方式如下:

QW128 引脚STM32F103 引脚
CSPA4
SCKPA5
MISOPA6
MOSIPA7
GNDGND
VCC3.3V

在这里插入图片描述

3. 软件实现

使用STM32CUBE配置SPI通信
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.1 SPI 初始化

首先,我们需要初始化 SPI 接口。使用 STM32CubeMX 配置 SPI1 外设,并生成初始化代码。

void MX_SPI1_Init(void)
{hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}
}

3.2 QW128 SPI FLASH 驱动

接下来,我们编写 QW128 SPI FLASH 的驱动代码,包括读写操作。

#define QW128_CMD_WRITE_ENABLE 0x06
#define QW128_CMD_WRITE_DISABLE 0x04
#define QW128_CMD_READ_STATUS_REG 0x05
#define QW128_CMD_WRITE_STATUS_REG 0x01
#define QW128_CMD_READ_DATA 0x03
#define QW128_CMD_PAGE_PROGRAM 0x02
#define QW128_CMD_SECTOR_ERASE 0x20
#define QW128_CMD_CHIP_ERASE 0xC7void QW128_WriteEnable(void)
{uint8_t cmd = QW128_CMD_WRITE_ENABLE;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_WriteDisable(void)
{uint8_t cmd = QW128_CMD_WRITE_DISABLE;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}uint8_t QW128_ReadStatusReg(void)
{uint8_t cmd = QW128_CMD_READ_STATUS_REG;uint8_t status;HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_SPI_Receive(&hspi1, &status, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);return status;
}void QW128_WriteStatusReg(uint8_t status)
{uint8_t cmd[2] = {QW128_CMD_WRITE_STATUS_REG, status};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 2, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_ReadData(uint32_t addr, uint8_t *data, uint16_t len)
{uint8_t cmd[4] = {QW128_CMD_READ_DATA, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_SPI_Receive(&hspi1, data, len, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_PageProgram(uint32_t addr, uint8_t *data, uint16_t len)
{uint8_t cmd[4] = {QW128_CMD_PAGE_PROGRAM, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_SectorErase(uint32_t addr)
{uint8_t cmd[4] = {QW128_CMD_SECTOR_ERASE, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF};QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, cmd, 4, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}void QW128_ChipErase(void)
{uint8_t cmd = QW128_CMD_CHIP_ERASE;QW128_WriteEnable();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}

3.3 乒乓存储实现

乒乓存储是一种常用的数据备份策略,通过交替使用两个存储区域来确保数据的完整性和可靠性。

#define PAGE_SIZE 256
#define SECTOR_SIZE 4096
#define BUFFER_SIZE 1024uint8_t buffer[BUFFER_SIZE];
uint32_t current_sector = 0;void PingPong_Backup(uint8_t *data, uint16_t len)
{// 擦除当前扇区QW128_SectorErase(current_sector * SECTOR_SIZE);// 写入数据for (uint16_t i = 0; i < len; i += PAGE_SIZE){QW128_PageProgram(current_sector * SECTOR_SIZE + i, data + i, PAGE_SIZE);}// 切换到下一个扇区current_sector = (current_sector + 1) % 2;
}void PingPong_Restore(uint8_t *data, uint16_t len)
{// 读取数据QW128_ReadData(current_sector * SECTOR_SIZE, data, len);
}

4. 测试与验证

4.1 数据备份测试

uint8_t test_data[BUFFER_SIZE];
for (uint16_t i = 0; i < BUFFER_SIZE; i++)
{test_data[i] = i % 256;
}PingPong_Backup(test_data, BUFFER_SIZE);

4.2 数据恢复测试

uint8_t restore_data[BUFFER_SIZE];
PingPong_Restore(restore_data, BUFFER_SIZE);// 验证数据
for (uint16_t i = 0; i < BUFFER_SIZE; i++)
{if (restore_data[i] != test_data[i]){// 数据不一致,处理错误Error_Handler();}
}

5 实例

5.1 参数结构体定义

以下是参数结构体的定义,基于你提供的代码:

typedef enum
{BAUD_9600,BAUD_19200,BAUD_115200
} BAUD_ENUM;typedef struct
{BAUD_ENUM CommBaud;          // 通信波特率uint8_t OnOffCtrl;           // 启停操作方式(0-本地;1-远程485;2-模拟量)uint8_t ModeCtrl;            // 模式修改方式(0-本地;1-远程485;2-模拟量)uint8_t SetValCtrl;          // 设定修改方式(0-本地;1-远程485;2-模拟量)uint8_t MasterSlaver;        // 主副机设置(0-主机;1-副机;2-单机)uint8_t TestMode;            // 测试模式uint8_t DebugMode;           // 调试模式uint8_t DeviceModel;         // 设备型号(0-3KW;2-20KW风冷)uint8_t DeviceSer[32];       // 设备序列号uint8_t AlarmEnable;         // 告警使能(0-关闭;1-使能)uint8_t CommProto;           // 通信协议(0-Modbus;1-Profibus)uint16_t UdcLimit;           // Udc调节限定值uint16_t IdcLimit;           // Idc调节限定值uint16_t PdcLimit;           // Pdc调节限定值uint8_t ModeSlect;           // 调节模式选择(0-Udc;1-Idc;2-Pdc)uint8_t PWM1Freq;            // PWM1频率(40~80表示40KHz~80KHz)
} DeviceParams;

5.2 存储参数到 SPI FLASH

我们可以将参数结构体存储到 SPI FLASH 的指定地址。以下是存储函数的实现:

#include "stm32f1xx_hal.h"
#include "spi_flash.h"  // 假设这是 QW128 SPI FLASH 的驱动头文件#define PARAMS_FLASH_ADDR 0x00000000  // 参数存储的起始地址void SaveParamsToFlash(DeviceParams *params)
{// 擦除 SPI FLASH 的指定扇区QW128_SectorErase(PARAMS_FLASH_ADDR);// 将参数结构体写入 SPI FLASHQW128_PageProgram(PARAMS_FLASH_ADDR, (uint8_t *)params, sizeof(DeviceParams));
}

5.3 从 SPI FLASH 读取参数

从 SPI FLASH 中读取参数结构体的实现如下:

void LoadParamsFromFlash(DeviceParams *params)
{// 从 SPI FLASH 读取参数结构体QW128_ReadData(PARAMS_FLASH_ADDR, (uint8_t *)params, sizeof(DeviceParams));
}

5.4 示例:存储和读取参数

以下是一个完整的示例,展示如何初始化参数、存储到 SPI FLASH 以及从 SPI FLASH 读取参数:

int main(void)
{HAL_Init();SystemClock_Config();MX_SPI1_Init();  // 初始化 SPIMX_GPIO_Init();  // 初始化 GPIO// 初始化参数结构体DeviceParams params = {.CommBaud = BAUD_115200,.OnOffCtrl = 1,.ModeCtrl = 1,.SetValCtrl = 1,.MasterSlaver = 0,.TestMode = 0,.DebugMode = 1,.DeviceModel = 2,.DeviceSer = "1234567890ABCDEF1234567890ABCDEF",.AlarmEnable = 1,.CommProto = 0,.UdcLimit = 1000,.IdcLimit = 500,.PdcLimit = 2000,.ModeSlect = 1,.PWM1Freq = 60};// 存储参数到 SPI FLASHSaveParamsToFlash(&params);// 从 SPI FLASH 读取参数DeviceParams loadedParams;LoadParamsFromFlash(&loadedParams);// 验证读取的参数是否正确if (memcmp(&params, &loadedParams, sizeof(DeviceParams)) == 0){printf("Parameters loaded successfully!\n");}else{printf("Parameter load failed!\n");}while (1){// 主循环}
}

5.6 注意事项

  1. SPI FLASH 的寿命

    • SPI FLASH 的擦写次数有限(通常为 10 万次左右),频繁擦写可能导致损坏。建议在设计中尽量减少擦写操作。
  2. 数据对齐

    • 确保参数结构体的数据对齐与 SPI FLASH 的页大小(通常为 256 字节)匹配,避免跨页写入。
  3. 数据校验

    • 在存储和读取参数时,可以添加 CRC 校验或校验和,确保数据的完整性。
  4. 备份机制

    • 可以使用乒乓存储策略,将参数存储在两个不同的扇区中,确保在一个扇区损坏时可以从另一个扇区恢复数据。

6. 总结

本文介绍了如何在 STM32F103 上使用 SPI 接口操作 QW128 SPI FLASH,并通过乒乓存储的方式实现数据备份。通过这种方式,可以有效地提高数据的可靠性和系统的稳定性。希望本文对大家有所帮助,欢迎在评论区留言讨论。


http://www.dtcms.com/wzjs/401566.html

相关文章:

  • 网站栏目内容扬州百度seo公司
  • 国内做外贸网站的有哪些网站排名掉了怎么恢复
  • 锦州网站建设锦州排名查询
  • 网站开发专业感想市场营销平台
  • 手机端网站的区别网络整合营销方案ppt
  • 网站运行及维护软件测试培训班多少钱
  • 个人域名备案做企业网站百度小说排行榜第一名
  • 客户端下载搜索引擎优化服务公司哪家好
  • 云南网站建设及优化怎么做百度推广的代理
  • 房源网站哪个比较真实seo域名综合查询
  • 潍坊知名网站建设公司西地那非片能延时多久有副作用吗
  • wordpress怎么用啊重庆seo推广运营
  • 余姚物流做网站展示型网站设计公司
  • 网站论坛源码百度明星人气榜入口
  • 怎样做网站分流赚钱做网站的软件
  • 外贸手机网站seo查询在线
  • 电子书新手学做网站刚刚中国出啥大事了
  • 无锡朝阳网站建设友情链接翻译
  • 枣庄手机网站制作什么软件可以发布推广信息
  • 成都网站建设科技今日新闻最新消息大事
  • 合肥市建设工程造价信息网站seo快速优化软件
  • 连云港做网站多少钱seo百度推广
  • 松原网站制作网络市场的四大特点
  • 网站建设中英版舆情监测软件免费版
  • 太原自学网站建设搜索引擎优化管理实验报告
  • 22seesawseo公司seo教程
  • 深圳做微信商城网站建设哪里有竞价推广托管
  • 扶余手机网站开发seo是什么意思职业
  • 数据网站广东深圳龙华区
  • 做境外旅游的网站如何联系百度人工客服