[STM32WBA] 【NUCLEO-WBA65RI 测评】+串口输出ADC采样值

[STM32WBA] 【NUCLEO-WBA65RI 测评】+串口输出ADC采样值 这次采样ADC值使用了中值滤波跟直接采还是有一点点差距的。一、硬件95494693bb4592057f.png(126.01 KB, 下载次数: 0)下载附件2025-12-12 14:21 上传ADC输入端ADC4_5-------PA4USART1:RX-----PA 8; TX -----PB12二、IDE设置ADC设置DMA其他按正常流程设置即可。不累赘了三、代码main函数/* 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 ------------------------------------------------------------------*/#includemain.h#includeadc.h#includegpdma.h#includeusart.h#includegpio.h/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */#includestdio.h#includestring.h#includestdlib.h// 定义中值滤波结构体typedefstruct{uint32_t*buffer;// 存储数据的缓冲区uint32_tbuffer_size;// 缓冲区大小uint32_tcurrent_index;// 当前写入位置uint8_tis_full;// 缓冲区是否已填满}MedianFilter_t;/* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */#defineBUFFER_SIZE 100#defineMEDIAN_FILTER_SIZE 9// 中值滤波窗口大小建议使用奇数(3,5,7,9)uint32_tadc_value 0;uint32_tfiltered_adc_value 0;// 新增滤波后的ADC值volatileuint32_tadc_buffer[BUFFER_SIZE];// 中值滤波缓冲区uint32_tmedian_buffer[MEDIAN_FILTER_SIZE];/* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM */voidProcessADCData(void);voidSendDataViaUART(void);voidMonitorADCBuffer(void);// 新增中值滤波相关函数voidMedianFilter_Init(MedianFilter_t*filter,uint32_t*buffer,uint32_tsize);voidMedianFilter_AddValue(MedianFilter_t*filter,uint32_tvalue);uint32_tMedianFilter_GetMedian(MedianFilter_t*filter);intcompare_uint32(constvoid*a,constvoid*b);/* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */// 中值滤波实例MedianFilter_tmedian_filter;/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/voidSystemClock_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.* retvalint*/intmain(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and theSystick. */HAL_Init();/* USER CODE BEGINInit*//* USER CODE ENDInit*//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPDMA1_Init();MX_GPIO_Init();MX_ADC4_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */chartest_msg[] ADC with Median Filter Started...\r\n;HAL_UART_Transmit(huart1, (uint8_t*)test_msg,strlen(test_msg), HAL_MAX_DELAY);// 初始化中值滤波器MedianFilter_Init(median_filter, median_buffer, MEDIAN_FILTER_SIZE);// 显示滤波配置信息charconfig_msg[100];sprintf(config_msg,Median Filter Size: %d\r\n, MEDIAN_FILTER_SIZE);HAL_UART_Transmit(huart1, (uint8_t*)config_msg,strlen(config_msg), HAL_MAX_DELAY);// 修正的ADC通道检查charhw_msg[200];sprintf(hw_msg,ADC Instance: 0x%lX\r\n, (uint32_t)hadc4.Instance);HAL_UART_Transmit(huart1, (uint8_t*)hw_msg,strlen(hw_msg), HAL_MAX_DELAY);// 启动ADCHAL_ADC_Start_DMA(hadc4, (uint32_t*)adc_buffer, BUFFER_SIZE);// 立即检查缓冲区状态HAL_Delay(10);// 短暂延时让DMA有机会填充数据sprintf(hw_msg,Initial Buffer[0]: %lu, [1]: %lu, [2]: %lu\r\n,adc_buffer[0], adc_buffer[1], adc_buffer[2]);HAL_UART_Transmit(huart1, (uint8_t*)hw_msg,strlen(hw_msg), HAL_MAX_DELAY);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */ProcessADCData();SendDataViaUART();HAL_Delay(1000);}/* USER CODE END 3 */}/* USER CODE BEGIN 4 */// 实时监控ADC缓冲区voidMonitorADCBuffer(void){staticuint32_tlast_values[3] {0, 0, 0};uint8_tchanged 0;for(inti 0; i 3; i) {if(adc_buffer! last_values) {changed 1;last_values adc_buffer;}}if(changed) {charbuffer_msg[150];sprintf(buffer_msg,BUFFER CHANGED - [0]:%lu[1]:%lu[2]:%lu[99]:%lu\r\n,adc_buffer[0], adc_buffer[1], adc_buffer[2], adc_buffer[99]);HAL_UART_Transmit(huart1, (uint8_t*)buffer_msg,strlen(buffer_msg), HAL_MAX_DELAY);}}voidProcessADCData(void){uint32_tsum 0;uint32_tvalid_samples 0;// 计算原始ADC平均值for(inti 0; i BUFFER_SIZE; i) {if(adc_buffer! 0) {// 只计算非零值sum adc_buffer;valid_samples;}}if(valid_samples 0) {adc_value sum / valid_samples;// 将当前平均值添加到中值滤波器MedianFilter_AddValue(median_filter, adc_value);// 获取中值滤波结果filtered_adc_value MedianFilter_GetMedian(median_filter);}else{adc_value 0;filtered_adc_value 0;}}voidSendDataViaUART(void){staticuint32_tlast_raw_value 0;staticuint32_tlast_filtered_value 0;uint32_tvoltage_mv_raw (adc_value * 3300) / 4095;uint32_tvoltage_mv_filtered (filtered_adc_value * 3300) / 4095;charbuffer[200];// 只有当数据发生变化时才发送可选可以减少串口输出if(adc_value ! last_raw_value || filtered_adc_value ! last_filtered_value) {last_raw_value adc_value;last_filtered_value filtered_adc_value;sprintf(buffer,Raw: %4lu (%4lumV) | Filtered: %4lu (%4lumV) |Diff: %4ld\r\n,adc_value, voltage_mv_raw,filtered_adc_value, voltage_mv_filtered,(int32_t)filtered_adc_value - (int32_t)adc_value);HAL_UART_Transmit(huart1, (uint8_t*)buffer,strlen(buffer), HAL_MAX_DELAY);}}// 中值滤波函数实现 // 比较函数用于qsort排序intcompare_uint32(constvoid*a,constvoid*b){uint32_tval_a *(constuint32_t*)a;uint32_tval_b *(constuint32_t*)b;if(val_a val_b)return-1;if(val_a val_b)return1;return0;}// 初始化中值滤波器voidMedianFilter_Init(MedianFilter_t*filter,uint32_t*buffer,uint32_tsize){filter-buffer buffer;filter-buffer_size size;filter-current_index 0;filter-is_full 0;// 清空缓冲区for(uint32_ti 0; i size; i) {filter-buffer 0;}}// 添加新值到滤波器voidMedianFilter_AddValue(MedianFilter_t*filter,uint32_tvalue){// 将新值添加到缓冲区filter-buffer[filter-current_index] value;// 更新索引filter-current_index;// 检查缓冲区是否已满if(filter-current_index filter-buffer_size) {filter-current_index 0;filter-is_full 1;}}// 获取中值uint32_tMedianFilter_GetMedian(MedianFilter_t*filter){uint32_ttemp_buffer[MEDIAN_FILTER_SIZE];uint32_tsample_count;if(filter-is_full) {// 缓冲区已满使用所有数据sample_count filter-buffer_size;memcpy(temp_buffer, filter-buffer, filter-buffer_size*sizeof(uint32_t));}elseif(filter-current_index 0) {// 缓冲区未满使用已有数据sample_count filter-current_index;memcpy(temp_buffer, filter-buffer, filter-current_index*sizeof(uint32_t));}else{// 没有数据return0;}// 排序数据qsort(temp_buffer, sample_count,sizeof(uint32_t), compare_uint32);// 返回中值if(sample_count % 2 1) {// 奇数个样本直接返回中间值returntemp_buffer[sample_count / 2];}else{// 偶数个样本返回中间两个值的平均值uint32_tmid1 temp_buffer[sample_count / 2 - 1];uint32_tmid2 temp_buffer[sample_count / 2];return(mid1 mid2) / 2;}}/* USER CODE END 4 *//*** brief System Clock Configuration* retvalNone*/voidSystemClock_Config(void){RCC_OscInitTypeDefRCC_OscInitStruct {0};RCC_ClkInitTypeDefRCC_ClkInitStruct {0};/** Supply configuration update enable*/HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);/** Configure the main internal regulator output voltage*/if(HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) !HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks*/RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState RCC_HSE_ON;RCC_OscInitStruct.HSEDiv RCC_HSE_DIV1;RCC_OscInitStruct.PLL1.PLLState RCC_PLL_NONE;if(HAL_RCC_OscConfig(RCC_OscInitStruct) !HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks*/RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2|RCC_CLOCKTYPE_PCLK7|RCC_CLOCKTYPE_HCLK5;RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_HSE;RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV1;RCC_ClkInitStruct.APB7CLKDivider RCC_HCLK_DIV1;RCC_ClkInitStruct.AHB5_PLL1_CLKDivider RCC_SYSCLK_PLL1_DIV1;RCC_ClkInitStruct.AHB5_HSEHSI_CLKDivider RCC_SYSCLK_HSEHSI_DIV1;if(HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_0) !HAL_OK){Error_Handler();}}/*** brief This function is executed in case of error occurrence.* retvalNone*/voidError_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 */四、效果视频串口输出ADC码值电压值、中值码值电压值、码值差值如下图span]。---------------------作者LiuDW091链接https://bbs.21ic.com/icview-3499646-1-1.html来源21ic.com此文章已获得原创/原创奖标签著作权归21ic所有任何人未经允许禁止转载。