STM32F103C8T6标准库与寄存器编程实战指南

news2026/3/14 18:09:12
1. 从零开始认识你的STM32F103C8T6最小系统板如果你刚拿到一块STM32F103C8T6最小系统板看着上面密密麻麻的引脚和芯片可能会有点不知所措。别担心这其实是一块功能强大但入门友好的“蓝色小板子”江湖人称“Blue Pill”。它核心是一颗ARM Cortex-M3内核的32位微控制器主频高达72MHz拥有64KB的Flash和20KB的RAM对于学习嵌入式开发来说资源完全够用。这块板子之所以成为经典入门神器原因有几个首先是价格极其亲民一杯奶茶钱就能搞定其次是社区资源异常丰富无论遇到什么问题基本都能在网上找到答案最后是它的外设足够典型GPIO、定时器、ADC、USART、I2C、SPI等常用功能一应俱全学会了它再上手其他STM32系列甚至其他ARM芯片都会轻松很多。我们学习它通常有两条路径寄存器编程和标准库StdPeriph_Lib编程。这就好比学开车寄存器编程就像让你直接操作离合器、油门和方向盘连杆每一个动作都对应着底层硬件的直接控制你能深刻理解汽车是如何跑起来的但刚开始会手忙脚乱。而标准库编程则像给你一辆自动挡汽车你只需要挂D挡、踩油门库函数已经帮你封装好了换挡等复杂操作让你能快速上路专注于目的地。本指南将带你双线并进通过最基础的“点灯”实验让你亲手体验这两种编程方式的异同理解硬件是如何被我们“驯服”的。无论你未来是想深耕底层驱动还是快速进行应用开发这个基础都至关重要。2. 搭建你的第一个工程寄存器与库函数点灯对比2.1 工程创建与文件结构动手之前我们需要一个“工地”也就是工程。使用Keil MDK现在也叫Keil Studio是常见选择。新建一个工程选择芯片型号为STM32F103C8。之后我们需要为工程添加必要的“建筑材料”。核心启动文件在STM32标准库包中例如STM32F10x_StdPeriph_Lib_V3.5.0找到Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm目录。这里有一堆以.s结尾的汇编启动文件对于我们的C8T6属于中等容量产品选择startup_stm32f10x_md.s文件复制到你的工程文件夹例如Startup并添加到工程。这个文件包含了芯片上电后最先执行的代码负责设置堆栈、初始化中断向量表最后跳转到我们的main函数。关键头文件与系统文件同样在上述库包的Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x目录下找到stm32f10x.h、system_stm32f10x.c和system_stm32f10x.h。stm32f10x.h是芯片的“户口本”定义了所有寄存器的地址和结构两个system文件则包含了系统时钟比如设置到72MHz的配置函数。把它们也放进Startup文件夹并添加。用户代码区在工程目录下新建一个User文件夹在里面创建我们的主战场main.c。现在一个最精简的工程骨架就搭好了。别忘了在Keil的“Options for Target” - “C/C” - “Include Paths”里把Startup和User文件夹的路径添加进去这样编译器才知道去哪找头文件。2.2 寄存器版本点灯直接与硬件对话假设我们板子上的LED连接在GPIOC的第13引脚PC13且低电平点亮。用寄存器方式点灯我们需要翻阅《STM32F10x参考手册》找到控制相关硬件的三个关键寄存器地址并进行操作。第一步打开GPIOC的时钟。STM32的任何外设在使用前都必须先给它供电使能时钟。GPIOC挂载在APB2总线上。在参考手册的“复位和时钟控制RCC”章节找到RCC_APB2ENR寄存器。它的第4位IOPCEN控制GPIOC时钟。我们需要将这一位置1。// 使能GPIOC时钟将RCC_APB2ENR寄存器的第4位置1 *(unsigned int *)0x40021018 | (1 4);这行代码的意思是找到地址0x40021018RCC_APB2ENR的地址取出其中的值与(14)即二进制0001 0000进行或操作结果写回原地址。这样就只改变了第4位不影响其他位。第二步配置PC13为输出模式。在“通用和复用功能I/O”章节找到GPIOC_CRH寄存器因为PC8-PC15由CRH控制。每个引脚由4个位控制CNFy[1:0]和MODEy[1:0]。我们要将PC13配置为通用推挽输出最大速度50MHz。查表可知CNF13应为00MODE13应为11。// 配置PC13为推挽输出速度50MHz // 即GPIOC_CRH寄存器的[23:20]位应为 0011 *(unsigned int *)0x40011004 ~(0xF 20); // 先清零 *(unsigned int *)0x40011004 | (0x3 20); // 再设置为0011 (0x3)第三步控制PC13输出低电平。找到GPIOC_ODR寄存器端口输出数据寄存器。它的第13位ODR13控制PC13的输出电平。置0输出低电平点亮LED。// 设置PC13输出低电平点亮LED *(unsigned int *)0x4001100C ~(1 13);把这三步代码放到main.c的while(1)循环前编译下载LED就应该常亮了。寄存器编程代码非常简洁但你需要熟记或查阅大量寄存器地址和位定义且直接操作寄存器容易影响同一端口其他引脚的配置比如我们清零CRH时如果不小心把其他引脚配置也清了。通常更安全的做法是使用“读-改-写”操作寄存器 ~(掩码); 寄存器 | 新值;。2.3 标准库版本点灯站在巨人的肩膀上标准库将底层寄存器操作封装成了一个个直观的函数让我们编程时更关注功能而非地址。首先我们需要把库文件加入工程。添加库文件将库包中Libraries\STM32F10x_StdPeriph_Driver\src和inc文件夹下的所有文件misc.c/h是内核相关其他是外设驱动复制到工程Libraries文件夹并添加。同时将库包Project\STM32F10x_StdPeriph_Template下的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h复制到User文件夹并添加。最后在Keil的魔术棒 - C/C - Define 中添加USE_STDPERIPH_DRIVER宏定义这样stm32f10x.h才会去包含stm32f10x_conf.h和我们添加的库头文件。库函数点灯三步曲使能时钟不用再查地址直接调用函数。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);配置GPIO使用结构体来设置参数非常清晰。GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOC, GPIO_InitStructure);控制输出函数名一目了然。GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 置低点亮LED // GPIO_SetBits(GPIOC, GPIO_Pin_13); // 置高熄灭LED对比之下库函数版本代码更长但可读性和可维护性大大提升。你不需要记住0x4001100C是什么只需要知道你想操作GPIOC的Pin_13。库函数内部其实也是帮我们完成了那些寄存器操作例如GPIO_ResetBits最终可能就是操作ODR寄存器。第一个坑与解决如果你在C99标准之前编译可能会遇到“变量声明不能在可执行语句后”的错误。这是因为旧C标准要求变量定义在作用域开头。解决方法是在Keil魔术棒 - C/C 中勾选C99 Mode。3. 深入GPIO八种模式与工作原理点亮LED只是GPIO最基本的功能——输出。STM32的GPIO功能强大共有8种工作模式可以分为两大类输入和输出每类又细分为4种。4种输入模式浮空输入 (GPIO_Mode_IN_FLOATING)引脚完全悬空电平完全由外部电路决定。常用于通信总线如I2C、USART的数据接收脚或者按键检测需外部上/下拉电阻。上拉输入 (GPIO_Mode_IPU)芯片内部通过一个电阻连接到VDD。当外部无信号时引脚被拉至高电平。适合连接默认需要高电平的器件或者按键另一端接地的情况。下拉输入 (GPIO_Mode_IPD)芯片内部通过一个电阻连接到GND。当外部无信号时引脚被拉至低电平。模拟输入 (GPIO_Mode_AIN)信号直接进入ADC模块不经过施密特触发器。用于采集模拟电压信号。4种输出模式开漏输出 (GPIO_Mode_Out_OD)只能输出强低电平高电平靠外部上拉电阻实现。优点是允许“线与”即多个开漏输出接在一起只要有一个输出低总线就是低。常用于I2C等总线。推挽输出 (GPIO_Mode_Out_PP)可以输出强高电平和强低电平驱动能力强。是最常用的输出模式驱动LED、继电器等。复用开漏输出 (GPIO_Mode_AF_OD)输出信号由片上外设如I2C的SDA控制硬件结构与开漏输出相同。复用推挽输出 (GPIO_Mode_AF_PP)输出信号由片上外设如USART的TX控制硬件结构与推挽输出相同。GPIO内部结构浅析 你可以把每个GPIO引脚想象成一个带有多路开关的复杂电路。以推挽输出为例当我们写ODR寄存器时数据经过一个“输出控制电路”这个电路会根据配置同时控制一个PMOS管接VDD和一个NMOS管接GND。输出高电平时PMOS导通NMOS截止引脚连接到VDD输出低电平时PMOS截止NMOS导通引脚连接到GND。这就实现了强驱动。对于输入信号会先经过一个施密特触发器进行整形将缓慢变化的模拟信号整形成干净的数字信号再存入IDR寄存器供CPU读取。模拟输入模式则 bypass 了这个触发器。理解这些模式是正确配置GPIO的关键。例如驱动一个需要5V信号的模块但STM32是3.3V系统这时就可以用开漏输出模式在引脚外部接一个上拉电阻到5V这样高电平就是5V低电平是0V实现了电平转换。4. 按键检测与状态机思维控制LED输出后我们自然想通过输入来控制它最常见的就是按键。按键检测看似简单但要做好却涉及消抖和检测模式两个关键点。4.1 硬件连接与GPIO配置通常按键一端接地另一端接GPIO引脚。我们配置该引脚为上拉输入模式 (GPIO_Mode_IPU)。这样按键未按下时引脚被内部电阻拉高读到的IDR寄存器值为1按键按下时引脚被接地读到的值为0。// 初始化按键引脚假设接在PB0 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; // 输入模式下速度配置影响不大 GPIO_Init(GPIOB, GPIO_InitStructure);4.2 软件消抖与检测模式机械按键在闭合和断开的瞬间会产生一段时间的抖动约5-10ms导致电平快速变化。如果不处理一次按键可能会被误判为多次。最简单的消抖方法是检测到按键状态变化后延时10-20ms再读一次如果状态稳定则确认。更关键的是按键检测模式这体现了状态机思维支持连续触发模式只要按键处于按下状态每次调用检测函数都返回“已按下”。适用于需要快速连续响应的场景比如调整数值。uint8_t KEY_Scan(void) { if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) 0) { // 按下为0 Delay_ms(10); // 消抖 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) 0) { return 1; // 确认按下 } } return 0; // 未按下 }不支持连续触发模式一次按下到松开只返回一次“已按下”。适用于菜单选择、开关切换等场景。这里需要用一个static变量记录上一次的状态。uint8_t KEY_Scan(void) { static uint8_t key_up 1; // 静态变量记录按键未按下 if (key_up (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) 0)) { Delay_ms(10); if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) 0) { key_up 0; // 标记已按下 return 1; } } else if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) 1) { key_up 1; // 按键已松开恢复状态 } return 0; }模式合一通过一个参数mode来决定工作模式灵活性更高。uint8_t KEY_Scan(uint8_t mode) { // mode1:连续触发; mode0:单次触发 static uint8_t key_up 1; if (mode 1) key_up 1; // 连续模式总是认为上次已松开 if (key_up (按键按下)) { Delay_ms(10); if (按键确认按下) { key_up 0; return 1; } } else if (按键松开) { key_up 1; } return 0; }在主循环中不断扫描按键根据返回值控制LED的亮灭或翻转你就完成了一个完整的输入输出交互系统。这种“扫描-消抖-状态判断”的思路是处理所有开关量输入的基础。5. 时钟树STM32的脉搏与节能艺术为什么STM32的时钟系统看起来那么复杂不像51单片机一个晶振走天下。这背后是性能与功耗的精密平衡。复杂时钟源的意义节能不是所有外设都需要72MHz全速运行。比如看门狗只需要40kHz的低速内部时钟(LSI)实时时钟(RTC)只需要32.768kHz的低速外部时钟(LSE)。让它们各取所需可以大幅降低整体功耗。精度与稳定内部RC振荡器(HSI)成本低但精度差外部晶振(HSE)精度高但成本高。高速时钟用于核心计算低速时钟用于低功耗计时物尽其用。灵活性通过PLL锁相环可以对时钟进行倍频让CPU跑在比外部晶振更高的频率上提升性能。剖析时钟树 你可以把STM32的时钟系统想象成一个大型的自来水厂配水管网系统。水源时钟源有内部高速RC(HSI, 8MHz)、外部高速晶振(HSE, 常8MHz)、内部低速RC(LSI, 40kHz)、外部低速晶振(LSE, 32.768kHz)以及PLL。总水厂系统时钟SYSCLK来自HSI、HSE或PLL三者之一。我们通常用8MHz的HSE经过PLL 9倍频得到72MHz的SYSCLK。主干管AHB总线SYSCLK直接供给AHB总线速度最快。AHB再分给内核、内存和DMA。支线管APB1/APB2总线AHB经过分频器预分频器降速后供给APB1和APB2总线。APB2连接高速外设如GPIOA-G、USART1、SPI1等APB1连接低速外设如USART2/3、I2C1/2、SPI2等。在标准库的system_stm32f10x.c的SystemInit()函数里默认设置AHB不分频(72MHz)APB1 2分频(36MHz)APB2 1分频(72MHz)。特殊供水定时器时钟APB1上的定时器TIM2-TIM7如果分频系数不是1它的时钟会在APB1时钟基础上再×2。所以虽然APB1是36MHz但定时器时钟仍是72MHz。关键配置寄存器RCC_CR使能/关闭各时钟源查看时钟就绪标志。RCC_CFGR配置系统时钟源、AHB/APB分频、PLL倍频系数等。RCC_APB2ENR/RCC_APB1ENR这就是我们点灯时用到的“外设时钟使能寄存器”。想用哪个外设必须先在这里打开它的时钟开关。理解时钟树你就能明白为什么使用任何外设前都要先使能它的时钟打开水龙头也能在后续需要低功耗设计时灵活地关闭不必要的时钟源以省电。6. 精准延时SysTick系统滴答定时器Delay_ms(500)这样的延时函数我们一直在用它是怎么实现的简单的for循环延时极不准确且占用CPU。STM32内核提供了一个专用于延时的外设——SysTick系统滴答定时器。SysTick是一个24位的递减计数器它捆绑在NVIC中可以产生中断异常号15。它的时钟源可以选为内核时钟AHB时钟72MHz或AHB时钟的8分频9MHz。我们通常选择内核时钟这样延时最精确。用SysTick实现毫秒延时初始化配置重装载值启动计数器并开启中断。// SystemCoreClock 是系统核心时钟频率通常为72000000 (72MHz) // 72000000 / 1000 72000即计数器每减72000次耗时1ms if (SysTick_Config(SystemCoreClock / 1000)) { while (1); // 初始化失败死循环 }SysTick_Config()这个库函数帮我们设置了重装载值(LOAD)清空了当前值(VAL)选择了时钟源并开启了中断。中断服务函数SysTick中断函数名是固定的void SysTick_Handler(void)。我们在其中对一个全局变量进行递减。volatile uint32_t TimingDelay; // volatile防止编译器优化 void SysTick_Handler(void) { if (TimingDelay ! 0) { TimingDelay--; } }延时函数在需要延时的地方给全局变量赋值然后等待它被中断函数减到0。void Delay_ms(uint32_t nTime) { TimingDelay nTime; while(TimingDelay ! 0); }这样一个不阻塞CPU虽然while循环占用了CPU但计数器是由硬件独立递减的while只是查询标志、精度高的延时函数就完成了。基于它你可以轻松实现微秒延时、软件定时器等更复杂的功能。SysTick还是RTOS实时操作系统的心跳时钟其重要性不言而喻。7. 串口通信连接单片机与世界的桥梁串口(USART)是单片机调试和通信中最常用的外设。它允许STM32与电脑、另一个单片机或各种模块如GPS、蓝牙交换数据。7.1 串口硬件与协议基础物理上只需要两根线TX发送和RX接收交叉连接。注意电平标准STM32是3.3V TTL电平如果连接电脑的RS232接口±12V需要电平转换芯片如MAX232。协议上每个字节的数据被打包成一个“帧”包含起始位1位低电平标志帧开始。数据位通常8位低位先行。校验位可选用于检错奇校验或偶校验。停止位1位或1.5、2位高电平标志帧结束。 通信双方必须约定相同的波特率每秒传输的比特数如9600、115200。7.2 标准库配置串口以USART1为例PA9为TXPA10为RX使能时钟GPIOA和USART1的时钟都在APB2上。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);配置GPIOPA9复用推挽输出PA10浮空输入或上拉输入。GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, GPIO_InitStructure);配置USART参数使用结构体设置波特率、数据位、停止位、校验位等。USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 9600; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_Mode USART_Mode_Tx | USART_Mode_Rx; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_Init(USART1, USART_InitStructure);使能串口USART_Cmd(USART1, ENABLE);7.3 发送与接收数据发送一个字节查询方式。void USART_SendByte(USART_TypeDef* USARTx, uint8_t Byte) { USART_SendData(USARTx, Byte); while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) RESET); // 等待发送完成 }USART_FLAG_TXE标志位表示发送数据寄存器空可以写入下一个数据。接收一个字节中断方式更高效。在初始化时开启接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);配置NVIC中断优先级。编写中断服务函数uint8_t USART_RX_BUF; // 接收缓冲区 void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { USART_RX_BUF USART_ReceiveData(USART1); // 读取数据 // ... 处理数据例如存入数组或置位标志位 USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除中断标志 } }USART_FLAG_RXNE标志位表示接收数据寄存器非空有数据可读。7.4 实现printf重定向为了方便调试我们常想用printf函数通过串口打印信息。需要重定向fputc函数// 在工程选项中勾选“Use MicroLIB” #include stdio.h int fputc(int ch, FILE *f) { USART_SendByte(USART1, (uint8_t)ch); return ch; }之后就可以在代码中直接使用printf(Value: %d\r\n, value);了。注意printf会显著增加代码体积在资源紧张时慎用。8. 外部中断与NVIC响应外部事件的利器轮询方式检测按键会占用CPU时间。使用外部中断(EXTI)可以让CPU在按键按下时才去处理大大提高效率。8.1 EXTI与NVIC配置步骤假设我们用PA0引脚接按键下降沿触发中断。使能时钟GPIOA和AFIO因为要配置EXTI线路映射的时钟。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);配置GPIO为上拉输入按键另一端接地。配置GPIO引脚与EXTI线路的映射PA0映射到EXTI0。GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);配置EXTI线路选择触发边沿使能。EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line EXTI_Line0; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; // 中断模式 EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; // 下降沿触发 EXTI_InitStructure.EXTI_LineCmd ENABLE; EXTI_Init(EXTI_InitStructure);配置NVIC嵌套向量中断控制器设置优先级使能中断通道。NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 先设置优先级分组整个系统一次 NVIC_InitStructure.NVIC_IRQChannel EXTI0_IRQn; // 中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; // 抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; // 响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure);优先级规则抢占优先级高的可以打断正在执行的抢占优先级低的中断。抢占优先级相同时响应优先级高的先执行。两者都相同时按硬件中断编号排序。编写中断服务函数函数名必须与启动文件中定义的一致如EXTI0_IRQHandler。void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) ! RESET) { // 你的中断处理代码例如点亮LED EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志位非常重要 } }8.2 外部中断的妙用编码器与唤醒外部中断不仅用于按键。结合定时器的编码器接口可以轻松读取旋转编码器的方向和步数。在低功耗模式下如停止模式外部中断是唤醒CPU的主要方式之一。例如配置一个引脚为外部中断当有上升沿信号时将芯片从低功耗停止模式唤醒继续执行程序这对于电池供电设备至关重要。通过以上八个部分的实战你已经掌握了STM32F103C8T6最核心的几种外设操作。寄存器编程让你洞悉本质标准库编程让你高效开发。理解时钟树和中断系统是你写出稳定、高效代码的基石。后续的定时器、ADC、DMA、I2C、SPI等外设其学习路径和思想都是相通的配置时钟、初始化外设、理解其工作模式查询/中断/DMA、编写数据处理逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2411933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…