调试NO_MORE_USER_HANDLES问题

文章描述了一台站机管理多台分机时,界面出现卡顿的问题。当分机数量达到400时,界面卡死,而200台时正常。通过分析发现,SetTimer失败,错误码为1158,即进程已用尽窗口管理对象句柄。进一步排查发现,注油器构造函数中初始化了大量的非模态弹出消息框,导致用户对象过多。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

一台站机管理m台分机,测试多分机时,发现如下现象:当分机数位400时,界面卡死;当分机数为200时,一切正常。
由于界面刷新是通过定时器来不停刷新界面的,于是在定时器处理函数中添加断点。但该断点一直没执行。
在msdn上查Cwnd::SetTimer说明,该函数正常返回非零数值,失败则返回零。检查SetTimer返回值,在失败情况下,通过GetLastError()获取最近的错误代码。结果发现SetTimer失败,错误码为1158.
在MSDN是这样藐视1158的:
ERROR_NO_MORE_USER_HANDLES 1158 (0x486)
The current process has used all of its system allowance of handles for Window Manager objects.

分析过程

不清楚“handles for window manager objects”什么意思,字面意思是窗口管理对象句柄。于是通过“任务管理器”来查看该软件对应的句柄数和线程数,结果发现句柄数和线程数分别为555和14,和其他进程对比,并不是特别多。
在网上搜索相关资料,有篇文章说,打开“任务管理器”的"用户对象"列,观察其数值,如果接近10000,就必须优化(操作系统为每个进程最多分配10000个用户对象)。结果发现9484。这个数目确实多。
接下来,顺着程序启动流程来定位问题所在。基本方法是:断点和观测用户对象数。
最后确定了出错地点:在注油器构造函数中,初始化了5倍分机数的非模态弹出消息框。由于分机数为375,所以有1875个弹出框(如果每个弹出框有5个用户对象,则有9375个用户对象)。

/********************************************************************************************************* * * 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
最新发布
07-16
一、系统分层功能 感知层:用实验箱的两个传感器模块 传感器 1:温湿度传感器,采集温度、湿度数据。 传感器 2:红外对射 ,采集触发状态。 网络层: Zigbee 通信:传感器 1、2 的数据,经 Zigbee 节点传给协调器,协调器通过串口发 PC 端。 数据处理:解析串口数据,分主题发 MQTT 网络,或存数据库 。 应用层:用 Python 做终端,实现界面、串口、数据库交互(可加 MQTT),完成这些功能: 二、具体功能 数据上传: 远程设备实时收传感器 1 数据,格式:学号姓名缩写+温度+湿度 。 远程设备实时收传感器 2 数据,格式:学号姓名缩写+传感器名+interrupt 。 Mysql 数据库:建不同数据表存两个传感器数据,表含 学号姓名缩写、传感器名、数据值、传感器状态 等字段 。 命令下发: 发 学号姓名缩写+Num1Led+on ,传感器 1 连的 Zigbee 模块 LED2 亮;发 ...+off 则灭 。 发 学号姓名缩写+Num2Led+on ,传感器 2 连的 Zigbee 模块 LED2 亮;发 ...+off 则灭 。 数据联动: 传感器 1:温度>25 且湿度>60,其连的 Zigbee 模块 LED2 闪烁,远程设备、数据库表显示 “温湿度异常”;恢复后显示 “异常解除” 。 传感器 2:触发超 5 次,其连的 Zigbee 模块 LED2 闪烁,远程设备、数据库表显示 “传感状态异常”;恢复后显示 “传感异常解除” 。 强制解除:发 学号姓名缩写+Num1Led+relie ,传感器 1 连的 LED2 停闪,设备和表显示 “强制异常解除温湿度” ;发 ...+Num2Led+relie 同理。 数据展示:Python 界面里,串口控制,实时显示传感器 1 的 学号姓名缩写、温度、湿度 数据,呈现底层传感器联动状态 。 #include <stdio.h> #include <string.h> #include "OSAL.h" #include "ZGlobals.h" #include "AF.h" #include "aps_groups.h" #include "ZDApp.h" #include "MT_UART.h" //???? #include "SampleApp.h" #include "SampleAppHw.h" #include "OnBoard.h" /* HAL */ #include "hal_lcd.h" #include "hal_led.h" #include "hal_key.h" #include "hal_uart.h" #include "hal_mcu.h" #include "sht11.h" // P1 interrupt vector value is already defined in ioCC2530.h // #define P1INT_VECTOR 0x7B // Commented out to avoid redefinition warning // Sensor type configuration: // Combined sensor: supports both temp/humidity and IR sensor functions // sht11 command activates temp/humidity sensor, interrupt command activates IR sensor //#define COMBINED_SENSOR // Single sensor configuration (optional): //#define TEMP_HUMIDITY_SENSOR // Temperature/humidity sensor only // Default: IR sensor only (no macro defined) /********************************************************************* * CONSTANTS */ /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ // This list should be filled with Application specific Cluster IDs. const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] = { SAMPLEAPP_PERIODIC_CLUSTERID, SAMPLEAPP_FLASH_CLUSTERID, SAMPLEAPP_BUZZER_CLUSTERID, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, }; // Add function declarations at the top of the file, after other declarations void SetBuzzerStatus(uint8 status); void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg); void InitIRSensorInterrupt(void); void ProcessIRSensorInterrupt(void); void ProcessLED2Flash(void); // LED2闪烁处理函数 void PrintDeviceInfo(void); // 打印设备信息 void PrintHexBytes(const char* title, const char* data, uint8 len); // 十六进制打印辅助函数 const SimpleDescriptionFormat_t SampleApp_SimpleDesc = { SAMPLEAPP_ENDPOINT, // int Endpoint; SAMPLEAPP_PROFID, // uint16 AppProfId[2]; SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; SAMPLEAPP_FLAGS, // int AppFlags:4; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumOutClusters; (cId_t *)SampleApp_ClusterList // uint8 *pAppOutClusterList; }; // This is the Endpoint/Interface description. It is defined here, but // filled-in in SampleApp_Init(). Another way to go would be to fill // in the structure here and make it a "const" (in code space). The // way it's defined in this sample app it is define in RAM. endPointDesc_t SampleApp_epDesc; // Add global variable to control temperature and humidity reading static uint8 g_bReadTempHumi = 0; // Add IR sensor status variable static uint8 g_IRSensorStatus = 0; // Add sensor type variable - configure this based on device type // For combined sensor nodes, set to SENSOR_TYPE_COMBINED // For temperature/humidity sensor nodes, set to SENSOR_TYPE_TEMP_HUMIDITY // For IR sensor nodes, set to SENSOR_TYPE_IR #ifdef COMBINED_SENSOR static uint8 g_SensorType = SENSOR_TYPE_COMBINED; #elif defined(TEMP_HUMIDITY_SENSOR) static uint8 g_SensorType = SENSOR_TYPE_TEMP_HUMIDITY; #else static uint8 g_SensorType = SENSOR_TYPE_IR; #endif // 添加全局变量,用于防止中断处理函数重入 static uint8 g_IRProcessingInProgress = 0; // 添加控制LED2闪烁的全局变量 static uint8 g_LED2FlashStatus = 0; // 0: 停止闪烁, 1: 闪烁中 // 定义命令字符串常量,避免硬编码字符串和在函数调用中重复创建 const char* CMD_NUM1LED_ON = "42213238YFC+Num1Led+on"; const char* CMD_NUM1LED_OFF = "42213238YFC+Num1Led+off"; const char* CMD_NUM2LED_ON = "42213238YFC+Num2Led+on"; const char* CMD_NUM2LED_OFF = "42213238YFC+Num2Led+off"; const char* CMD_ON = "on"; const char* CMD_OFF = "off"; const char* CMD_HT = "ht"; const char* CMD_HF = "hf"; const char* CMD_FLASH = "flash"; // 闪烁命令 const char* CMD_RELIE = "42213238YFC+Num1Led+relie"; // 停止闪烁命令 const char* CMD_SHUO = "shuo"; // 红外对射传感器闪烁命令 const char* CMD_IR_RELIE = "42213238YFC+Num2Led+relie"; // 红外对射传感器停止闪烁命令 /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ uint8 SampleApp_TaskID; // Task ID for internal task/event processing // This variable will be received when // SampleApp_Init() is called. devStates_t SampleApp_NwkState; uint8 SampleApp_TransID; // This is the unique message ID (counter) afAddrType_t SampleApp_Periodic_DstAddr; afAddrType_t SampleApp_Flash_DstAddr; aps_Group_t SampleApp_Group; uint8 SampleAppPeriodicCounter = 0; uint8 SampleAppFlashCounter = 0; /********************************************************************* * LOCAL FUNCTIONS */ void SampleApp_HandleKeys( uint8 shift, uint8 keys ); void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pckt ); void SampleApp_SendPeriodicMessage( void ); void SampleApp_SendFlashMessage( uint16 flashTime ); /********************************************************************* * NETWORK LAYER CALLBACKS */ /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn SampleApp_Init * * @brief Initialization function for the Generic App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notificaiton ... ). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void SampleApp_Init( uint8 task_id ) { SampleApp_TaskID = task_id; SampleApp_NwkState = DEV_INIT; SampleApp_TransID = 0; // Device hardware initialization can be added here or in main() (Zmain.c). // If the hardware is application specific - add it here. // If the hardware is other parts of the device add it in main(). // Initialize IR sensor interrupt InitIRSensorInterrupt(); #if defined ( BUILD_ALL_DEVICES ) // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered // together - if they are - we will start up a coordinator. Otherwise, // the device will start as a router. if ( readCoordinatorJumper() ) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; else zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; #endif // BUILD_ALL_DEVICES #if defined ( HOLD_AUTO_START ) // HOLD_AUTO_START is a compile option that will surpress ZDApp // from starting the device and wait for the application to // start the device. ZDOInitDevice(0); #endif // Setup for the periodic message's destination address // Broadcast to everyone SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; // Setup for the flash command's destination address - Group 1 SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; // Fill out the endpoint description. SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_epDesc.task_id = &SampleApp_TaskID; SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister( &SampleApp_epDesc ); // Register for all key events - This app will handle all key events RegisterForKeys( SampleApp_TaskID ); MT_UartRegisterTaskID( SampleApp_TaskID ); //add by 1305106 // By default, all devices start out in Group 1 SampleApp_Group.ID = 0x0001; osal_memcpy( SampleApp_Group.name, "Group 1", 7 ); aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); #if defined ( LCD_SUPPORTED ) HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 ); #endif // 打印设备类型和传感器类型信息 PrintDeviceInfo(); } /********************************************************************* * @fn SampleApp_ProcessEvent * * @brief Generic Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a key is pressed case KEY_CHANGE: SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break;; case SPI_INCOMING_ZAPP_DATA: SampleApp_ProcessMTMessage(MSGpkt); MT_UartAppFlowControl (MT_UART_ZAPP_RX_READY); break; // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); Sht11Init(); if ( (SampleApp_NwkState == DEV_ZB_COORD) || (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState == DEV_END_DEVICE) ) { // Start sending the periodic message in a regular interval. HalLedSet(HAL_LED_1, HAL_LED_MODE_ON); osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); } else { // Device is no longer in the network } break; default: break; } osal_msg_deallocate( (uint8 *)MSGpkt ); MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } return (events ^ SYS_EVENT_MSG); // return unprocessed events } // Send a message out - This event is generated by a timer // (setup in SampleApp_Init()). if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { SampleApp_SendPeriodicMessage(); // Send the periodic message // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); // return unprocessed events } // Process IR sensor interrupt event if ( events & SAMPLEAPP_SEND_SENSOR_INT_EVT ) { ProcessIRSensorInterrupt(); return (events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT); } // 处理LED2闪烁事件 if ( events & SAMPLEAPP_LED2_FLASH_EVT ) { // 添加调试输出 char buf[100]; sprintf(buf, "处理LED2闪烁事件, g_LED2FlashStatus=%d, g_SensorType=%d\r\n", g_LED2FlashStatus, g_SensorType); HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 检查是否是温湿度传感器或红外对射传感器,且闪烁标志为1 if (g_LED2FlashStatus == 1 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_IR)) { // 执行闪烁处理函数 ProcessLED2Flash(); // 不需要在这里设置下一次闪烁计时器,已在ProcessLED2Flash函数中处理 } else { // g_LED2FlashStatus不为1时,确保LED2关闭 if (g_LED2FlashStatus == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"闪烁标志为0,停止闪烁并关闭LED2\r\n", 32); } } return (events ^ SAMPLEAPP_LED2_FLASH_EVT); } return 0; // Discard unknown events } /********************************************************************* * Event Generation Functions */ /********************************************************************* * @fn SampleApp_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ void SampleApp_HandleKeys( uint8 shift, uint8 keys ) { (void)shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_SW_6 ) { /* This key sends the Flash Command is sent to Group 1. * This device will not receive the Flash Command from this * device (even if it belongs to group 1). */ SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION ); } if ( keys & HAL_KEY_SW_2 ) { /* The Flashr Command is sent to Group 1. * This key toggles this device in and out of group 1. * If this device doesn't belong to group 1, this application * will not receive the Flash command sent to group 1. */ aps_Group_t *grp; grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP ); if ( grp ) { // Remove from the group aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP ); } else { // Add to the flash group aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); } } } /********************************************************************* * LOCAL FUNCTIONS */ /********************************************************************* * @fn SampleApp_MessageMSGCB * * @brief Data message processor callback. This function processes * any incoming data - probably from other devices. So, based * on cluster ID, perform the intended action. * * @param none * * @return none */ void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; uint8 *buf; switch(pkt->clusterId) { case SAMPLEAPP_PERIODIC_CLUSTERID: buf = pkt->cmd.Data; if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { // Coordinator received data from end device if(pkt->cmd.DataLength == 4 && buf[0] <= 100) { // Format and print temperature data char tempStr[50]; sprintf(tempStr, "42213238YFC+温湿度传感器+温度:%d.%d C+湿度:%d.%d%%\r\n", buf[0], buf[1], buf[2], buf[3]); HalUARTWrite(0, (uint8*)tempStr, strlen(tempStr)); } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x02) { // Process IR sensor data char irStr[50]; if(buf[1] == 0x01) { sprintf(irStr, "IR Sensor Node: Obstacle Detected!\r\n"); } else { sprintf(irStr, "IR Sensor Node: No Obstacle\r\n"); } HalUARTWrite(0, (uint8*)irStr, strlen(irStr)); } else if(pkt->cmd.DataLength == 3 && buf[0] == 0x03) { // Process interrupt message from end device if(buf[1] == 0x01) { // Coordinator prints the message and also blinks LED2 HalUARTWrite(0, (uint8*)"42213238YFC+红外对射传感器+interrupt\r\n", 36); // Flash LED2 10 times on coordinator as well HalLedBlink(HAL_LED_2, 10, 50, 200); } } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x04) { // Process sensor identification response uint8 sensorType = buf[1]; char coordMsg[80]; uint16 srcAddr = pkt->srcAddr.addr.shortAddr; if(sensorType == SENSOR_TYPE_TEMP_HUMIDITY) { sprintf(coordMsg, "Device 0x%04X: Temperature/Humidity sensor identified and LED2 activated\r\n", srcAddr); HalUARTWrite(0, (uint8*)coordMsg, strlen(coordMsg)); } else if(sensorType == SENSOR_TYPE_IR) { sprintf(coordMsg, "Device 0x%04X: IR sensor identified and LED2 activated\r\n", srcAddr); HalUARTWrite(0, (uint8*)coordMsg, strlen(coordMsg)); } } } else { // End device received command from coordinator if(pkt->cmd.DataLength == 1) { if(buf[0] == 0x01) { // Start temperature reading g_bReadTempHumi = 1; osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 1000); } else { // Stop temperature reading g_bReadTempHumi = 0; osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT); } } else if(pkt->cmd.DataLength == 2 && buf[0] == 0x10) { // 处理协调器转发的闪烁命令,仅终端设备响应 if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR && g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { if(buf[1] == 0x01) { // 启动LED2闪烁 g_LED2FlashStatus = 1; osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到闪烁命令,启动LED2闪烁\r\n", 30); } else { // 停止LED2闪烁 g_LED2FlashStatus = 0; HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到停止命令,停止LED2闪烁\r\n", 30); } } } // 处理协调器转发的红外对射传感器闪烁命令 else if(pkt->cmd.DataLength == 2 && buf[0] == 0x11) { // 处理协调器转发的红外对射传感器闪烁命令,仅终端设备响应 if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR && g_SensorType == SENSOR_TYPE_IR) { if(buf[1] == 0x01) { // 启动红外对射传感器LED2闪烁 g_LED2FlashStatus = 1; osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到红外对射传感器闪烁命令,启动LED2闪烁\r\n", 42); } else { // 停止红外对射传感器LED2闪烁 g_LED2FlashStatus = 0; HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"接收到红外对射传感器停止命令,停止LED2闪烁\r\n", 42); } } } } break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2]); HalLedBlink(HAL_LED_4, 4, 50, (flashTime / 4)); break; case SAMPLEAPP_BUZZER_CLUSTERID: SetBuzzerStatus(pkt->cmd.Data[0]); break; case SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID: // Handle sensor identification requests if(zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // This is an end device, check if we should respond uint8 cmd = pkt->cmd.Data[0]; if(cmd == SENSOR_IDENTIFY_CMD_SHT11 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_COMBINED)) { // This is a temperature/humidity sensor or combined sensor responding to sht11 command // Turn on LED2 and send identification response HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); // Send identification response to coordinator uint8 response[2]; response[0] = 0x04; // Sensor identification response // For combined sensor responding to sht11, report as temp/humidity sensor response[1] = SENSOR_TYPE_TEMP_HUMIDITY; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, response, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(cmd == SENSOR_IDENTIFY_CMD_INTERRUPT && (g_SensorType == SENSOR_TYPE_IR || g_SensorType == SENSOR_TYPE_COMBINED)) { // This is an IR sensor or combined sensor responding to interrupt command // Turn on LED2 and send identification response HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); // Send identification response to coordinator uint8 response[2]; response[0] = 0x04; // Sensor identification response // For combined sensor responding to interrupt, report as IR sensor response[1] = SENSOR_TYPE_IR; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, response, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(cmd == 0x05 && (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY || g_SensorType == SENSOR_TYPE_COMBINED)) { // Turn off LED2 for temperature/humidity sensors HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } else if(cmd == 0x06 && (g_SensorType == SENSOR_TYPE_IR || g_SensorType == SENSOR_TYPE_COMBINED)) { // Turn off LED2 for IR sensors HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } } break; } } /********************************************************************* * @fn SampleApp_SendPeriodicMessage * * @brief Send the periodic message. * * @param none * * @return none */ void SampleApp_SendPeriodicMessage(void) { if(g_bReadTempHumi) { uint8 temp_int, temp_dec, humi_int, humi_dec; char buf[50]; float humi, temp; // Initialize SHT11 sensor Sht11Init(); if(GetHumiAndTemp(&humi, &temp) == 0) { // Convert float to integer parts temp_int = (uint8)temp; temp_dec = (uint8)((temp - temp_int) * 10); humi_int = (uint8)humi; humi_dec = (uint8)((humi - humi_int) * 10); // Format the message sprintf(buf, "42213238YFC+温湿度传感器+温度:%d.%d C+湿度:%d.%d%%\r\n", temp_int, temp_dec, humi_int, humi_dec); // Send to UART HalUARTWrite(0, (uint8*)buf, strlen(buf)); // Prepare network data packet buf[0] = temp_int; buf[1] = temp_dec; buf[2] = humi_int; buf[3] = humi_dec; // Send data to network and check result afStatus_t status = AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 4, // Only send 4 bytes of data (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); // 只记录错误但不中断流程,保持原有功能不变 if (status != afStatus_SUCCESS) { // 可以在这里添加错误处理代码,如重试或记录日志 // 但不要中断原有功能流程 } } // Restart timer for next reading osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 2000); // Read every 2 seconds } } /********************************************************************* * @fn SampleApp_SendFlashMessage * * @brief Send the flash message to group 1. * * @param flashTime - in milliseconds * * @return none */ void SampleApp_SendFlashMessage( uint16 flashTime ){ uint8 buffer[3]; buffer[0] = (uint8)(SampleAppFlashCounter++); buffer[1] = LO_UINT16( flashTime ); buffer[2] = HI_UINT16( flashTime ); if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc, SAMPLEAPP_FLASH_CLUSTERID, 3, buffer, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } } void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg) { // 增加安全检查,确保msg指针有效 if(msg == NULL) { return; } const char *msgPtr = ((const char *)msg+2); uint8 status; // 调试输出,打印收到的命令 HalUARTWrite(0, (uint8*)"收到命令: ", 10); HalUARTWrite(0, (uint8*)msgPtr, strlen(msgPtr)); HalUARTWrite(0, (uint8*)"\r\n", 2); // 打印命令的十六进制值,帮助调试 PrintHexBytes("命令十六进制", msgPtr, strlen(msgPtr)); // 打印预期命令常量进行比较 char buf[100]; sprintf(buf, "预期relie命令: %s, 长度: %d\r\n", CMD_RELIE, strlen(CMD_RELIE)); HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印预期命令的十六进制值 PrintHexBytes("预期十六进制", CMD_RELIE, strlen(CMD_RELIE)); // 使用更安全的字符串比较方式 if(strncmp(msgPtr, CMD_NUM1LED_OFF, strlen(CMD_NUM1LED_OFF)) == 0) { // Send command to turn off LED2 for temperature/humidity sensors uint8 cmd[2]; cmd[0] = 0x05; // LED control command cmd[1] = 0x00; // Turn off LED2 for temp/humidity sensors AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM2LED_OFF, strlen(CMD_NUM2LED_OFF)) == 0) { // Send command to turn off LED2 for IR sensors uint8 cmd[2]; cmd[0] = 0x06; // LED control command cmd[1] = 0x00; // Turn off LED2 for IR sensors AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_ON, strlen(CMD_ON)) == 0) { status = 0x01; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_BUZZER_CLUSTERID, 1, &status, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_OFF, strlen(CMD_OFF)) == 0) { status = 0x00; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_BUZZER_CLUSTERID, 1, &status, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_HT, strlen(CMD_HT)) == 0) { // Forward the command to end device uint8 cmd = 0x01; // Command for starting temperature reading AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_HF, strlen(CMD_HF)) == 0) { // Forward the command to end device uint8 cmd = 0x00; // Command for stopping temperature reading AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM1LED_ON, strlen(CMD_NUM1LED_ON)) == 0) { // Send sensor identification request for temperature/humidity sensors uint8 cmd = SENSOR_IDENTIFY_CMD_SHT11; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_NUM2LED_ON, strlen(CMD_NUM2LED_ON)) == 0) { // Send sensor identification request for IR sensors uint8 cmd = SENSOR_IDENTIFY_CMD_INTERRUPT; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_SENSOR_IDENTIFY_CLUSTERID, 1, &cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } else if(strncmp(msgPtr, CMD_FLASH, strlen(CMD_FLASH)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"收到flash命令\r\n", 14); // 只有温湿度传感器模块响应flash命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是温湿度传感器模块\r\n", 25); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行闪烁,协调器不闪烁 // 启动LED2闪烁 g_LED2FlashStatus = 1; // 触发闪烁事件,立即开始 osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"终端设备开始LED2闪烁\r\n", 24); } else { // 协调器接收到flash命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x01; // 开始闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发flash命令到网络\r\n", 27); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是温湿度传感器模块,忽略命令\r\n", 32); } } else if(strncmp(msgPtr, CMD_RELIE, strlen(CMD_RELIE)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"匹配到relie命令\r\n", 17); // 只有温湿度传感器模块响应relie命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是温湿度传感器模块\r\n", 25); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"终端设备停止LED2闪烁\r\n", 24); } else { // 协调器接收到relie命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发停止闪烁命令到网络\r\n", 31); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是温湿度传感器模块,忽略命令\r\n", 32); } } // 添加对红外对射传感器停止闪烁命令的处理 else if(strncmp(msgPtr, CMD_IR_RELIE, strlen(CMD_IR_RELIE)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"匹配到红外对射停止闪烁命令\r\n", 29); // 只有红外对射传感器模块响应停止闪烁命令 if (g_SensorType == SENSOR_TYPE_IR) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是红外对射传感器模块\r\n", 27); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备停止LED2闪烁\r\n", 31); } else { // 协调器接收到停止闪烁命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发红外对射停止闪烁命令到网络\r\n", 38); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是红外对射传感器模块,忽略命令\r\n", 34); } } // 尝试直接匹配红外对射传感器停止闪烁命令 else if(strcmp(msgPtr, "42213238YFC+Num2Led+relie") == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"直接匹配到红外对射停止闪烁命令\r\n", 33); // 只有红外对射传感器模块响应停止闪烁命令 if (g_SensorType == SENSOR_TYPE_IR) { if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备直接停止LED2闪烁\r\n", 35); } else { // 协调器接收到停止闪烁命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器直接转发红外对射停止闪烁命令到网络\r\n", 42); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } } // 尝试另一种方式匹配温湿度传感器的relie命令(恢复原有逻辑) else if(strcmp(msgPtr, "42213238YFC+Num1Led+relie") == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"直接匹配到温湿度传感器relie命令\r\n", 33); // 只有温湿度传感器模块响应relie命令 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行停止闪烁,协调器不处理 // 停止LED2闪烁 g_LED2FlashStatus = 0; // 关闭LED2 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // 明确停止闪烁定时器 osal_stop_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"温湿度传感器终端设备直接停止LED2闪烁\r\n", 39); } else { // 协调器接收到relie命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x10; // 自定义的flash命令标识 cmd[1] = 0x00; // 停止闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器直接转发温湿度传感器停止闪烁命令到网络\r\n", 46); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } } // 添加对shuo命令的处理 - 红外对射传感器LED闪烁命令 else if(strncmp(msgPtr, CMD_SHUO, strlen(CMD_SHUO)) == 0) { // 添加调试输出 HalUARTWrite(0, (uint8*)"收到shuo命令\r\n", 14); // 只有红外对射传感器模块响应shuo命令 if (g_SensorType == SENSOR_TYPE_IR) { // 添加调试输出 HalUARTWrite(0, (uint8*)"当前是红外对射传感器模块\r\n", 27); if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 只有终端设备执行闪烁,协调器不闪烁 // 启动LED2闪烁 g_LED2FlashStatus = 1; // 触发闪烁事件,立即开始 osal_set_event(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT); // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射终端设备开始LED2闪烁\r\n", 30); } else { // 协调器接收到shuo命令时,转发给所有设备 uint8 cmd[2]; cmd[0] = 0x11; // 自定义的红外闪烁命令标识,与温湿度传感器区分 cmd[1] = 0x01; // 开始闪烁 // 添加调试输出 HalUARTWrite(0, (uint8*)"协调器转发shuo命令到网络\r\n", 27); AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, cmd, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } else { // 添加调试输出 HalUARTWrite(0, (uint8*)"不是红外对射传感器模块,忽略命令\r\n", 34); } } } // Initialize IR sensor interrupt function void InitIRSensorInterrupt(void) { // Set P1_2 as input pin P1DIR &= ~BV(2); // Configure P1_2 as input P1SEL &= ~BV(2); // Set as general I/O, not peripheral function // Configure P1_2 as pull-up input P1INP &= ~BV(2); // Set as tri-state input P2INP &= ~BV(5); // Clear P1 port pull-down setting, configure as pull-up // Read current status g_IRSensorStatus = (P1 & BV(2)) ? 0 : 1; // Set P1_2 as falling edge triggered PICTL |= BV(1); // P1 port uses falling edge trigger (PICTL.P1ICON = 1) // Enable P1_2 interrupt P1IEN |= BV(2); // Enable P1_2 interrupt function // Clear possible interrupt flags P1IFG &= ~BV(2); // Enable P1 port interrupt IEN2 |= BV(4); // Enable P1 port interrupt (IEN2.P1IE = 1) } // Process IR sensor interrupt function void ProcessIRSensorInterrupt(void) { // 简单的重入保护:如果已经在处理中,则退出 if(g_IRProcessingInProgress) { return; } g_IRProcessingInProgress = 1; // 设置处理中标志 // Read current status uint8 currentStatus = (P1 & BV(2)) ? 0 : 1; // For end devices, flash LED2 10 times and send interrupt message to coordinator if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // Flash LED2 10 times on end device only HalUARTWrite(0, (uint8*)"42213238YFC+红外对射传感器+interrupt\r\n", 36); HalLedBlink(HAL_LED_2, 10, 50, 200); uint8 buf[3]; buf[0] = 0x03; // Indicates this is an interrupt event message buf[1] = 0x01; // Interrupt occurred buf[2] = currentStatus; // Current sensor status AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 3, (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } // Status changed if (currentStatus != g_IRSensorStatus) { g_IRSensorStatus = currentStatus; // Send status to coordinator if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { uint8 buf[2]; buf[0] = 0x02; // Indicates this is IR sensor data buf[1] = g_IRSensorStatus; AF_DataRequest(&SampleApp_Periodic_DstAddr, &SampleApp_epDesc, SAMPLEAPP_PERIODIC_CLUSTERID, 2, (uint8*)buf, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); } } // Re-enable interrupt after processing // Clear interrupt flag P1IFG &= ~BV(2); // Re-enable interrupt P1IEN |= BV(2); g_IRProcessingInProgress = 0; // 清除处理中标志 } // LED2闪烁处理函数 void ProcessLED2Flash(void) { // 添加调试输出 HalUARTWrite(0, (uint8*)"执行LED2闪烁处理函数\r\n", 22); // 判断是温湿度传感器还是红外对射传感器 if (zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) { // 温湿度传感器模块执行闪烁 if (g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY && g_LED2FlashStatus == 1) { // 添加调试输出 HalUARTWrite(0, (uint8*)"温湿度传感器符合条件,切换LED2状态\r\n", 35); // 切换LED2状态 (开/关) if ((HalLedGetState() & HAL_LED_2) == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); HalUARTWrite(0, (uint8*)"温湿度传感器LED2打开\r\n", 22); } else { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"温湿度传感器LED2关闭\r\n", 22); } // 继续闪烁,500ms后再次触发 osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT, 500); } // 红外对射传感器模块执行闪烁 else if (g_SensorType == SENSOR_TYPE_IR && g_LED2FlashStatus == 1) { // 添加调试输出 HalUARTWrite(0, (uint8*)"红外对射传感器符合条件,切换LED2状态\r\n", 37); // 切换LED2状态 (开/关) if ((HalLedGetState() & HAL_LED_2) == 0) { HalLedSet(HAL_LED_2, HAL_LED_MODE_ON); HalUARTWrite(0, (uint8*)"红外对射传感器LED2打开\r\n", 24); } else { HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); HalUARTWrite(0, (uint8*)"红外对射传感器LED2关闭\r\n", 24); } // 继续闪烁,300ms后再次触发(红外传感器闪烁频率比温湿度传感器快一些) osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_LED2_FLASH_EVT, 300); } else { // LED2闪烁状态为0或传感器类型不匹配,不执行闪烁 if (g_LED2FlashStatus == 0) { HalUARTWrite(0, (uint8*)"闪烁状态为0,不执行LED2闪烁\r\n", 29); // 确保LED2处于关闭状态 HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); } else { // 传感器类型不匹配 HalUARTWrite(0, (uint8*)"传感器类型不匹配,不执行LED2闪烁\r\n", 33); } } } else { // 协调器不执行闪烁 HalUARTWrite(0, (uint8*)"协调器不执行LED2闪烁\r\n", 22); } } // Modify P1 interrupt handler related code, add P1 interrupt service routine HAL_ISR_FUNCTION(halP1Isr, P1INT_VECTOR) { if (P1IFG & BV(2)) { // Clear interrupt flag P1IFG &= ~BV(2); // Notify application to process interrupt via OSAL event osal_set_event(SampleApp_TaskID, SAMPLEAPP_SEND_SENSOR_INT_EVT); } // Clear P1 port interrupt flag P1IF = 0; } // Modify SetBuzzerStatus function to use another pin (P1_0) as buzzer output void SetBuzzerStatus(uint8 status) { if(status == 0x01) { P1_0 = 1; // Use P1_0 as buzzer control pin (active high) } else { P1_0 = 0; // Turn off buzzer } } void PrintDeviceInfo(void) { char buf[80]; // 打印设备类型信息 if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { sprintf(buf, "设备类型: 协调器 (ZG_DEVICETYPE_COORDINATOR)\r\n"); } else if(zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER) { sprintf(buf, "设备类型: 路由器 (ZG_DEVICETYPE_ROUTER)\r\n"); } else if(zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE) { sprintf(buf, "设备类型: 终端设备 (ZG_DEVICETYPE_ENDDEVICE)\r\n"); } else { sprintf(buf, "设备类型: 未知 (%d)\r\n", zgDeviceLogicalType); } HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印传感器类型信息 if(g_SensorType == SENSOR_TYPE_TEMP_HUMIDITY) { sprintf(buf, "传感器类型: 温湿度传感器 (SENSOR_TYPE_TEMP_HUMIDITY)\r\n"); } else if(g_SensorType == SENSOR_TYPE_IR) { sprintf(buf, "传感器类型: 红外传感器 (SENSOR_TYPE_IR)\r\n"); } else if(g_SensorType == SENSOR_TYPE_COMBINED) { sprintf(buf, "传感器类型: 组合传感器 (SENSOR_TYPE_COMBINED)\r\n"); } else { sprintf(buf, "传感器类型: 未知 (%d)\r\n", g_SensorType); } HalUARTWrite(0, (uint8*)buf, strlen(buf)); // 打印编译时定义的宏 #ifdef TEMP_HUMIDITY_SENSOR sprintf(buf, "宏定义: TEMP_HUMIDITY_SENSOR 已定义\r\n"); #else sprintf(buf, "宏定义: TEMP_HUMIDITY_SENSOR 未定义\r\n"); #endif HalUARTWrite(0, (uint8*)buf, strlen(buf)); #ifdef COMBINED_SENSOR sprintf(buf, "宏定义: COMBINED_SENSOR 已定义\r\n"); #else sprintf(buf, "宏定义: COMBINED_SENSOR 未定义\r\n"); #endif HalUARTWrite(0, (uint8*)buf, strlen(buf)); } // 辅助函数,将字符串以十六进制格式打印出来,帮助调试 void PrintHexBytes(const char* title, const char* data, uint8 len) { char buf[200]; uint8 offset = 0; uint8 i; // 打印标题 offset = sprintf(buf, "%s: ", title); // 打印十六进制值 for (i = 0; i < len && offset < 190; i++) { offset += sprintf(buf + offset, "%02X ", (uint8)data[i]); } sprintf(buf + offset, "\r\n"); HalUARTWrite(0, (uint8*)buf, strlen(buf)); } /********************************************************************* *********************************************************************/ 根据要求和代码,实现相关功能,给出修改后的完整代码
06-28
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值