[STM32F1] stm32f103的内部Flash读写,double数值读写

[复制链接]
1266|14
 楼主| 雨果喝水 发表于 2023-11-27 22:51 | 显示全部楼层 |阅读模式
单片机stm32f103c8t6,程序存储器64Kb:
498136564acd77f61a.png

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

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

506546564acea8d5d7.png

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


 楼主| 雨果喝水 发表于 2023-11-27 22:51 | 显示全部楼层
main.c代码:
  1. /* USER CODE BEGIN Header */
  2. /**
  3.   ******************************************************************************
  4.   * [url=home.php?mod=space&uid=288409]@file[/url]           : main.c
  5.   * [url=home.php?mod=space&uid=247401]@brief[/url]          : Main program body
  6.   ******************************************************************************
  7.   * @attention
  8.   *
  9.   * Copyright (c) 2022 STMicroelectronics.
  10.   * All rights reserved.
  11.   *
  12.   * This software is licensed under terms that can be found in the LICENSE file
  13.   * in the root directory of this software component.
  14.   * If no LICENSE file comes with this software, it is provided AS-IS.
  15.   *
  16.   ******************************************************************************
  17.   */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "main.h"
  21. #include "rtc.h"
  22. #include "usart.h"
  23. #include "gpio.h"

  24. /* Private includes ----------------------------------------------------------*/
  25. /* USER CODE BEGIN Includes */
  26. #include "stdio.h"
  27. /* USER CODE END Includes */

  28. /* Private typedef -----------------------------------------------------------*/
  29. /* USER CODE BEGIN PTD */

  30. /* USER CODE END PTD */

  31. /* Private define ------------------------------------------------------------*/
  32. /* USER CODE BEGIN PD */
  33. /* USER CODE END PD */

  34. /* Private macro -------------------------------------------------------------*/
  35. /* USER CODE BEGIN PM */

  36. /* USER CODE END PM */

  37. /* Private variables ---------------------------------------------------------*/

  38. /* USER CODE BEGIN PV */
  39. uint8_t rxdata1;
  40. /* USER CODE END PV */

  41. /* Private function prototypes -----------------------------------------------*/
  42. void SystemClock_Config(void);
  43. /* USER CODE BEGIN PFP */
  44. #ifdef __GNUC__                                                                        //串口重定向
  45. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  46. #else
  47. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  48. #endif
  49. PUTCHAR_PROTOTYPE
  50. {
  51.     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
  52.     return ch;
  53. }

  54. /* USER CODE END PFP */

  55. /* Private user code ---------------------------------------------------------*/
  56. /* USER CODE BEGIN 0 */

  57. //发字符串函数
  58. uint8_t Usart_SendString(const uint8_t* str)
  59. {

  60.         while(*str!='\0')
  61.         {
  62.                 if(HAL_UART_Transmit(&huart1, (uint8_t *)str, 1, 1000)!=HAL_OK)
  63.                 {
  64.                         return 0;  //发送失败
  65.                 }
  66.                 str++;
  67.         }
  68.         return 1;  //发送成功
  69. }

  70. void  HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  71. {
  72.         if (huart->Instance == USART1){
  73.         /* 将接收成功的数据通过串口发出*/
  74.         //HAL_UART_Transmit_IT(&huart1,&rxdata1, 1); //不要在此处用中断式发送,不然会丢失信息
  75.         HAL_UART_Transmit(&huart1,&rxdata1, 1, 0xffff);//查询法发
  76.         HAL_UART_Receive_IT(&huart1, &rxdata1, 1);    //重新启,接收1个数
  77.         }

  78. }

  79. // 芯片的Flash为64K,最后一页Flash的首地址为0x0x0800FC00,每页1Kb。
  80. #define FLASH_FOR_EEPROM_ADDRESS                0x0800FC00
  81. uint32_t WriteFlashData[3] = {0x12345678,0x22222222,0x33333333};//数据
  82. uint32_t addr = 0x0800FC00; // 芯片的Flash为64K,最后一页Flash的首地址为0x0x0800FC00,每页1Kb。
  83. /*FLASH写入程序*/
  84. void WriteFlashTest(uint32_t L,uint32_t Data[],uint32_t addr)
  85. {
  86.         uint32_t i=0;
  87.         /* 1/4解锁FLASH*/
  88.         HAL_FLASH_Unlock();
  89.         /* 2/4擦除FLASH*/
  90.         /*初始化FLASH_EraseInitTypeDef*/
  91.         /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/
  92.         /*擦除页数*/
  93.         /*擦除地址*/
  94.         FLASH_EraseInitTypeDef FlashSet;
  95.         FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;
  96.         FlashSet.PageAddress = addr;
  97.         FlashSet.NbPages = 1;
  98.         /*设置PageError,调用擦除函数*/
  99.         uint32_t PageError = 0;
  100.         HAL_FLASHEx_Erase(&FlashSet, &PageError);
  101.         /* 3/4对FLASH烧写*/
  102.         for(i=0;i<L;i++)
  103.         {
  104.                 HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr+4*i, Data[i]);
  105.         }
  106.         /* 4/4锁住FLASH*/
  107.         HAL_FLASH_Lock();
  108. }
  109. /*FLASH读取打印程序*/
  110. void PrintFlashTest(uint32_t L,uint32_t addr)
  111. {
  112.         uint32_t i=0;
  113.         for(i=0;i<L;i++)
  114.         {
  115.                 printf("addr is:0x%x, data is:0x%x\n", addr+i*4,  *(__IO uint32_t*)(addr+i*4));
  116.         }
  117. }

  118. double WriteFlashData2[3]={3.5,1234567890,-3.5};
  119. typedef union{
  120.         double doubleNum;
  121.         uint64_t u64Num;
  122. } DoubleAndU64;
  123. void WriteFlashDouble(uint32_t L,double Data[],uint32_t addr)
  124. {
  125.         DoubleAndU64 data2u64;
  126.         uint32_t i=0;

  127.         /* 1/4解锁FLASH*/
  128.         HAL_FLASH_Unlock();
  129.         /* 2/4擦除FLASH*/
  130.         /*初始化FLASH_EraseInitTypeDef*/
  131.         /*擦除方式页擦除FLASH_TYPEERASE_PAGES,块擦除FLASH_TYPEERASE_MASSERASE*/
  132.         /*擦除页数*/
  133.         /*擦除地址*/
  134.         FLASH_EraseInitTypeDef FlashSet;
  135.         FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;
  136.         FlashSet.PageAddress = addr;
  137.         FlashSet.NbPages = 1;
  138.         /*设置PageError,调用擦除函数*/
  139.         uint32_t PageError = 0;
  140.         HAL_FLASHEx_Erase(&FlashSet, &PageError);

  141.         /* 3/4对FLASH烧写*/
  142.         for(i=0;i<L;i++)
  143.         {
  144.                 data2u64.doubleNum=Data[i];
  145.                 HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr+8*i, data2u64.u64Num);
  146.         }
  147.         /* 4/4锁住FLASH*/
  148.         HAL_FLASH_Lock();
  149. }
  150. void PrintFlashDouble(uint32_t L,uint32_t addr)
  151. {
  152.         DoubleAndU64 data2double;
  153.         uint32_t i=0;
  154.         for(i=0;i<L;i++)
  155.         {
  156.                 data2double.u64Num=*(__IO uint64_t*)(addr+i*8);
  157.                 printf("addr is:0x%x, data is:%f\n", addr+i*8, data2double.doubleNum );
  158.         }
  159. }

  160. /* USER CODE END 0 */

  161. /**
  162.   * @brief  The application entry point.
  163.   * @retval int
  164.   */
  165. int main(void)
  166. {
  167.   /* USER CODE BEGIN 1 */
  168.         uint8_t dat1[]={"China "};
  169.         uint8_t dat2[]={"Back!\r\n"};
  170. //        uint8_t *dat2="7777 ";
  171.   /* USER CODE END 1 */

  172.   /* MCU Configuration--------------------------------------------------------*/

  173.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  174.   HAL_Init();

  175.   /* USER CODE BEGIN Init */

  176.   /* USER CODE END Init */

  177.   /* Configure the system clock */
  178.   SystemClock_Config();

  179.   /* USER CODE BEGIN SysInit */

  180.   /* USER CODE END SysInit */

  181.   /* Initialize all configured peripherals */
  182.   MX_GPIO_Init();
  183.   MX_USART1_UART_Init();
  184.   MX_RTC_Init();
  185.   /* USER CODE BEGIN 2 */

  186.   HAL_UART_Receive_IT(&huart1, &rxdata1, 1);  //中断接收函数


  187.         WriteFlashDouble(3,WriteFlashData2,addr);
  188.         PrintFlashDouble(3,addr);

  189.   /* USER CODE END 2 */

  190.   /* Infinite loop */
  191.   /* USER CODE BEGIN WHILE */

  192.   while (1)
  193.   {
  194.           //记得看看奇偶校验
  195.           HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
  196.           HAL_Delay(2000);
  197.           HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);

  198. //          HAL_UART_Transmit(&huart1,(uint8_t*)"China ",sizeof("China "), 0xffff);
  199.           HAL_Delay(2000);
  200.           while(huart1.gState != HAL_UART_STATE_READY);
  201.           HAL_UART_Transmit_IT(&huart1,dat1,6); //不要在此处用sizeof(dat1),不然下一次连续发送就会失效!
  202.           while(huart1.gState != HAL_UART_STATE_READY);
  203.           HAL_UART_Transmit_IT(&huart1,dat2,7);


  204.           while(huart1.gState != HAL_UART_STATE_READY);
  205.       printf("Hello\r\n");  //使用printf必须用\n结束!!

  206.     /* USER CODE END WHILE */

  207.     /* USER CODE BEGIN 3 */
  208.   }
  209.   /* USER CODE END 3 */
  210. }

  211. /**
  212.   * @brief System Clock Configuration
  213.   * @retval None
  214.   */
  215. void SystemClock_Config(void)
  216. {
  217.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  218.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  219.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  220.   /** Initializes the RCC Oscillators according to the specified parameters
  221.   * in the RCC_OscInitTypeDef structure.
  222.   */
  223.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
  224.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  225.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  226.   RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  227.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  228.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  229.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  230.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  231.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  232.   {
  233.     Error_Handler();
  234.   }

  235.   /** Initializes the CPU, AHB and APB buses clocks
  236.   */
  237.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  238.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  239.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  240.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  241.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  242.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  243.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  244.   {
  245.     Error_Handler();
  246.   }
  247.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  248.   PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  249.   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  250.   {
  251.     Error_Handler();
  252.   }
  253. }

  254. /* USER CODE BEGIN 4 */

  255. /* USER CODE END 4 */

  256. /**
  257.   * @brief  This function is executed in case of error occurrence.
  258.   * @retval None
  259.   */
  260. void Error_Handler(void)
  261. {
  262.   /* USER CODE BEGIN Error_Handler_Debug */
  263.   /* User can add his own implementation to report the HAL error return state */
  264.   __disable_irq();
  265.   while (1)
  266.   {
  267.   }
  268.   /* USER CODE END Error_Handler_Debug */
  269. }

  270. #ifdef  USE_FULL_ASSERT
  271. /**
  272.   * @brief  Reports the name of the source file and the source line number
  273.   *         where the assert_param error has occurred.
  274.   * @param  file: pointer to the source file name
  275.   * @param  line: assert_param error line source number
  276.   * @retval None
  277.   */
  278. void assert_failed(uint8_t *file, uint32_t line)
  279. {
  280.   /* USER CODE BEGIN 6 */
  281.   /* User can add his own implementation to report the file name and line number,
  282.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  283.   /* USER CODE END 6 */
  284. }
  285. #endif /* USE_FULL_ASSERT */
 楼主| 雨果喝水 发表于 2023-11-27 22:52 | 显示全部楼层
debug中的memory:
960996564ad2ec2643.png
正好对应WriteFlashData2[3]={3.5,1234567890,-3.5}中的三个双精度浮点数。
 楼主| 雨果喝水 发表于 2023-11-27 22:52 | 显示全部楼层
串口打印出来的数据,与实际一致。
902236564ad4594660.png
 楼主| 雨果喝水 发表于 2023-11-27 22:53 | 显示全部楼层
这里double类型数据的存储,采用了联合体(union)完成的。
公羊子丹 发表于 2024-8-1 07:01 | 显示全部楼层

主电路那些环路产生的噪声会加到控制信号上
万图 发表于 2024-8-1 08:04 | 显示全部楼层

多次检查也会给单片机带来负荷,对功耗不利
Uriah 发表于 2024-8-1 09:07 | 显示全部楼层

在GR-SAKURA中,从IO30引脚到IO35引脚接收来自外部的中断信号
帛灿灿 发表于 2024-8-1 11:03 | 显示全部楼层

在掌握对象的变化频度时是有效的
Bblythe 发表于 2024-8-1 12:06 | 显示全部楼层

中断信号直接从各外部设备通知中断控制器
周半梅 发表于 2024-8-1 14:02 | 显示全部楼层

通过交流电源插头从产品中流走
Pulitzer 发表于 2024-8-1 15:05 | 显示全部楼层

来自单 片机内部的定时器和GPIO、串行通信设备UART等外设机器的中断被称为外部设备中断
童雨竹 发表于 2024-8-1 17:01 | 显示全部楼层

交流电压在发射EMI
Wordsworth 发表于 2024-8-1 18:04 | 显示全部楼层

中断产生于单片机内部和外部的各种设备
Clyde011 发表于 2024-8-1 19:07 | 显示全部楼层

这样的设定只需在setup()中定义一次便能在整个程序中有效
您需要登录后才可以回帖 登录 | 注册

本版积分规则

90

主题

1213

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部