首页 > 其他分享 >stm32 f4 SRAM

stm32 f4 SRAM

时间:2024-06-02 11:30:06浏览次数:21  
标签:__ f4 SRAM stm32 编译 BKPSRAM 头文件 include

        备用SRAM是很好的临时数据保存单元,一些需要掉电后保存的数据建议使用备用SRAM保存,只有需要永久保存的数据再用FLASH进行保存。

SRAM地址范围

电源与复位相关的库文件(备用域的电池管理)

#ifndef BKPSRAM_BKPSRAM_H_
#define BKPSRAM_BKPSRAM_H_

#include "stm32f4xx_hal.h"

#define BKPSRAM_BEGIN 	0x40024000 //备用SRAM的起始地址
#define BKPSRAM_END  	0x40024FFF //备用SRAM的结束地址

void US_BKPSRAM_INIT(void);//备用SRAM初始化
uint8_t US_BKPSRAM_WRITE_BYTE(uint32_t Bkpsram_Add,uint8_t *pBuffer,uint32_t Num); //8位字节写备用SRAM
void US_BKPSRAM_READ_BYTE (uint32_t Bkpsram_Add,uint8_t *pBuffer,uint32_t Num);    //8位字节读备用SRAM

#endif /* BKPSRAM_BKPSRAM_H_ */
#include "bkpsram.h"

void US_BKPSRAM_INIT(void){//备用SRAM初始化
	__HAL_RCC_PWR_CLK_ENABLE();//使能PWR电源时钟(即开启备用域时钟)
	HAL_PWR_EnableBkUpAccess(); //使能备用域写(取消写保护)
	__HAL_RCC_BKPSRAM_CLK_ENABLE();//使能备用SRAM时钟
	HAL_PWREx_EnableBkUpReg(); //使能备用域稳压器
}

uint8_t US_BKPSRAM_WRITE_BYTE(uint32_t Bkpsram_Add,uint8_t *pBuffer,uint32_t Num){//以8位字节写备用SRAM(参数:地址,数据内容,数量)
	uint32_t a=0;
	if(Bkpsram_Add<BKPSRAM_BEGIN || (Bkpsram_Add+Num)>BKPSRAM_END)return 1;//如地址不在备用SRAM地址区间,返回错误代码1
	while(a < Num){//循环写入,直到最大数量
		*(__IO uint8_t *)(Bkpsram_Add+a) = *pBuffer;//向备用SRAM写入数据
		pBuffer++; a++;//指针地址加1,数量加1
	}
	return 0;
}

void US_BKPSRAM_READ_BYTE (uint32_t Bkpsram_Add,uint8_t *pBuffer,uint32_t Num){ //以字节读出备用SRAM(参数:备用SRAM地址,存放数组,数量)
	uint32_t a=0;
	while(a < Num){//循环读取,直到最大数量
    	*pBuffer = *(__IO uint8_t*)(Bkpsram_Add + a); //读出1个字节数据
    	pBuffer++; a++;//指针地址加1,数量加1
    }
}

库和头文件的关系
平时我们写程序都必须 include 很多头文件,因为可以避免重复造轮子,软件大厦可不是单靠一个人就能完成的。但是你是否知道引用的那些头文件中的函数是怎么被执行的呢?这就要牵扯到链接库了!

库有两种,一种是 静态链接库,一种是 动态链接库,不管是哪一种库,要使用它们,都要在程序中包含相应的 include 头文件。我们先来回顾一下程序编译的过程。

)宏常量

一般在main函数的上面声明,用大写命名。

语法:#define 常量名 值

)常量的特点

程序中不允许改变常量的值,否则编译的时候会报错。

编译预处理

C++程序编译的过程:预处理 -> 编译(优化、汇编)-> 链接

预处理指令主要有以下三种:

  1. 包含头文件:#include
  2. 宏定义:#define(定义宏)、#undef(删除宏)。
  3. 条件编译:#ifdef、#ifndef。

1)包含头文件

#include 包含头文件有两种方式:

  1. #include <文件名>:直接从编译器自带的函数库目录中寻找文件。
  2. #include "文件名":先从自定义的目录中寻找文件,如果找不到,再从编译器自带的函数库目录中寻找。

#include也包含其它的文件,如:*.h、*.cpp或其它的文件。

C++98标准后的头文件:

  1. C的标准库:老版本的有.h后缀;新版本没有.h的后缀,增加了字符c的前缀。例如:老版本是<stdio.h>,新版本是<cstdio>,新老版本库中的内容是一样的。在程序中,不指定std命名空间也能使用库中的内容。
  2. C++的标准库:老版本的有.h后缀;新版本没有.h的后缀。例如:老版本是<iostream.h>,新版本是<iostream>,老版本已弃用,只能用新版本。在程序中,必须指定std命名空间才能使用库中的内容。

注意:用户自定义的头文件还是用.h为后缀。

2)宏定义指令

无参数的宏:#define 宏名  宏内容

有参数的宏:#define MAX(x,y)  ((x)>(y) ? (x) : (y))    MAX(3,5)  ((3)>(5) ? (3) : (5))

编译的时候,编译器把程序中的宏名用宏内容替换,是为宏展开(宏替换)。

宏可以只有宏名,没有宏内容。

在C++中,内联函数可代替有参数的宏,效果更好。

C++中常用的宏:

  1. 当前源代码文件名:__FILE__
  2. 当前源代码函数名:__FUNCTION__
  3. 当前源代码行号:__LINE__
  4. 编译的日期:__DATE__
  5. 编译的时间:__TIME__
  6. 编译的时间戳:__TIMESTAMP__
  7. 当用C++编译程序时,宏__cplusplus就会被定义。

3)条件编译

最常用的两种:#ifdef、#ifndef    if #define  if not #define

#ifdef 宏名

  程序段一

#else

  程序段二

#endif

含义:如果#ifdef后面的宏名已存在,则使用程序段一,否则使用程序段二。

#ifndef 宏名

  程序段一

#else

  程序段二

#endif

含义:如果#ifndef后面的宏名不存在,则使用程序段一,否则使用序段二。

4)解决头文件中代码重复包含的问题

在C/C++中,在使用预编译指令#include的时候,为了防止头文件被重复包含,有两种方式。

第一种:用#ifndef指令

#ifndef _GIRL_

    #define _GIRL_

    //代码内容。

#endif

第二种:把#pragma once指令放在文件的开头。

#ifndef方式受C/C++语言标准的支持,不受编译器的任何限制;而#pragma once方式有些编译器不支持。

#ifndef可以针对文件中的部分代码;而#pragma once只能针对整个文件。

#ifndef更加灵活,兼容性好;#pragma once操作简单,效率高。

166、编译和链接

一、源代码的组织

头文件(*.h):#include头文件、函数的声明、结构体的声明、类的声明、模板的声明、内联函数、#define和const定义的常量等。

源文件(*.cpp):函数的定义、类的定义、模板具体化的定义。

主程序(main函数所在的程序):主程序负责实现框架和核心流程,把需要用到的头文件用#include包含进来。

二、编译预处理

预处理的包括以下方面: 

1)处理#include头文件包含指令。

2)处理#ifdef #else #endif、#ifndef #else #endif条件编译指令。

3)处理#define宏定义。

4)为代码添加行号、文件名和函数名。

5)删除注释。

6)保留部分#pragma编译指令(编译的时候会用到)。

三、编译

将预处理生成的文件,经过词法分析、语法分析、语义分析以及优化和汇编后,编译成若干个目标文件(二进制文件)。

四、链接

将编译后的目标文件,以及它们所需要的库文件链接在一起,形成一个体整。

五、更多细节

1)分开编译的好处:每次只编译修改过的源文件,然后再链接,效率最高。

2)编译单个*.cpp文件的时候,必须要让编译器知道名称的存在,否则会出现找不到标识符的错误。(直接和间接包含头文件都可以)

3)编译单个*.cpp文件的时候,编译器只需要知道名称的存在,不会把它们的定义一起编译

4)如果函数和类的定义不存在,编译不会报错,但链接会出现无法解析的外部命令。

5)链接的时候,变量、函数和类的定义只能有一个,否则会出现重定义的错误。(如果把变量、函数和类的定义放在*.h文件中,*.h会被多次包含,链接前可能存在多个副本;如果放在*.cpp文件中,*.cpp文件不会被包含,只会被编译一次,链接前只存在一个版本)

6)把变量、函数和类的定义放在*.h中是不规范的做法,如果*.h被多个*.cpp包含,会出现重定义。

7)用#include包含*.cpp也是不规范的做法,原理同上。

8)尽可能不使用全局变量,如果一定要用,要在*.h文件中声明(需要加extern关键字),在*.cpp文件中定义。

9)全局的const常量在头文件中定义(const常量仅在单个文件内有效)。

10)*.h文件重复包含的处理方法只对单个的*.cpp文件有效,不是整个项目。

11)函数模板和类模板的声明和定义可以分开书写,但它们的定义并不是真实的定义,只能放在*.h文件中;函数模板和类模板的具体化版本的代码是真实的定义,所以放在*.cpp文件中。

12)Linux下C++编译和链接的原理与VS一样。

逻辑运算

根据给定的逻辑因子(表达式或值)返回一个新的逻辑因子。

运算符

术语

示例

结果

&&

逻辑与

a&&b;

如果a和b都为真,则结果为真,否则为假。

||

逻辑或

a||b;

如果a和b中有一个为真,则结果为真,二者都为假时,结果为假。

!

逻辑非(反)

!a;

如果a为假,则!a为真; 如果a为真,则!a为假。

注意:

  1. 逻辑运算符的两边可以是数值,也可以是表达式;
  2. 用std::cout输出逻辑运算表达式时,逻辑表达式要加括号;
  3. 在实际开发中,逻辑运算的多重组合是重点。

指针用于函数的参数

使用地址可以提升效率

如果把函数的形参声明为指针,调用的时候把实参的地址传进去,形参中存放的是实参的地址,在函数中通过解引用的方法直接操作内存中的数据,可以修改实数的值,这种方法被通俗的称为地址传递传地址

如果函数返回值需要多个结果可以用地址

标签:__,f4,SRAM,stm32,编译,BKPSRAM,头文件,include
From: https://blog.csdn.net/weixin_55418511/article/details/139383968

相关文章

  • 基于stm32的智能家居系统
    目录1.课题研究目的和内容1.1课题研究目的1.2课题研究内容2.系统总体方案设计及功能模块介绍2.1总体方案设计2.2 DHT11模块介绍2.3  TFTLCD显示功能模块介绍2.4 ESP8266WIFI模块介绍2.5 MQ-135空气质量模块介绍2.6 步进电机模块介绍2.7 ......
  • 基于标准库的STM32的外部中断EXTI
            毕设已经告一段落了,接下来准备开始整理一下毕设中用到的知识与技术细节,今天整理的是STM32从编码器获取数据的方式-----外部中断(EXTI):外部中断分为四个硬件相关外设,GPIO/AFIO/EXTI/NVIC(EXTI/NVIC不需要开启时钟)1.RCC开启时钟RCC_APB2PeriphClockCmd(RCC_APB2P......
  • 基于FREERTOS的STM32多功能手表(软件设计)
    目录前言程序现象 项目背景项目介绍目前版本实现的功能设计到的freertos知识使用到的硬件硬件连线图实现思路任务调度流程图​编辑 任务具体操作导图      代码讲解freertos初始化按键中断回调函数显示时间任务显示菜单任务其它任务(ShowCalenda......
  • 基于MBD的电机控制算法开发-STM32
    使用simulink搭建V/F电机控制框架,并集成到STM32F4中1.Simulink模型搭建本例子使用V/F拖动启动方法控制永磁同步电机启动,simulink模型其中V/F启动部分输出d,q轴的期望电压,并通过SVPWM调制算法施加到电机的三相:模型的输入为空,模型输出为为三路PWM波的占空比。function[ud_out,u......
  • STM32学习笔记(二)流水灯
    STM32学习笔记(二)流水灯一、原理部分1.1LED原理1.2GPIO原理二、工程部分三、加入宏定义这次我们来实现LED流水灯成为点灯大师。使用的核心板的MCU型号为STM32F103ZET6,使用标准库函数来实现。一、原理部分1.1LED原理其中PWR是系统电源指示灯,为蓝色。LED0......
  • 杂项——STM32ZET6要注意的一些问题——高级定时器问题和PB3,PB4引脚问题
    ZET6可能会用到定时器,高级定时器要输出PWM要加上这样一行代码,否则无法正常输出PWM波TIM_CtrlPWMOutputs(TIM8,ENABLE); //主输出使能,当使用的是通用定时器时,这句不需要ZET6中PB3,PB4引脚默认功能是JTDO和NJTRST,如果想将其当作正常IO口使用需要加上两行代码 RCC_APB2Pe......
  • (中文参数)可编程逻辑IC 5SGXEB6R2F40I2G、5SGXEB6R2F40I3G、5SGXEB6R3F40I3G、5SGXEB6R
    概述StratixV是业内第一款可提供精度可变DSP模块的FPGA,这使得它可提供业内效率最高、性能最好的多精度DSP数据通路和功能,如FFT、FIR和浮点DSP。StratixVFPGA具有1.6Tbps串行交换能力,采用各种创新技术和前沿28-nm工艺,突破带宽瓶颈,降低了宽带应用的成本和功耗。StratixVFP......
  • Linux低功耗Suspend/Resume梳理(基于STM32MP1)
    基于STM32MP1简单梳理Linuxsuspend/resume涉及到的内容:触发Suspend流程,以及唤醒手段和后续resume流程。Linuxkernel中Suspend/Resume流程。TFA中冷启动、热启动、SMC处理、PSCI实现等等。其他低功耗相关:poweroff、reboot、fiq处理。PowerDomainTree介绍;PSCI移植指导等。......
  • STM32和ESP32哪个更适合初学者
    对于初学者来说,STM32和ESP32都有各自的优点和适用场景,但考虑到初学者的学习曲线和资源可用性,以下是对两者的一些比较和建议:STM32优点:丰富的教程和社区支持:STM32拥有庞大的用户群体和活跃的社区,这意味着你可以找到大量的教程、示例代码和解答问题的资源。完善的开发环境:STM32......
  • 新手学习STM32还是ESP32
    对于新手来说,选择学习STM32还是ESP32取决于个人的学习目标和背景。以下是针对这两种微控制器的详细分析,以便您做出更明智的选择:STM321.处理器架构与性能STM32采用单核或多核处理器架构,基于ARMCortex®-M0,M0+,M3,M4和M7内核。这些内核具有高性能,优化的指令集和较大的内存,能够......