/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 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 "cmsis_os.h" #include "can.h" #include "dma.h" #include "i2c.h" #include "iwdg.h" #include "rtc.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ volatile uint8_t uart2DataReady = 0; #define BUFFER_SIZE2 9 uint8_t dataReceive2[BUFFER_SIZE2]; uint16_t eeMLX90640[832]; float mlx90640To[768]; uint16_t frame[834]; paramsMLX90640 mlx90640; float emissivity=0.95; int status; uint16_t badPixels[5]; // 坏点数组,最大支�?? 5 个坏�?? uint16_t blockNumber = 1; // 数据块编号,每次采集递增 uint8_t packet[350]; // 存放�??包数据用于发�?? #define INPUT_WIDTH 32 #define INPUT_HEIGHT 24 #define OUTPUT_WIDTH 64 #define OUTPUT_HEIGHT 48 //float interpolatedStep1[INPUT_WIDTH * 4 * INPUT_HEIGHT * 4]; // 第一次插值后的数据存�?? float finalImage[OUTPUT_WIDTH * OUTPUT_HEIGHT]; // �??终插值后图像 uint32_t start_tick = 0; /* 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); void MX_FREERTOS_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint16_t CalculateCRC(uint8_t *data, uint16_t length) { uint16_t crc = 0xFFFF; for (int i = 0; i < length; i++) { crc ^= data[i]; for (int j = 0; j < 8; j++) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; else crc >>= 1; } } return crc; } uint8_t packetNum = 1; // 初始包序号为1 uint8_t sendingInProgress = 0; // 状�?�标志:0表示未发送,1表示正在发�?? void SendDataFrame(uint16_t blockNumber,float *mlx90640To) { uint16_t i, packetLength; uint8_t packetnum = 1; // 初始包序号为1 while (packetnum <= 5) // 循环直到发�?�完5个数据包 { // 构�?�数据包�?? uint16_t packetIndex = 0; // 0xABCD (2字节) packet[packetIndex++] = 0xAB; packet[packetIndex++] = 0xCD; // 0x0002 (2字节) packet[packetIndex++] = 0x00; packet[packetIndex++] = 0x02; // 0x014E (2字节) packet[packetIndex++] = 0x01; packet[packetIndex++] = 0x4E; // 数据块编�?? (2字节) packet[packetIndex++] =(uint8_t)(blockNumber >> 8); // 数据包编�??: 0x0001, 0x0002 ... packet[packetIndex++] =(uint8_t)(blockNumber & 0xFF); // 0x0686 (2字节) packet[packetIndex++] = 0x06; packet[packetIndex++] = 0x86; // 0x0005 (2字节) packet[packetIndex++] = 0x00; packet[packetIndex++] = 0x05; // 0x0001, 0x0002, ..., 0x0005 (2字节) - 数据包序�?? packet[packetIndex++] = 0x00; // 根据包编号设置包序号 packet[packetIndex++] = (uint8_t)(packetnum); // 填充frame数据 for (i = (packetnum - 1) * 167; i < packetnum * 167; i++) { if (i < 768) { // �?? mlx90640To[i] 乘以10后转换为 uint16_t uint16_t temp = (uint16_t)(mlx90640To[i] * 10); packet[packetIndex++] = (uint8_t)(temp >> 8); // 高字�?? packet[packetIndex++] = (uint8_t)(temp & 0xFF); // 低字�?? } else { // 若数据不足,则填�??0 packet[packetIndex++] = 0x00; packet[packetIndex++] = 0x00; } } // 计算CRC16 uint16_t crc = CalculateCRC(packet, packetIndex); // 计算CRC16 packet[packetIndex++] = (uint8_t)(crc & 0xFF); // CRC 高字�?? packet[packetIndex++] = (uint8_t)(crc >> 8); // CRC 低字�?? // 发�?�数据包 packetLength = packetIndex; HAL_UART_Transmit(&huart2, packet, packetLength, HAL_MAX_DELAY); // HAL_UART_Transmit_IT(&huart2, packet, packetLength); // HAL_UART_Transmit_DMA(&huart2, packet, packetLength); HAL_Delay(50); packetnum ++; } } // 定义读取异常时最大重试次�?? #define MAX_RETRY_COUNT 3 /* 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_DMA_Init(); MX_USART2_UART_Init(); MX_I2C1_Init(); MX_CAN1_Init(); MX_RTC_Init(); // MX_IWDG_Init(); /* USER CODE BEGIN 2 */ uint32_t start_tick = osKernelGetTickCount(); printf("start_tick %lu\r\n",start_tick); printf("MLX90640 25_4_24\r\n"); uart_init(); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); CAN_FilterInit(); HAL_CAN_Start(&hcan1);// 开启can HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);// 启用CAN FIFO 0消息挂起中断 HAL_Delay(50); MLX90640_SetRefreshRate(MLX90640_ADDR, RefreshRate8HZ); // 设置帧率�??0-7对应0.5,1,2,4,8,16,32,64HZ�?? status = MLX90640_DumpEE(MLX90640_ADDR, eeMLX90640); // 读取像素校正参数 status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640); // 解析校正参数 // HAL_Delay(3000); // printf("0\r\n"); /* USER CODE END 2 */ /* Init scheduler */ osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */ MX_FREERTOS_Init(); /* Start scheduler */ osKernelStart(); /* We should never get here as control is now taken by the scheduler */ /* 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}; /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } /** Configure LSE Drive Capability */ HAL_PWR_EnableBkUpAccess(); __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI |RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 1; RCC_OscInitStruct.PLL.PLLN = 8; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; 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_DIV4; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void uart_init(void) { memset(dataReceive2, 0, sizeof(dataReceive2)); __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); HAL_UART_Receive_DMA(&huart2, dataReceive2, BUFFER_SIZE2); // 启动USART2的DMA接收485 } /* USER CODE END 4 */ /** * @brief Period elapsed callback in non blocking mode * @note This function is called when TIM6 interrupt took place, inside * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment * a global variable "uwTick" used as application time base. * @param htim : TIM handle * @retval None */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* USER CODE BEGIN Callback 0 */ /* USER CODE END Callback 0 */ if (htim->Instance == TIM6) { HAL_IncTick(); } /* USER CODE BEGIN Callback 1 */ /* USER CODE END Callback 1 */ } /** * @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 */