AI数字员工:AIOK.WORK你的未来同事可能是个“代码侠”!

部署运行你感兴趣的模型镜像

# AI数字员工:你的未来同事可能是个"代码侠"!

各位打工人注意啦!你们可能很快就要和一群"007工作制"还从不喊累的"卷王"做同事了——没错,就是AI数字员工!这些虚拟小伙伴正在以光速占领办公室,让我们一起来看看这些"代码侠"都在哪些领域大显身手吧~

## 一、AI数字员工现状:从"人工智障"到"职场卷王"

ai数字员工

还记得几年前那些答非所问的客服机器人吗?现在的AI数字员工已经进化成了"职场六边形战士"!根据最新数据,2025年中国虚拟人核心市场规模预计将达到480.6亿元,而且这些"数字打工人"正在以下领域疯狂"抢饭碗":

1. **客服界的永动机**:中国石化的AI数字员工已经在全国40多座加油站上岗,不仅能报油价,还能给客户规划旅游路线,比真人导游还贴心。想象一下,以后去加油站可能会听到:"95号加满?要不要顺便去隔壁景点打卡?"

2. **政务大厅的"活雷锋"**:磐石市的"政务AI数字员工"已经能处理1735项政务服务事项,市民对着机器喊"办营业执照"就能拿到全套指南,再也不用看办事员脸色了。终于可以实现"零门槛怼政府"的梦想了(大误)!

3. **金融圈的"人形计算器"**:某证券公司的AI投顾通过学习金融知识,成功让公司减少了数百名高学历员工的需求。看来以后金融精英们比拼的不是学历,而是谁能驯服更聪明的AI!

## 二、AI数字员工的"职场超能力"

AI数字员工 代码侠



这些数字同事之所以能迅速上位,全靠以下几项"职场外挂":

1. **24小时待机不眨眼**:它们不需要咖啡续命,不用午休,甚至不会在周一早晨发朋友圈抱怨"不想上班"。深圳福田区的70名"AI数智员工"上岗后,公文处理效率直接提升90%,这效率让人类同事瑟瑟发抖。

2. **一人能顶一个部门**:Manus这样的全能AI,10分钟就能写出安卓APP,5分钟生成28页旅行攻略,还能同时操作Chrome、Excel和企业数据库。建议给它们颁发"最佳多线程处理奖"!

3. **学习能力堪比学霸**:追一科技的AI员工通过持续学习,现在已经能处理保险比价、金融咨询等专业工作。看来以后职场竞争不是"拼爹"而是"拼数据集"了!

## 三、那些正在被AI"革命"的职场场景



1. **客服岗位**:AI客服已经能处理47%的客户咨询,逼得宜家把8500名客服转岗成了虚拟室内设计顾问,还创造了14亿美元的新收入。以后客服转行做设计可能成为新常态?

2. **文书工作**:深圳福田区的AI员工4分钟就能生成原本需要4小时的仲裁裁决书。法律助理们,是时候考虑转行当AI驯兽师了!

3. **数据分析**:跨境电商的AI员工能自动分析竞品定价,给出调价策略,还附赠GMV增长预测图表。市场分析师们,你们的Excel宏该升级成AI宏了!

4. **编程开发**:有程序员用AI工具10分钟就完成了一个安卓APP的开发打包。GitHub上的"一周学习编程"教程该改成"一杯咖啡时间学习编程"了!

5. **教学工作**:北京的王老师用AI 20分钟就能做出媲美网课机构的备课素材,而以前需要4小时。老师们终于可以从"PPT奴隶"解放出来,专心对付熊孩子了!

## 四、未来趋势:你的AI同事会变得更"人精"

1. **从"工具人"变"心机BOY"**:未来的AI数字员工将更加情感化、人性化,可能会学会在老板面前假装很忙,在同事面前装傻充愣(并不是)。

2. **"数字分身"时代来临**:追一科技正在打造"AI员工梦工厂",以后每个人可能都有个AI分身帮你上班,自己在家躺平(老板:这功能我们不约!)。

3. **人机"宫斗"大戏上演**:中层管理者要开始管理"人类+数字"混合团队,想象一下晨会场景:"小张你这个月KPI又没完成...还有你,GPT-7,别以为躲在服务器里我就找不到你!"

4. **AI开始"拉帮结派"**:多Agent协作模式将成为趋势,未来可能会出现AI小团体:"ChatGPT帮我把这份报告写了,我去DeepSeek那儿帮你查资料!"

## 五、人类员工的生存指南

AI数字员工 AIOK.WORK



别急着写辞职信!虽然AI来势汹汹,但它们也有软肋:

1. **创造力仍是人类专利**:AI可以10分钟写APP,但让它想个"程序员鼓励师"这样的职位可能还得再学几年。

2. **背锅能力有待提高**:深圳政府给每个AI员工都配了人类"监护人",出问题还是得人类背锅。终于找到AI替代不了的工作了!

3. **办公室政治不擅长**:目前还没AI学会在茶水间传八卦,或者在周报里暗戳戳甩锅给隔壁部门。

所以打工人请记住:未来不是AI取代人类,而是会用AI的人类取代不用AI的人类。赶紧去和你的未来AI同事搞好关系吧,说不定它能帮你写年终总结呢!

> "AI不会取代任何工种,AI只会帮助我们节省时间、减少解决不了bug的焦虑、弥补我们的知识盲区。" —— 某位已经用AI摸鱼的聪明程序员

(悄悄说:如果你现在开始训练AI帮你工作,说不定能成为全公司最早下班的人哦~)

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

/* 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 "adc.h" #include "dma.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "oled.h" #include "key.h" #include <math.h> #include "NanoEdgeAI.h" #include "knowledge.h" #include <stdarg.h> #include <stdio.h> #include <string.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ // 当前分类结果的类别ID标识符,该值指向分类系统的类别索引 uint16_t id_class = 0; /* 输入数据缓冲区,用于存储单片机捕捉到的敲击点数据 由一个大小为3的数组存储 DATA_INPUT_USER = 1 AXIS_NUMBER = 3 */ float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; /* 分类结果概率缓冲区,存储每个类别的预测概率值 数组大小为CLASS_NUMBER = 36 */ float output_class_buffer[CLASS_NUMBER]; /* 类别ID到名称的映射表 索引0为"unknown",后续索引对应具体板面各点分类名称 数组大小为CLASS_NUMBER+1,含所有的分类名称 */ const char *id2class[CLASS_NUMBER + 1] = { "unknown", "KL910", "KL78", "KL56", "KL34", "KL12", "KL1112", "IJ910", "IJ78", "IJ56", "IJ34", "IJ12", "IJ1112", "GH910", "GH78", "GH56", "GH34", "GH12", "GH1112", "EF910", "EF78", "EF56", "EF34", "EF12", "EF1112", "CD910", "CD78", "CD56", "CD34", "CD12", "CD1112", "AB910", "AB78", "AB56", "AB34", "AB12", "AB1112", }; /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ char OLED_Flage = 0; //显示标志位(1:更新一次OLED屏幕显示,0:不更新) char time_Data_Flage = 0; //位置数据记录成功标志位(1:成功捕捉到一个敲击点 0:尚未捕捉到一个敲击点) int time_Data_Filtering[3]; //A---B---C 一个点在一个周期内只能被触发一次 uint32_t time_Data[3]; //A---B---C 用以记录该敲击点的三个接收端时间差 // 记录捕捉一个敲击点数据的状态 int point_number = 0; //0:未识别到有敲击 1:第一个接收端触发 2:第二个接收端触发 3:第三个接收端触发 //将捕捉到的敲击点数据传递给AI数据接口,实现数据传递 void fill_buffer(float input_user_buffer[]) { input_user_buffer[0]=time_Data[0]; input_user_buffer[1]=time_Data[1]; input_user_buffer[2]=time_Data[2]; } /* 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 */ //串口打印函数 用于调试 static void UART_Printf(const char *format, ...) { char tmp[128]; va_list argptr; va_start(argptr, format); vsprintf((char* )tmp, format, argptr); va_end(argptr); HAL_UART_Transmit(&huart1, (const uint8_t *)&tmp, strlen(tmp), HAL_MAX_DELAY); } /* 用户指示灯开关函数 Led_Num: 0:LED1 1:LED2 2:LED3 3:LED4 4:LED5 Led_State: 0:关 1:开 */ void LED_Switch(char Led_Num,char Led_State); /* 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_TIM3_Init(); MX_TIM4_Init(); MX_USART1_UART_Init(); MX_I2C1_Init(); MX_ADC1_Init(); MX_TIM1_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start (&htim3 ); //开启定时器3 读取时间,得到3个触发点的时间差 HAL_TIM_Base_Start_IT (&htim4); //开启定时器4 10ms中断一次 HAL_Delay(20); //等待20ms OLED_Init(); //初始化OLED屏 //创建4个字符串用于存储显示数据 char masage1[22] = ""; char masage2[22] = ""; char masage3[22] = ""; char masage4[22] = ""; //当前已捕捉到的敲击点数 int Point_number = 0; //键码 unsigned char key_number = 0; //初始化显示 sprintf(masage1,"当前点数: %-2d",Point_number); sprintf(masage2,"A点: %-5d %d ",time_Data[0],time_Data_Filtering[0]); sprintf(masage3,"B点: %-5d %d",time_Data[1],time_Data_Filtering[1]); sprintf(masage4,"C点: %-5d %d",time_Data[2],time_Data_Filtering[2]); /* 初始化分类器知识库同时验证硬件兼容性。若初始化失败(返回非NEAI_OK错误码---0), 表示当前知识库与AI库不匹配或硬件平台不支持,通过串口输出错误标识。 */ enum neai_state error_code = neai_classification_init(knowledge); if (error_code != NEAI_OK) { UART_Printf("aiok\r\n"); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { key_number = Key(); //获取键码 switch (key_number){ case 1: // 显示3个触发点状态 sprintf(masage1,"当前点数: %-2d",Point_number); sprintf(masage2,"A点: %-5d %d ",time_Data[0],time_Data_Filtering[0]); sprintf(masage3,"B点: %-5d %d",time_Data[1],time_Data_Filtering[1]); sprintf(masage4,"C点: %-5d %d",time_Data[2],time_Data_Filtering[2]); LED_Switch(1,0); break; case 2: // 删除一个触发点,如废点 memset(time_Data_Filtering, 0, sizeof(time_Data_Filtering)); // 清零数组,允许触发 point_number = 0; Point_number --; if(Point_number < 0 ) Point_number = 0; sprintf(masage1,"当前点数: %-2d",Point_number); sprintf(masage2,"A点: %-5d %d ",time_Data[0],time_Data_Filtering[0]); sprintf(masage3,"B点: %-5d %d",time_Data[1],time_Data_Filtering[1]); sprintf(masage4,"C点: %-5d %d",time_Data[2],time_Data_Filtering[2]); break; case 3: //判断单片机是否正常运行,切换二号灯状态 static int i = 0; //静态变量 i = (i + 1) % 2; if(i == 1) LED_Switch(2,1); else LED_Switch(2,0); break; default: break; } if(time_Data_Flage == 1){ // 判断是否有敲击点 // 安全检测,排除异常数据 if(time_Data_Filtering[0] < 1000 && time_Data_Filtering[1] < 1000 && time_Data_Filtering[2] < 1000){ Point_number++; //将捕捉到的敲击点数据传递给AI数据接口,实现数据传递 fill_buffer(input_user_buffer); // 分类AI调用接口 neai_classification(input_user_buffer, output_class_buffer, &id_class); // 串口打印结果 UART_Printf("result=%s\r\n",id2class[id_class]); // OLED显示结果 sprintf(masage1,"%s 点数: %-2d",id2class[id_class],Point_number); sprintf(masage2,"A点: %-5d %d ",time_Data[0],time_Data_Filtering[0]); sprintf(masage3,"B点: %-5d %d",time_Data[1],time_Data_Filtering[1]); sprintf(masage4,"C点: %-5d %d",time_Data[2],time_Data_Filtering[2]); UART_Printf("%d,%d,%d\r\n",time_Data[0],time_Data[1],time_Data[2]); HAL_Delay(20); //延时防止振动造成影响,错误开启第二个点 //允许三点中断触发 HAL_NVIC_EnableIRQ(EXTI1_IRQn); HAL_NVIC_EnableIRQ(EXTI2_IRQn); HAL_NVIC_EnableIRQ(EXTI3_IRQn); // 清零数组,允许触发(双重保险) memset(time_Data_Filtering, 0, sizeof(time_Data_Filtering)); // 重置标志位 time_Data_Flage = 0; } } // 刷新OLED屏显示 if(OLED_Flage == 1){ OLED_NewFrame(); OLED_PrintString(0,0,masage1,&font16x16,OLED_COLOR_NORMAL); OLED_PrintString(0,16,masage2,&font16x16,OLED_COLOR_NORMAL); OLED_PrintString(0,32,masage3,&font16x16,OLED_COLOR_NORMAL); OLED_PrintString(0,48,masage4,&font16x16,OLED_COLOR_NORMAL); OLED_ShowFrame(); // 重置标志位 OLED_Flage = 0; } /* 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 */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; 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_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ //外部中断回调 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ // A点捕捉到强烈振动且该周期内并未触发过 if(GPIO_Pin == point_A_Pin && time_Data_Filtering[0] == 0){ // A点已经触发 time_Data_Filtering[0] = 1; switch (point_number) { case 0: //为第一个触发点 __HAL_TIM_SET_COUNTER (&htim3 ,0); //计为最近点 , 重载计时器为0 time_Data[0] = 0; //最近点时间记为0时刻 HAL_NVIC_DisableIRQ(EXTI1_IRQn); break; case 1: //为第二个触发点 time_Data[0] = __HAL_TIM_GET_COUNTER(&htim3); //记录当前时刻计数值 HAL_NVIC_DisableIRQ(EXTI1_IRQn); break; case 2: //为第三个触发点 time_Data[0] = __HAL_TIM_GET_COUNTER(&htim3); //记录当前时刻计数值 HAL_NVIC_DisableIRQ(EXTI1_IRQn); time_Data_Flage = 1; //激活一次数据显示 break; default: break; } point_number = (point_number + 1) % 3; //当前点进度+1(3结束当前点) } // B点捕捉到强烈振动且该周期内并未触发过 else if(GPIO_Pin == point_B_Pin && time_Data_Filtering[1] == 0){ // B点已经触发 time_Data_Filtering[1] = 1; switch (point_number) { case 0: //为第一个触发点 __HAL_TIM_SET_COUNTER (&htim3 ,0); //计为最近点(0时刻) time_Data[1] = 0; HAL_NVIC_DisableIRQ(EXTI2_IRQn); break; case 1: //为第二个触发点 time_Data[1] = __HAL_TIM_GET_COUNTER(&htim3); HAL_NVIC_DisableIRQ(EXTI2_IRQn); break; case 2: //为第三个触发点 time_Data[1] = __HAL_TIM_GET_COUNTER(&htim3); HAL_NVIC_DisableIRQ(EXTI2_IRQn); time_Data_Flage = 1; //激活一次数据显示 break; default: break; } point_number = (point_number + 1) % 3; //当前点进度+1(3结束当前点) } // C点捕捉到强烈振动且该周期内并未触发过 else if(GPIO_Pin == point_C_Pin && time_Data_Filtering[2] == 0){ // C点已经触发 time_Data_Filtering[2] = 1; switch (point_number) { case 0: //为第一个触发点 __HAL_TIM_SET_COUNTER (&htim3 ,0); //计为最近点 time_Data[2] = 0; HAL_NVIC_DisableIRQ(EXTI3_IRQn); break; case 1: //为第二个触发点 time_Data[2] = __HAL_TIM_GET_COUNTER(&htim3); HAL_NVIC_DisableIRQ(EXTI3_IRQn); break; case 2: //为第三个触发点 time_Data[2] = __HAL_TIM_GET_COUNTER(&htim3); HAL_NVIC_DisableIRQ(EXTI3_IRQn); time_Data_Flage = 1; //激活一次数据显示 break; default: break; } point_number = (point_number + 1) % 3; //当前点进度+1(3结束当前点) } } //定时器回调 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ static char time = 0; if(htim == &htim4){ //10ms触发一次 time = (time + 1) % 3; if(time == 0 ) //30ms OLED_Flage = 1; } } //0:开启,1:关 void LED_Switch(char Led_Num,char Led_State){ switch (Led_Num) { case 1: if (Led_State == 1) { HAL_GPIO_WritePin(led1_GPIO_Port,led1_Pin,GPIO_PIN_SET); } else if(Led_State == 0) { HAL_GPIO_WritePin(led1_GPIO_Port,led1_Pin,GPIO_PIN_RESET); } break; case 2: if (Led_State == 1) { HAL_GPIO_WritePin(led2_GPIO_Port,led2_Pin,GPIO_PIN_SET); } else if(Led_State == 0) { HAL_GPIO_WritePin(led2_GPIO_Port,led2_Pin,GPIO_PIN_RESET); } break; case 3: if (Led_State == 1) { HAL_GPIO_WritePin(led3_GPIO_Port,led3_Pin,GPIO_PIN_SET); } else if(Led_State == 0) { HAL_GPIO_WritePin(led3_GPIO_Port,led3_Pin,GPIO_PIN_RESET); } break; case 4: if (Led_State == 1) { HAL_GPIO_WritePin(led4_GPIO_Port,led4_Pin,GPIO_PIN_SET); } else if(Led_State == 0) { HAL_GPIO_WritePin(led4_GPIO_Port,led4_Pin,GPIO_PIN_RESET); } break; default: break; } } /* 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 */ 帮我生成一个流程图
10-25
/* 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 "adc.h" #include "dma.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdarg.h> #include <stdio.h> #include <string.h> #include "arm_math.h" #include "arm_const_structs.h" #include "oled.h" #include "NanoEdgeAI.h" #include "knowledge.h" #include "stm32f4xx_it.h" #define ADC_BUFFER_LENGTH 256 #define FFT_LEN ADC_BUFFER_LENGTH #define Frequency_NUM 5 //频率段 #define Power_NUM 3 //接收端口数 //结果结构体 // 结果结构体(单频率) typedef struct FFT_Result_ALL { float max_amp; // 幅值 float phase; // 相位(弧度) } FFT_Result_ALL; // 相位差结果结构体(单频率) typedef struct Phase_Result { float phase_diff; // 相位差(相对于通道2,弧度) } Phase_Result; /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ uint16_t id_class = 0; // Point to id class (see argument of neai_classification fct) float input_user_buffer[DATA_INPUT_USER * AXIS_NUMBER]; // Buffer of input values float output_class_buffer[CLASS_NUMBER]; // Buffer of class probabilities const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name "unknown", "44", "43", "42", "41", "34", "33", "32", "31", "24", "23", "22", "21", "14", "13", "12", "11", }; /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ // ADC缓冲区 uint16_t adc_buffer1[ADC_BUFFER_LENGTH]; uint16_t adc_buffer2[ADC_BUFFER_LENGTH]; uint16_t adc_buffer3[ADC_BUFFER_LENGTH]; // ADC转换完成标志 __IO uint8_t AdcConvEnd = 0; // FFT结构体存放傅里叶相关信息 arm_cfft_radix4_instance_f32 scfft; // 数据输入缓存 float FFT_INPUT[FFT_LEN * 2]; // 实部和虚部 // 数据输出(幅度) float FFT_OUTPUT_chang1[FFT_LEN]; float FFT_OUTPUT_chang2[FFT_LEN]; float FFT_OUTPUT_chang3[FFT_LEN]; // 复数FFT结果(用于相位计算) float FFT_COMPLEX_chang1[FFT_LEN * 2]; float FFT_COMPLEX_chang2[FFT_LEN * 2]; float FFT_COMPLEX_chang3[FFT_LEN * 2]; // 最大值 FFT_Result_ALL result_ch1, result_ch2, result_ch3; // 相位差 Phase_Result phase_ch1, phase_ch3; // 通道1和3相对于通道2的相位差 // 串口接收缓存 uint8_t readBuffer[2]; // 采集结束继续后续操作 uint8_t continue_flag = 0; // 结果输出标志位 uint8_t result_flag = 0; //采集状态机 uint8_t mpde_flag = 0; // OLED显示标志位 char OLED_Flage = 0; /* 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 */ static void UART_Printf(const char *format, ...) { char tmp[128]; va_list argptr; va_start(argptr, format); vsprintf((char* )tmp, format, argptr); va_end(argptr); HAL_UART_Transmit(&huart1, (const uint8_t *)&tmp, strlen(tmp), HAL_MAX_DELAY); } // FFT计算 void FFT_Operation(float *INPUT, float *OUTPUT, float *COMPLEX_OUTPUT, uint8_t mode); // 获取最大值 float FFT_GetMaxAmplitude(float *fft_result, uint16_t fft_len); // 获取最大幅值对应的频率索引 uint16_t FFT_GetMaxFreqIndex(float *fft_result, uint16_t fft_len); // 计算相位差(相对于基准通道) float FFT_GetPhaseDiff(float *fft_target, float *fft_reference, uint16_t fft_len); void fill_buffer(float input_user_buffer[]); /* 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_ADC1_Init(); MX_TIM3_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_ADC2_Init(); MX_ADC3_Init(); MX_TIM2_Init(); MX_I2C2_Init(); /* USER CODE BEGIN 2 */ arm_cfft_radix4_init_f32(&scfft, FFT_LEN, 0, 1); // 先停止定时器 HAL_TIM_Base_Stop(&htim3); // 配置但不启动ADC HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buffer1, ADC_BUFFER_LENGTH); HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc_buffer2, ADC_BUFFER_LENGTH); HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_buffer3, ADC_BUFFER_LENGTH); // 短暂延迟让DMA配置完成 for(volatile int i = 0; i < 1000; i++); // 同时启动定时器,让3个ADC尽量同步开始 HAL_TIM_Base_Start(&htim3); HAL_TIM_Base_Start_IT(&htim2); HAL_UARTEx_ReceiveToIdle_DMA(&huart2, readBuffer, sizeof(readBuffer)); //开启串口接收 __HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT); HAL_Delay(20); OLED_Init(); char masage1[22] = ""; /* 初始化分类器知识库同时验证硬件兼容性。若初始化失败(返回非NEAI_OK错误码---0), 表示当前知识库与AI库不匹配或硬件平台不支持,通过串口输出错误标识。 */ enum neai_state error_code = neai_classification_init(knowledge); if (error_code != NEAI_OK) { UART_Printf("aiok\r\n"); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { //UART_Printf("1\r\n"); if(continue_flag == 1){ continue_flag = 0; AdcConvEnd = 0; // 先停止定时器 HAL_TIM_Base_Stop(&htim3); HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buffer1, ADC_BUFFER_LENGTH); HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc_buffer2, ADC_BUFFER_LENGTH); HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_buffer3, ADC_BUFFER_LENGTH); // 短暂延迟 for(volatile int i = 0; i < 1000; i++); // 重新启动定时器 HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd); HAL_TIM_Base_Stop(&htim3); HAL_ADC_Stop_DMA(&hadc1); HAL_ADC_Stop_DMA(&hadc2); HAL_ADC_Stop_DMA(&hadc3); // 可选:输出原始数据 // for(int i = 0; i < ADC_BUFFER_LENGTH; i++){ // UART_Printf("%f,%f,%f\r\n", adc_buffer1[i] * 3.3 / 4095, // adc_buffer2[i] * 3.3 / 4095, adc_buffer3[i] * 3.3 / 4095); // } //UART_Printf("1\r\n"); // FFT波形分析 FFT_Operation(FFT_INPUT, FFT_OUTPUT_chang1, FFT_COMPLEX_chang1, 0); FFT_Operation(FFT_INPUT, FFT_OUTPUT_chang2, FFT_COMPLEX_chang2, 1); FFT_Operation(FFT_INPUT, FFT_OUTPUT_chang3, FFT_COMPLEX_chang3, 2); //UART_Printf("2\r\n"); // 获取3个通道的FFT幅值最大值 result_ch1.max_amp = FFT_GetMaxAmplitude(FFT_OUTPUT_chang1, FFT_LEN); result_ch2.max_amp = FFT_GetMaxAmplitude(FFT_OUTPUT_chang2, FFT_LEN); result_ch3.max_amp = FFT_GetMaxAmplitude(FFT_OUTPUT_chang3, FFT_LEN); //UART_Printf("3\r\n"); // 计算相位差(以通道2为基准) phase_ch1.phase_diff = FFT_GetPhaseDiff(FFT_COMPLEX_chang1, FFT_COMPLEX_chang2, FFT_LEN); phase_ch3.phase_diff = FFT_GetPhaseDiff(FFT_COMPLEX_chang3, FFT_COMPLEX_chang2, FFT_LEN); //UART_Printf("4\r\n"); result_flag = 1; // 设置结果输出标志 } if(result_flag == 1){ result_flag = 0; // 输出幅值结果 // UART_Printf("%.4f,%.4f,%.4f\r\n", // result_ch1.max_amp, result_ch2.max_amp, result_ch3.max_amp); // 输出相位差(弧度) // UART_Printf("Phase(rad): %.4f,%.4f\r\n", // phase_ch1.phase_diff, phase_ch3.phase_diff); // 输出为度数 // UART_Printf("%.2f,%.2f\r\n", // phase_ch1.phase_diff * 180.0f / PI, // phase_ch3.phase_diff * 180.0f / PI); } if(OLED_Flage == 1){ OLED_Flage = 0; fill_buffer(input_user_buffer); // 分类AI调用接口 neai_classification(input_user_buffer, output_class_buffer, &id_class); sprintf(masage1,"OK:%s",id2class[id_class]); OLED_NewFrame(); OLED_PrintString(0,0,masage1,&font16x16,OLED_COLOR_NORMAL); OLED_ShowFrame(); } /* 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 */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; 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_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ static uint8_t time2_flag = 0; if(htim == &htim2){ //100ms time2_flag = (time2_flag + 1) % 2 == 0; //200ms if(time2_flag == 0){ continue_flag = 1; OLED_Flage = 1; } } } // ADC DMA������ɻص����ɼ���768�����ݺ󴥷��� void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc == &hadc1) { AdcConvEnd = 1; // ��λ��ɱ�־ } } // FFT计算 void FFT_Operation(float *INPUT, float *OUTPUT, float *COMPLEX_OUTPUT, uint8_t mode) { // 生成FFT输入数据,转换为复数 switch(mode){ case 0: for(int i = 0; i < FFT_LEN; i++){ INPUT[i * 2] = adc_buffer1[i] * 3.3 / 4095; INPUT[i * 2 + 1] = 0; } break; case 1: for(int i = 0; i < FFT_LEN; i++){ INPUT[i * 2] = adc_buffer2[i] * 3.3 / 4095; INPUT[i * 2 + 1] = 0; } break; case 2: for(int i = 0; i < FFT_LEN; i++){ INPUT[i * 2] = adc_buffer3[i] * 3.3 / 4095; INPUT[i * 2 + 1] = 0; } break; default: return; } // 调用FFT计算 arm_cfft_radix4_f32(&scfft, INPUT); // 保存复数结果用于相位计算 for(int i = 0; i < FFT_LEN * 2; i++){ COMPLEX_OUTPUT[i] = INPUT[i]; } // 复数转实数,取模 arm_cmplx_mag_f32(INPUT, OUTPUT, FFT_LEN); } uint16_t FFT_GetMaxFreqIndex(float *fft_result, uint16_t fft_len) { if (fft_result == NULL || fft_len < 2) return 0; uint16_t max_index = 0; float max_amp = fft_result[0]; uint16_t half_fft_len = fft_len / 2; for (uint16_t i = 1; i < half_fft_len; i++) { if (fft_result[i] > max_amp) { max_amp = fft_result[i]; max_index = i; } } return max_index; } float FFT_GetPhaseDiff(float *fft_target, float *fft_reference, uint16_t fft_len) { if (fft_target == NULL || fft_reference == NULL || fft_len < 2) { return 0.0f; } // 直接遍历复数数组找最大幅值对应的索引 uint16_t max_index = 0; float max_mag = 0.0f; // 只遍历前半段有效频率(跳过DC分量,从索引1开始) uint16_t half_len = fft_len / 2; for (uint16_t i = 1; i < half_len; i++) // 从1开始,跳过DC分量 { float real = fft_reference[i * 2]; float imag = fft_reference[i * 2 + 1]; float mag = real * real + imag * imag; if (mag > max_mag) { max_mag = mag; max_index = i; } } // 提取该频率点的实部和虚部 float target_real = fft_target[max_index * 2]; float target_imag = fft_target[max_index * 2 + 1]; float ref_real = fft_reference[max_index * 2]; float ref_imag = fft_reference[max_index * 2 + 1]; // 计算各自的相位角 float target_phase = atan2f(target_imag, target_real); float ref_phase = atan2f(ref_imag, ref_real); // 计算相位差 float phase_diff = target_phase - ref_phase; // 将相位差归一化到[-π, π]区间 if (phase_diff > PI) { phase_diff -= 2.0f * PI; } else if (phase_diff < -PI) { phase_diff += 2.0f * PI; } return phase_diff; } float FFT_GetMaxAmplitude(float *fft_result, uint16_t fft_len) { if (fft_result == NULL || fft_len < 2) return 0.0f; float max_amp = fft_result[0]; uint16_t half_fft_len = fft_len / 2; for (uint16_t i = 1; i < half_fft_len; i++) { if (fft_result[i] > max_amp) { max_amp = fft_result[i]; } } return max_amp; } //串口回调 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart == &huart2) // 确保处理的是UART2 { // 检查是否接收到"OK" if (Size == 2 && readBuffer[0] == 'O' && readBuffer[1] == 'K') { //UART_Printf("Received OK command!\r\n"); mpde_flag ++; } // 处理"ST"命令 - 重新开始 else if (Size >= 2 && readBuffer[0] == 'S' && readBuffer[1] == 'T') { //UART_Printf("Restarting...\r\n"); mpde_flag ++; result_flag = 1; } continue_flag = 1; //执行一次采集 // 重新启动DMA接收 HAL_UARTEx_ReceiveToIdle_DMA(&huart2, readBuffer, sizeof(readBuffer)); __HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT); } } // // AIj接口处理函数 void fill_buffer(float input_user_buffer[]){ // A - B input_user_buffer[0] = phase_ch1.phase_diff * 180.0f / PI; input_user_buffer[1] = phase_ch3.phase_diff * 180.0f / PI; return; } /* 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 */ 不改代码可以提取不同频率的信号相位差吗
11-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值