简介该资源面向嵌入式初学者与温度采集开发者围绕STM32F103C8T6驱动PT100热电阻测温并串口上传计算机这一典型场景提供可直接参考的工程实现。包内共253个文件以40个h头文件、38个c源文件为核心配合37个d依赖文件、37个o目标文件及36个crf交叉引用文件另有uvprojx工程文件、hex烧录文件、map映射表与pdf说明文档压缩包约7.42MB完整保留了Keil工程编译与调试痕迹。内容覆盖ADC通道配置与采样时间设定、连续转换与DMA/中断读取方式、USART波特率与帧格式设置以及上位机接收解析思路便于读者理解从电阻微小变化到数字温度值的信号链路。已有1214人学习下载适合作为STM32外设综合练习与PT100测温方案的起步参考。1. 拿到一个只有压缩包的 PT100 采集工程先看它能干什么前阵子帮人调一块板子对方甩过来一个压缩包名字就叫STM32f103PT100.zip里面没有 README没有原理图连工程说明都没有。打开一看是 STM32F103C8T6 配 PT100 热电阻做温度采集的完整工程。这种“裸包”在项目一线太常见了——上一任工程师走了代码留下你得从main.c一行行倒推它到底怎么接的线、怎么算的温度。这个工程解决的是一个很具体的问题用最便宜的一颗 F103C8T6把 PT100 的微弱电阻变化变成可读的温度值并且能通过串口把数据吐出来。适合谁适合手上正好有 PT100 探头、想快速搭一个温度采集节点的人也适合拿它当 STM32 模拟前端ADC 运放调理入门案例的开发者。它不复杂但把“传感器—调理—采样—换算—输出”这条链路走完整了这一点比很多只点个灯的例程有价值。2. 工程结构与技术选型一颗 F103C8T6 怎么把 PT100 读出来2.1 目录骨架与文件职责解压后典型的目录结构大致是这样不同人打包习惯略有差异但核心文件跑不掉STM32f103PT100/ ├── CORE/ # 内核启动文件、core_cm3.h ├── HARDWARE/ │ ├── ADC/ # ADC 初始化与采样 │ ├── PT100/ # 温度换算核心逻辑 │ ├── USART/ # 串口输出 │ └── TIM/ # 定时采样节拍 ├── STM32F10x_FWLib/ # 标准外设库 ├── USER/ │ ├── main.c │ ├── stm32f10x_it.c │ └── system_stm32f10x.c └── OBJ/ # 编译输出看到STM32F10x_FWLib就知道这是标准外设库SPL工程不是 HAL。SPL 的好处是寄存器级操作看得清楚坏处是新建工程麻烦但既然包已经给全了直接编译就行。HARDWARE/PT100这个目录是整个项目的灵魂温度换算全在里面其他都是伺候它的。2.2 硬件链路PT100 为什么不能直接接 ADC这是新手最容易翻车的地方。PT100 在 0℃ 时是 100Ω温度每升 1℃ 电阻大约增加 0.385Ω100℃ 时约 138.5Ω。这个电阻变化量很小而且 F103 的 ADC 测的是电压不是电阻。所以中间必须有一个调理电路常见做法是恒流源激励 差分放大或者电桥 仪表放大器。工程里对应的采样链路一般是PT100 串在一个精密恒流源回路里两端电压送进运放做差分放大再进 F103 的 ADC 通道常见是 PA0/ADC1_IN0。代码里你看到的Get_Adc()拿到的就是这个放大后的电压对应的数字量。理解这一点后面看换算代码才不会懵——代码算的不是电阻是电压再反推电阻再查表或套公式得温度。提示如果你手上的板子和工程原作者用的调理电路不一样比如恒流源电流不同、放大倍数不同换算结果一定偏先确认硬件再调参数。2.3 采样与滤波ADC 读一次不能用F103 的 ADC 是 12 位参考电压一般 3.3V理论分辨率 3.3/4096 ≈ 0.8mV。但实际读数会抖尤其是 PT100 这种小信号放大后的通道。工程里通常的做法是多次采样取平均代码长这样// 连续采样 N 次取平均抑制随机噪声 u16 Get_Adc_Average(u8 ch, u8 times) { u32 temp_val 0; u8 t; for(t 0; t times; t) { temp_val Get_Adc(ch); // 单次采样内部含通道切换与转换等待 delay_ms(5); // 间隔一点时间避开同频干扰 } return temp_val / times; }ch是 ADC 通道号times是平均次数一般取 1020。delay_ms(5)不是随便加的采样间隔太密相邻两次读到的是同一个干扰相位平均了等于没平均。这个函数返回的是原始数字量后面还要转电压、转电阻。参数上唯一要动的是times信号越脏加得越大但别超过 50否则采样周期拖太长温度响应变慢。2.4 温度换算查表还是公式HARDWARE/PT100里的核心是一个换算函数。PT100 的电阻-温度关系在 -200℃0℃ 和 0℃850℃ 是两段不同的多项式工程里为了省事常见两种实现一是分段线性查表二是直接套 Callendar-Van Dusen 公式的简化版。查表法代码大概是这样// 电阻值(单位:0.01欧)映射到温度(单位:0.1度)表按需截取常用区间 const s16 PT100_Table[][2] { {10000, 0}, // 100.00Ω - 0.0℃ {10385, 100}, // 103.85Ω - 10.0℃ {10770, 200}, // ... 中间按 0.385Ω/℃ 递增 }; s16 PT100_Get_Temp(u32 res_001ohm) { u8 i; for(i 0; i TABLE_SIZE - 1; i) { if(res_001ohm PT100_Table[i][0] res_001ohm PT100_Table[i1][0]) { // 线性插值避免表太密占 Flash s32 dt PT100_Table[i1][1] - PT100_Table[i][1]; s32 dr PT100_Table[i1][0] - PT100_Table[i][0]; return PT100_Table[i][1] (res_001ohm - PT100_Table[i][0]) * dt / dr; } } return -999; // 越界标志 }res_001ohm是以 0.01Ω 为单位的电阻值这样整数运算就能保住精度不用浮点。表项间隔 10℃ 左右中间靠线性插值补误差能压到 0.1℃ 以内对大多数场景够用。如果你要更准把表加密到 1℃ 一档或者改用公式法。这里的关键参数是电阻单位——一旦你上游算电阻时单位搞错比如用了 0.1Ω整个温度就全错这是排查时第一个要看的地方。3. 从零跑起来编译、烧录、看串口数据3.1 用 Keil 打开并确认目标芯片工程一般带.uvprojx文件双击用 Keil MDK 打开。第一件事不是点编译是进Options for Target确认 Device 选的是STM32F103C8因为 F103 系列型号多选错了 Flash/RAM 大小对不上链接会报错。然后在Debug页选你的下载器ST-Link 或 J-LinkUtilities里勾上Use Debug Driver并进Settings确认能识别到芯片 ID。时钟配置在system_stm32f10x.c里C8T6 外部晶振一般是 8MHzPLL 倍频到 72MHz。如果你板子上没焊外部晶振得改成内部 HSI否则程序卡在SetSysClockTo72()里出不来。这个坑很隐蔽现象是程序下载成功但不跑串口没输出。3.2 编译与烧录的具体命令路径Keil 里直接F7编译F8下载。如果你习惯命令行也可以用UV4.exe -b project.uvprojx -o build.log做批量编译CI 里常用。烧录完成后复位程序开始跑。判断有没有跑起来最快的办法是看串口——工程里USART模块一般初始化在 115200 或 9600具体看USART_Init里的bound参数。// 串口初始化片段波特率按实际改 USART_InitStructure.USART_BaudRate 115200; 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_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure);接线是 PA9 接 USB 转串口的 RXPA10 接 TX共地。打开串口助手波特率对上应该能看到周期性打印的温度值。如果全是乱码九成是波特率不对或者晶振没起振导致主频偏了。3.3 验证数据是否可信跑通不等于跑对。拿一杯冰水混合物0℃和沸水注意海拔影响约 100℃做两点校验看串口输出是否落在合理区间。如果 0℃ 时读数偏了五六度先别改代码去量调理电路输出的电压用万用表对着算一遍确认是硬件偏置还是换算公式偏。这一步能省掉大量瞎调参数的时间。注意PT100 引线有电阻两线制接法会把线阻算进温度里长线时误差明显。工程如果按两线制写的短距离用没问题长距离要换三线或四线制代码里的电阻补偿也得跟着改。4. 核心代码拆解一次采样到温度输出的完整链路4.1 main 函数里的主循环节奏main.c的结构很朴素初始化时钟、延时、串口、ADC、定时器然后进while(1)。主循环里一般靠定时器标志位控制采样节奏而不是死等延时这样串口打印和采样互不阻塞。int main(void) { u16 adc_val; u32 res_val; s16 temp; delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200); Adc_Init(); TIM3_Int_Init(4999, 7199); // 72MHz/(71991)/(49991) 2Hz while(1) { if(TIM3_FLAG) // 定时器置位500ms 一次 { TIM3_FLAG 0; adc_val Get_Adc_Average(ADC_Channel_0, 10); res_val Adc_To_Res(adc_val); // 数字量 - 电阻(0.01Ω) temp PT100_Get_Temp(res_val); printf(T%d.%d C\r\n, temp/10, temp%10); } } }TIM3_Int_Init(4999, 7199)这两个参数决定采样频率前者是自动重装值后者是预分频。算下来 2Hz对温度这种慢变量足够。Adc_To_Res是硬件相关的换算把数字量按“参考电压—放大倍数—恒流源电流”反推成电阻这个函数里的常数必须和你的实际电路一致改硬件就得改它。4.2 数字量到电阻的换算细节这一步是整条链路里最容易出错的地方因为它把模拟电路的参数硬编码进了代码。典型实现// 假设: Vref3.3V, 12位ADC, 放大倍数G10, 恒流I1mA // V_adc adc_val * 3.3 / 4096 // V_pt100 V_adc / G // R_pt100 V_pt100 / I u32 Adc_To_Res(u16 adc_val) { float v_adc adc_val * 3.3f / 4096.0f; float v_pt v_adc / 10.0f; float r v_pt / 0.001f; // 单位 Ω return (u32)(r * 100); // 转成 0.01Ω }3.3f是参考电压10.0f是运放增益0.001f是恒流源电流1mA。这三个数只要有一个和实际电路对不上温度就系统性偏移。我一般会把它们提成宏定义放文件头改硬件时只动一处。另外这里用了浮点F103C8T6 没有 FPU浮点运算是软件模拟慢但在这个 2Hz 的节奏下完全无所谓不用为了省这点时间改成定点可读性更重要。4.3 串口输出与数据格式printf重定向到串口是 SPL 工程的标准操作在usart.c里重写fputcint fputc(int ch, FILE *f) { while(USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET); USART_SendData(USART1, (u8)ch); return ch; }输出格式T%d.%d C把 0.1℃ 单位的整数拆成整数位和小数位打印避免浮点 printf 占空间。如果你要把数据送上位机做曲线建议改成 CSV 格式temp,raw_adc\r\n把原始值也带上方便回头分析是传感器问题还是换算问题。5. 避坑与排查调 PT100 采集时最常撞上的五件事5.1 串口有输出但温度恒定不变现象串口一直打印同一个值晃动探头也不变。原因多半是 ADC 通道配错或者Get_Adc里没做通道切换读的一直是内部参考通道。解决确认ADC_Channel_x和实际接线一致单次转换前调用ADC_RegularChannelConfig重新指定通道别指望初始化时设一次就一劳永逸。5.2 温度整体偏移一个固定值现象冰水显示 5℃沸水显示 105℃斜率对但截距错。原因通常是恒流源电流或运放增益和代码里的常数不符也可能是两线制引线电阻被算进去了。解决先用万用表实测调理电路输出电压反推实际增益和电流改Adc_To_Res里的常数长线场景加线阻补偿。5.3 读数跳动大平均了也没用现象温度值上下跳 23℃。原因可能是采样间隔太短导致平均无效或者 ADC 参考电压不稳直接用 VDDA 且电源脏。解决加大delay_ms间隔参考电压改用外部基准如 TL431模拟地和数字地单点连接探头线用屏蔽线。5.4 程序下载成功但不运行现象Keil 提示下载完成但串口无输出复位也没用。原因常见是外部晶振没起振却配置了 PLL程序卡在时钟初始化。解决确认板上有 8MHz 晶振和匹配电容或者把system_stm32f10x.c改成 HSI 内部时钟启动先跑起来再排查晶振。5.5 换一块板子数据全乱现象同一份代码A 板正常B 板温度离谱。原因两块板的调理电路参数不同增益、电流、甚至 PT100 接法而代码里常数是写死的。解决把硬件相关常数集中成配置宏每块板子编译前改一遍别指望一份 hex 通吃所有硬件。6. 二次开发把这份工程改成你自己的温度节点拿到这种工程最忌讳的是直接在main.c里堆功能。我的习惯是先做一件事把硬件相关常数全部抽到一个board_config.h里包括参考电压、运放增益、恒流源电流、PT100 接法两线/三线、ADC 通道号。这样换硬件只改一个文件代码逻辑一行不动。// board_config.h —— 换板子只改这里 #define VREF_VOLT 3.3f #define OPAMP_GAIN 10.0f #define EXCIT_CURRENT_A 0.001f #define PT100_WIRE_MODE 2 // 2 或 3 #define PT100_ADC_CH ADC_Channel_0改造方向上几个比较实用的点一是把温度换算从查表换成 Callendar-Van Dusen 公式精度更高且不用维护大表代价是浮点运算多一点2Hz 采样完全扛得住二是加一个滑动平均或一阶低通滤波替代简单的多次平均对缓变温度更友好三是把串口输出改成 Modbus RTU 从机这样能直接接 PLC 或组态软件工程价值立刻上一个台阶。验证方法上我一般会做三步先用信号源或精密电阻箱替代 PT100输入 100.00Ω、138.51Ω 两个标准点看输出是否对应 0℃ 和 100℃再上真实探头做冰水和沸水两点校验最后连续跑两小时看漂移。这三步走完数据基本可信。血泪经验是别在没确认硬件参数的情况下调换算代码。我见过太多人对着公式改半天最后发现是运放增益焊错了电阻。从那以后我每次接手这种裸包工程都强制先用万用表把调理电路的输入输出量一遍把实测参数写进配置头文件再动一行代码。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?