【STM32CubeIDE】 stm32f103的内部Flash读写,double数值读写

单片机stm32f103c8t6,程序存储器64Kb:

对其最后一页,第63页进行读写操作,空间1Kb。

 写入一个32位的数据0x12345678到Flash首地址为0x0800FC00.则在Flash中存储情况如下:

 即,低位地址存储数据的低位,高位地址存储数据的高位。数据的首地址为存储地址的低位。

浮点数存储格式参考:

浮点数double在内存中的存储方式_double存储格式_HeisenbergWDG的博客-CSDN博客

Flash读写参考:

STM32CUBEIDE(16)----内部Flash读写_记帖的博客-CSDN博客

main.c代码:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "rtc.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
uint8_t rxdata1;
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
#ifdef __GNUC__									//串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch;
}/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *///发字符串函数
uint8_t Usart_SendString(const uint8_t* str)
{while(*str!='\0'){if(HAL_UART_Transmit(&huart1, (uint8_t *)str, 1, 1000)!=HAL_OK){return 0;  //发送失败}str++;}return 1;  //发送成功
}void  HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){/* 将接收成功的数据通过串口发出*///HAL_UART_Transmit_IT(&huart1,&rxdata1, 1); //不要在此处用中断式发送,不然会丢失信息HAL_UART_Transmit(&huart1,&rxdata1, 1, 0xffff);//查询法发HAL_UART_Receive_IT(&huart1, &rxdata1, 1);    //重新启,接收1个数}}// 芯片的Flash为64K,最后一页Flash的首地址为0x0x0800FC00,每页1Kb。
#define FLASH_FOR_EEPROM_ADDRESS		0x0800FC00
uint32_t WriteFlashData[3] = {0x12345678,0x22222222,0x33333333};//数据
uint32_t addr = 0x0800FC00; // 芯片的Flash为64K,最后一页Flash的首地址为0x0x0800FC00,每页1Kb。
/*FLASH写入程序*/
void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr)
{uint32_t i=0;/* 1/4解锁FLASH*/HAL_FLASH_Unlock();/* 2/4擦除FLASH*//*初始化FLASH_EraseInitTypeDef*//*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*//*擦除页数*//*擦除地址*/FLASH_EraseInitTypeDef FlashSet;FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;FlashSet.PageAddress = addr;FlashSet.NbPages = 1;/*设置PageError,调用擦除函数*/uint32_t PageError = 0;HAL_FLASHEx_Erase(&FlashSet, &PageError);/* 3/4对FLASH烧写*/for(i=0;i<L;i++){HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);}/* 4/4锁住FLASH*/HAL_FLASH_Lock();
}
/*FLASH读取打印程序*/
void PrintFlashTest(uint32_t L,uint32_t addr)
{uint32_t i=0;for(i=0;i<L;i++){printf("addr is:0x%x, data is:0x%x\n", addr+i*4,  *(__IO uint32_t*)(addr+i*4));}
}double WriteFlashData2[3]={3.5,1234567890,-3.5};
typedef union{double doubleNum;uint64_t u64Num;
} DoubleAndU64;
void WriteFlashDouble(uint32_t L,double Data[],uint32_t addr)
{DoubleAndU64 data2u64;uint32_t i=0;/* 1/4解锁FLASH*/HAL_FLASH_Unlock();/* 2/4擦除FLASH*//*初始化FLASH_EraseInitTypeDef*//*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*//*擦除页数*//*擦除地址*/FLASH_EraseInitTypeDef FlashSet;FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;FlashSet.PageAddress = addr;FlashSet.NbPages = 1;/*设置PageError,调用擦除函数*/uint32_t PageError = 0;HAL_FLASHEx_Erase(&FlashSet, &PageError);/* 3/4对FLASH烧写*/for(i=0;i<L;i++){data2u64.doubleNum=Data[i];HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr+8*i, data2u64.u64Num);}/* 4/4锁住FLASH*/HAL_FLASH_Lock();
}
void PrintFlashDouble(uint32_t L,uint32_t addr)
{DoubleAndU64 data2double;uint32_t i=0;for(i=0;i<L;i++){data2double.u64Num=*(__IO uint64_t*)(addr+i*8);printf("addr is:0x%x, data is:%f\n", addr+i*8, data2double.doubleNum );}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */uint8_t dat1[]={"China "};uint8_t dat2[]={"Back!\r\n"};
//	uint8_t *dat2="7777 ";/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_RTC_Init();/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, &rxdata1, 1);  //中断接收函数WriteFlashDouble(3,WriteFlashData2,addr);PrintFlashDouble(3,addr);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){//记得看看奇偶校验HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);HAL_Delay(2000);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);//	  HAL_UART_Transmit(&huart1,(uint8_t*)"China ",sizeof("China "), 0xffff);HAL_Delay(2000);while(huart1.gState != HAL_UART_STATE_READY);HAL_UART_Transmit_IT(&huart1,dat1,6); //不要在此处用sizeof(dat1),不然下一次连续发送就会失效!while(huart1.gState != HAL_UART_STATE_READY);HAL_UART_Transmit_IT(&huart1,dat2,7);while(huart1.gState != HAL_UART_STATE_READY);printf("Hello\r\n");  //使用printf必须用\n结束!!/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.LSEState = RCC_LSE_ON;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

debug中的memory:

正好对应WriteFlashData2[3]={3.5,1234567890,-3.5}中的三个双精度浮点数。

串口打印出来的数据,与实际一致。

这里double类型数据的存储,采用了联合体(union)完成的。

完整stm32cubeide工程:

https://download.csdn.net/download/fengyuzhe13/88049497

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/23016.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Linq 详解三

目录 概述 十三、Sum / Min / Max / Average 十四、Distinct 十五、Concat 十六、Join 十七、ToList 十八、ToArray 十九、ToDictionary C# Linq 详解一 1.Where 2.Select 3.GroupBy 4.First / FirstOrDefault 5.Last / LastOrDefault C# Linq 详解二 1.OrderBy 2.O…

【优选算法题练习】day6

文章目录 一、76. 最小覆盖子串1.题目简介2.解题思路3.代码4.运行结果 二、704. 二分查找1.题目简介2.解题思路3.代码4.运行结果 三、34. 在排序数组中查找元素的第一个和最后一个位置1.题目简介2.解题思路3.代码4.运行结果 总结 一、76. 最小覆盖子串 1.题目简介 76. 最小覆…

拓宽“主航道”的Serverless与EDA领域,亚马逊云科技不断创新开拓

在新潮如走马灯般变换的时尚界&#xff0c;每隔几年就会刮起一阵复古风。被誉为“时尚教父”的著名设计师安德烈莱昂塔利曾说&#xff1a;“时尚总是在寻找新的灵感和方向&#xff0c;而复古是其中一个重要的来源。” 无独有偶。日新月异的高科技领域也会出现公认的“过时”…

单片机第一季:零基础6——按键

目录 1&#xff0c;独立按键 2&#xff0c;矩阵按键 &#xff08;注意&#xff1a;文章中的代码仅供参考学习&#xff0c;实际使用时要根据需要修改&#xff09; 1&#xff0c;独立按键 按键管脚两端距离长的表示默认是导通状态&#xff0c;距离短的默认是断开状态&#xf…

【监控系统】Prometheus监控组件Mysql-Exporter配置实战

Mysql-Exporter主要监控Mysql数据库的稳定性、吞吐量、连接情况、缓冲池使用情况、查询性能等各项指标&#xff0c;是我们压测时常常需要监控的一些指标。 目前&#xff0c;Exporter 支持高于5.6版本的 MySQL 和高于10.1版本的 MariaDB。在 MySQL/MariaDB 低于5.6版本时&#…

Jmeter接口关联(四)【使用正则表达式提取值】关联上下接口实际当中的运用

文章目录 前言一、Jmeter中正则表达式的运用&#xff08;使用案例讲解&#xff09;注意 前言 这篇主要是用一个实际的例子讲解正则表达式在2个有关联的接口中运用。 天气预报接口&#xff1a; 请求Key&#xff1a;79a35e2a5997710f3bdc86de81f21dbb 根据城市查询天气 接口地…

WSL2 忘记用户密码

步骤一&#xff1a;将默认用户切换为root 在Windows里启动命令提示符&#xff0c;输入&#xff1a; ubuntu2004 config --default-user root这就已经将我的ubuntu20.04的默认用户切换为了root&#xff0c; 不同的WSL版本可能命令的第一个符号不一样&#xff0c;区别如下图&am…

网络安全设备Bypass功能介绍及分析

网络安全平台厂商往往需要用到一项比较特殊的技术&#xff0c;那就是Bypass&#xff0c;那么到底什么是Bypass呢&#xff0c;Bypass设备又是如何来实现的&#xff1f;下面我就对Bypass技术做一下简单的介绍和说明。 一、 什么是Bypass。 大家知道&#xff0c;网络安全设备一般…

K8s为什么需要calico? calico 原理深入理解.

文章目录 为什么需要calico&#xff1f;-网络插件”千千万”&#xff0c;为何k8s要用calicocalico的架构calico Pod 跨node通信tunl0 的作用&#xff1f;为什么所有pod的默认网关都是169.254.1.1 &#xff1f;什么是ARP 代理&#xff1f;jksj BGP模式的calico工作原理calico BG…

《深度学习推荐系统》笔记

目录 一、推荐系统是什么1.作用和意义2.推荐系统的架构2.1 逻辑架构2.2 技术架构 二、传统的推荐系统方法1. 协同过滤算法1.1 userCF&&ItemCF1.3 矩阵分解算法 2. 逻辑回归算法3. 因子分解机3.1 POLY2模型3.2 FM模型3.3 FFM模型3.4 小结 4. 组合模型4.1 GBDTLR组合模型…

MySQL 事务与存储引擎

目录 一、MySQL事务的概念 二、事务的ACID特点 2.1 原子性 2.2 一致性 2.3 隔离性 2.4 持久性 2.5 事务之间的相互影响 三、Mysql及事物隔离级别 3.1 查询全局事务隔离级别 3.2 查询会话事务隔离级别 3.3 设置全局事务隔离级别 3.4 设置会话事务隔离级别 …

剑指oferr68-II.二叉树的最近公共祖先

为什么这道题的难度是easy&#xff0c;我感觉挺难的啊&#xff0c;我想了挺久没有一点思路就直接看题解了。题解有两种解法&#xff0c;先看第一种存储父节点 class Solution {Map<Integer,TreeNode> parent new HashMap<Integer,TreeNode>();Set<Integer>…