活动介绍

/* magic code on every sector header. 'EF' is 0xEF30EF30 */ #define LOG_SECTOR_MAGIC 0xEF30EF30 /* sector header size, includes the sector magic code and status magic code */ #define LOG_SECTOR_HEADER_SIZE 12 /* sector header word si

时间: 2025-08-30 08:11:08 AIGC 浏览: 9
<think>好的,我现在要解决用户关于EF30EF30和LOG_SECTOR_HEADER_SIZE的问题。首先,我需要查看用户提供的引用内容,看看有没有相关的线索。用户给出的引用[1]是关于ef_port_init()函数的修改,里面提到了将ef_port_init()的引用定义从w25q64改为sfud_dev。这可能涉及到嵌入式系统中的Flash存储管理,特别是使用SFUD(Serial Flash Universal Driver)库的情况。 首先,EF30EF30看起来像是一个十六进制的数值。在嵌入式系统中,这样的数值常用来表示特定的标识符或魔数(magic number),用于识别数据结构或配置的有效性。例如,在文件系统或日志系统中,魔数用来标识一个扇区的开始或验证数据的完整性。我需要确认这个值是否是某个特定的标识符,比如日志扇区的头部标识。 接下来是LOG_SECTOR_HEADER_SIZE,这应该是指日志扇区头部的字节大小。通常,日志系统会将存储空间划分为多个扇区,每个扇区有一个头部,用于存储元数据,比如魔数、版本号、校验和、扇区状态等信息。头部的大小需要根据这些字段的总和来计算,确保数据结构对齐和正确解析。 现在,我需要结合用户提供的代码片段进行分析。在代码中,flash变量被赋值为sfud_dev->user_data,这说明使用的是SFUD库来操作Flash设备。SFUD通常会抽象不同的SPI Flash芯片,提供统一的API。而EfEnv(可能指EasyFlash的环境变量模块)在这里进行了初始化,设置默认的环境变量和锁机制。 EF30EF30可能是在EasyFlash或类似库中定义的日志扇区魔数。例如,在EasyFlash中,日志存储模块可能使用特定的魔数来标识扇区的开始,确保在读取时能够正确识别有效数据。魔数通常为4字节或8字节,这里EF30EF30是4字节的十六进制数,转换成ASCII字符的话,可能对应某些字母或符号,但更可能是一个随机选择的数值,用于唯一标识。 LOG_SECTOR_HEADER_SIZE则是日志扇区头部的结构体大小。假设头部包含魔数(4字节)、扇区状态(1字节)、校验和(如CRC32,4字节)、扇区编号(4字节)等信息,总大小可能为4+1+4+4=13字节,但实际中会根据对齐要求调整,比如16字节。需要查看具体的结构体定义才能确定,但用户没有提供这部分代码,所以只能根据常见情况进行推测。 总结来说,EF30EF30是日志扇区的标识符,用于确认扇区数据的有效性,而LOG_SECTOR_HEADER_SIZE是头部结构的大小,确保正确读取和写入元数据。用户可能需要查阅EasyFlash的文档或源码中的相关定义,以获取准确的信息。</think>关于$EF30EF30$的定义与$LOG\_SECTOR\_HEADER\_SIZE$的含义,结合代码上下文分析如下: ### 1. EF30EF30的定义解析 $EF30EF30$是十六进制数值,在嵌入式存储系统中常用于表示**日志扇区魔数标识**: - 作为日志扇区起始的固定标识符,用于检测扇区有效性 - 在EasyFlash等嵌入式存储框架中,魔数用于区分正常数据与初始化状态 - 对应ASCII字符为"EF0",可能表示"EasyFlash Sector 0"的缩写[^1] ### 2. LOG_SECTOR_HEADER_SIZE的作用 该宏定义表示日志扇区头部的数据结构大小: ```c typedef struct { uint32_t magic; // EF30EF30 (4字节) uint8_t status; // 扇区状态 (1字节) uint32_t checksum; // CRC校验值 (4字节) uint32_t sector_num; // 扇区编号 (4字节) } log_sector_header_t; // 总大小=13字节 (实际可能对齐到16字节) ``` 典型实现中: $$LOG\_SECTOR\_HEADER\_SIZE = sizeof(log\_sector\_header\_t)$$ ### 3. 与SFUD的关联 代码中`flash = (sfud_flash_t)(sfud_dev->user_data)`表明: - 使用SFUD(Serial Flash Universal Driver)抽象层操作Flash - 日志扇区头部存储在SPI Flash的特定位置 - 通过魔数校验确保断电恢复时能正确识别日志结构[^1] 相关问题
阅读全文

相关推荐

/********************************************************************************************************* * * File : W25Qx.h * Hardware Environment: * Build Environment : RealView MDK-ARM Version: 5.15 * Version : V1.0 * By : * * (c) Copyright 2005-2015, WaveShare * http://www.waveshare.net * All Rights Reserved * *********************************************************************************************************/ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __W25QXX_H #define __W25QXX_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f1xx.h" #include "spi.h" /** @addtogroup BSP * @{ */ /** @addtogroup Components * @{ */ /** @addtogroup W25Q128FV * @{ */ /** @defgroup W25Q128FV_Exported_Types * @{ */ /** * @} */ /** @defgroup W25Q128FV_Exported_Constants * @{ */ /** * @brief W25Q128FV Configuration */ #define W25Q128FV_FLASH_SIZE 0x1000000 /* 128 MBits => 16MBytes */ #define W25Q128FV_SECTOR_SIZE 0x10000 /* 256 sectors of 64KBytes */ #define W25Q128FV_SUBSECTOR_SIZE 0x1000 /* 4096 subsectors of 4kBytes */ #define W25Q128FV_PAGE_SIZE 0x100 /* 65536 pages of 256 bytes */ #define W25Q128FV_DUMMY_CYCLES_READ 4 #define W25Q128FV_DUMMY_CYCLES_READ_QUAD 10 #define W25Q128FV_BULK_ERASE_MAX_TIME 250000 #define W25Q128FV_SECTOR_ERASE_MAX_TIME 3000 #define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME 800 #define W25Qx_TIMEOUT_VALUE 1000 /** * @brief W25Q128FV Commands */ /* Reset Operations */ #define RESET_ENABLE_CMD 0x66 #define RESET_MEMORY_CMD 0x99 #define ENTER_QPI_MODE_CMD 0x38 #define EXIT_QPI_MODE_CMD 0xFF /* Identification Operations */ #define READ_ID_CMD 0x90 #define DUAL_READ_ID_CMD 0x92 #define QUAD_READ_ID_CMD 0x94 #define READ_JEDEC_ID_CMD 0x9F /* Read Operations */ #define READ_CMD 0x03 #define FAST_READ_CMD 0x0B #define DUAL_OUT_FAST_READ_CMD 0x3B #define DUAL_INOUT_FAST_READ_CMD 0xBB #define QUAD_OUT_FAST_READ_CMD 0x6B #define QUAD_INOUT_FAST_READ_CMD 0xEB /* Write Operations */ #define WRITE_ENABLE_CMD 0x06 #define WRITE_DISABLE_CMD 0x04 /* Register Operations */ #define READ_STATUS_REG1_CMD 0x05 #define READ_STATUS_REG2_CMD 0x35 #define READ_STATUS_REG3_CMD 0x15 #define WRITE_STATUS_REG1_CMD 0x01 #define WRITE_STATUS_REG2_CMD 0x31 #define WRITE_STATUS_REG3_CMD 0x11 /* Program Operations */ #define PAGE_PROG_CMD 0x02 #define QUAD_INPUT_PAGE_PROG_CMD 0x32 /* Erase Operations */ #define SECTOR_ERASE_CMD 0x20 #define CHIP_ERASE_CMD 0xC7 #define PROG_ERASE_RESUME_CMD 0x7A #define PROG_ERASE_SUSPEND_CMD 0x75 /* Flag Status Register */ #define W25Q128FV_FSR_BUSY ((uint8_t)0x01) /*!< busy */ #define W25Q128FV_FSR_WREN ((uint8_t)0x02) /*!< write enable */ #define W25Q128FV_FSR_QE ((uint8_t)0x02) /*!< quad enable */ #define W25Qx_Enable() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET) #define W25Qx_Disable() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET) #define W25Qx_OK ((uint8_t)0x00) #define W25Qx_ERROR ((uint8_t)0x01) #define W25Qx_BUSY ((uint8_t)0x02) #define W25Qx_TIMEOUT ((uint8_t)0x03) uint8_t BSP_W25Qx_Init(void); static void BSP_W25Qx_Reset(void); static uint8_t BSP_W25Qx_GetStatus(void); uint8_t BSP_W25Qx_WriteEnable(void); void BSP_W25Qx_Read_ID(uint8_t *ID); uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size); uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size); uint8_t BSP_W25Qx_Erase_Block(uint32_t Address); uint8_t BSP_W25Qx_Erase_Chip(void); /** * @} */ /** @defgroup W25Q128FV_Exported_Functions * @{ */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ #ifdef __cplusplus } #endif #endif /* __W25Qx_H */ /********************************************************************************************************* * * File : ws_W25Qx.c * Hardware Environment: * Build Environment : RealView MDK-ARM Version: 4.20 * Version : V1.0 * By : * * (c) Copyright 2005-2011, WaveShare * http://www.waveshare.net * All Rights Reserved * *********************************************************************************************************/ #include "W25QXX.h" /** * @brief Initializes the W25Q128FV interface. * @retval None */ uint8_t BSP_W25Qx_Init(void) { /* Reset W25Qxxx */ BSP_W25Qx_Reset(); return BSP_W25Qx_GetStatus(); } /** * @brief This function reset the W25Qx. * @retval None */ static void BSP_W25Qx_Reset(void) { uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD}; W25Qx_Enable(); /* Send the reset command */ HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE); W25Qx_Disable(); } /** * @brief Reads current status of the W25Q128FV. * @retval W25Q128FV memory status */ static uint8_t BSP_W25Qx_GetStatus(void) { uint8_t cmd[] = {READ_STATUS_REG1_CMD}; uint8_t status; W25Qx_Enable(); /* Send the read status command */ HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE); /* Reception of the data */ HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE); W25Qx_Disable(); /* Check the value of the register */ if((status & W25Q128FV_FSR_BUSY) != 0) { return W25Qx_BUSY; } else { return W25Qx_OK; } } /** * @brief This function send a Write Enable and wait it is effective. * @retval None */ uint8_t BSP_W25Qx_WriteEnable(void) { uint8_t cmd[] = {WRITE_ENABLE_CMD}; uint32_t tickstart = HAL_GetTick(); /*Select the FLASH: Chip Select low */ W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE); /*Deselect the FLASH: Chip Select high */ W25Qx_Disable(); /* Wait the end of Flash writing */ while(BSP_W25Qx_GetStatus() == W25Qx_BUSY); { /* Check for the Timeout */ if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE) { return W25Qx_TIMEOUT; } } return W25Qx_OK; } /** * @brief Read Manufacture/Device ID. * @param return value address * @retval None */ void BSP_W25Qx_Read_ID(uint8_t *ID) { uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00}; W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); /* Reception of the data */ HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE); W25Qx_Disable(); } /** * @brief Reads an amount of data from the QSPI memory. * @param pData: Pointer to data to be read * @param ReadAddr: Read start address * @param Size: Size of data to read * @retval QSPI memory status */ uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size) { uint8_t cmd[4]; /* Configure the command */ cmd[0] = READ_CMD; cmd[1] = (uint8_t)(ReadAddr >> 16); cmd[2] = (uint8_t)(ReadAddr >> 8); cmd[3] = (uint8_t)(ReadAddr); W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); /* Reception of the data */ if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK) { return W25Qx_ERROR; } W25Qx_Disable(); return W25Qx_OK; } /** * @brief Writes an amount of data to the QSPI memory. * @param pData: Pointer to data to be written * @param WriteAddr: Write start address * @param Size: Size of data to write,No more than 256byte. * @retval QSPI memory status */ uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) { uint8_t cmd[4]; uint32_t end_addr, current_size, current_addr; uint32_t tickstart = HAL_GetTick(); /* Calculation of the size between the write address and the end of the page */ current_addr = 0; while (current_addr <= WriteAddr) { current_addr += W25Q128FV_PAGE_SIZE; } current_size = current_addr - WriteAddr; /* Check if the size of the data is less than the remaining place in the page */ if (current_size > Size) { current_size = Size; } /* Initialize the adress variables */ current_addr = WriteAddr; end_addr = WriteAddr + Size; /* Perform the write page by page */ do { /* Configure the command */ cmd[0] = PAGE_PROG_CMD; cmd[1] = (uint8_t)(current_addr >> 16); cmd[2] = (uint8_t)(current_addr >> 8); cmd[3] = (uint8_t)(current_addr); /* Enable write operations */ BSP_W25Qx_WriteEnable(); W25Qx_Enable(); /* Send the command */ if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK) { return W25Qx_ERROR; } /* Transmission of the data */ if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK) { return W25Qx_ERROR; } W25Qx_Disable(); /* Wait the end of Flash writing */ while(BSP_W25Qx_GetStatus() == W25Qx_BUSY); { /* Check for the Timeout */ if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE) { return W25Qx_TIMEOUT; } } /* Update the address and size variables for next page programming */ current_addr += current_size; pData += current_size; current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE; } while (current_addr < end_addr); return W25Qx_OK; } /** * @brief Erases the specified block of the QSPI memory. * @param BlockAddress: Block address to erase * @retval QSPI memory status */ uint8_t BSP_W25Qx_Erase_Block(uint32_t Address) { uint8_t cmd[4]; uint32_t tickstart = HAL_GetTick(); cmd[0] = SECTOR_ERASE_CMD; cmd[1] = (uint8_t)(Address >> 16); cmd[2] = (uint8_t)(Address >> 8); cmd[3] = (uint8_t)(Address); /* Enable write operations */ BSP_W25Qx_WriteEnable(); /*Select the FLASH: Chip Select low */ W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); /*Deselect the FLASH: Chip Select high */ W25Qx_Disable(); /* Wait the end of Flash writing */ while(BSP_W25Qx_GetStatus() == W25Qx_BUSY); { /* Check for the Timeout */ if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME) { return W25Qx_TIMEOUT; } } return W25Qx_OK; } /** * @brief Erases the entire QSPI memory.This function will take a very long time. * @retval QSPI memory status */ uint8_t BSP_W25Qx_Erase_Chip(void) { uint8_t cmd[4]; uint32_t tickstart = HAL_GetTick(); cmd[0] = SECTOR_ERASE_CMD; /* Enable write operations */ BSP_W25Qx_WriteEnable(); /*Select the FLASH: Chip Select low */ W25Qx_Enable(); /* Send the read ID command */ HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE); /*Deselect the FLASH: Chip Select high */ W25Qx_Disable(); /* Wait the end of Flash writing */ while(BSP_W25Qx_GetStatus() != W25Qx_BUSY); { /* Check for the Timeout */ if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME) { return W25Qx_TIMEOUT; } } return W25Qx_OK; } /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 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 "spi.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stm32f1xx_hal.h" #include <stdio.h> #include <string.h> #include "W25QXX.h" uint8_t wData[0x100]; uint8_t rData[0x100]; uint32_t i; uint8_t ID[2]; extern UART_HandleTypeDef huart1; //声明串口 /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /** * 函数功能: 重定向c库函数printf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); return ch; } /** * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, &ch, 1, 0xffff); return ch; } /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* 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_SPI1_Init(); /* USER CODE BEGIN 2 */ printf("\r\n SPI-W25Qxxx Example \r\n\r\n"); /*##-1- Read the device ID ########################*/ BSP_W25Qx_Init(); BSP_W25Qx_Read_ID(ID); printf(" W25Qxxx ID is : 0x%02X 0x%02X \r\n\r\n",ID[0],ID[1]); /*##-2- Erase Block ##################################*/ if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK) printf(" SPI Erase Block ok\r\n"); else Error_Handler(); /*##-3- Written to the flash ########################*/ /* fill buffer */ for(i =0;i<0x100;i ++) { wData[i] = i; rData[i] = 0; } if(BSP_W25Qx_Write(wData,0x00,0x100)== W25Qx_OK) printf(" SPI Write ok\r\n"); else Error_Handler(); /*##-4- Read the flash ########################*/ if(BSP_W25Qx_Read(rData,0x00,0x100)== W25Qx_OK) printf(" SPI Read ok\r\n\r\n"); else Error_Handler(); printf("SPI Read Data : \r\n"); for(i =0;i<0x100;i++) printf("0x%02X ",rData[i]); printf("\r\n\r\n"); /*##-5- check date ########################*/ if(memcmp(wData,rData,0x100) == 0 ) printf(" W25Q128FV SPI Test OK\r\n"); else printf(" W25Q128FV SPI Test False\r\n"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* 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}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; 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(); } } /* 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 */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file gpio.c * @brief This file provides code for the configuration * of all used GPIO pins. ****************************************************************************** * @attention * * Copyright (c) 2025 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 "gpio.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /*----------------------------------------------------------------------------*/ /* Configure GPIO */ /*----------------------------------------------------------------------------*/ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = SPI1_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SPI1_CS_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file spi.c * @brief This file provides code for the configuration * of the SPI instances. ****************************************************************************** * @attention * * Copyright (c) 2025 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 "spi.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ SPI_HandleTypeDef hspi1; /* SPI1 init function */ void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ 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_64; 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(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* SPI1 clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { if(spiHandle->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * Copyright (c) 2025 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 "usart.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ UART_HandleTypeDef huart1; /* USART1 init function */ void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 1 */ /* USER CODE END USART1_Init 1 */ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file stm32f1xx_it.c * @brief Interrupt Service Routines. ****************************************************************************** * @attention * * Copyright (c) 2025 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 "stm32f1xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ /* USER CODE END TD */ /* 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 */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ /* USER CODE BEGIN EV */ /* USER CODE END EV */ /******************************************************************************/ /* Cortex-M3 Processor Interruption and Exception Handlers */ /******************************************************************************/ /** * @brief This function handles Non maskable interrupt. */ void NMI_Handler(void) { /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ /* USER CODE END NonMaskableInt_IRQn 0 */ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ while (1) { } /* USER CODE END NonMaskableInt_IRQn 1 */ } /** * @brief This function handles Hard fault interrupt. */ void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn 0 */ /* USER CODE END HardFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_HardFault_IRQn 0 */ /* USER CODE END W1_HardFault_IRQn 0 */ } } /** * @brief This function handles Memory management fault. */ void MemManage_Handler(void) { /* USER CODE BEGIN MemoryManagement_IRQn 0 */ /* USER CODE END MemoryManagement_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ /* USER CODE END W1_MemoryManagement_IRQn 0 */ } } /** * @brief This function handles Prefetch fault, memory access fault. */ void BusFault_Handler(void) { /* USER CODE BEGIN BusFault_IRQn 0 */ /* USER CODE END BusFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_BusFault_IRQn 0 */ /* USER CODE END W1_BusFault_IRQn 0 */ } } /** * @brief This function handles Undefined instruction or illegal state. */ void UsageFault_Handler(void) { /* USER CODE BEGIN UsageFault_IRQn 0 */ /* USER CODE END UsageFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ /* USER CODE END W1_UsageFault_IRQn 0 */ } } /** * @brief This function handles System service call via SWI instruction. */ void SVC_Handler(void) { /* USER CODE BEGIN SVCall_IRQn 0 */ /* USER CODE END SVCall_IRQn 0 */ /* USER CODE BEGIN SVCall_IRQn 1 */ /* USER CODE END SVCall_IRQn 1 */ } /** * @brief This function handles Debug monitor. */ void DebugMon_Handler(void) { /* USER CODE BEGIN DebugMonitor_IRQn 0 */ /* USER CODE END DebugMonitor_IRQn 0 */ /* USER CODE BEGIN DebugMonitor_IRQn 1 */ /* USER CODE END DebugMonitor_IRQn 1 */ } /** * @brief This function handles Pendable request for system service. */ void PendSV_Handler(void) { /* USER CODE BEGIN PendSV_IRQn 0 */ /* USER CODE END PendSV_IRQn 0 */ /* USER CODE BEGIN PendSV_IRQn 1 */ /* USER CODE END PendSV_IRQn 1 */ } /** * @brief This function handles System tick timer. */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } /******************************************************************************/ /* STM32F1xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32f1xx.s). */ /******************************************************************************/ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file stm32f1xx_hal_msp.c * @brief This file provides code for the MSP Initialization * and de-Initialization codes. ****************************************************************************** * @attention * * Copyright (c) 2025 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" /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ /* USER CODE END TD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN Define */ /* USER CODE END Define */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN Macro */ /* USER CODE END Macro */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* External functions --------------------------------------------------------*/ /* USER CODE BEGIN ExternalFunctions */ /* USER CODE END ExternalFunctions */ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * Initializes the Global MSP. */ void HAL_MspInit(void) { /* USER CODE BEGIN MspInit 0 */ /* USER CODE END MspInit 0 */ __HAL_RCC_AFIO_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); /* System interrupt init*/ /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); /* USER CODE BEGIN MspInit 1 */ /* USER CODE END MspInit 1 */ } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ 这段代码串口打印出来的都是0x00,是什么原因,要怎么改,使用的芯片为stm32f103rct6,cpol设置为low cpha设置为1Edge,SPI1_sck、SPI1_miso、SPI1_mosi分别对应的引脚为PA5、PA6、PA7

/* * module_extend_flash.h * * Created on: Feb 23, 2025 * Author: XWM */ #ifndef MODULE_MODULE__EXTEND_FLASH_MODULE_FLASH_EXTEND_H_ #define MODULE_MODULE__EXTEND_FLASH_MODULE_FLASH_EXTEND_H_ #include "main.h" #include <stdint.h> #include <stdbool.h> /* 外部Flash模块编译开关(0=禁用,1=启用) */ #define EXTEND_FLASH_SWITCH (1) /* 外部Flash模块编译开关 */ #if EXTEND_FLASH_SWITCH /* W25X系列/Q系列芯片列表 */ #define W25Q80 (0XEF13) #define W25Q16 (0XEF14) #define W25Q32 (0XEF15) #define W25Q64 (0XEF16) #define W25Q128 (0XEF17) #define W25Q256 (0XEF18) #define NM25Q80 (0X5213) #define NM25Q16 (0X5214) #define NM25Q32 (0X5215) #define NM25Q64 (0X5216) #define NM25Q128 (0X5217) #define NM25Q256 (0X5218) /* 使能器件 */ #define W25QXX_CS_ENABLE() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET); /* 取消片选 */ #define W25QXX_CS_DISABLE() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); /* 指令 */ #define W25X_WRITE_ENABLE (0x06) #define W25X_WRITE_DISABLE (0x04) #define W25X_READ_STATUS_REG1 (0x05) #define W25X_READ_STATUS_REG2 (0x35) #define W25X_READ_STATUS_REG3 (0x15) #define W25X_WRITE_STATUS_REG1 (0x01) #define W25X_WRITE_STSTUS_REG2 (0x31) #define W25X_WRITE_STSTUS_REG3 (0x11) #define W25X_READ_DATA (0x03) #define W25X_FAST_READ_DATA (0x0B) #define W25X_FAST_READ_DUAL (0x3B) #define W25X_PAGE_PROGRAM (0x02) #define W25X_BLOCK_ERASE (0xD8) #define W25X_SECTOR_ERASE (0x20) #define W25X_CHIP_ERASE (0xC7) #define W25X_POWER_DOWN (0xB9) #define W25X_RELEASE_POWER_DOWN (0xAB) #define W25X_DEVICE_ID (0xAB) #define W25X_MANUFACT_DEVICE_ID (0x90) #define W25X_JEDEC_DEVICE_ID (0x9F) #define W25X_ENABLE_4BYTE_ADDR (0xB7) #define W25X_EXIT_4Byte_ADDR (0xE9) /* 存储sector分配 */ #define FLASH_SVAE_SECTOR0 (0x0000000)// 4K 账号密码 #define FLASH_SVAE_SECTOR1 (0x0001000)// 4K 时计划任务 #define FLASH_SVAE_SECTOR2 (0x0002000)// 4K 机器参数 #define FLASH_SVAE_SECTOR3 (0x0003000)// 4K 计划任务 #define FLASH_SVAE_SECTOR4 (0x0004000)// 4K RTK #define FLASH_SVAE_SECTOR5 (0x0005000)// 4K NET #define FLASH_SVAE_SECTOR6 (0x0006000)// 4K RADIO #define FLASH_SVAE_SECTOR7 (0x0007000)// 4K BLE #define FLASH_SVAE_SECTOR8 (0x0008000)// 4K 是否从升级中启动 #define FLASH_SVAE_SECTOR9 (0x0009000)// 4K 机器地图 #define FLASH_SVAE_SECTOR10 (0x000A000)// 4K 区域地图0 #define FLASH_SVAE_SECTOR11 (0x000B000)// 4K 区域地图0 #define FLASH_SVAE_SECTOR12 (0x000C000)// 4K 区域地图0 #define FLASH_SVAE_SECTOR13 (0x000D000)// 4K 区域地图0 #define FLASH_SVAE_SECTOR14 (0x000E000)// 4K 区域地图0 #define FLASH_SVAE_SECTOR15 (0x000F000)// 4K 区域地图0 /* 存储block分配 */ #define FLASH_SAVE_BLOCK1 (0x0010000)// 64k 区域0 #define FLASH_SAVE_BLOCK2 (0x0020000)// 64K 区域1 #define FLASH_SAVE_BLOCK3 (0x0030000)// 64K 区域2 #define FLASH_SAVE_BLOCK4 (0x0040000)// 64K 区域3 #define FLASH_SAVE_BLOCK5 (0x0050000)// 64K 区域4 #define FLASH_SAVE_BLOCK6 (0x0060000)// 64K 区域5 #define FLASH_SAVE_BLOCK7 (0x0070000)// 64K 区域6 #define FLASH_SAVE_BLOCK8 (0x0080000)// 64K 区域7 #define FLASH_SAVE_BLOCK9 (0x0090000)// 64K 区域8 #define FLASH_SAVE_BLOCK10 (0x00A0000)// 64K 区域9 #define FLASH_SVAE_SECTOR256 (0x0100000)// 4K FACTORY 大小 #define FLASH_SVAE_SECTOR257 (0x0101000)// 4K FACTOEY 固件 SECTOR257 - ECTOR511 #define FLASH_SVAE_SECTOR512 (0x0200000)// 4K DOWNLOAD 大小 #define FLASH_SVAE_SECTOR513 (0x0201000)// 4K DOWNLOAD 固件 SECTOR513 - SECTOR4096 /* * 函数名 :extend_flash_init * 功能 :外部闪存初始化 * 参数 :无 * 返回值 :无 * 备注 :无 */ void extend_flash_init(void); /* * 函数名 :w25qxx_init * 功能 :W25QXX初始化 * 参数 :无 * 返回值 :无 * 备注 :无 */ void w25qxx_init(void); /* * 函数名 :w25qxx_write * 功能 :写SPI FLASH 在指定地址开始写入指定长度的数据 * 参数 :buffer要写入的数据 * :addr写入FLASH的地址 * :size要写入的字节数(最大65535) * 返回值 :无 * 备注 :该函数带擦除操作! */ void w25qxx_write(uint8_t* buffer, uint32_t addr, uint16_t size); /* * 函数名 :W25QXX_Read * 功能 :读取SPI FLASH 在指定地址开始读取指定长度的数据 * 参数 :pBuffer数据存储区 ReadAddr开始读取的地址(24bit) NumByteToRead要读取的字节数(最大65535) * 返回值 :无 * 备注 :无 */ void w25qxx_read(uint8_t* buffer, uint32_t addr, uint16_t size); /* * 函数名 :w25qxx_read_id * 功能 :读取芯片ID * 参数 :无 * 返回值 :如下 * :0XEF13,表示芯片型号为W25Q80 * :0XEF14,表示芯片型号为W25Q16 * :0XEF15,表示芯片型号为W25Q32 * :0XEF16,表示芯片型号为W25Q64 * :0XEF17,表示芯片型号为W25Q128 * :0XEF18,表示芯片型号为W25Q256 * 备注 :无 */ uint16_t w25qxx_read_id(void); /* * 函数名 :w25qxx_erase_chip * 功能 :擦除整个芯片 * 参数 :无 * 返回值 :无 * 备注 :等待时间超长... */ void w25qxx_erase_chip(void); /* * 函数名 :w25qxx_erase_sector * 功能 :擦除一个扇区 * 参数 :addr扇区地址(根据实际容量设置) * 返回值 :无 * 备注 :擦除一个扇区的最少时间150ms */ void w25qxx_erase_sector(uint32_t addr); #endif #endif /* MODULE_MODULE__EXTEND_FLASH_MODULE_FLASH_EXTEND_H_ */ 给上述添加注释

在移植flashDB的时候使用fal 以及sfud的时候 设置 #define SFUD_FLASH_DEVICE_TABLE \ { \ [SFUD_W25_DEVICE_INDEX] = {.name = "norflash0",.spi.name = "QSPI1",.chip.name="W25Q64JV",.chip.mf_id =0xEF,.chip.type_id =0x40,.chip.capacity_id = 0x17,.chip.capacity =8L * 1024L * 1024L,.chip.write_mode = SFUD_WM_PAGE_256B,.chip.erase_gran = 4096,.chip.erase_gran_cmd =0x20}, \ } sfud_flash sfud_norflash0 = { .name = "norflash0", .spi.name = "QSPI1", .chip = {"W25Q64JV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L * 1024L * 1024L, SFUD_WM_PAGE_256B, 4096, 0x20}}; /* ====================== Partition Configuration ========================== */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WORD, "fdb_kvdb1", "norflash0", 0x00000000, 256 * 1024, 0}, \ {FAL_PART_MAGIC_WORD, "fdb_tsdb1", "norflash0", 256 * 1024, 256 * 1024, 0}, \ } #endif /* FAL_PART_HAS_TABLE_CFG */ /* * Copyright (c) 2020, Armink, <[email protected]> * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief configuration template file. You need to rename the file to "fbd_cfg.h" and modify the configuration items in it to suit your use. */ #ifndef _FDB_CFG_H_ #define _FDB_CFG_H_ #include "stdio.h" /* using KVDB feature */ #define FDB_USING_KVDB #ifdef FDB_USING_KVDB /* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */ /* #define FDB_KV_AUTO_UPDATE */ #endif /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB /* Using FAL storage mode */ #define FDB_USING_FAL_MODE /* TSDB 记录时间精度 int64_t */ #define FDB_USING_TIMESTAMP_64BIT /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN 1 /* MCU Endian Configuration, default is Little Endian Order. */ /* #define FDB_BIG_ENDIAN */ /* log print macro. default EF_PRINT macro is printf() */ #define FDB_PRINT(...) printf(__VA_ARGS__) /* print debug information */ #define FDB_DEBUG_ENABLE #endif /* _FDB_CFG_H_ */ /* USER CODE BEGIN 1 */ /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); SCB->CACR |= 1 << 2; /* USER CODE END 1 */ /* MPU Configuration--------------------------------------------------------*/ MPU_Config(); /* 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(); /* USER CODE BEGIN 2 */ MX_DMA_Init(); MX_USART1_UART_Init(); QSPI_W25Qxx_Init(); // 初始化W25Q64 printf("Clion STM32 UART Clion PANGGUOFU \r\n"); // /* SFUD initialize */ // if (sfud_init() == SFUD_SUCCESS) // { // /* enable qspi fast read mode, set four data lines width */ // sfud_qspi_fast_read_enable(sfud_get_device(SFUD_W25_DEVICE_INDEX), 4); // sfud_demo(0, sizeof(sfud_demo_test_buf), sfud_demo_test_buf); // } spi_flash_init(); //sfud_qspi_fast_read_enable(sfud_get_device(SFUD_W25_DEVICE_INDEX), 4); // 1. 验证Flash识别信息 sfud_flash *flash = sfud_get_device(SFUD_W25_DEVICE_INDEX); printf("sfud_flash name:%s index:%d flash->spi.name %s \n", (char *)flash->name, flash->index,(char *)flash->spi.name); printf("sfud_flash_chip name:%s capacity:0x%08x mf_id %x type_id %x capacity_id %x erase_gran %d \n", (char *)flash->chip.name, flash->chip.capacity,flash->chip.mf_id,flash->chip.type_id,flash->chip.capacity_id,flash->chip.erase_gran); HAL_Delay(100); #ifdef FDB_USING_KVDB { /* KVDB Sample */ struct fdb_default_kv default_kv; fdb_err_t result; default_kv.kvs = default_kv_table; default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]); /* set the lock and unlock function if you want */ fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock); fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock); /* Key-Value database initialization * * &kvdb: database object * "env": database name * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table. * Please change to YOUR partition name. * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully. * NULL: The user data if you need, now is empty. */ result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL); if (result != FDB_NO_ERR) { printf("Clion STM32 UART Clion KVDB Sample -1 \r\n"); return -1; } /* run basic KV samples */ kvdb_basic_sample(&kvdb); /* run string KV samples */ kvdb_type_string_sample(&kvdb); /* run blob KV samples */ kvdb_type_blob_sample(&kvdb); } #endif /* FDB_USING_KVDB */ 但是一直出现[SFUD]norflash0 flash device initialized successfully. sfud_flash name:norflash0 index:0 flash->spi.name QSPI1 sfud_flash_chip name:W25Q64JV capacity:0x00800000 mf_id ef type_id 40 capacity_id 17 erase_gran 4096 [D/FAL] (fal_flash_init:47) Flash device | norflash0 | addr: 0x00000000 | len: 0x00800000 | blk_size: 0x00001000 |initialized finish. [I/FAL] ==================== FAL partition table ==================== [I/FAL] | name | flash_dev | offset | length | [I/FAL] ------------------------------------------------------------- [I/FAL] | fdb_kvdb1 | norflash0 | 0x00000000 | 0x00040000 | [I/FAL] | fdb_tsdb1 | norflash0 | 0x00040000 | 0x00040000 | [I/FAL] ============================================================= [I/FAL] Flash Abstraction Layer (V0.5.99) initialize success. [FlashDB][kv][env][fdb_kvdb1] (E:/Clion_code/STM32_Clion/STM32H7_SFUD_clion/Module_Library/FlashDB/src/fdb_kvdb.c:1801) The oldest addr is @0x00000000 [FlashDB][kv][env][fdb_kvdb1] (E:/Clion_code/STM32_Clion/STM32H7_SFUD_clion/Module_Library/FlashDB/src/fdb_kvdb.c:1817) KVDB size is 262144 bytes. [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (goot_count@0x00000010) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (~emp@0x00000036) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (üemp@0x00000055) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (ÿemp@0x00000074) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (emp@0x00000094) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (goot_count@0x000000B4) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (ÿoot_count@0x00000100) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (boot_count@0x00000126) CRC32 check failed! [FlashDB] FlashDB V2.1.1 is initialize success. [FlashDB] You can get the latest version on https://github.com/armink/FlashDB . [FlashDB][sample][kvdb][basic] ==================== kvdb_basic_sample ==================== [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (ooot_count@0x00000010) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (~emp@0x00000036) CRC32 check failed! [FlashDB][kv][env][fdb_kvdb1] Error: Read the KV (üemp@0x00000055) CRC32 check failed! 这个是什么原因呢

#ifndef __LCD_H #define __LCD_H #include "sys.h" #include "stdlib.h" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK STM32F407开发板 //2.4寸/2.8寸/3.5寸/4.3寸/7寸 TFT液晶驱动 //支持驱动IC型号包括:ILI9341/ILI9325/RM68042/RM68021/ILI9320/ILI9328/LGDP4531/LGDP4535/ // SPFD5408/1505/B505/C505/NT35310/NT35510/SSD1963等 //正点原子@ALIENTEK //技术论坛:www.openedv.com //创建日期:2010/7/4 //版本:V4.2 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2014-2024 //All rights reserved //******************************************************************************** //V4.0 20211111 //1,去掉大部分不常用驱动IC的支持 //2,新增对ST7789驱动IC的支持 //3,优化代码结构(精简源码) //V4.1 20211208 //修改NT5510 ID读取方式,改为先发送秘钥,然后读取C500和C501,从而获取正确的ID(0X5510) //V4.2 20211222 //1,修改FSMC速度,兼容7789显示OV2640数据 //2,解决因NT5510 ID读取(发送C501指令)导致SSD1963误触发软件复位进而读取不到ID问题,加延时解决 ////////////////////////////////////////////////////////////////////////////////// //LCD重要参数集 typedef struct { u16 width; //LCD 宽度 u16 height; //LCD 高度 u16 id; //LCD ID u8 dir; //横屏还是竖屏控制:0,竖屏;1,横屏。 u16 wramcmd; //开始写gram指令 u16 setxcmd; //设置x坐标指令 u16 setycmd; //设置y坐标指令 }_lcd_dev; //LCD参数 extern _lcd_dev lcddev; //管理LCD重要参数 //LCD的画笔颜色和背景色 extern u16 POINT_COLOR;//默认红色 extern u16 BACK_COLOR; //背景颜色.默认为白色 ////////////////////////////////////////////////////////////////////////////////// //-----------------LCD端口定义---------------- #define LCD_LED PBout(15) //LCD背光 PB15 //LCD地址结构体 typedef struct { vu16 LCD_REG; vu16 LCD_RAM; } LCD_TypeDef; //使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A6作为数据命令区分线 //注意设置时STM32内部会右移一位对其! 111 1110=0X7E #define LCD_BASE ((u32)(0x6C000000 | 0x0000007E)) #define LCD ((LCD_TypeDef *) LCD_BASE) ////////////////////////////////////////////////////////////////////////////////// //扫描方向定义 #define L2R_U2D 0 //从左到右,从上到下 #define L2R_D2U 1 //从左到右,从下到上 #define R2L_U2D 2 //从右到左,从上到下 #define R2L_D2U 3 //从右到左,从下到上 #define U2D_L2R 4 //从上到下,从左到右 #define U2D_R2L 5 //从上到下,从右到左 #define D2U_L2R 6 //从下到上,从左到右 #define D2U_R2L 7 //从下到上,从右到左 #define DFT_SCAN_DIR L2R_U2D //默认的扫描方向 //画笔颜色 #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define BROWN 0XBC40 //棕色 #define BRRED 0XFC07 //棕红色 #define GRAY 0X8430 //灰色 //GUI颜色 #define DARKBLUE 0X01CF //深蓝色 #define LIGHTBLUE 0X7D7C //浅蓝色 #define GRAYBLUE 0X5458 //灰蓝色 //以上三色为PANEL的颜色 #define LIGHTGREEN 0X841F //浅绿色 //#define LIGHTGRAY 0XEF5B //浅灰色(PANNEL) #define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 #define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) #define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) void LCD_Init(void); //初始化 void LCD_DisplayOn(void); //开显示 void LCD_DisplayOff(void); //关显示 void LCD_Clear(u16 Color); //清屏 void LCD_SetCursor(u16 Xpos, u16 Ypos); //设置光标 void LCD_DrawPoint(u16 x,u16 y); //画点 void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color); //快速画点 u16 LCD_ReadPoint(u16 x,u16 y); //读点 void LCD_Draw_Circle(u16 x0,u16 y0,u8 r); //画圆 void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //画线 void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2); //画矩形 void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color); //填充单色 void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color); //填充指定颜色 void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode); //显示一个字符 void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size); //显示一个数字 void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode); //显示 数字 void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p); //显示一个字符串,12/16字体 void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue); u16 LCD_ReadReg(u16 LCD_Reg); void LCD_WriteRAM_Prepare(void); void LCD_WriteRAM(u16 RGB_Code); void LCD_SSD_BackLightSet(u8 pwm); //SSD1963 背光控制 void LCD_Scan_Dir(u8 dir); //设置屏扫描方向 void LCD_Display_Dir(u8 dir); //设置屏幕显示方向 void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height); //设置窗口 //LCD分辨率设置 #define SSD_HOR_RESOLUTION 800 //LCD水平分辨率 #define SSD_VER_RESOLUTION 480 //LCD垂直分辨率 //LCD驱动参数设置 #define SSD_HOR_PULSE_WIDTH 1 //水平脉宽 #define SSD_HOR_BACK_PORCH 46 //水平前廊 #define SSD_HOR_FRONT_PORCH 210 //水平后廊 #define SSD_VER_PULSE_WIDTH 1 //垂直脉宽 #define SSD_VER_BACK_PORCH 23 //垂直前廊 #define SSD_VER_FRONT_PORCH 22 //垂直前廊 //如下几个参数,自动计算 #define SSD_HT (SSD_HOR_RESOLUTION+SSD_HOR_BACK_PORCH+SSD_HOR_FRONT_PORCH) #define SSD_HPS (SSD_HOR_BACK_PORCH) #define SSD_VT (SSD_VER_RESOLUTION+SSD_VER_BACK_PORCH+SSD_VER_FRONT_PORCH) #define SSD_VPS (SSD_VER_BACK_PORCH) #endif 这是LCD头文件,请使用头文件中的函数

#include "SHT30.h" #define SHT30I2C_SCL GPIO_PIN_2 #define SHT30I2C_SDA GPIO_PIN_3 #define GPIO_I2C GPIOC #define I2C_SCL_H GPIO_SetBits(GPIO_I2C,SHT30I2C_SCL) #define I2C_SCL_L GPIO_ResetBits(GPIO_I2C,SHT30I2C_SCL) #define I2C_SDA_H GPIO_SetBits(GPIO_I2C,SHT30I2C_SDA) #define I2C_SDA_L GPIO_ResetBits(GPIO_I2C,SHT30I2C_SDA) #define SDA_IN GPIO_ReadInputDataBit(GPIO_I2C,SHT30I2C_SDA) #define write 0 //第8位是写命令 #define read 1 //第8位是读命令 //定义温湿度存储变量 u8 humiture_buff1[20]; float Temperature = 0.000000; float Humidity = 0.000000; //初始化IIC void SHT30_Init(void) { GPIO_InitType GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//输出 GPIO_InitStructure.GPIO_Current = GPIO_DC_2mA; GPIO_InitStructure.Pin = SHT30I2C_SCL | SHT30I2C_SDA; GPIO_InitPeripheral(GPIO_I2C, &GPIO_InitStructure); I2C_SCL_H; I2C_SDA_H; } //设置为输出模式 static void I2C_SDA_OUT(void) { GPIO_InitType GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//输出 GPIO_InitStructure.GPIO_Current = GPIO_DC_2mA; GPIO_InitStructure.Pin = SHT30I2C_SDA; GPIO_InitPeripheral(GPIO_I2C, &GPIO_InitStructure); } //设置为输入模式 static void I2C_SDA_IN(void) { GPIO_InitType GPIO_InitStructure; GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = SHT30I2C_SDA; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitPeripheral(GPIO_I2C, &GPIO_InitStructure); } //主机发送确认字符ACK void IIC_ACK(void) { I2C_SDA_OUT(); I2C_SCL_L; Delayus(2); I2C_SDA_L; Delayus(2); I2C_SCL_H; Delayus(2); I2C_SCL_L; Delayus(1); } //主机不发送确认字符ACK void IIC_NACK(void) { I2C_SDA_OUT();//输出模式 I2C_SCL_L; Delayus(2); I2C_SDA_H; Delayus(2); I2C_SCL_H; Delayus(2); I2C_SCL_L; Delayus(1); } //主机等待从机的确认字符ACK u8 IIC_wait_ACK(void) { u8 t = 200; I2C_SDA_OUT(); I2C_SDA_H; Delayus(1); I2C_SCL_L; Delayus(1); I2C_SDA_IN(); Delayus(1); while(SDA_IN)//等待SHT30应答 { t--; Delayus(1); if(t == 0) { I2C_SCL_L; return 1; } Delayus(1); } Delayus(1); I2C_SCL_H; Delayus(1); I2C_SCL_L; Delayus(1); return 0; } //启动IIC通讯 void IIC_Start(void) { I2C_SDA_OUT(); I2C_SDA_H; I2C_SCL_H; Delayus(4); I2C_SDA_L; Delayus(4); I2C_SCL_L; } //结束IIC总线通讯 void IIC_Stop(void) { I2C_SDA_OUT(); I2C_SCL_L; I2C_SDA_L; Delayus(4); I2C_SCL_H; Delayus(4); I2C_SDA_H; Delayus(4); } //将byte数据发送出去 void IIC_SendByte(u8 byte) { u8 Count; I2C_SDA_OUT(); I2C_SCL_L; for(Count = 0; Count < 8; Count++) //要传送的数据长度为8位 { if(byte & 0x80) { I2C_SDA_H; } else { I2C_SDA_L; } byte <<= 1; Delayus(2); I2C_SCL_H; Delayus(2); I2C_SCL_L; Delayus(2); } } //用来接收从器件传来的数据 u8 IIC_RcvByte(void) { u8 retc; u8 Count; retc = 0; I2C_SDA_IN();//配置数据线为输入方式 Delayus(1); for(Count = 0; Count < 8; Count++) { I2C_SCL_L; Delayus(2); I2C_SCL_H; retc = retc << 1; if(SDA_IN) retc |= 1; Delayus(1); } I2C_SCL_L; return(retc); } //读取系列号 u8 ReadHumitureSensorType(u8 addr) { u32 SerialNumber = 0; u8 type = TYPE_SHT40;//默认是TYPE_SHT30 // u8 type = TYPE_SHT30;//默认是TYPE_SHT30 #if 0 u8 buff[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; IIC_Start(); IIC_SendByte(addr << 1 | write); IIC_wait_ACK(); IIC_SendByte(0x89); IIC_wait_ACK(); IIC_Stop(); Delayms(50); IIC_Start(); IIC_SendByte(addr << 1 | read); //写7位I2C设备地址加1作为读取位,1为读取位 if(!IIC_wait_ACK()) { Delayus(1); buff[0] = IIC_RcvByte(); //返回系列号的高8位 IIC_ACK(); buff[1] = IIC_RcvByte(); //返回系列号的高8位 IIC_ACK(); buff[2] = IIC_RcvByte(); //温度crc校验位 IIC_ACK(); buff[3] = IIC_RcvByte(); //返回湿度高8位 IIC_ACK(); buff[4] = IIC_RcvByte(); //返回湿度低8位 IIC_ACK(); buff[5] = IIC_RcvByte(); //湿度crc校验位 IIC_NACK(); IIC_Stop(); } else { SerialNumber = 0; IIC_Stop(); Delayms(50); } SerialNumber = buff[0]; SerialNumber <<= 8; SerialNumber |= buff[1]; SerialNumber <<= 8; SerialNumber |= buff[3]; SerialNumber <<= 8; SerialNumber |= buff[4]; if(SerialNumber > 0) { type = TYPE_SHT40; } #endif return type; } //读出温湿度 void SHT30_read_result(u8 addr, u8 type) { int ret = 0; u16 tem, hum; u16 buff[6]; //发送指令为0x2C06(默认) IIC_Start(); IIC_SendByte(addr << 1 | write); //写7位I2C设备地址加0作为写取位,1为写取位 IIC_wait_ACK(); if(type == TYPE_SHT40) { //SHT40 IIC_SendByte(0xFD); IIC_wait_ACK(); } else { //SHT30 IIC_SendByte(0x2c); IIC_wait_ACK(); IIC_SendByte(0x06); IIC_wait_ACK(); } IIC_Stop(); Delayms(50); IIC_Start(); IIC_SendByte(addr << 1 | read); //写7位I2C设备地址加1作为读取位,1为读取位 ret = IIC_wait_ACK(); if(!ret) { Delayus(1); buff[0] = IIC_RcvByte(); //返回温度高8位 IIC_ACK(); buff[1] = IIC_RcvByte(); //返回温度低8位 IIC_ACK(); buff[2] = IIC_RcvByte(); //温度crc校验位 IIC_ACK(); buff[3] = IIC_RcvByte(); //返回湿度高8位 IIC_ACK(); buff[4] = IIC_RcvByte(); //返回湿度低8位 IIC_ACK(); buff[5] = IIC_RcvByte(); //湿度crc校验位 IIC_NACK(); IIC_Stop(); } tem = ((buff[0] << 8) | buff[1]); hum = ((buff[3] << 8) | buff[4]); if(type == TYPE_SHT40) { //温湿度的计算方法如下 Temperature = 175.0 * (float)tem / 65535.0 - 45.0 ; Humidity = 125.0 * (float)hum / 65535.0 - 6; } else { //温湿度的计算方法如下 Temperature = 175.0 * (float)tem / 65535.0 - 45.0 ; Humidity = 100.0 * (float)hum / 65535.0; } hum = 0; tem = 0; } #ifndef __TYPE_H #define __TYPE_H #include "main.h" typedef enum { RANG_70DB = 0x00, RANG_100DB = 0x01, RANG_130DB = 0x02 } MEA_RANGE_TypeDef; //typedef enum //{ // POINT_100DB = 0x00, // POINT_70DB = 0x01, // POINT_40DB = 0x02 //} CAL_POINT_TypeDef; typedef enum { SHORT_PRESS = 0x00, LONG_PRESS = 0x01, } PRESS_MODE_TypeDef; typedef enum { A_WEIGHT = 0x00, C_WEIGHT = 0x01, } FREQ_WEIGHT_TypeDef; typedef enum { FAST_RESP = 0x00, SLOW_RESP = 0x01, } FREQ_RESP_TypeDef; typedef enum { MAIN_STATE = 0x00, SET_STATE = 0x01, } SYS_STATE_TypeDef; typedef enum { SET_ALM = 0x00 ,//原噪音,现在作为温度使用 SET_ALM2 ,//新增:作为湿度使用 SET_ALM_TIME , SET_ALM_Type , SET_YEAR , SET_MONTH , SET_DAY , SET_HOUR , SET_MINUTE , SET_SECOND , SET_ALM_CLOCK_HOUR , SET_ALM_CLOCK_MINUTE , SET_ALM_CLOCK_EN , } SET_STATE_TypeDef; typedef enum { NO_OUT_RANGE = 0x00, OVER_RANGE = 0x01, UNDER_RANGE = 0x02, } OUT_RANGE_TypeDef; typedef struct { u8 KeyAge : 8; u8 KeyPress : 4; u8 KeyProcessed : 4; GPIO_Module *KeyPort; uint16_t KeyPin; void (*fun) (PRESS_MODE_TypeDef); } SysKey; typedef struct { u8 First_Press; u8 Mea_OK; u8 EEPROM_ERR; u8 SPIFlashErr; u8 Cal_Finish; // u8 Cal_DB_Finish; u8 Cal_En; u8 DispSetEn; u8 LCDFlick; u8 FlickEn; u8 RecFull; u8 Alarms; u8 UpOver; u8 ClockSoundEn; u8 GetRec; u8 BiBiBi; u8 Nop; u8 GetDate; u8 Test; u8 PWD, PWDErr; u8 EraseDoing; u8 UsbCmdLen; u8 SensorType; //温湿度传感器类型 u8 DMA_OK; u8 shutdown; u8 showLcd; u8 Negative; } FLAG_TYPE; typedef struct { double ADC_VALUE[3]; double ADC_Sum_Value; u32 ADC_INT_Value; u16 ADC_CNT; // u16 DB_Disp; u16 TEMP_Disp; u16 HUMI_Disp; u32 ADC_INT_Value_TAB[8]; u32 CAL_INT_Value; u16 Disp_ALM; //CAL u8 ADC_TAB_CNT; u8 Cal_Mode; //系统状态 // CAL_POINT_TypeDef Cal_DB_Point; FREQ_WEIGHT_TypeDef Freq_Weight; FREQ_RESP_TypeDef Freq_Resp; SYS_STATE_TypeDef Sys_State; OUT_RANGE_TypeDef Mea_Range; MEA_RANGE_TypeDef Adc_Range; SET_STATE_TypeDef Set_State; FunctionalState ALM_EN; u8 SaveCnt_2s; u16 Wait; // u8 DispDB_Cnt; u8 DispTEMP_Cnt; u8 DispHUMI_Cnt; u8 CalEn; s16 SET_Value; u16 Save_2s_Data[14]; u32 Start_Rec;//1开始 但是程序中所有的变量 统一从0开始 所以在使用时要-1 u32 End_Rec;//1开始 但是程序中所有的变量 统一从0开始 所以在使用时要-1 u8 Cal_Step; u8 Save_Cnt; u8 FlashNum; u8 WaitReleaseKey; u32 OverCntt[3]; u8 Alm_Time; u8 Alm_Type; int16_t Alm; int16_t Alm2; // u16 MaxDB_Save; u16 MaxTEMP_Save; u16 MaxHUMI_Save; u8 SaveTime2s; u8 DMA_Group; u8 BattCnt; u16 BattBuff[64]; u32 Batt; u8 Units; // 0:摄氏度, 1:华氏度 } DATA_TYPE; typedef struct { unsigned char year ; unsigned char month ; unsigned char day ; unsigned char hour ; unsigned char minute ; unsigned char second ; } DATE_TIME; typedef struct { unsigned char hour ; unsigned char minute ; unsigned char second ; unsigned char enabled ; } TIME_INFO; typedef union { u32 Mem[2]; struct { int16_t Alm_Value : 16; int16_t Alm2_Value : 16; u8 Alm_Switch : 4; u8 Alm_Type : 4; u8 Alm_Time : 8; } Struct_Para; } UNION_PARA; typedef struct { u16 ID; u16 ChipStart; u32 REC_HalfPages;//从0开始 0至MAX_REC_Pages-1 int16_t Cal_Adc[3]; // int16_t Cal_DB[3]; int32_t Cal_Adc_Squ[3]; UNION_PARA AlmPara; u8 PWRON_Erase; u8 AlarmClockOk;//产生报警 TIME_INFO AlarmClockInfo; } SYS_INFO; //128 typedef struct { u8 Header; u8 Machine_State; u8 Year ; u8 Month ; u8 Day ; u8 Hour ; u8 Minute ; u8 Second ; u16 Result[60]; //Noise_Result: Freq_Weight + Freq_Respon + DB_Value 存储用 } STORAGE; #endif #include <stdio.h> #include "main.h" FLAG_TYPE SysFlag; DATA_TYPE SysData; double Phasea; u32 Phaseb; SYS_INFO SysInfo; STORAGE Storage, Rec_Data; uint8_t Report_buf[MY_DEF_PACKET]; //usb接收BUFF uint8_t Send_Buffer[MY_DEF_PACKET]; //usb发射BUFF u8 SysClock, Clock_150, Clock_500, Clock_750, test; u8 USB_Device_dev; uint16_t TEMP = 0, TEMP2 = 0, TEMP3 = 0, TEMP4 = 0; uint16_t DMA_Test_Value[5], DMA_Test_Value1[5]; uint16_t ADC1ConvertedValue1[5]; #define HUMIMAX 32 float humi_bak[HUMIMAX]; unsigned char humi_pt=0; //const u32 CAL_DB[3] = {10000, 7000, 4000}; RCC_ClocksType RCC_Clocks_;//获得时钟频率 u8 RedLelOnFlag; void timeTempCompensation(void) { static u16 powerOnTime = 0; static u8 second = 0; if(Time_Dec.second != second) { if(powerOnTime < 900) //10分钟 { powerOnTime++; } } second = Time_Dec.second; if(powerOnTime < 600) { Temperature = Temperature - powerOnTime * (2.0 / 600.0f); } else { Temperature = Temperature - (2.0 + (powerOnTime - 600) * (0.5 / 300.0f)); } } u8 TwinkleControl(void) { static unsigned char second = 0; static unsigned char showFlag = 0; static s16 SET_Value = 0; static unsigned char enabled = 0; if(second != Time_Dec.second) { second = Time_Dec.second; if((SET_Value != SysData.SET_Value) || (SysInfo.AlarmClockInfo.enabled != enabled)) { showFlag = 1; SET_Value = SysData.SET_Value; enabled = SysInfo.AlarmClockInfo.enabled; } else { if(showFlag) { showFlag = 0; } else { showFlag = 1; } } } return showFlag; } # //温湿度时间处理 void humitureTaskPro() { unsigned char showFlag = 0,loopi; float tmp[HUMIMAX]; Get_Time(); if((SysData.Sys_State != SET_STATE) || ((SysData.Sys_State == SET_STATE) && (SysData.Set_State < SET_ALM_CLOCK_HOUR))) { SHT30_read_result(0x44, SysFlag.SensorType); for(loopi=1;loopi<(HUMIMAX);loopi++) { humi_bak[loopi-1]=humi_bak[loopi]; tmp[loopi-1]=humi_bak[loopi-1]; } humi_bak[HUMIMAX-1]=Humidity; tmp[HUMIMAX-1]=Humidity; bubble_float(tmp,HUMIMAX); Humidity=(tmp[HUMIMAX>>1]+tmp[(HUMIMAX>>1)+1])/2.0f; timeTempCompensation(); } } void AlarmSettingTaskPro() { unsigned char showFlag = 0; if((SysData.Sys_State == SET_STATE) && (SysData.Set_State > SET_SECOND)) { showFlag = TwinkleControl(); switch(SysData.Set_State) { case SET_ALM_CLOCK_HOUR: Disp_AL(); if(!showFlag) { ClearHour(); } break; case SET_ALM_CLOCK_MINUTE: Disp_AL(); if(!showFlag) { ClearMinute(); } break; case SET_ALM_CLOCK_EN: if(showFlag) { if(SysInfo.AlarmClockInfo.enabled) { Disp_ON(); } else { Disp_OFF(); } } else { Disp_Clear(); } break; default: break; } // ClearTemp(); // ClearHumi(); if(showFlag) { displayAlarmClockTime(SysInfo.AlarmClockInfo.hour, SysInfo.AlarmClockInfo.minute); SysFlag.showLcd = 0; } RefreshDisplay(); } } void GreenLedOn(void)//电量指示灯 { LED_Green_ON; } void GreenLedOff(void) { LED_Green_OFF; } void RedLedOn(void) { LED_Red_ON; } void RedLedOff(void) { LED_Red_OFF; } void Led_2_On(void)//报警指示灯 { LED_2_ON; } void Led_2_Off(void) { LED_2_OFF; } void Led_3_On(void)//摄氏度指示灯 { LED_3_ON; } void Led_3_Off(void) { LED_3_OFF; } void Led_4_On(void)//华氏度指示灯 { LED_4_ON; } void Led_4_Off(void) { LED_4_OFF; } void RedLedTwinkleOnce(u16 period) { static u16 count = 0; static u8 LedOnFlag = 0; count++; if(count > period) { LED_Green_OFF; RedLedOn(); RedLelOnFlag = 1; } if(count > (period + 1)) { RedLedOff(); count = 0; RedLelOnFlag = 0; } } void RedLedTwinkle(u16 period) { static u16 count = 0; static u8 LedOnFlag = 0; count++; if(count > period) { if(LedOnFlag) { LED_Green_OFF; Led_2_On(); SysFlag.LCDFlick = 1; LedOnFlag = 0; } else { LED_Green_OFF; Led_2_Off(); SysFlag.LCDFlick = 0; LedOnFlag = 1; } count = 0; } } void GreenLedTwinkle(u16 period) { static u16 count = 0; static u8 LedOnFlag = 0; count++; if(count > period) { if(LedOnFlag) { GreenLedOn(); LedOnFlag = 0; } else { GreenLedOff(); LedOnFlag = 1; } count = 0; } } void GreenLedTwinkle_USBCHECK_ON(u16 period)//debug { static u16 count = 0; static u8 LedOnFlag = 0; count++; if(count > period) { if(LedOnFlag) { RedLedOff(); GreenLedOn(); SysFlag.LCDFlick = 1; LedOnFlag = 0; } else { RedLedOff(); GreenLedOff(); SysFlag.LCDFlick = 0; LedOnFlag = 1; } count = 0; } } void RedGreenLedTwinkle(u16 period) { static u16 count = 0; static u8 GreenLedOnFlag = 0; static u8 RedLedOnFlag = 0; static u16 periodCnt = 0; periodCnt++; if(periodCnt > period) { if(RedLedOnFlag) { GreenLedOff(); RedLedOff(); RedLedOnFlag = 0; } else { count++; if(count == 3) { RedLedOn(); RedLedOnFlag = 1; count = 0; } else { GreenLedOn(); RedLedOnFlag = 1; } } periodCnt = 0; } } void alarmLedEvent(void) { if(SysData.ALM_EN == ENABLE) { if(SysFlag.Alarms) { RedLedTwinkle(0); } else { // RedLedTwinkleOnce(7); Led_2_On(); } } else { Led_2_Off(); } } //LED控制 500ms调用一次 void LedControl(void) { if(VUSB_CHECK) { RedLedOff(); if(CHARGE_FULL) // if(1) //test { //充满 GreenLedOn(); // if(!SysFlag.shutdown) // { // alarmLedEvent(); // } } else { //未充满 /* if((SysData.ALM_EN==ENABLE)&&(SysFlag.Alarms)&&(!SysFlag.shutdown)) { alarmLedEvent(); } else { GreenLedTwinkle(1); } */ if(SysData.ALM_EN == ENABLE) { if(SysFlag.Alarms) { // alarmLedEvent(); GreenLedTwinkle_USBCHECK_ON(0); } else { #ifdef NO_RED_LED GreenLedTwinkle(0);//debug #else RedGreenLedTwinkle(1); #endif } } else { GreenLedTwinkle(0); } } } else { GreenLedOff(); if((SysData.ALM_EN == ENABLE) && (SysFlag.Alarms)) { alarmLedEvent(); } else { if(SysData.Batt < BattLOW) { RedLedOn(); if(SysData.Batt < BattSHUT) { Shut_Down(); } } else { alarmLedEvent(); } } } } //报警任务 void AlarmClockTask(void) { if((SysInfo.AlarmClockInfo.hour == Time_Dec.hour) && (SysInfo.AlarmClockInfo.minute == Time_Dec.minute) && (SysInfo.AlarmClockInfo.second == Time_Dec.second) && (SysInfo.AlarmClockInfo.enabled)) { if(!SysInfo.AlarmClockOk) { SysInfo.AlarmClockOk = 1; SysFlag.ClockSoundEn = 1; } } } void AlarmClockControl(void) { static unsigned char second = 0; static unsigned char AlarmClocksecond = 0; static unsigned char AlarmClockcvt = 0; if(SysInfo.AlarmClockOk) { if(second != Time_Dec.second) { AlarmClocksecond++; second = Time_Dec.second; } if(AlarmClocksecond < 30) { SysFlag.ClockSoundEn = 1; } else { SysFlag.ClockSoundEn = 0; if(AlarmClocksecond > 35) { AlarmClocksecond = 0; AlarmClockcvt++; if(AlarmClockcvt > 2) { SysInfo.AlarmClockOk = 0; SysFlag.ClockSoundEn = 0; } } } } else { second = 0; AlarmClocksecond = 0; AlarmClockcvt = 0; SysFlag.ClockSoundEn = 0; } } void ResetAlarmClockTime(void) { if((SysInfo.AlarmClockInfo.hour > 23) || (SysInfo.AlarmClockInfo.minute > 59) || (SysInfo.AlarmClockInfo.second > 59)) { SysInfo.AlarmClockInfo.hour = Time_Dec.hour; SysInfo.AlarmClockInfo.minute = Time_Dec.minute; SysInfo.AlarmClockInfo.second = 0; } } int main(void) { uint8_t ret = 0; uint8_t keyUpFlag = 0; Init_Pro(); Init_Var(); LED_Red_OFF; LED_Green_OFF; ResetAlarmClockTime(); while (1) { if(!SysFlag.shutdown) { if(SysFlag.UsbCmdLen) { USB_Decode(); SysFlag.UsbCmdLen = 0; USB_Pro(); } if(SysClock) { SysClock = 0; Key_Pro(); AlarmSettingTaskPro(); } if(Clock_150 > 2) { Clock_150 = 0; humitureTaskPro(); AlarmClockTask(); Data_Pro(); Disp_Set(); AlarmClockControl(); if(Clock_750 > 14) { Clock_750 = 0; if(((SysFlag.UpOver==1)||(SysFlag.ClockSoundEn))&&(Turn_On_Wait>=5))//开机等待一段时间再报警 { switch(SysInfo.AlmPara.Struct_Para.Alm_Type) { case 1: bi(2); break; case 2: bi(3); break; case 3: bi(4); break; } } if((SysData.Sys_State==SET_STATE)&&(SysData.Set_State==SET_ALM_Type)&&(SysFlag.FlickEn)) { switch(SysData.SET_Value) { case 1: bi(2); break; case 2: bi(3); break; case 3: bi(4); break; } } } } else { if(VUSB_CHECK) { Disp_Clear(); ClearTimeDisplay(); // ClearTempDisplay(); } else { Shut_Down(); } } if(Clock_500 > 9) { Clock_500 = 0; if(!SysFlag.shutdown) { if(SysFlag.PWD == 1) { SysFlag.PWDErr++; //隔了1s还是处于低电 未关机状态 认为判断失败 //重新归零 恢复正常 if(SysFlag.PWDErr > 1) { SysFlag.PWDErr = 0; SysFlag.PWD = 0; } } LCD_Disp(); Clock_500_Pro(); } else { //如果充电的情况下关机,在按电源键正常开机 if(GPIO_ReadInputDataBit(KEy[Num_Power].KeyPort, KEy[Num_Power].KeyPin) == 0) { KEy[Num_Power].KeyAge++; if(KEy[Num_Power].KeyAge > 0) { if(keyUpFlag) { SysFlag.shutdown = 0; KEy[Num_Power].KeyAge = 0; keyUpFlag = 0; SysData.Sys_State = MAIN_STATE; SysFlag.First_Press = 1; Disp_All(); Delayms(500); } } } else { KEy[Num_Power].KeyAge = 0; keyUpFlag = 1; } } LedControl(); } } } } void Delayms(u32 Cnt) { u32 i, j; for(j = 0; j < Cnt; j++) { for(i = 0; i < 29760; i++); } } void Delayus(u32 Cnt) { u32 i, j; for(j = 0; j < Cnt; j++) { for(i = 0; i < 35; i++); } } void Init_Var(void) { SysFlag.First_Press = 1; SysFlag.Mea_OK = 0; SysData.ALM_EN = ENABLE; SysData.ADC_CNT = 0; SysData.Freq_Weight = A_WEIGHT; SysData.Freq_Resp = FAST_RESP; SysData.Sys_State = MAIN_STATE; switch(SysData.Freq_Weight) { case A_WEIGHT: FREQ_WEIGHT_A; break; case C_WEIGHT: FREQ_WEIGHT_C; break; } SysData.DispTEMP_Cnt = 0; SysData.DispHUMI_Cnt = 0; SysData.TEMP_Disp = 0; SysData.ADC_CNT = 0; SysData.Wait = 0; SysData.Save_Cnt = 0; SysFlag.EEPROM_ERR = 0; Init_Para(); SysData.Alm = SysInfo.AlmPara.Struct_Para.Alm_Value; SysData.ALM_EN = SysInfo.AlmPara.Struct_Para.Alm_Switch; SysData.Alm_Type = SysInfo.AlmPara.Struct_Para.Alm_Type; SysData.Alm_Time = SysInfo.AlmPara.Struct_Para.Alm_Time; if(SysData.ALM_EN) //yanggj { LED_2_ON; } else { LED_2_OFF; } SPI_FLASH_Dec(); if(SysInfo.PWRON_Erase) { SysInfo.PWRON_Erase = 0; Save_Param(&SysInfo.PWRON_Erase, sizeof(SysInfo.PWRON_Erase)); SysData.FlashNum = 1; SPI_Flash_EraseChip(); if(SysInfo.ChipStart == 0) SysInfo.ChipStart = 1; //FLASH2为起始 else SysInfo.ChipStart = 0; //FLASH1为起始 Save_Param(&SysInfo.ChipStart, sizeof(SysInfo.ChipStart)); } Buzzer_Init(); Buzzer_Setup(0); SysData.FlashNum = 1; if(SysInfo.REC_HalfPages > W25X_MAX_PAGE * 2) { SysData.FlashNum = 2; } Check_REC_Valid(); SysFlag.RecFull = 0; Clock_150 = 0; Clock_500 = 0; SysClock = 0; SysData.Cal_Mode = 0; SysFlag.Cal_En = 0; Delayms(500); if((SysFlag.EEPROM_ERR) || (SysFlag.SPIFlashErr)) { Disp_Err(); Delayms(500); } //获取温湿度传感器类型 SysFlag.SensorType = ReadHumitureSensorType(0x44); SysInfo.AlarmClockOk = 0; } void LCD_Disp(void) { switch(SysData.Sys_State) { case MAIN_STATE: displayTime(Time_Dec.hour, Time_Dec.minute, Time_Dec.second); Disp_TempHumi(); Disp_Date(); break; case SET_STATE: break; } RefreshDisplay(); } void Get_AD_SUM(void) { uint64_t Sum[3] = {0, 0, 0}; //这里有3种计算,分别是sum[0],sum[1],sum[2] u8 Ratio; u16 loopi, *Data; u32 Temp; Data = Noise_Data.Buff1;//将DMA移过来的地址给Data if(SysData.DMA_Group != 0) Data = Noise_Data.Buff0;//将DMA移过来的地址给Data SysData.BattCnt = 0; //sum[0] for(loopi = 0; loopi < DMA_CAL_BUFF_SIZE; loopi += 4) //循环480/3=150次 { Temp = (u32)(*Data); //将Noise_Data.Buff1的值给Temp Data++;//地址++ if(Temp > ADC_HLimit) SysData.OverCntt[0]++; //如果Temp>2482,数据溢出的标志位++,这个数据溢出的标志位也有3种,用数组来表示 Temp = Temp + (s32)SysInfo.Cal_Adc[0];// 这个应该是存放校准后的ADC if(Temp > 0x80000000)Temp = 0; Temp = Temp * Temp; //不知道平方一次是用来干啥的 Sum[0] += (uint64_t)Temp; //计算总和,存到sum[0] //sum[1] Temp = (u32)(*Data); Data++; if(Temp > ADC_HLimit_H) SysData.OverCntt[1]++; Temp = Temp + (s32)SysInfo.Cal_Adc[1]; if(Temp > 0x80000000)Temp = 0; Temp = Temp * Temp; Sum[1] += (uint64_t)Temp; //计算总和,存到sum[1] //sum[2] Temp = (u32)(*Data); Data++; Temp = Temp + (s32)SysInfo.Cal_Adc[2]; if(Temp > 0x80000000) Temp = 0; Temp = Temp * Temp; Sum[2] += (uint64_t)Temp; //计算总和,存到sum[2] if(SysData.BattCnt < 64) { SysData.BattBuff[SysData.BattCnt++] = *Data; } Data++; } SysData.Batt = 0; for(loopi = 0; loopi < 64; loopi++) { SysData.Batt += SysData.BattBuff[loopi]; } SysData.Batt = SysData.Batt / 64; //报警时低于3.3V不关机问题,电源检测这里添加关机 if(SysData.Batt < BattSHUT) { Shut_Down(); } //将计算的总和,存到SysData.ADC_VALUE SysData.ADC_VALUE[0] += (double)Sum[0]; SysData.ADC_VALUE[1] += (double)Sum[1]; SysData.ADC_VALUE[2] += (double)Sum[2]; SysData.ADC_CNT++; Ratio = SysData.Freq_Resp * 7 + 1; //不知道这2句是干嘛的 if(SysData.ADC_CNT >= (SMP_DMA_CNT * Ratio)) { SysData.ADC_CNT = 0; // if(SysData.Cal_Mode == 0) // { // if(SysData.OverCntt[0] < MIN_OVER_CNT) //溢出计数判断 // { // SysData.Adc_Range = RANG_70DB; // } // else if(SysData.OverCntt[1] < MIN_OVER_CNT) // { // SysData.Adc_Range = RANG_100DB; // } // else // { // SysData.Adc_Range = RANG_130DB; // } // } SysData.ADC_Sum_Value = (SysData.ADC_VALUE[SysData.Adc_Range] / (float)Ratio) + SysInfo.Cal_Adc_Squ[SysData.Adc_Range]; if(SysData.ADC_Sum_Value < 0) { ; } else { // Get_Noise_Data(); } SysData.ADC_VALUE[0] = 0; SysData.ADC_VALUE[1] = 0; SysData.ADC_VALUE[2] = 0; SysData.OverCntt[0] = 0; SysData.OverCntt[1] = 0; SysData.OverCntt[2] = 0; } } //void Get_Noise_Data(void) //{ // Phasea = SysData.ADC_Sum_Value; // /* // 523公式:10*log10(SysData.ADC_Sum_Value) *10 //是为了扩大10倍 用于获取小数部分,来显示 // */ // Phasea = log10(Phasea); // Phasea = Phasea * 1000; // Phaseb = (u32)Phasea; // SysData.CAL_INT_Value = Phaseb + SysInfo.Cal_DB[SysData.Adc_Range]; // SysData.ADC_INT_Value = SysData.CAL_INT_Value / 10; // if(SysData.Cal_Mode == 0) // { // if(SysData.ADC_TAB_CNT == 0) // { // SysData.ADC_TAB_CNT = 1; // SysData.ADC_INT_Value_TAB[1] = SysData.ADC_INT_Value; // SysData.ADC_INT_Value_TAB[2] = SysData.ADC_INT_Value; // SysData.ADC_INT_Value_TAB[3] = SysData.ADC_INT_Value; // } // else // { // SysData.ADC_INT_Value_TAB[3] = SysData.ADC_INT_Value_TAB[2]; // SysData.ADC_INT_Value_TAB[2] = SysData.ADC_INT_Value_TAB[1]; // SysData.ADC_INT_Value_TAB[1] = SysData.ADC_INT_Value_TAB[0]; // } // SysData.ADC_INT_Value_TAB[0] = SysData.ADC_INT_Value; // } // else // { // SysData.CalEn = 1; // if(SysData.Adc_Range == RANG_130DB) // { // if(SysData.ADC_INT_Value == 1300) // { // SysFlag.FlickEn = 1; // } // else // { // SysFlag.FlickEn = 0; // } // } // } //} void HexToBcd(int32_t Data) { if (Data < 0) { HexData[0] = 0x0b; u32 absData = -Data; if (absData >= 10) { HexData[1] = absData / 10 % 10; HexData[2] = absData % 10; } else { HexData[1] = 0x0a; HexData[2] = absData; } } else { HexData[0] = Data / 100 % 10; HexData[1] = Data / 10 % 10; HexData[2] = Data % 10; } } void Copy_Data(u8 *Src, u8 *Des, u8 Num) { u8 loopi; u8 *S = Src, *D = Des; for(loopi = 0; loopi < Num; loopi++) { *D = *S; D ++; S ++; } } void Fill_Data(void) { Copy_Data(HexData, MainData, 3);//这里改为3进入设置模式只有前三位显示 } u32 MAX(u32 *src, u8 Num) { u8 loopi; u32 MaxValue; MaxValue = 0; for(loopi = 0; loopi < Num; loopi++) { if(MaxValue < (*src)) { MaxValue = *src; } src++; } return MaxValue; } u16 MAX_HalfWorld(u16 *src, u8 Num) { u8 loopi; u16 MaxValue; MaxValue = 0; for(loopi = 0; loopi < Num; loopi++) { if(MaxValue < (*src)) { MaxValue = *src; } src++; } return MaxValue; } void Get_DispData(void) { static u8 AlarmClockOver = 0; if(SysData.Sys_State == SET_STATE) return;//设置时不存储 //校准模式直接送显 if(SysData.Cal_Mode) { SysData.TEMP_Disp = SysData.ADC_INT_Value; return; } //获取一次结果 if(SysData.Freq_Resp == FAST_RESP) { //450ms获取一次数据送显示 SysData.TEMP_Disp = MAX(SysData.ADC_INT_Value_TAB, 4); //求最大 } else { //1s获取一次 SysData.DispTEMP_Cnt = 0; SysData.TEMP_Disp = SysData.ADC_INT_Value_TAB[0]; } if(SysFlag.UpOver == 0) { if(SysData.Wait > 0) //这是测量时间 { SysData.Wait--; if(!SysInfo.AlarmClockOk) { SysData.TEMP_Disp = SysData.Disp_ALM; } } else if((SysData.TEMP_Disp > SysData.Alm) && (SysData.ALM_EN == ENABLE)) { SysData.Disp_ALM = SysData.TEMP_Disp; SysInfo.AlarmClockOk = 0; SysFlag.UpOver = 1; SysFlag.Alarms = 1; } else { ALM_OUT_EN(DISABLE); SysFlag.Alarms = 0; } } else { //报警显示 SysData.TEMP_Disp = SysData.Disp_ALM; } //每两秒存储一次 if(SysData.MaxTEMP_Save < SysData.TEMP_Disp) { SysData.MaxTEMP_Save = SysData.TEMP_Disp; } } void Data_Pro(void) { Get_DispData(); } void bubble(unsigned int a[], unsigned char n) { unsigned char i, j; unsigned int k; for(i = 1; i < n; i++) for(j = 0; j < n - i; j++) if(a[j] > a[j + 1]) { k = a[j]; a[j] = a[j + 1]; a[j + 1] = k; } } void bubble_float( float a[], unsigned char n) { unsigned char i, j; float k; for(i = 1; i < n; i++) for(j = 0; j < n - i; j++) if(a[j] > a[j + 1]) { k = a[j]; a[j] = a[j + 1]; a[j + 1] = k; } } void Cal_Pro(void)//校准 { // u32 Limit, Tmp; // Limit = CAL_DB[SysData.Cal_DB_Point]; //这个是校准点,有4000,7000,10000 // if(SysData.CAL_INT_Value == Limit) //如果 SysData.CAL_INT_Value==4000/7000/10000 // { // SysFlag.Cal_Finish = 1; //校准完成标志=1 // SysData.CalEn = 0; // if(SysFlag.Cal_DB_Finish == 0) // { // //这里要采集下一通道的差值 // switch(SysData.Cal_DB_Point)//通过按键,会对SysData.Cal_DB_Point++,从而来判断当前校准哪个点 // { // case POINT_100DB: // SysData.Adc_Range = RANG_100DB; //将这个范围给到SysData.Adc_Range // Delayms(300); // break; // case POINT_70DB: // SysData.Adc_Range = RANG_70DB; // Delayms(300); // break; // case POINT_40DB: // Para_Save(); // Delayms(300); // Shut_Down(); // break; // } // SysFlag.Cal_DB_Finish = 1; // } // } // if((SysData.CalEn) && (SysFlag.Cal_Finish == 0)) // { // SysFlag.FlickEn = 0; // SysData.CalEn = 0; // if(SysData.CAL_INT_Value > Limit) // { // Tmp = SysData.CAL_INT_Value - Limit; // if(Tmp < 10) // { // SysData.Cal_Step = 2; // } // switch(SysData.Cal_Step) // { // case 0: // SysData.Cal_Step = 1; // SysInfo.Cal_Adc[SysData.Adc_Range]--; // break; // case 1: // SysInfo.Cal_Adc[SysData.Adc_Range]--; // break; // case 2: // case 3: // SysData.Cal_Step = 2; // SysInfo.Cal_Adc_Squ[SysData.Adc_Range] -= 20000; // break; // } // } // if(SysData.CAL_INT_Value < Limit) // { // Tmp = Limit - SysData.CAL_INT_Value ; // if(Tmp < 10) // { // SysData.Cal_Step = 2; // } // switch(SysData.Cal_Step) // { // case 0: // SysData.Cal_Step = 3; // SysInfo.Cal_Adc[SysData.Adc_Range]++; // break; // case 3: // SysInfo.Cal_Adc[SysData.Adc_Range]++; // break; // case 1: // case 2: // SysData.Cal_Step = 2; // SysInfo.Cal_Adc_Squ[SysData.Adc_Range] += 40000; // break; // } // } // } // if((SysFlag.Cal_DB_Finish) && (SysData.CalEn) && (SysFlag.FlickEn == 0)) // { // SysData.CalEn = 0; // SysData.ADC_INT_Value_TAB[SysData.ADC_TAB_CNT] = SysData.CAL_INT_Value; // SysData.ADC_TAB_CNT++; // if(SysData.ADC_TAB_CNT >= MAX_CAL_NUM) // { // SysData.ADC_TAB_CNT = 0; // bubble(SysData.ADC_INT_Value_TAB, MAX_CAL_NUM); // Tmp = SysData.ADC_INT_Value_TAB[MAX_CAL_NUM / 2]; // SysInfo.Cal_DB[SysData.Adc_Range] = CAL_DB[SysData.Cal_DB_Point] - Tmp; // SysFlag.FlickEn = 1; // if(SysData.Adc_Range == RANG_70DB) // { // Para_Save(); // Disp_All(); // Delayms(1000); // SysData.Cal_Mode = 0; // KEy[Num_Alm].KeyProcessed = 1; // SysData.Freq_Weight = A_WEIGHT; // SysData.Freq_Resp = FAST_RESP; // switch(SysData.Freq_Weight) // { // case A_WEIGHT: // FREQ_WEIGHT_A; // break; // case C_WEIGHT: // FREQ_WEIGHT_C; // break; // } // return; // } // } // } KEy[Num_Alm].KeyProcessed = 0; } void Shut_Down(void) { // LED_Red_OFF; // Disp_Clear(); // ClearTimeDisplay(); // POWER_OFF; // Delayms(200); // POWER_OFF; // Delayms(200); // POWER_OFF; // Delayms(200); // while(1) // { // ; // } } //时间检查 void Check_Date(void) { unsigned char month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if(Time_Dec.year > 99) Time_Dec.year = 0; if(Time_Dec.year < 0) Time_Dec.year = 99; if(Time_Dec.month < 1) Time_Dec.month = 12; if(Time_Dec.month > 12) Time_Dec.month = 1; if(Time_Dec.day < 1) Time_Dec.day = 31; if(Time_Dec.day > 31) Time_Dec.day = 1; if(Time_Dec.hour > 23) Time_Dec.hour = 0; if(Time_Dec.hour < 0) Time_Dec.hour = 23; if(Time_Dec.minute > 59) Time_Dec.minute = 0; if(Time_Dec.minute < 0) Time_Dec.minute = 59; if(Time_Dec.second > 59) Time_Dec.second = 0; if(Time_Dec.second < 0) Time_Dec.second = 59; month[2] = 28; if (Time_Dec.year % 4 == 0 || Time_Dec.year % 100 == 0 || Time_Dec.year % 400 == 0) //???ūìˇ?ū???29?c month[2] = 29; if(Time_Dec.day > month[Time_Dec.month]) Time_Dec.day = 1; Time_Hex.year = (Time_Dec.year / 10) << 4 | (Time_Dec.year % 10); Time_Hex.month = (Time_Dec.month / 10) << 4 | (Time_Dec.month % 10); Time_Hex.day = (Time_Dec.day / 10) << 4 | (Time_Dec.day % 10); Time_Hex.hour = (Time_Dec.hour / 10) << 4 | (Time_Dec.hour % 10); Time_Hex.minute = (Time_Dec.minute / 10) << 4 | (Time_Dec.minute % 10); Time_Hex.second = (Time_Dec.second / 10) << 4 | (Time_Dec.second % 10); } void Clock_500_Pro(void) { if(!SysFlag.UpOver) { SysFlag.LCDFlick = !SysFlag.LCDFlick; } if((SysData.Sys_State == SET_STATE) && (SysData.Set_State == SET_ALM) && (SysData.Set_State == SET_ALM2)) { } Get_Time(); if(Turn_On_Wait < 5) { Turn_On_Wait++; } if(SysData.Sys_State == SET_STATE)return; if((SysFlag.UpOver == 1) && (Turn_On_Wait >= 5)) //开机等待一段时间再报警 { if(((SysData.Wait == 0) && (SysFlag.BiBiBi == 0)) || (SysInfo.AlarmClockOk)) { ALM_OUT_EN(ENABLE); SysFlag.BiBiBi = 1; SysData.Wait = SysData.Alm_Time * 2; } else { if(SysData.Wait) { SysData.Wait--; } } } Save_Data(); } void Check_Set(void) { unsigned char month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; switch(SysData.Set_State) { case SET_ALM: if(SysData.SET_Value > MAX_ALM_TEMP) SysData.SET_Value = MAX_ALM_TEMP;//55 if(SysData.SET_Value < MIN_ALM_TEMP) SysData.SET_Value = MIN_ALM_TEMP;//-10 break; case SET_ALM2: if(SysData.SET_Value > MAX_ALM_HUMI) SysData.SET_Value = MAX_ALM_HUMI; if(SysData.SET_Value < 0) SysData.SET_Value = 0; break; case SET_ALM_TIME: if(SysData.SET_Value > MAX_ALM_TIME) SysData.SET_Value = MAX_ALM_TIME; if(SysData.SET_Value < MIN_ALM_TIME) SysData.SET_Value = MIN_ALM_TIME; break; case SET_ALM_Type: if(SysData.SET_Value > MAX_ALM_Type) SysData.SET_Value = MAX_ALM_Type; if(SysData.SET_Value < MIN_ALM_Type) SysData.SET_Value = MIN_ALM_Type; break; case SET_YEAR: if(SysData.SET_Value > 99) SysData.SET_Value = 0; if(SysData.SET_Value < 0) SysData.SET_Value = 99; break; case SET_MONTH: if(SysData.SET_Value < 1) SysData.SET_Value = 12; if(SysData.SET_Value > 12) SysData.SET_Value = 1; break; case SET_DAY: month[2] = 28; if ((Time_Set.year % 4 == 0 && Time_Set.year % 100 != 0) || (Time_Set.year % 400 == 0) ) month[2] = 29; if(SysData.SET_Value > month[Time_Set.month]) SysData.SET_Value = 1; if(SysData.SET_Value < 1) SysData.SET_Value = month[Time_Dec.month]; break; case SET_ALM_CLOCK_HOUR: case SET_HOUR: if(SysData.SET_Value > 23) SysData.SET_Value = 0; if(SysData.SET_Value < 0) SysData.SET_Value = 23; break; case SET_ALM_CLOCK_MINUTE: case SET_MINUTE: if(SysData.SET_Value > 59)SysData.SET_Value = 0; if(SysData.SET_Value < 0) SysData.SET_Value = 59; break; case SET_SECOND: if(SysData.SET_Value > 59) SysData.SET_Value = 0; if(SysData.SET_Value < 0) SysData.SET_Value = 59; break; case SET_ALM_CLOCK_EN: break; } } u32 HacedSendRec; void USB_Correspondence(void) //USB通信部份 { u16 Max_Sector = 23; //一天24个扇区 u16 Max_Read; u32 Read_Num; u8 *usb_p, Max_SendNum = 64, loopi; HacedSendRec = 0; //读取记录,把记录发送到PC if(SysFlag.GetRec == 1) { SysFlag.GetRec = 0; USB_Busy = 1; while(Max_Sector) { Max_SendNum = 64; Max_Read = 32; //一个扇区32组记录 Read_Num = SysData.Start_Rec ; SysData.Start_Rec += 32; usb_p = SPI_Rec_BUFF; if(SysData.Start_Rec > SysData.End_Rec) { Max_Read = (SysData.End_Rec - (SysData.Start_Rec - 32) + 1); Max_SendNum = Max_Read * 2; Max_Sector = 0;//下一步跳出while } while(Max_Read--)//读完32组 { SPI_Flash_ReadHalfPage(usb_p, Read_Num - 1); Read_Num++; usb_p += 128; } usb_p = SPI_Rec_BUFF; //一次把一个扇区 发送完 while(Max_SendNum--) { //发送64组数据 USBD_HID_SendReport(&USB_Device_dev, usb_p, MY_DEF_PACKET); usb_p += 64; HacedSendRec++; } } for(loopi = 0; loopi < 64; loopi++)SPI_Rec_BUFF[loopi] = 0xff; USBD_HID_SendReport(&USB_Device_dev, SPI_Rec_BUFF, MY_DEF_PACKET); USB_Busy = 0; Delayms(1500); } else if (SysFlag.GetDate == 1) //193 { SysFlag.GetDate = 0; USB_Busy = 1; Max_Sector = 193; SysData.Start_Rec = 1; usb_p = SPI_Rec_BUFF; while(Max_Sector--) { Max_SendNum = 64; Max_Read = 1365; Read_Num = SysData.Start_Rec; SysData.Start_Rec += 1365; if(SysData.Start_Rec > SysInfo.REC_HalfPages) { Max_Read = SysInfo.REC_HalfPages - (SysData.Start_Rec - 1365) + 1; Max_SendNum = (Max_Read * 3 - 1) / 64 + 1; Max_Sector = 0;//下一步跳出while } //1365 while(Max_Read--) { SPI_Flash_ReadDate(usb_p, Read_Num - 1); Read_Num++; usb_p += 3; } usb_p = SPI_Rec_BUFF; while(Max_SendNum--) { USBD_HID_SendReport(&USB_Device_dev, usb_p, MY_DEF_PACKET); usb_p += 64; } usb_p = SPI_Rec_BUFF; } while(SysData.Start_Rec <= SysInfo.REC_HalfPages) { SPI_Flash_ReadDate((u8 *)&SPI_Rec_BUFF, SysData.Start_Rec - 1); SysData.Start_Rec++; USBD_HID_SendReport(&USB_Device_dev, usb_p, 3); } for(loopi = 0; loopi < 64; loopi++)SPI_Rec_BUFF[loopi] = 0xff; USBD_HID_SendReport(&USB_Device_dev, SPI_Rec_BUFF, MY_DEF_PACKET);//选择日期框 USB_Busy = 0; Delayms(1500); } } void USB_Pro(void) { USB_Correspondence(); } void Save_Rec(void) { SysInfo.REC_HalfPages++; if(SysInfo.REC_HalfPages > MAX_REC_Pages) { //擦除前半个芯片 SysData.FlashNum = 1; SysFlag.EraseDoing = 1; SPI_Flash_EraseChip(); SysFlag.EraseDoing = 0; if(SysFlag.PWD) { SysInfo.PWRON_Erase = 1; Save_Param(&SysInfo.PWRON_Erase, sizeof(SysInfo.PWRON_Erase)); return; } if(SysInfo.ChipStart == 0) SysInfo.ChipStart = 1; //FLASH2为起始 else SysInfo.ChipStart = 0; //FLASH1为起始 Save_Param(&SysInfo.ChipStart, sizeof(SysInfo.ChipStart)); SysInfo.REC_HalfPages = MAX_PAGE + 1; } //一定要先保存页数,这样在写的时候断电,下次开机会自动跳到新的一页写,不会去覆盖未写完的那一页 Save_Param(&SysInfo.REC_HalfPages, sizeof(SysInfo.REC_HalfPages)); SPI_Flash_WriteHalfPage((u8 *)&Storage.Header, SysInfo.REC_HalfPages - 1); } void Check_Time(void) { if((Time_Bak.second == 59) && (Time_Dec.second == 0)) { if(Time_Bak.minute == Time_Dec.minute) { Get_Time(); return; } else if((Time_Bak.minute == 59) && (Time_Dec.minute == 0)) { if(Time_Bak.hour == Time_Dec.hour) { Get_Time(); return; } } } } void Save_Data(void) { Get_Time(); if(Time_Bak.second != Time_Dec.second) { Check_Time(); Time_Bak.year = Time_Dec.year ; Time_Bak.month = Time_Dec.month; Time_Bak.day = Time_Dec.day ; Time_Bak.hour = Time_Dec.hour ; Time_Bak.minute = Time_Dec.minute ; Time_Bak.second = Time_Dec.second ; SysData.SaveTime2s++; } else return; if(SysData.SaveTime2s < 2) { return; } SysData.SaveTime2s = 0; Storage.Result[SysData.Save_Cnt] = SysData.MaxTEMP_Save; SysData.MaxTEMP_Save = 0; if(SysData.Save_Cnt == 0) { //先获取时间 Storage.Header = 0XFD; Storage.Machine_State = 0; if(SysData.Freq_Weight == C_WEIGHT) { Storage.Machine_State |= 0X10; } if(SysData.Freq_Resp == FAST_RESP) { Storage.Machine_State |= 0X40; } Storage.Year = Time_Hex.year; Storage.Month = Time_Hex.month; Storage.Day = Time_Hex.day; Storage.Hour = Time_Hex.hour; Storage.Minute = Time_Hex.minute; Storage.Second = Time_Hex.second; } SysData.Save_Cnt++; if(SysData.Save_Cnt >= 60) { SysData.Save_Cnt = 0; if(SysFlag.PWD == 0) { Save_Rec(); } } } void USB_Decode(void) { uint8_t test_x1 = 0; uint8_t Buff_Test1[64]; switch(Report_buf[0]) { case 0xb4: SysFlag.GetDate = 1; break; case 0xA3: //读时间 Get_Time(); Send_Buffer[5] = Time_Hex.second; Send_Buffer[4] = Time_Hex.minute; Send_Buffer[3] = Time_Hex.hour; Send_Buffer[2] = Time_Hex.day; Send_Buffer[1] = Time_Hex.month; Send_Buffer[0] = Time_Hex.year; USBD_HID_SendReport (&USB_Device_dev, Send_Buffer, MY_DEF_PACKET); break; case 0xb3: Send_Buffer[0] = SysData.TEMP_Disp >> 8; Send_Buffer[1] = SysData.TEMP_Disp & 0x00ff; Send_Buffer[2] = 0;//这部分应改为温度 Send_Buffer[3] = SysData.HUMI_Disp >> 8; Send_Buffer[4] = SysData.HUMI_Disp & 0x00ff; Send_Buffer[5] = 0;//添加这部分为湿度 if(SysData.Freq_Resp == FAST_RESP) { Send_Buffer[2] |= 0x40; } Send_Buffer[2] |= 0x00;//默认范围30-130 Send_Buffer[3] = 0; USBD_HID_SendReport (&USB_Device_dev, Send_Buffer, MY_DEF_PACKET); break; case 0xb5://点击导入弹出的选项 Send_Buffer[0] = 0xfe; if(SysInfo.REC_HalfPages) { Send_Buffer[0] = 0xef; Send_Buffer[1] = SysInfo.REC_HalfPages >> 24; Send_Buffer[2] = (SysInfo.REC_HalfPages >> 16) & 0xff; Send_Buffer[3] = (SysInfo.REC_HalfPages >> 8) & 0xff; Send_Buffer[4] = SysInfo.REC_HalfPages & 0xff; } USBD_HID_SendReport (&USB_Device_dev, Send_Buffer, MY_DEF_PACKET); break; case 0xc4: //导入记录就等于0xc4 SysFlag.GetRec = 1; SysData.Start_Rec = (Report_buf[1] << 24) | (Report_buf[2] << 16) | (Report_buf[3] << 8 ) | Report_buf[4]; SysData.End_Rec = (Report_buf[5] << 24) | (Report_buf[6] << 16) | (Report_buf[7] << 8 ) | Report_buf[8]; if((SysData.End_Rec - SysData.Start_Rec) >= 720) { SysData.End_Rec = SysData.Start_Rec + 720 - 1; } Delayms(500); break; case 0x7c: Time_Hex.second = Report_buf[1]; Time_Hex.minute = Report_buf[2]; Time_Hex.hour = Report_buf[3]; Time_Hex.day = Report_buf[4]; Time_Hex.month = Report_buf[5]; Time_Hex.year = Report_buf[6]; Save_TimeDate(); break; case 0x56: break; } } void USBD_HID_SendReport (u8 *NoUse, u8 *Buff, u8 Num) { u32 loopi = 0; PrevXferComplete = 0; USB_SilWrite(EP1_IN, Buff, Num); _SetEPTxStatus(ENDP1, EP_TX_VALID); while(PrevXferComplete != 1 && loopi < 100) //10ms超时等待 { loopi++; Delayus(100); } } 现在要做的是把原来有关噪音的部分替换成温湿度的,还有usb部分

/* * w25qxx.c * * Finished on: 2024/7/17 * Author: Administrator */ #include "../flash/flash.h" #include "main.h" uint32_t FLASH_CURSOR=0;//flash光标 uint16_t W25QXX_TYPE=W25Q128;//默认是W25Q128 //4Kbytes为一个Sector //16个扇区为1个Block //W25Q128 //容量为16M字节,共有128个Block,4096个Sector //SPI2总线读写一个字节 //参数是写入的字节,返回值是读出的字节 uint8_t SPI1_ReadWriteByte(uint8_t TxData) { uint8_t Rxdata=0;//定义一个变量Rxdata HAL_SPI_TransmitReceive(&hspi1,&TxData,&Rxdata,1,1000);//调用固件库函数收发数据 return Rxdata;//返回收到的数据 } //软件控制函数(0为低电平,其他值为高电平) void W25QXX_CS(uint8_t a) { if(a==0)HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET); else HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET); } //初始化SPI FLASH的IO口 uint8_t W25QXX_Check(void) { uint8_t temp;//定义一个变量temp W25QXX_TYPE = W25QXX_ReadID();//读取FLASH ID. if(W25QXX_TYPE == W25Q256)//SPI FLASH为W25Q256时才用设置为4字节地址模式 { temp = W25QXX_ReadSR(3);//读取状态寄存器3,判断地址模式 if((temp&0x01)==0)//如果不是4字节地址模式,则进入4字节地址模式 { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_Enable4ByteAddr);//发送进入4字节地址模式指令 W25QXX_CS(1);//0片选开启,1片选关闭 } } if(W25QXX_TYPE==W25Q256||W25QXX_TYPE==W25Q128||W25QXX_TYPE==W25Q64 ||W25QXX_TYPE==W25Q32||W25QXX_TYPE==W25Q16||W25QXX_TYPE==W25Q80) return 0; else return 1;//如果读出ID是现有型号列表中的一个,则识别芯片成功 } //读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器 //状态寄存器1: //BIT7 6 5 4 3 2 1 0 //SPR RV TB BP2 BP1 BP0 WEL BUSY //SPR:默认0,状态寄存器保护位,配合WP使用 //TB,BP2,BP1,BP0:FLASH区域写保护设置 //WEL:写使能锁定 //BUSY:忙标记位(1,忙;0,空闲) //默认:0x00 //状态寄存器2: //BIT7 6 5 4 3 2 1 0 //SUS CMP LB3 LB2 LB1 (R) QE SRP1 //状态寄存器3: //BIT7 6 5 4 3 2 1 0 //HOLD/RST DRV1 DRV0 (R) (R) WPS (R) (R) //regno:状态寄存器号,范:1~3 //返回值:状态寄存器值 uint8_t W25QXX_ReadSR(uint8_t regno) { uint8_t byte=0,command=0; switch(regno) { case 1: command=W25X_ReadStatusReg1;//读状态寄存器1指令 break; case 2: command=W25X_ReadStatusReg2;//读状态寄存器2指令 break; case 3: command=W25X_ReadStatusReg3;//读状态寄存器3指令 break; default: command=W25X_ReadStatusReg1;//读状态寄存器1指令 break; } W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(command);//发送读取状态寄存器命令 byte=SPI1_ReadWriteByte(0Xff);//读取一个字节 W25QXX_CS(1);//0片选开启,1片选关闭 return byte;//返回变量byte } //写W25QXX状态寄存器 void W25QXX_Write_SR(uint8_t regno,uint8_t sr) { uint8_t command=0; switch(regno) { case 1: command=W25X_WriteStatusReg1;//写状态寄存器1指令 break; case 2: command=W25X_WriteStatusReg2;//写状态寄存器2指令 break; case 3: command=W25X_WriteStatusReg3;//写状态寄存器3指令 break; default: command=W25X_WriteStatusReg1; break; } W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(command);//发送写取状态寄存器命令 SPI1_ReadWriteByte(sr);//写入一个字节 W25QXX_CS(1);//0片选开启,1片选关闭 } //W25QXX写使能 //将WEL置位 void W25QXX_Write_Enable(void) { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_WriteEnable);//发送写使能 W25QXX_CS(1);//0片选开启,1片选关闭 } //W25QXX写禁止 //将WEL清零 void W25QXX_Write_Disable(void) { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_WriteDisable);//发送写禁止指令 W25QXX_CS(1);//0片选开启,1片选关闭 } //读取芯片ID //高8位是厂商代号(本程序不判断厂商代号) //低8位是容量大小 //0XEF13型号为W25Q80 //0XEF14型号为W25Q16 //0XEF15型号为W25Q32 //0XEF16型号为W25Q64 //0XEF17型号为W25Q128(目前洋桃2号开发板使用128容量芯片) //0XEF18型号为W25Q256 uint16_t W25QXX_ReadID(void) { uint16_t Temp = 0; W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(0x90);//发送读取ID命令 SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); SPI1_ReadWriteByte(0x00); Temp|=SPI1_ReadWriteByte(0xFF)<<8; Temp|=SPI1_ReadWriteByte(0xFF); W25QXX_CS(1);//0片选开启,1片选关闭 return Temp; } //读取SPI FLASH //在指定地址开始读取指定长度的数据 //pBuffer:数据存储区 //ReadAddr:开始读取的地址(24bit) //NumByteToRead:要读取的字节数(最大65535) void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead) { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_ReadData);//发送读取命令 if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位 { SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>24)); } SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>16));//发送24bit地址 SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>8)); SPI1_ReadWriteByte((uint8_t)ReadAddr); HAL_SPI_Receive(&hspi1, pBuffer, NumByteToRead, 1000); W25QXX_CS(1);//0片选开启,1片选关闭 } //SPI在一页(0~65535)内写入少于256个字节的数据 //在指定地址开始写入最大256字节的数据 //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!! void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) { W25QXX_Write_Enable();//SET WEL W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_PageProgram);//发送写页命令 if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位 { SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>24)); } SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>16));//发送24bit地址 SPI1_ReadWriteByte((uint8_t)((WriteAddr)>>8)); SPI1_ReadWriteByte((uint8_t)WriteAddr); HAL_SPI_Transmit(&hspi1, pBuffer, NumByteToWrite, 1000); W25QXX_CS(1);//0片选开启,1片选关闭 W25QXX_Wait_Busy();//等待写入结束 } //无检验写SPI FLASH //必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败! //具有自动换页功能 //在指定地址开始写入指定长度的数据,但是要确保地址不越界! //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大65535) //CHECK OK void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) { uint16_t pageremain; pageremain=256-WriteAddr%256; //单页剩余的字节数 if(NumByteToWrite<=pageremain) pageremain=NumByteToWrite;//不大于256个字节 while(1) { W25QXX_Write_Page(pBuffer,WriteAddr,pageremain); if(NumByteToWrite==pageremain) break;//写入结束 else //NumByteToWrite>pageremain { pBuffer+=pageremain; WriteAddr+=pageremain; NumByteToWrite-=pageremain; //减去已经写入了的字节数 if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节 else pageremain=NumByteToWrite; //不够256个字节了 } } } //写SPI FLASH //在指定地址开始写入指定长度的数据 //该函数带擦除操作! //pBuffer:数据存储区 //WriteAddr:开始写入的地址(24bit) //NumByteToWrite:要写入的字节数(最大65535) uint8_t W25QXX_BUFFER[4096]; void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) { FLASH_CURSOR=WriteAddr+NumByteToWrite;//光标指向写完的下一个位置 uint32_t secpos; uint16_t secoff; uint16_t secremain; uint16_t i; uint8_t* W25QXX_BUF; W25QXX_BUF=W25QXX_BUFFER; secpos=WriteAddr/4096;//扇区地址 secoff=WriteAddr%4096;//在扇区内的偏移 secremain=4096-secoff;//扇区剩余空间大小 if(NumByteToWrite<=secremain) secremain=NumByteToWrite;//要写的不超过扇区 while(1) { W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容 for(i=0;i<secremain;i++)//检查数据 { if(W25QXX_BUF[secoff+i]!=0XFF) break;//需要擦除 } if(i<secremain)//需要擦除 { W25QXX_Erase_Sector(secpos);//擦除这个扇区 for(i=0;i<secremain;i++)//复制写入内容 { W25QXX_BUF[i+secoff]=pBuffer[i]; } W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区 }else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. if(NumByteToWrite==secremain) break;//写入结束 else//写入未结束 { secpos++;//扇区地址增1 secoff=0;//偏移位置为0 pBuffer+=secremain; //指针偏移 WriteAddr+=secremain;//写地址偏移 NumByteToWrite-=secremain;//字节数减写过的 if(NumByteToWrite>4096)secremain=4096;//下一个扇区还是写不完 else secremain=NumByteToWrite;//下一个扇区可以写完了 } } } //擦除整个芯片 //等待时间超长... void W25QXX_Erase_Chip(void) { W25QXX_Write_Enable();//SET WEL W25QXX_Wait_Busy();//等待忙状态 W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_ChipErase);//发送片擦除命令 W25QXX_CS(1);//0片选开启,1片选关闭 W25QXX_Wait_Busy();//等待芯片擦除结束 } //擦除一个扇区 //Dst_Addr:扇区地址 根据实际容量设置 //擦除一个扇区的最少时间:150ms void W25QXX_Erase_Sector(uint32_t Dst_Addr) { Dst_Addr*=4096; W25QXX_Write_Enable();//SET WEL W25QXX_Wait_Busy(); W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_SectorErase);//发送扇区擦除指令 if(W25QXX_TYPE==W25Q256)//如果是W25Q256的话地址为4字节的,要发送最高8位 { SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>24)); } SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>16));//发送24bit地址 SPI1_ReadWriteByte((uint8_t)((Dst_Addr)>>8)); SPI1_ReadWriteByte((uint8_t)Dst_Addr); W25QXX_CS(1);//0片选开启,1片选关闭 W25QXX_Wait_Busy();//等待擦除完成 } //等待空闲 void W25QXX_Wait_Busy(void) { while((W25QXX_ReadSR(1)&0x01)==0x01);//等待BUSY位清空 } //进入掉电模式 void W25QXX_PowerDown(void) { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_PowerDown);//发送掉电命令 0xB9 W25QXX_CS(1);//0片选开启,1片选关闭 delay_us(3);//等待TPD } //唤醒 void W25QXX_WAKEUP(void) { W25QXX_CS(0);//0片选开启,1片选关闭 SPI1_ReadWriteByte(W25X_ReleasePowerDown);//发送电源唤醒指令 0xAB W25QXX_CS(1);//0片选开启,1片选关闭 delay_us(3);//等待TRES1 } 根据这个flash代码

最新推荐

recommend-type

前端开发基于jQuery的选择器与DOM操作技术:网页元素精准定位及动态交互功能实现

内容概要:本文系统介绍了jQuery的基础知识,涵盖其概念、优势、开发环境搭建、核心语法与选择器、DOM遍历与操作方法,以及事件处理机制。文章强调jQuery作为轻量级JavaScript库在简化DOM操作、跨浏览器兼容性及提升开发效率方面的突出作用,并通过大量代码示例详细讲解了选择器(如标签、类、ID、属性、自定义及表单选择器)、DOM遍历方法(如filter、next、siblings等)、元素访问方式(.get()和索引访问)以及事件绑定与委托(如on、off、hover、ready等),帮助读者掌握jQuery的核心使用技巧。; 适合人群:具备HTML、CSS和JavaScript基础,初入前端领域的开发者或希望巩固jQuery基础的1-3年经验研发人员。; 使用场景及目标:①快速实现DOM元素选取与操作,提升页面交互开发效率;②理解jQuery事件机制与DOM遍历逻辑,用于传统项目维护或兼容性开发;③为学习现代前端框架前打下扎实的JavaScript操作基础。; 阅读建议:建议结合文中示例动手实践,重点理解选择器的使用场景与事件委托机制,注意区分jQuery对象与原生DOM对象的操作差异,并在实际项目中逐步应用所学内容以加深理解。
recommend-type

Info2007v1.0更新至v2.0:优化管理与前台功能

根据提供的文件信息,可以挖掘出以下知识点: ### 标题知识点: 1. **免费时代WEB程序INFO2007 V1.0:** - 该标题表明存在一个名为INFO2007的WEB程序版本1.0,该版本是在免费时代推出的,可能意味着该程序是开源的或者提供免费下载。 ### 描述知识点: 1. **软件缺陷说明:** - 开发者提到程序存在BUG(程序缺陷),并提供了一个更新和反馈的渠道,说明软件仍在开发中,且有后续版本计划。 2. **联系方式:** - 开发者提供了QQ和邮箱作为联系方式,用于反馈问题或询问更新情况。 3. **Info2007v2.0更新内容:** - 提及了升级后的版本INFO2007v2.0新增功能,包括数据库结构变化(添加会员和公告表)、后台管理功能的增加与优化、前台功能的增加与优化等。 4. **安装要求:** - 软件需要特定的服务器环境支持,比如FSO(文件系统对象)、数据采集功能和JMAIL(邮件发送组件)。 5. **配置与安装细节:** - 对config.asp下的目录配置和pageurlsa变量做了说明,这些通常涉及程序的运行环境和安全设置。 6. **默认登录信息:** - 提供了默认的管理员用户名和密码,以及后台管理的默认目录,这对于安装和测试程序很重要。 7. **使用前的必要步骤:** - 强调了解压后生成静态页面的重要性,这可能是确保网站内容可被正确浏览的前置操作。 ### 标签知识点: 1. **ASP源码其他类别:** - 这表明该程序使用ASP(Active Server Pages)作为后端编程语言,并且归类于其他类别,可能意味着它不局限于某一特定功能或领域。 ### 压缩包文件名称列表知识点: 1. **www.codejia.com:** - 这个文件名可能指示了程序被托管或下载的来源网站,也暗示了可能含有与网站域名相关的程序文件。 ### 综合知识点: 1. **软件开发与维护:** - 从描述中可以看出开发者在推动软件的持续改进,并鼓励用户参与软件的测试和反馈过程。 2. **软件环境配置:** - 软件对运行环境有所要求,特别是服务器端的支持,需要了解FSO、数据采集、JMAIL等组件的使用和配置。 3. **后台管理系统:** - 更新内容中提及的后台管理功能,如会员管理、公告管理、文章管理等,显示了该程序提供了一套用于网站内容和用户管理的后台解决方案。 4. **前台展示优化:** - 对前台页面的优化和增加功能,如会员注册、文章页、下载页和分类栏目的改进,说明了对用户体验的重视。 5. **安全与权限控制:** - 默认用户名和密码的提供,以及后台目录的默认设置,强调了安装过程中应立即更改编译以提高安全性。 6. **静态页面生成:** - 生成静态页面作为必要步骤可能涉及到网站的性能优化和安全措施。 7. **开源与社区支持:** - 由于提及了更新的可能和用户反馈渠道,这表明软件具有一定的开源特性或至少鼓励社区参与。 综上所述,这些知识点涵盖了软件开发的常见方面,包括软件生命周期的维护、功能更新、环境配置、安全实践以及优化用户体验。了解和掌握这些知识点可以帮助开发者和用户更好地利用和改进免费时代WEB程序INFO2007 V1.0。
recommend-type

Rust测试实战:错误处理、环境变量与模拟服务器

### Rust 测试实战:错误处理、环境变量与模拟服务器 在 Rust 开发中,测试是确保代码质量和稳定性的重要环节。本文将深入探讨 Rust 中的测试技巧,包括错误处理、使用环境变量测试 Config 模块以及使用模拟服务器测试 profanity 模块。 #### 1. 错误处理与比较 在 Rust 中,我们可以为自定义错误类型实现 `std::fmt::Display` 特征,以便将错误转换为字符串。以下是一个示例: ```rust impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::For
recommend-type

请分析下面代码:<tbody> <#if (paginationSupport.items)?has_content> <#list paginationSupport.items?sort_by('caseNo') as s> <tr class="b"> <td><a href="../user/viewRequestForm.action?requestFormId=${s.id}">${s.caseNo?default("Not Assigned")?if_exists}</a></td> <td>${s.lotId?if_exists}</td> <td><@m.directoryLink s.applicant?if_exists /></td> <td>${s.prodId?if_exists}</td> <td>${s.lotStageId?if_exists}</td> <td>${s.status?if_exists}</td> <td> <#if s.status!="Waiting For STR"> <#if s.workflowId?exists> <#list s.queuedOwners as owner> <#if owner?matches("[MmAaEeTt]\\d{3}.*")> <@m.directoryLink owner/> <#elseif owner?matches("[K-Z][A-Z][A-Z].*[_].*")> <#list adminService.loadGroupMembersByName(owner) as member> <@m.directoryLink member/><!--by Group--> </#list> <#else> <@m.orgManager owner?if_exists/><!--by Org--> </#if> </#list> </#if> <#else> <#if s.ercCategory=="Input the STR Number"||s.ercCategory=="STR"||s.ercCategory=="MSTR"> STR NO:<a href="${ercService.strLink?if_exists}${s.strEnNo?if_exists}" target="_blank">${s.strEnNo?if_exists}</a> is not effective <#else> EN NO:<a href="${ercService.enLink?if_exists}${s.strEnNo?if_exists}" target="_blank">${s.strEnNo?if_exists}</a> is not effective </#if> </#if> </td> <td><#if s.submitDate?exists>${s.submitDate?datetime?if_exists}</#if></td> <td>${s.purpose?default('')}</td> </tr> </#list> </#if> </tbody>

这段代码是使用 FreeMarker 模板引擎生成 HTML 表格内容的一部分,主要功能是根据分页数据展示请求表单的信息。以下是代码的详细分析: --- ### 1. **条件判断与循环** ```html <#if (paginationSupport.items)?has_content> ``` 判断 `paginationSupport.items` 是否存在且非空,只有存在数据时才执行表格渲染。 ```html <#list paginationSupport.items?sort_by('caseNo') as s> ``` 对 `paginationSupport.item
recommend-type

op-drone:监控未平仓头寸的市场利器

标题中提到的“op-drone”很可能是指一个特定的监控系统或服务的名称,它被用来“持续监控市场中的未平仓头寸”。未平仓头寸是指在金融市场上尚未完成交易结算的买卖双方的持仓数量。监控未平仓头寸对于市场参与者来说至关重要,因为它可以提供有关市场流动性和投资者情绪的重要信息。 在深入探讨之前,需要了解几个基础概念: 1. 未平仓头寸:指交易者在期货、期权、外汇或其他衍生品市场上建立的但尚未平仓的头寸。这些头寸在到期前仍然具有价值,而且市场上的价格变动会对它们的总体价值产生影响。 2. 持续监控:这通常是指使用软件工具或服务不断跟踪和分析市场数据的过程。持续监控可帮助交易者或市场分析师及时捕捉市场的动态变化,并根据最新情况做出交易决策。 3. 市场监控系统:这类系统通常具备收集实时数据、分析市场趋势、识别异常交易行为等多种功能。它们对于投资者了解市场状况、进行风险管理以及制定交易策略至关重要。 从描述中可以推断出,op-drone是一个专门用于持续监控未平仓头寸的系统或服务。这种系统需要具备以下功能: 1. 数据收集:系统需要有能力实时收集金融市场中的数据,包括但不限于期货、期权、股票、债券等金融产品的交易信息。 2. 数据分析:通过算法或机器学习技术分析收集到的数据,识别市场趋势、投资者行为模式以及潜在风险。 3. 异常检测:能够识别出市场中的异常交易活动,比如未平仓头寸的急剧变化,这可能是市场重大变动的前兆。 4. 风险预警:系统应能向用户发出风险预警,告知用户潜在的市场风险,帮助他们进行风险管理。 5. 报告与可视化:提供详细的数据报告和可视化图表,帮助用户更直观地理解市场状况和未平仓头寸变化。 此外,虽然文件中未提供标签和具体的文件名称列表,但可以推测“op-drone-main”可能是系统中的一个核心组件或主程序的名称。这个组件可能是整个op-drone系统运行的基础,负责处理大部分的监控和分析功能。 综合以上信息,我们可以得出一个结论:op-drone是一个专门设计用于监控金融市场上未平仓头寸的系统或服务。它可能具备实时数据收集和分析、异常行为识别、风险预警以及报告和可视化展示等多种功能,从而帮助用户在复杂的市场环境中做出更加明智的决策。对于需要精确把握市场动态、进行风险管理的金融分析师、交易员、投资组合经理等专业人士来说,这样的系统是不可或缺的工具。
recommend-type

RustWeb服务部署与环境变量配置全解析

### Rust Web 服务部署与环境变量配置全解析 在 Rust 开发中,完成业务逻辑编写后,将应用部署到生产环境是关键的下一步。本文将深入探讨 Rust 应用部署过程中的重要环节,包括环境变量的配置、二进制文件的优化以及跨平台编译等内容。 #### 1. 认证与授权相关未覆盖内容 在认证和授权方面,有一些内容未详细涉及。例如,设置会话数据库来存储令牌,以便在数据泄露或用户有其他需求时使令牌失效。可以通过设置 Redis 实例,在生成每个令牌时,不仅将结果返回给客户端,还将其存储在 Redis 键值存储中。 另外,重置用户密码和创建刷新令牌也是重要的话题。重置用户密码可以通过创建一个
recommend-type

消灭病毒 源代码

要查找消灭病毒游戏的源代码,可通过以下几种常见途径获取: ### 开源代码平台 - **GitHub**:作为全球最大的开源代码托管平台,有开发者会将自己开发的消灭病毒游戏源代码分享到上面。在GitHub的搜索框输入“消灭病毒游戏”相关关键词,如“Virus Elimination Game” 、“消灭病毒 Unity”等,就能筛选出相关的代码仓库。有些仓库可能是完整的项目,包含游戏开发所需的全部代码和资源;有些则可能是部分功能的实现,需要进一步整合。 - **Gitee**:国内的开源代码托管平台,很多国内开发者会将自己的项目上传至此。同样使用相关关键词搜索,或许能找到符合需求的消灭病毒游
recommend-type

Apache Directory:Java编写的LDAP v3兼容目录解决方案

标题中所提及的“directory”一词在IT领域有多种含义,而描述中提供了具体的上下文信息,即Apache Directory项目。这个项目是Apache软件基金会下的一个子项目,它提供了使用Java语言开发的开源目录服务解决方案。下面详细说明Apache Directory项目中涉及的知识点。 **Apache Directory项目知识点** 1. **目录服务(Directory Service)** - 目录服务是一种特殊类型的数据库,它主要用于存储关于网络中的对象信息,如用户、组、设备等,并使得这些信息可以被集中管理和查询。与传统的关系数据库不同,目录服务通常是为了读操作比写操作更频繁的应用场景优化的,这使得它特别适合用于存储诸如用户身份验证信息、配置数据、策略信息等。 2. **LDAP(轻量级目录访问协议)** - LDAP是目录服务使用的一种协议标准,它定义了客户端与目录服务进行交互的规则和方法。LDAP v3是LDAP协议的第三个版本,它在功能上比前两个版本更为强大和灵活。LDAP服务器通常被称为目录服务器(Directory Server),用于存储目录信息并提供查询服务。 3. **ApacheDS(Apache Directory Server)** - Apache Directory Server是Apache Directory项目的主要组件之一,是一个完全用Java编写的LDAP v3兼容的目录服务器。它符合LDAP标准的所有基本要求,还提供了丰富的可扩展性,如扩展协议操作、自定义属性类型、自定义操作等。它的设计目标是成为一个轻量级、易于使用且功能强大的目录服务器,特别适用于企业环境中的用户身份管理。 4. **认证和授权** - 在一个目录服务环境中,认证是指验证用户身份的过程,而授权是指授予已认证用户访问资源的权限。Apache Directory Server在设计上提供了对这些安全特性的支持,包括但不限于:密码策略、访问控制列表(ACLs)等。 5. **Eclipse和Apache Directory Studio** - Apache Directory Studio是一个基于Eclipse的开源集成开发环境(IDE),它专门为目录服务的开发和管理提供工具。它包含一个LDAP浏览器、一个LDIF编辑器、一个Schema编辑器等工具。开发者和管理员可以利用Apache Directory Studio来浏览和管理LDAP服务器,以及创建和修改LDAP条目和Schema。 6. **LDIF(LDAP数据交换格式)** - LDIF是LDAP数据交换的文件格式,用于在文本文件中表示LDAP目录的信息。它通常用于备份和恢复LDAP数据,以及将数据导入到LDAP目录中。Apache Directory API允许用户操作LDIF文件,为这些操作提供了丰富的接口。 **网络服务器与网络客户端** 网络服务器是位于服务器端的软件,负责处理来自客户端的请求,并将信息回传给客户端。网络客户端则是发起请求的软件,它连接到服务器并获取服务或数据。Apache Directory Server作为网络服务器的一个例子,为客户端提供目录服务的访问能力。这可能包括身份验证服务、数据检索服务等。网络客户端则需要使用适当的协议和API与目录服务器通信,例如使用LDAP协议。 **压缩包子文件的文件名称列表** 提供的文件名称“apache-ldap-api-1.0.3-bin”表明这是一个可执行的二进制包,其中包含了Apache Directory API的版本1.0.3。API通常包含了一系列用于与目录服务进行交互的类和方法。开发者可以使用这些API来编写代码,实现对LDAP服务器的管理操作,如查询、更新、删除和添加目录信息。 总结上述内容,Apache Directory项目是针对提供目录服务解决方案的开源项目,包括了Apache Directory Server作为服务器组件,和Apache Directory Studio作为客户端工具。项目遵守LDAP v3协议标准,并提供易于使用的API接口,使得开发者能够构建和管理一个高效、安全的目录服务环境。在使用过程中,了解LDAP协议、目录服务的安全机制以及相关的API使用是基础知识点。同时,由于Apache Directory项目采用Java语言编写,了解Java编程语言和其生态系统也对开发和部署相关服务有极大的帮助。
recommend-type

Rust项目中用户认证与登录功能的实现与优化

### Rust 项目中用户认证与登录功能的实现与优化 在开发 Web 应用时,用户认证是一个至关重要的环节。它涉及到用户密码的安全存储、账户注册时的重复错误处理以及登录逻辑的实现等多个方面。下面将详细介绍如何在 Rust 项目中实现这些功能。 #### 1. 密码哈希与加盐 为了确保用户密码的安全,我们不能直接存储明文密码。常见的做法是使用哈希算法对密码进行处理。不过,单纯的哈希还不够,因为攻击者可能通过比对已知破解的哈希列表来获取明文密码。因此,我们还需要对密码进行加盐处理,即在哈希之前添加一个随机生成的序列。 我们引入了两个新的 crate 来实现这个功能: - `rand`:用于
recommend-type

如何使用使用QZipReader解压文件

`QZipReader` 是一个方便的工具,用于在 Qt 应用程序中解压 ZIP 压缩包,它提供了读取 ZIP 文件的接口,并能提取其中的内容。以下是使用 `QZipReader` 解压文件的示例代码: ```cpp #include <QZipReader> #include <QFile> #include <QDir> void zip_decompress(const QString &fileName, const QString &path) { if (fileName.isEmpty()) { return; } QFileInfo f