加入微积分库
This commit is contained in:
117
bsp_Device/bsp_Calculus.cpp
Normal file
117
bsp_Device/bsp_Calculus.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_Calculus.cpp
|
||||
* @brief 离散微积分
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-11-23 02:46
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 头文件
|
||||
#include "bsp_Calculus.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 类函数
|
||||
/**
|
||||
* @brief 对数据微分
|
||||
* @param var 此处填入浮点数据
|
||||
* @return 此时的微分值
|
||||
*/
|
||||
float bsp_Differential::Differential(float var) {
|
||||
static float old=var;
|
||||
float result= (var - old) / dt;
|
||||
old = var;
|
||||
return result;}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 类函数
|
||||
/**
|
||||
* @brief 对数据积分
|
||||
* @param var 此处填入浮点数据
|
||||
* @return 从开始到现在的总积分值
|
||||
*/
|
||||
float bsp_Integral::Integral(float var) {
|
||||
results += var * dt;
|
||||
return results;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 重设当前积分值
|
||||
* @param var 要设置的积分值
|
||||
*/
|
||||
void bsp_Integral::Integral_set(float results) {
|
||||
bsp_Integral::results = results;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 赋予历史缓存长度
|
||||
* @param var 分配的缓存长度
|
||||
* @return 返回分配的内存位置,0为分配失败
|
||||
*/
|
||||
u32 bsp_Integral::Integral_makelist(u32 len) {
|
||||
result_list = (float*)malloc(sizeof(float)* len);
|
||||
result_len = len;
|
||||
Integral_clslist();
|
||||
return (u32)result_list;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 进行带有缓冲区的积分
|
||||
* @param var 需要积分的数值
|
||||
* @return 返回积分值
|
||||
*/
|
||||
float bsp_Integral::Integral_list(float var) {
|
||||
static u32 len=0;
|
||||
results += var * dt;
|
||||
// 保存历史
|
||||
result_list[len] = var * dt;
|
||||
// 轮盘转
|
||||
++len;
|
||||
if (len == result_len)len = 0;
|
||||
// 去除尾值
|
||||
if (len < result_len - 1)
|
||||
results -= result_list[len + 1];
|
||||
else
|
||||
results -= result_list[0];
|
||||
//
|
||||
return results;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 删除并释放历史缓冲区
|
||||
*/
|
||||
void bsp_Integral::Integral_dellist(void) {
|
||||
free(result_list);
|
||||
result_len = 0;
|
||||
result_list = NULL;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 清空历史缓存区
|
||||
*/
|
||||
void bsp_Integral::Integral_clslist(void) {
|
||||
if (result_list == NULL)return;
|
||||
for (u32 i = 0; i < result_len; i++)
|
||||
result_list[i] = 0;}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
81
bsp_Device/bsp_Calculus.h
Normal file
81
bsp_Device/bsp_Calculus.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_Calculus.h
|
||||
* @brief 离散微积分
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-11-23 02:46
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include "varint.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 类目
|
||||
/**
|
||||
* @brief 一个微分对象
|
||||
*/
|
||||
class bsp_Differential{
|
||||
public:
|
||||
bsp_Differential(float dt) {
|
||||
bsp_Differential::dt = dt;}
|
||||
public:
|
||||
float Differential(float var);
|
||||
public:
|
||||
float dt; ///< 时间参数
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 一个积分对象
|
||||
* @note 不应当混用Integral和Integral_list
|
||||
* @note 选定一种方式(带缓冲区或者不带)后,就不应该更改使用方式
|
||||
* @note 虽然带缓冲区方式对算法时间影响不大,但是为了避免浪费空间,不建议使用过大的缓冲区
|
||||
*/
|
||||
class bsp_Integral {
|
||||
public:
|
||||
bsp_Integral(float dt) {
|
||||
bsp_Integral::result_list = NULL;
|
||||
bsp_Integral::dt = dt;
|
||||
bsp_Integral::results = 0;}
|
||||
~bsp_Integral(void) {
|
||||
free(result_list);
|
||||
result_list = NULL;}
|
||||
public:
|
||||
float Integral(float var);
|
||||
void Integral_set(float results);
|
||||
|
||||
float Integral_list(float var);
|
||||
u32 Integral_makelist(u32 len);
|
||||
void Integral_dellist(void);
|
||||
void Integral_clslist(void);
|
||||
public:
|
||||
float *result_list; ///< 数据历史
|
||||
u32 result_len; ///< 历史缓冲区长度
|
||||
float results; ///< 积分缓存
|
||||
float dt; ///< 时间参数
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -82,7 +82,6 @@ u8 bsp_IIC_STM32::IIC_SCK(u8 var) {
|
||||
}}
|
||||
/**
|
||||
* @brief 控制SDA管脚口
|
||||
*
|
||||
* @param var 此处有三个状态,IIC_SET置位管脚,IIC_RESET复位管脚
|
||||
* @return 当var为IIC_READ时返回管脚状态
|
||||
*/
|
||||
|
||||
456
bsp_Device/bsp_SD.cpp
Normal file
456
bsp_Device/bsp_SD.cpp
Normal file
@@ -0,0 +1,456 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_SD.cpp
|
||||
* @brief 操作SD卡的库
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-11-22 03:50
|
||||
*/
|
||||
|
||||
#include "bsp_SD.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 程序
|
||||
//
|
||||
/**
|
||||
* @brief 片选信号
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_SD::SD_CS(u8 p){
|
||||
HAL_GPIO_WritePin(GPIOx_CS, GPIO_Pin_CS, p == 0 ? GPIO_PIN_SET: GPIO_PIN_RESET);}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 写SD卡
|
||||
* @param cmd 命令
|
||||
* @param arg
|
||||
* @param crc 校验码
|
||||
* @return
|
||||
*/
|
||||
u32 bsp_SD::SD_sendcmd(u8 cmd, u32 arg, u8 crc){
|
||||
u8 r1;
|
||||
u8 retry;
|
||||
SD_CS(0);
|
||||
__nop();
|
||||
SD_CS(1);
|
||||
do retry = spi_readwrite(DFF);while(retry != 0xFF);
|
||||
spi_readwrite(cmd | 0x40);
|
||||
spi_readwrite(arg >> 24);
|
||||
spi_readwrite(arg >> 16);
|
||||
spi_readwrite(arg >> 8);
|
||||
spi_readwrite(arg);
|
||||
spi_readwrite(crc);
|
||||
if (cmd == CMD12) spi_readwrite(DFF);
|
||||
do r1 = spi_readwrite(0xFF);while(r1 & 0X80);
|
||||
return r1;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 初始化SD卡
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::SD_init(void){
|
||||
u8 r1;
|
||||
u8 buff[6] = {0};
|
||||
u16 retry;
|
||||
u8 i;
|
||||
// MX_SPI3_Init();
|
||||
SPI_setspeed(SPI_BAUDRATEPRESCALER_256);
|
||||
SD_CS(0);
|
||||
for (retry = 0; retry < 10; retry++) spi_readwrite(DFF);
|
||||
// SD卡进入IDLE状态
|
||||
do r1 = SD_sendcmd(CMD0, 0, 0x95);while(r1 != 0x01);
|
||||
// 查看SD卡的类型
|
||||
SD_TYPE = 0;
|
||||
r1 = SD_sendcmd(CMD8, 0x1AA, 0x87);
|
||||
if (r1 == 0x01) {
|
||||
for (i = 0; i < 4; i++) buff[i] = spi_readwrite(DFF); //Get trailing return value of R7 resp
|
||||
if (buff[2] == 0X01 && buff[3] == 0XAA) { //卡是否支持2.7~3.6V
|
||||
retry = 0XFFFE;
|
||||
do {
|
||||
SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
|
||||
r1 = SD_sendcmd(CMD41, 0x40000000, 0X01); //发送CMD41
|
||||
}while(r1 && retry--);
|
||||
if (retry && SD_sendcmd(CMD58, 0, 0X01) == 0) { //鉴别SD2.0卡版本开始
|
||||
for (i = 0; i < 4; i++) buff[i] = spi_readwrite(0XFF); //得到OCR值
|
||||
if (buff[0] &0x40) SD_TYPE = V2HC;
|
||||
else SD_TYPE = V2;}}
|
||||
else {
|
||||
SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
|
||||
r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41
|
||||
if (r1 <= 1) {
|
||||
SD_TYPE = V1;
|
||||
retry = 0XFFFE;
|
||||
do { //等待退出IDLE模式
|
||||
SD_sendcmd(CMD55, 0, 0X01); //发送CMD55
|
||||
r1 = SD_sendcmd(CMD41, 0, 0X01); //发送CMD41
|
||||
}while(r1 && retry--);}
|
||||
else { //MMC卡不支持CMD55+CMD41识别
|
||||
SD_TYPE = MMC; //MMC V3
|
||||
retry = 0XFFFE;
|
||||
do r1 = SD_sendcmd(CMD1, 0, 0X01);while(r1 && retry--);} //等待退出IDLE模式
|
||||
if (retry == 0 || SD_sendcmd(CMD16, 512, 0X01) != 0) SD_TYPE = ERR;} //错误的卡
|
||||
}
|
||||
SD_CS(0);
|
||||
SPI_setspeed(SPI_BAUDRATEPRESCALER_2);
|
||||
if (SD_TYPE) return 0;
|
||||
else return 1;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 读取SD卡指定长度信息
|
||||
* @param *data 数据缓存区
|
||||
* @param len 长度
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::SD_ReceiveData(u8 * data, u16 len){
|
||||
u8 r1;
|
||||
SD_CS(1);
|
||||
do {
|
||||
r1 = spi_readwrite(0xFF);
|
||||
__nop();
|
||||
}while(r1 != 0xFE);
|
||||
while (len--) {
|
||||
*data = spi_readwrite(0xFF);
|
||||
data++;}
|
||||
spi_readwrite(0xFF);
|
||||
spi_readwrite(0xFF);
|
||||
return 0;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 向SD卡写入一个扇区
|
||||
* @param *buf 数据缓存区
|
||||
* @param cmd 操作指令
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::SD_SendBlock(u8 * buf, u8 cmd){
|
||||
u16 t;
|
||||
u8 r1;
|
||||
do r1 = spi_readwrite(0xFF);while(r1 != 0xFF);
|
||||
spi_readwrite(cmd);
|
||||
if (cmd != 0XFD) { //不是结束指令
|
||||
for (t = 0; t < 512; t++) spi_readwrite(buf[t]); //提高速度,减少函数传参时间
|
||||
spi_readwrite(0xFF); //忽略crc
|
||||
spi_readwrite(0xFF);
|
||||
t = spi_readwrite(0xFF); //接收响应
|
||||
if ((t & 0x1F) != 0x05) return 2;} //响应错误
|
||||
return 0;} //写入成功
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 获取CID信息
|
||||
* @return CID信息
|
||||
*/
|
||||
u8 bsp_SD::SD_GETCID(u8 * cid_data){
|
||||
u8 r1;
|
||||
r1 = SD_sendcmd(CMD10, 0, 0x01); //读取CID寄存器
|
||||
if (r1 == 0x00) r1 = SD_ReceiveData(cid_data, 16);
|
||||
SD_CS(0);
|
||||
if (r1) return 1;
|
||||
else return 0;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 获取CSD信息
|
||||
* @return CSD信息
|
||||
*/
|
||||
u8 bsp_SD::SD_GETCSD(u8 * csd_data){
|
||||
u8 r1;
|
||||
r1 = SD_sendcmd(CMD9, 0, 0x01); //发CMD9命令,读CSD寄存器
|
||||
if (r1 == 0) r1 = SD_ReceiveData(csd_data, 16); //接收16个字节的数据
|
||||
SD_CS(0); //取消片选
|
||||
if (r1) return 1;
|
||||
else return 0;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 获取SD卡的总扇区数
|
||||
* @return 总扇区数
|
||||
*/
|
||||
u32 bsp_SD::SD_GetSectorCount(void){
|
||||
u8 csd[16];
|
||||
u32 Capacity;
|
||||
u8 n;
|
||||
u16 csize;
|
||||
//取CSD信息,如果期间出错,返回0
|
||||
if (SD_GETCSD(csd) != 0) return 0;
|
||||
//如果为SDHC卡,按照下面方式计算
|
||||
if ((csd[0] &0xC0) == 0x40) { //V2.00的卡
|
||||
csize = csd[9] + ((u16) csd[8] << 8) + 1;
|
||||
Capacity = (u32)
|
||||
csize << 10;} //得到扇区数
|
||||
else { //V1.XX的卡
|
||||
n = (csd[5] &15) + ((csd[10] &128) >> 7) + ((csd[9] &3) << 1) + 2;
|
||||
csize = (csd[8] >> 6) + ((u16) csd[7] << 2) + ((u16) (csd[6] &3) << 10) + 1;
|
||||
Capacity = (u32)
|
||||
csize << (n - 9);} //得到扇区数
|
||||
return Capacity;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
int bsp_SD::MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo){
|
||||
u8 r1;
|
||||
u8 CSD_Tab[16];
|
||||
u8 CID_Tab[16];
|
||||
/* Send CMD9, Read CSD */
|
||||
r1 = SD_sendcmd(CMD9, 0, 0xFF);
|
||||
if (r1 != 0x00) return r1;
|
||||
if (SD_ReceiveData(CSD_Tab, 16)) return 1;
|
||||
/* Send CMD10, Read CID */
|
||||
r1 = SD_sendcmd(CMD10, 0, 0xFF);
|
||||
if (r1 != 0x00) return r1;
|
||||
if (SD_ReceiveData(CID_Tab, 16)) return 2;
|
||||
/* Byte 0 */
|
||||
SD0_CardInfo->CSD.CSDStruct = (CSD_Tab[0] &0xC0) >> 6;
|
||||
SD0_CardInfo->CSD.SysSpecVersion = (CSD_Tab[0] &0x3C) >> 2;
|
||||
SD0_CardInfo->CSD.Reserved1 = CSD_Tab[0] &0x03;
|
||||
/* Byte 1 */
|
||||
SD0_CardInfo->CSD.TAAC = CSD_Tab[1];
|
||||
/* Byte 2 */
|
||||
SD0_CardInfo->CSD.NSAC = CSD_Tab[2];
|
||||
/* Byte 3 */
|
||||
SD0_CardInfo->CSD.MaxBusClkFrec = CSD_Tab[3];
|
||||
/* Byte 4 */
|
||||
SD0_CardInfo->CSD.CardComdClasses = CSD_Tab[4] << 4;
|
||||
/* Byte 5 */
|
||||
SD0_CardInfo->CSD.CardComdClasses |= (CSD_Tab[5] &0xF0) >> 4;
|
||||
SD0_CardInfo->CSD.RdBlockLen = CSD_Tab[5] &0x0F;
|
||||
/* Byte 6 */
|
||||
SD0_CardInfo->CSD.PartBlockRead = (CSD_Tab[6] &0x80) >> 7;
|
||||
SD0_CardInfo->CSD.WrBlockMisalign = (CSD_Tab[6] &0x40) >> 6;
|
||||
SD0_CardInfo->CSD.RdBlockMisalign = (CSD_Tab[6] &0x20) >> 5;
|
||||
SD0_CardInfo->CSD.DSRImpl = (CSD_Tab[6] &0x10) >> 4;
|
||||
SD0_CardInfo->CSD.Reserved2 = 0; /* Reserved */
|
||||
SD0_CardInfo->CSD.DeviceSize = (CSD_Tab[6] &0x03) << 10;
|
||||
/* Byte 7 */
|
||||
SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2;
|
||||
/* Byte 8 */
|
||||
SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[8] &0xC0) >> 6;
|
||||
SD0_CardInfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] &0x38) >> 3;
|
||||
SD0_CardInfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] &0x07);
|
||||
/* Byte 9 */
|
||||
SD0_CardInfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] &0xE0) >> 5;
|
||||
SD0_CardInfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] &0x1C) >> 2;
|
||||
SD0_CardInfo->CSD.DeviceSizeMul = (CSD_Tab[9] &0x03) << 1;
|
||||
/* Byte 10 */
|
||||
SD0_CardInfo->CSD.DeviceSizeMul |= (CSD_Tab[10] &0x80) >> 7;
|
||||
SD0_CardInfo->CSD.EraseGrSize = (CSD_Tab[10] &0x7C) >> 2;
|
||||
SD0_CardInfo->CSD.EraseGrMul = (CSD_Tab[10] &0x03) << 3;
|
||||
/* Byte 11 */
|
||||
SD0_CardInfo->CSD.EraseGrMul |= (CSD_Tab[11] &0xE0) >> 5;
|
||||
SD0_CardInfo->CSD.WrProtectGrSize = (CSD_Tab[11] &0x1F);
|
||||
/* Byte 12 */
|
||||
SD0_CardInfo->CSD.WrProtectGrEnable = (CSD_Tab[12] &0x80) >> 7;
|
||||
SD0_CardInfo->CSD.ManDeflECC = (CSD_Tab[12] &0x60) >> 5;
|
||||
SD0_CardInfo->CSD.WrSpeedFact = (CSD_Tab[12] &0x1C) >> 2;
|
||||
SD0_CardInfo->CSD.MaxWrBlockLen = (CSD_Tab[12] &0x03) << 2;
|
||||
/* Byte 13 */
|
||||
SD0_CardInfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] &0xc0) >> 6;
|
||||
SD0_CardInfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] &0x20) >> 5;
|
||||
SD0_CardInfo->CSD.Reserved3 = 0;
|
||||
SD0_CardInfo->CSD.ContentProtectAppli = (CSD_Tab[13] &0x01);
|
||||
/* Byte 14 */
|
||||
SD0_CardInfo->CSD.FileFormatGrouop = (CSD_Tab[14] &0x80) >> 7;
|
||||
SD0_CardInfo->CSD.CopyFlag = (CSD_Tab[14] &0x40) >> 6;
|
||||
SD0_CardInfo->CSD.PermWrProtect = (CSD_Tab[14] &0x20) >> 5;
|
||||
SD0_CardInfo->CSD.TempWrProtect = (CSD_Tab[14] &0x10) >> 4;
|
||||
SD0_CardInfo->CSD.FileFormat = (CSD_Tab[14] &0x0C) >> 2;
|
||||
SD0_CardInfo->CSD.ECC = (CSD_Tab[14] &0x03);
|
||||
/* Byte 15 */
|
||||
SD0_CardInfo->CSD.CSD_CRC = (CSD_Tab[15] &0xFE) >> 1;
|
||||
SD0_CardInfo->CSD.Reserved4 = 1;
|
||||
if (SD0_CardInfo->CardType == V2HC) {
|
||||
/* Byte 7 */
|
||||
SD0_CardInfo->CSD.DeviceSize = (u16) (CSD_Tab[8]) * 256;
|
||||
/* Byte 8 */
|
||||
SD0_CardInfo->CSD.DeviceSize += CSD_Tab[9];}
|
||||
SD0_CardInfo->Capacity = SD0_CardInfo->CSD.DeviceSize * MSD_BLOCKSIZE * 1024;
|
||||
SD0_CardInfo->BlockSize = MSD_BLOCKSIZE;
|
||||
/* Byte 0 */
|
||||
SD0_CardInfo->CID.ManufacturerID = CID_Tab[0];
|
||||
/* Byte 1 */
|
||||
SD0_CardInfo->CID.OEM_AppliID = CID_Tab[1] << 8;
|
||||
/* Byte 2 */
|
||||
SD0_CardInfo->CID.OEM_AppliID |= CID_Tab[2];
|
||||
/* Byte 3 */
|
||||
SD0_CardInfo->CID.ProdName1 = CID_Tab[3] << 24;
|
||||
/* Byte 4 */
|
||||
SD0_CardInfo->CID.ProdName1 |= CID_Tab[4] << 16;
|
||||
/* Byte 5 */
|
||||
SD0_CardInfo->CID.ProdName1 |= CID_Tab[5] << 8;
|
||||
/* Byte 6 */
|
||||
SD0_CardInfo->CID.ProdName1 |= CID_Tab[6];
|
||||
/* Byte 7 */
|
||||
SD0_CardInfo->CID.ProdName2 = CID_Tab[7];
|
||||
/* Byte 8 */
|
||||
SD0_CardInfo->CID.ProdRev = CID_Tab[8];
|
||||
/* Byte 9 */
|
||||
SD0_CardInfo->CID.ProdSN = CID_Tab[9] << 24;
|
||||
/* Byte 10 */
|
||||
SD0_CardInfo->CID.ProdSN |= CID_Tab[10] << 16;
|
||||
/* Byte 11 */
|
||||
SD0_CardInfo->CID.ProdSN |= CID_Tab[11] << 8;
|
||||
/* Byte 12 */
|
||||
SD0_CardInfo->CID.ProdSN |= CID_Tab[12];
|
||||
/* Byte 13 */
|
||||
SD0_CardInfo->CID.Reserved1 |= (CID_Tab[13] &0xF0) >> 4;
|
||||
/* Byte 14 */
|
||||
SD0_CardInfo->CID.ManufactDate = (CID_Tab[13] &0x0F) << 8;
|
||||
/* Byte 15 */
|
||||
SD0_CardInfo->CID.ManufactDate |= CID_Tab[14];
|
||||
/* Byte 16 */
|
||||
SD0_CardInfo->CID.CID_CRC = (CID_Tab[15] &0xFE) >> 1;
|
||||
SD0_CardInfo->CID.Reserved2 = 1;
|
||||
return 0;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 写SD卡
|
||||
* @param *buf 数据缓存区
|
||||
* @param sector 起始扇区
|
||||
* @param cnt 扇区数
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::SD_WriteDisk(u8 * buf, u32 sector, u8 cnt){
|
||||
u8 r1;
|
||||
if (SD_TYPE != V2HC) sector *= 512; //转换为字节地址
|
||||
if (cnt == 1){
|
||||
r1 = SD_sendcmd(CMD24, sector, 0X01); //读命令
|
||||
if (r1 == 0) //指令发送成功
|
||||
r1 = SD_SendBlock(buf, 0xFE);} //写512个字节
|
||||
else {
|
||||
if (SD_TYPE != MMC) {
|
||||
SD_sendcmd(CMD55, 0, 0X01);
|
||||
SD_sendcmd(CMD23, cnt, 0X01);} //发送指令
|
||||
r1 = SD_sendcmd(CMD25, sector, 0X01); //连续读命令
|
||||
if (r1 == 0) {
|
||||
do {
|
||||
r1 = SD_SendBlock(buf, 0xFC); //接收512个字节
|
||||
buf += 512;}while(--cnt && r1 == 0);
|
||||
r1 = SD_SendBlock(0, 0xFD);}} //接收512个字节
|
||||
SD_CS(0); //取消片选
|
||||
return r1;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 读SD卡
|
||||
* @param *buf 数据缓存区
|
||||
* @param sector 起始扇区
|
||||
* @param cnt 扇区数
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::SD_ReadDisk(u8 * buf, u32 sector, u8 cnt){
|
||||
u8 r1;
|
||||
if (SD_TYPE != V2HC) sector <<= 9; //转换为字节地址
|
||||
if (cnt == 1) {
|
||||
r1 = SD_sendcmd(CMD17, sector, 0X01); //读命令
|
||||
if (r1 == 0) //指令发送成功
|
||||
r1 = SD_ReceiveData(buf, 512);} //接收512个字节
|
||||
else {
|
||||
r1 = SD_sendcmd(CMD18, sector, 0X01); //连续读命令
|
||||
do {
|
||||
r1 = SD_ReceiveData(buf, 512); //接收512个字节
|
||||
buf += 512;}
|
||||
while(--cnt && r1 == 0);
|
||||
SD_sendcmd(CMD12, 0, 0X01);} //发送停止命令
|
||||
SD_CS(0); //取消片选
|
||||
return r1;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
u8 bsp_SD::spi_readwrite(u8 Txdata){
|
||||
u8 Rxdata;
|
||||
HAL_SPI_TransmitReceive(hspi, &Txdata, &Rxdata, 1, 0xFF);
|
||||
return Rxdata;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 设置SPI的速率
|
||||
* @param speed 速率
|
||||
* @return 无
|
||||
*/
|
||||
void bsp_SD::SPI_setspeed(u8 speed){
|
||||
hspi->Init.BaudRatePrescaler = speed;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 写入连贯的数据
|
||||
* @param offset 写入位置
|
||||
* @param *dat 数据缓冲区
|
||||
* @param datlen 写入长度
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::offsetWrite(u64 offset,u8* dat,u64 datlen) {
|
||||
u8 sectorBuff[512] = { 0 };
|
||||
u64 sectorBuffptr = 0;
|
||||
|
||||
u64 sectorSour = offset / 512; // 起始扇
|
||||
u64 sectorSourlen = offset % 512; // 起始扇内位
|
||||
|
||||
// 填入数据
|
||||
SD_ReadDisk(sectorBuff,sectorSour,1);
|
||||
sectorBuffptr = sectorSourlen;
|
||||
for (u64 i = 0; i < datlen; i++) {
|
||||
// 写入数据
|
||||
sectorBuff[sectorBuffptr] = dat[i];
|
||||
sectorBuffptr++;
|
||||
// 扇区回写
|
||||
if (sectorBuffptr == 512 || i == datlen - 1) {
|
||||
SD_WriteDisk(sectorBuff,sectorSour,1);
|
||||
sectorBuffptr = 0;
|
||||
sectorSour++;
|
||||
if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 读取连贯的数据
|
||||
* @param offset 读取位置
|
||||
* @param *dat 数据缓冲区
|
||||
* @param datlen 读取长度
|
||||
* @return 返回值:0,ok;其他,失败.
|
||||
*/
|
||||
u8 bsp_SD::offsetRead(u64 offset,u8* dat,u64 datlen) {
|
||||
u8 sectorBuff[512] = { 0 };
|
||||
u64 sectorBuffptr = 0;
|
||||
|
||||
u64 sectorSour = offset / 512; // 起始扇
|
||||
u64 sectorSourlen = offset % 512; // 起始扇内位
|
||||
|
||||
// 填入数据
|
||||
SD_ReadDisk(sectorBuff,sectorSour,1);
|
||||
sectorBuffptr = sectorSourlen;
|
||||
for (u64 i = 0; i < datlen; i++) {
|
||||
// 写入数据
|
||||
dat[i]=sectorBuff[sectorBuffptr];
|
||||
sectorBuffptr++;
|
||||
// 扇区回写
|
||||
if (sectorBuffptr == 512 || i == datlen - 1) {
|
||||
sectorBuffptr = 0;
|
||||
sectorSour++;
|
||||
if (i != datlen - 1)SD_ReadDisk(sectorBuff,sectorSour,1);}}
|
||||
return 0;}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 构造函数
|
||||
//
|
||||
bsp_SD::bsp_SD(
|
||||
SPI_HandleTypeDef *hspi,
|
||||
GPIO_TypeDef *GPIOx_CS,
|
||||
uint16_t GPIO_Pin_CS){
|
||||
bsp_SD::hspi=hspi;
|
||||
bsp_SD::GPIOx_CS=GPIOx_CS;
|
||||
bsp_SD::GPIO_Pin_CS=GPIO_Pin_CS;
|
||||
bsp_SD::DFF=0xFF;
|
||||
bsp_SD::SD_TYPE=0x00;}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
201
bsp_Device/bsp_SD.h
Normal file
201
bsp_Device/bsp_SD.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_SD.cpp
|
||||
* @brief 操作SD卡的库
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-11-22 03:50
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 头文件
|
||||
//
|
||||
#include "spi.h"
|
||||
#include "varint.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 数据
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//SD卡类型
|
||||
#define ERR 0x00
|
||||
#define MMC 0x01
|
||||
#define V1 0x02
|
||||
#define V2 0x04
|
||||
#define V2HC 0x06
|
||||
#define DUMMY_BYTE 0xFF
|
||||
#define MSD_BLOCKSIZE 512
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//CMD定义
|
||||
#define CMD0 0 //卡复位
|
||||
#define CMD1 1
|
||||
#define CMD8 8 //命令8 ,SEND_IF_COND
|
||||
#define CMD9 9 //命令9 ,读CSD数据
|
||||
#define CMD10 10 //命令10,读CID数据
|
||||
#define CMD12 12 //命令12,停止数据传输
|
||||
#define CMD16 16 //命令16,设置SectorSize 应返回0x00
|
||||
#define CMD17 17 //命令17,读sector
|
||||
#define CMD18 18 //命令18,读Multi sector
|
||||
#define CMD23 23 //命令23,设置多sector写入前预先擦除N个block
|
||||
#define CMD24 24 //命令24,写sector
|
||||
#define CMD25 25 //命令25,写Multi sector
|
||||
#define CMD41 41 //命令41,应返回0x00
|
||||
#define CMD55 55 //命令55,应返回0x01
|
||||
#define CMD58 58 //命令58,读OCR信息
|
||||
#define CMD59 59 //命令59,使能/禁止CRC,应返回0x00
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//数据写入回应字意义
|
||||
#define MSD_DATA_OK 0x05
|
||||
#define MSD_DATA_CRC_ERROR 0x0B
|
||||
#define MSD_DATA_WRITE_ERROR 0x0D
|
||||
#define MSD_DATA_OTHER_ERROR 0xFF
|
||||
//SD卡回应标记字
|
||||
#define MSD_RESPONSE_NO_ERROR 0x00
|
||||
#define MSD_IN_IDLE_STATE 0x01
|
||||
#define MSD_ERASE_RESET 0x02
|
||||
#define MSD_ILLEGAL_COMMAND 0x04
|
||||
#define MSD_COM_CRC_ERROR 0x08
|
||||
#define MSD_ERASE_SEQUENCE_ERROR 0x10
|
||||
#define MSD_ADDRESS_ERROR 0x20
|
||||
#define MSD_PARAMETER_ERROR 0x40
|
||||
#define MSD_RESPONSE_FAILURE 0xFF
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
enum _CD_HOLD {
|
||||
HOLD = 0,
|
||||
RELEASE = 1,
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
typedef struct { /* Card Specific Data */
|
||||
u8 CSDStruct; /* CSD structure */
|
||||
u8 SysSpecVersion; /* System specification version */
|
||||
u8 Reserved1; /* Reserved */
|
||||
u8 TAAC; /* Data read access-time 1 */
|
||||
u8 NSAC; /* Data read access-time 2 in CLK cycles */
|
||||
u8 MaxBusClkFrec; /* Max. bus clock frequency */
|
||||
u16 CardComdClasses; /* Card command classes */
|
||||
u8 RdBlockLen; /* Max. read data block length */
|
||||
u8 PartBlockRead; /* Partial blocks for read allowed */
|
||||
u8 WrBlockMisalign; /* Write block misalignment */
|
||||
u8 RdBlockMisalign; /* Read block misalignment */
|
||||
u8 DSRImpl; /* DSR implemented */
|
||||
u8 Reserved2; /* Reserved */
|
||||
u32 DeviceSize; /* Device Size */
|
||||
u8 MaxRdCurrentVDDMin; /* Max. read current @ VDD min */
|
||||
u8 MaxRdCurrentVDDMax; /* Max. read current @ VDD max */
|
||||
u8 MaxWrCurrentVDDMin; /* Max. write current @ VDD min */
|
||||
u8 MaxWrCurrentVDDMax; /* Max. write current @ VDD max */
|
||||
u8 DeviceSizeMul; /* Device size multiplier */
|
||||
u8 EraseGrSize; /* Erase group size */
|
||||
u8 EraseGrMul; /* Erase group size multiplier */
|
||||
u8 WrProtectGrSize; /* Write protect group size */
|
||||
u8 WrProtectGrEnable; /* Write protect group enable */
|
||||
u8 ManDeflECC; /* Manufacturer default ECC */
|
||||
u8 WrSpeedFact; /* Write speed factor */
|
||||
u8 MaxWrBlockLen; /* Max. write data block length */
|
||||
u8 WriteBlockPaPartial; /* Partial blocks for write allowed */
|
||||
u8 Reserved3; /* Reserded */
|
||||
u8 ContentProtectAppli; /* Content protection application */
|
||||
u8 FileFormatGrouop; /* File format group */
|
||||
u8 CopyFlag; /* Copy flag (OTP) */
|
||||
u8 PermWrProtect; /* Permanent write protection */
|
||||
u8 TempWrProtect; /* Temporary write protection */
|
||||
u8 FileFormat; /* File Format */
|
||||
u8 ECC; /* ECC code */
|
||||
u8 CSD_CRC; /* CSD CRC */
|
||||
u8 Reserved4; /* always 1*/
|
||||
} MSD_CSD;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
typedef struct { /*Card Identification Data*/
|
||||
u8 ManufacturerID; /* ManufacturerID */
|
||||
u16 OEM_AppliID; /* OEM/Application ID */
|
||||
u32 ProdName1; /* Product Name part1 */
|
||||
u8 ProdName2; /* Product Name part2*/
|
||||
u8 ProdRev; /* Product Revision */
|
||||
u32 ProdSN; /* Product Serial Number */
|
||||
u8 Reserved1; /* Reserved1 */
|
||||
u16 ManufactDate; /* Manufacturing Date */
|
||||
u8 CID_CRC; /* CID CRC */
|
||||
u8 Reserved2; /* always 1 */
|
||||
} MSD_CID;
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
MSD_CSD CSD;
|
||||
MSD_CID CID;
|
||||
u32 Capacity; /* Card Capacity */
|
||||
u32 BlockSize; /* Card Block Size */
|
||||
u16 RCA;
|
||||
u8 CardType;
|
||||
u32 SpaceTotal; /* Total space size in file system */
|
||||
u32 SpaceFree;
|
||||
} /* Free space size in file system */
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
MSD_CARDINFO, *PMSD_CARDINFO;
|
||||
extern MSD_CARDINFO SD0_CardInfo;
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 类目
|
||||
//
|
||||
/**
|
||||
* @brief 一个操作SD卡的类
|
||||
*/
|
||||
class bsp_SD{
|
||||
public:
|
||||
bsp_SD(SPI_HandleTypeDef *hspi,GPIO_TypeDef *GPIOx_CS,uint16_t GPIO_Pin_CS);
|
||||
public:
|
||||
u8 SD_init(void);
|
||||
u8 SD_ReadDisk(u8 * buf, u32 sector, u8 cnt);
|
||||
u8 SD_WriteDisk(u8 * buf, u32 sector, u8 cnt);
|
||||
u32 SD_GetSectorCount(void);
|
||||
u8 offsetWrite(u64 offset,u8* dat,u64 datlen);
|
||||
u8 offsetRead(u64 offset,u8* dat,u64 datlen);
|
||||
private:
|
||||
SPI_HandleTypeDef *hspi;
|
||||
GPIO_TypeDef *GPIOx_CS;
|
||||
uint16_t GPIO_Pin_CS;
|
||||
|
||||
u8 DFF;
|
||||
u8 SD_TYPE;
|
||||
MSD_CARDINFO SD0_CardInfo;
|
||||
|
||||
void SD_CS(u8 p);
|
||||
u8 SD_GETCID(u8 * cid_data);
|
||||
u8 SD_GETCSD(u8 * csd_data);
|
||||
int MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo);
|
||||
u8 SD_ReceiveData(u8 * data, u16 len);
|
||||
u8 SD_SendBlock(u8 * buf, u8 cmd);
|
||||
u32 SD_sendcmd(u8 cmd, u32 arg, u8 crc);
|
||||
|
||||
void SPI_setspeed(u8 speed);
|
||||
u8 spi_readwrite(u8 Txdata);
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
|
||||
94
bsp_Device/bsp_flash.c
Normal file
94
bsp_Device/bsp_flash.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_flash.h
|
||||
* @brief 写STM32的Flash库
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-07-13 22:38
|
||||
*/
|
||||
|
||||
|
||||
#include "main.h"
|
||||
uint32_t FlashAddr = 0x08010000; ///< 读写Flash起始地址,跳过程序部分
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#pragma pack(4)
|
||||
/**
|
||||
* @brief 一包数据的内容
|
||||
* @todo 随意更改内部内容方便读取
|
||||
*/
|
||||
struct struct_bsp_Flash_Pack{
|
||||
char Var0;
|
||||
short Var1;
|
||||
int Var2;
|
||||
}bsp_Flash_Pack={0,0,0};
|
||||
#pragma pack()
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 写入一页Flash空间
|
||||
* @param *dat 要写入的数据
|
||||
* @param num 要写入的数量
|
||||
* @return 返回0则成功
|
||||
*/
|
||||
uint32_t bsp_WriteFlashOnePage(uint32_t *dat,uint32_t num){
|
||||
FLASH_EraseInitTypeDef f;
|
||||
uint32_t PageError = 0; //错误号7
|
||||
HAL_FLASH_Unlock(); //解锁FLASH
|
||||
f.TypeErase = FLASH_TYPEERASE_PAGES; //Flash擦除
|
||||
f.PageAddress = FlashAddr; //擦除地址(起始页)
|
||||
f.NbPages = 1; //擦除1页
|
||||
HAL_FLASHEx_Erase(&f,&PageError); //调用擦除函数
|
||||
for(int i=0;i<num;i++)
|
||||
HAL_FLASH_Program(TYPEPROGRAM_WORD,FlashAddr+i*4,dat[i]); //对FLASH烧写
|
||||
HAL_FLASH_Lock(); //锁住FLASH
|
||||
return PageError;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 读取一页Flash空间
|
||||
* @param *dat 读取数据的缓冲区
|
||||
* @param num 读取数量
|
||||
* @return 无返回
|
||||
*/
|
||||
void bsp_ReadFlash(uint32_t *dat,uint32_t num){ //读入一串数据
|
||||
for(int i=0;i<num;i++)
|
||||
dat[i]=*(__IO uint32_t*)(FlashAddr+i*4);}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 将一包数据存入Flash
|
||||
* @return 无返回
|
||||
*/
|
||||
void bsp_WriteFlash_Pack(void){
|
||||
bsp_WriteFlashOnePage((uint32_t*)(&bsp_Flash_Pack),sizeof(struct struct_bsp_Flash_Pack));
|
||||
return;}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief 从Flash读取一包数据
|
||||
* @return 无返回
|
||||
*/
|
||||
void bsp_ReadFlash_Pack(void){
|
||||
bsp_ReadFlash((uint32_t*)(&bsp_Flash_Pack),sizeof(struct struct_bsp_Flash_Pack));
|
||||
return;}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
46
bsp_Device/bsp_flash.h
Normal file
46
bsp_Device/bsp_flash.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2022 Yuankang Liang(XerolySkinner)
|
||||
#
|
||||
# 本软件按原样提供,无任何明示或暗示
|
||||
# 在任何情况下,作者都不承担任何损害赔偿责任
|
||||
#
|
||||
# 使用的许可声明:
|
||||
# 1. 不得歪曲本软件的来源,你不能声称你编写了原始软件.
|
||||
# 2. 免费授予以任何目的,前提是版权声明出现在所有副本中.
|
||||
# 并且版权声明和许可声明同时出现.
|
||||
# 3. 你有使用,复制,修改,分发,和销售本软件的许可.
|
||||
# 4. 如果你在产品中使用,产品文档中的声明是赞赏的但不是必须的.
|
||||
# 5. 本通知不得从任何来源删除或更改.
|
||||
#
|
||||
# Yuankang Liang(XerolySkinner)
|
||||
# E-mail:zabbcccbbaz@163.com
|
||||
# QQ:2715099320
|
||||
# Mobile Phone:13005636215
|
||||
#
|
||||
# All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bsp_flash.h
|
||||
* @brief 写STM32的Flash库
|
||||
* @mainpage 主要信息
|
||||
* @author Yuankang Liang(XerolySkinner)
|
||||
* @email zabbcccbbaz@163.com
|
||||
* @version V1.0.0
|
||||
* @date 2022-07-13 22:38
|
||||
*/
|
||||
|
||||
#ifndef _XEROLYSKINNER_BSP_FLASH_H
|
||||
#define _XEROLYSKINNER_BSP_FLASH_H
|
||||
#include "main.h"
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// 程序
|
||||
//
|
||||
uint32_t bsp_WriteFlashOnePage(uint32_t *dat,uint32_t num);
|
||||
void bsp_ReadFlash(uint32_t *dat,uint32_t num);
|
||||
void bsp_WriteFlash_Pack(void);
|
||||
void bsp_ReadFlash_Pack(void);
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
Reference in New Issue
Block a user