基于STM32F103C8T6的光伏发电量检测系统设计与Proteus仿真 这次我们来看一个基于STM32F103C8T6的光伏板发电量检测系统设计。这个项目不是复杂的AI模型部署而是一个典型的嵌入式系统应用核心在于如何利用低成本、高性能的MCU实现对光伏板输出电压、电流的实时采集、计算功率与发电量并完成数据显示或上传。对于从事新能源监控、嵌入式开发或电子设计的工程师和学生来说这是一个非常实用的练手项目能完整走通从传感器选型、电路设计、代码编写到系统调试的全流程。项目的核心价值在于其完整性和可复现性。它基于经典的STM32F103C8T6“蓝桥杯”核心板硬件成本极低软件上则涵盖了ADC采样、定时器、串口通信、数据处理等关键模块。本文将带你从零开始梳理整个系统的设计思路、硬件连接、软件编程并重点讲解如何在Proteus中进行仿真验证让你无需实际硬件也能快速验证核心算法和逻辑。无论你是想学习STM32的ADC和定时器应用还是需要搭建一个简易的光伏发电监控原型这篇文章都能提供清晰的路径。1. 核心能力速览能力项说明核心控制器STM32F103C8T6 (ARM Cortex-M3, 72MHz, 64KB Flash, 20KB SRAM)检测对象光伏板太阳能电池板检测参数输出电压 (DC 0-XX V)、输出电流 (DC 0-XX A)、计算功率、累计发电量关键外设ADC (模数转换器) 用于电压/电流采样定时器用于周期采样与电量累计USART用于数据输出显示/通信可选OLED显示屏本地显示或通过串口发送至上位机/云平台开发环境Keil uVision / STM32CubeIDE仿真工具Proteus 8 Professional (用于电路与程序联合仿真)硬件门槛极低仅需STM32最小系统板、电压/电流传感器模块、少量阻容元件适合场景光伏发电系统教学实验、小型离网系统监控、嵌入式数据采集入门项目、课程设计/毕业设计2. 适用场景与使用边界这个设计主要适用于以下几类场景教学与学习对于电子、电气、自动化等相关专业的学生这是一个绝佳的综合性实践项目。它涵盖了模拟信号处理、MCU编程、传感器应用和系统集成等多个知识点。原型验证与课程设计在开发正式的光伏监控产品前可以用此方案快速搭建一个功能原型验证采样算法、通信协议和数据显示的可行性。小型离网系统监控适用于阳台光伏、小型户外照明系统等低功率场景用于实时了解发电状态进行简单的能量管理。数据采集入门对于刚接触STM32或嵌入式开发的工程师这是一个结构清晰、目标明确的入门项目能快速掌握ADC、定时器、串口等核心外设的使用。使用边界与注意事项非高精度计量设计通常采用分压电阻和霍尔电流传感器其精度受传感器本身、电阻温漂、ADC参考电压稳定性等因素限制适用于状态监控而非高精度电能计量。电压电流范围检测范围取决于前端传感器选型如电压分压比、电流传感器量程。设计时需根据目标光伏板的规格如最大开路电压、短路电流选择合适的传感器并留有一定裕量。安全第一光伏板在光照下会持续产生电压即使断开负载也可能存在危险电压。在实际接线、调试时必须遵守电气安全规范做好绝缘和防触电措施。环境因素实际发电量受光照强度、温度、遮挡等因素影响巨大。本系统检测的是“瞬时”电气参数如需进行发电效率分析与预测需要结合环境传感器和更复杂的算法。3. 环境准备与前置条件在开始动手之前你需要准备好软硬件环境。硬件准备实物开发主控板STM32F103C8T6最小系统板核心板。这是整个系统的大脑。电压检测模块通常采用电阻分压法。需要两个高精度电阻如1%精度构成分压电路将光伏板电压可能几十伏分压到STM32的ADC输入范围0-3.3V内。电流检测模块方案A采样电阻运放适用于小电流如几安培以内。在回路中串联一个毫欧级采样电阻用运放放大其两端压差。方案B霍尔电流传感器如ACS712、WCS1800等。这类模块隔离性好量程选择多5A, 20A, 30A等使用方便输出为模拟电压直接接ADC。电源为STM32最小系统板供电5V或3.3V。注意光伏板输出电压可能不稳定不建议直接用它给MCU供电最好使用独立的稳压电源或电池。显示/调试设备可选0.96寸OLED显示屏I2C/SPI接口或USB转TTL串口模块用于连接电脑上位机。连接线、面包板/洞洞板、万用表等。软件准备集成开发环境IDEKeil MDK-ARM (uVision5)经典选择需要安装STM32F1的Device Family Pack。STM32CubeIDEST官方免费IDE基于Eclipse集成STM32CubeMX图形化配置工具推荐新手使用。STM32CubeMX用于图形化配置引脚、时钟、外设ADC, TIM, USART等并生成初始化代码框架。即使使用Keil也强烈建议用CubeMX生成基础工程。串口调试助手如SSCOM、XCOM、Putty等用于接收STM32发送的发电量数据。Proteus 8 Professional用于电路仿真。你需要安装并拥有STM32F103C8T6、虚拟终端(VIRTUAL TERMINAL)、电压/电流探针、信号发生器模拟传感器输出等元件库。知识准备基础的C语言编程能力。对STM32的GPIO、ADC、定时器、中断、串口有基本了解。能看懂简单的电路原理图。4. 系统设计与硬件连接系统的核心设计思想是采集 - 计算 - 显示/上传。硬件连接框图光伏板输出正极 --- [电流传感器输入] --- [电流传感器输出-] --- 负载 | (电流信号) V [电流传感器信号输出] --- ADC1_IN0 (PA0) // 检测电流 | 光伏板输出正极 --- [电阻分压网络] --- ADC1_IN1 (PA1) // 检测电压 | V GND(注意电流传感器需串联在光伏板输出回路中电压检测是并联在光伏板输出两端。)STM32F103C8T6引脚分配示例使用CubeMX配置ADC1_IN0 (PA0)连接电流传感器模拟输出。ADC1_IN1 (PA1)连接电压分压网络输出。USART1_TX (PA9)连接USB转TTL模块的RX向上位机发送数据。USART1_RX (PA10)连接USB转TTL模块的TX可接收上位机指令可选。I2C1_SCL (PB6)/I2C1_SDA (PB7)连接OLED显示屏如果使用I2C接口。任意GPIO可连接LED作为系统运行指示灯。传感器信号调理这是保证测量准确的关键。假设使用ACS712-05A量程±5A输出灵敏度185mV/A。电流检测ACS712输出是VCC/2即2.5V为零点。电流I与输出电压V_out关系V_out 2.5V 0.185 * I。STM32的ADC需能测量2.5V附近的电压变化。电压检测假设光伏板最大电压为30V要分压到3.3V以内。选择R1100kΩ R210kΩ则分压比V_adc V_pv * R2/(R1R2) V_pv / 11。当V_pv30V时V_adc≈2.73V安全。在Proteus中仿真时可以用“DC VOLTMETER”和“DC AMMETER”显示真实值用“Signal Generator”模拟ACS712的输出电压一个2.5V左右的直流偏置加上一个小的交流分量模拟电流变化用“Resistor”和“Potentiometer”搭建分压电路。5. 软件编程与关键代码我们将使用STM32CubeMX生成工程骨架然后在Keil或CubeIDE中编写业务逻辑。5.1 使用STM32CubeMX配置工程选择MCUSTM32F103C8Tx。时钟配置在“Clock Configuration”标签页选择外部晶振HSE将系统时钟SYSCLK配置为72MHz。引脚配置在“Pinout Configuration”标签页找到“ADC1”。将“IN0”和“IN1”设置为“IN0”和“IN1”即启用PA0和PA1的ADC功能。找到“TIM2”或任意一个通用定时器将其模式设置为“Internal Clock”并配置预分频器PSC和自动重载值ARR以产生一个固定的中断频率例如1kHz1ms中断一次用于周期性启动ADC采样。找到“USART1”模式设置为“Asynchronous”配置波特率如115200。如果使用OLED找到“I2C1”模式设置为“I2C”。ADC配置在ADC1的“Parameter Settings”中设置“Resolution”为12位4096级。在“Scan Conversion Mode”选择“Enabled”因为我们要扫描两个通道。在“Continuous Conversion Mode”选择“Enabled”或“Disabled”。我们将在定时器中断中手动触发转换所以这里可以禁用连续转换。在“DMA Continuous Requests”选择“Disabled”简单应用可不用DMA。在“Rank”中添加两个通道Channel 0 (PA0) 和 Channel 1 (PA1)设置采样时间如“239.5 Cycles”以获得较好精度。生成代码选择你的IDEMDK-ARM或STM32CubeIDE设置工程名称和路径然后生成代码。5.2 关键业务逻辑代码在生成的工程中主要修改main.c和定时器中断回调函数。/* 在main.c文件用户变量区定义 */ float g_voltage_adc_raw 0; // 电压ADC原始值 float g_current_adc_raw 0; // 电流ADC原始值 float g_voltage_real 0; // 计算得到的真实电压 (V) float g_current_real 0; // 计算得到的真实电流 (A) float g_power 0; // 瞬时功率 (W) float g_energy_total 0; // 累计发电量 (Wh) uint32_t g_sample_count 0; // 采样计数用于定时计算和发送 /* 电压电流转换系数 (需根据实际传感器和电路校准!) */ #define VOLTAGE_DIVIDER_RATIO 11.0 // 分压比例如 R1R2/R2 #define CURRENT_SENSOR_SENSITIVITY 0.185 // V/A例如ACS712-05A为0.185 #define CURRENT_SENSOR_ZERO_VOLTAGE 2.5 // V例如ACS712零电流输出电压 #define ADC_REF_VOLTAGE 3.3 // STM32的ADC参考电压通常接3.3V /* 定时器中断回调函数 (例如在stm32f1xx_it.c或用户文件中) */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { // 判断是TIM2的中断 // 1. 启动ADC转换扫描两个通道 HAL_ADC_Start(hadc1); // 等待转换完成可以加超时判断 if (HAL_ADC_PollForConversion(hadc1, 10) HAL_OK) { // 读取通道0电流的值 g_current_adc_raw HAL_ADC_GetValue(hadc1); // 再次等待并读取通道1电压的值 if (HAL_ADC_PollForConversion(hadc1, 10) HAL_OK) { g_voltage_adc_raw HAL_ADC_GetValue(hadc1); } } HAL_ADC_Stop(hadc1); // 2. 将ADC原始值转换为实际物理量 // 公式物理量 (ADC原始值 / 4095) * ADC参考电压 * 转换系数 g_voltage_real (g_voltage_adc_raw / 4095.0) * ADC_REF_VOLTAGE * VOLTAGE_DIVIDER_RATIO; // 对于ACS712: 电流 (ADC电压 - 零点电压) / 灵敏度 float current_voltage (g_current_adc_raw / 4095.0) * ADC_REF_VOLTAGE; g_current_real (current_voltage - CURRENT_SENSOR_ZERO_VOLTAGE) / CURRENT_SENSOR_SENSITIVITY; // 确保电流不为负光伏板一般只输出正电流 if(g_current_real 0) g_current_real 0; // 3. 计算瞬时功率 g_power g_voltage_real * g_current_real; // 4. 累计发电量 (能量 功率 * 时间) // 假设定时器中断周期是T秒例如0.001s则每次中断产生的能量增量为 g_power * T (Ws) // 更常用的单位是Wh瓦时1 Wh 3600 Ws。 // 我们可以每N次采样例如1000次即1秒累加一次避免浮点运算过于频繁。 g_sample_count; if(g_sample_count 1000) { // 每秒计算一次 // 过去1秒内的平均功率近似为当前g_power或可做平均滤波 g_energy_total g_power / 3600.0; // 将1秒的功率累加到Wh单位 g_sample_count 0; // 5. 每秒通过串口发送一次数据或刷新OLED printf(V: %.2f V, I: %.3f A, P: %.2f W, E: %.3f Wh\r\n, g_voltage_real, g_current_real, g_power, g_energy_total); // 注意需要重定向printf到串口或直接使用HAL_UART_Transmit函数 } } }5.3 主函数初始化与循环int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM2_Init(); // 初始化定时器2 MX_USART1_UART_Init(); // MX_I2C1_Init(); // 如果使用OLED // 启动定时器开始产生中断 HAL_TIM_Base_Start_IT(htim2); // OLED初始化如果使用 // OLED_Init(); while (1) { // 主循环可以处理其他任务如按键扫描、显示刷新如果不用中断刷新 // 或者简单的延时 HAL_Delay(1000); } }6. Proteus仿真验证在没有实物硬件的情况下Proteus仿真可以极大帮助验证电路设计和程序逻辑。6.1 绘制仿真电路图打开Proteus新建工程。从库中放置以下元件STM32F103C8T6(在Microprocessor ICs - ARM - Cortex-M3系列下)RES(电阻)用于搭建电压分压电路。POT-HG(滑动变阻器)可以模拟光伏板输出电压的变化。DC VOLTMETER和DC AMMETER用于显示“真实”的电压电流值作为参考。Signal Generator用于模拟电流传感器如ACS712的输出电压。设置一个DC偏移如2.5V和一个小的Sine振幅如0.1V模拟0.5A左右的电流波动。VIRTUAL TERMINAL作为串口调试助手接收STM32发送的数据。按照前面“硬件连接框图”进行连线。将滑动变阻器两端接一个直流电压源如12V滑动端作为“光伏板正极”。将该点通过一个电阻模拟负载接地构成回路。在回路中串联一个DC AMMETER。用两个电阻对“光伏板正极”电压进行分压分压点接STM32的PA1。将Signal Generator的输出接STM32的PA0。将STM32的PA9 (USART1_TX) 接VIRTUAL TERMINAL的RXD。为STM32和虚拟终端提供电源和地。6.2 加载程序并运行仿真在STM32元件上右键选择“Edit Properties”。在“Program File”一栏选择你编译生成的.hex文件Keil生成在Objects文件夹CubeIDE生成在Debug或Release文件夹。在“Clock Frequency”一栏输入72MHz与程序配置一致。点击Proteus左下角的运行按钮。在弹出的虚拟终端窗口你应该能看到每秒打印一次的电压、电流、功率和累计电量数据。在仿真运行时你可以拖动滑动变阻器改变“光伏电压”或调整信号发生器的幅度改变“电流”观察虚拟终端输出的数据是否随之合理变化。同时对比DC VOLTMETER和DC AMMETER的示数可以验证你程序中的转换系数VOLTAGE_DIVIDER_RATIO和CURRENT_SENSOR_SENSITIVITY设置是否正确。仿真调试技巧如果虚拟终端没有输出检查STM32的USART配置波特率、接线TX-RXD以及程序中的printf重定向或UART发送函数是否正确。如果ADC值一直为0或固定值检查ADC引脚配置、采样时间是否太短以及仿真电路中信号是否确实加到了对应引脚。使用Proteus的“Debug”菜单下的“Watch Window”可以添加并监视STM32内部变量的值如g_voltage_adc_raw这对于调试非常有用。7. 功能测试与效果验证完成仿真和实物焊接后需要进行系统测试。7.1 静态校准测试电压校准使用可调稳压电源代替光伏板设置一个已知电压如10.0V用万用表测量分压点电压和STM32的ADC引脚电压。调整程序中的VOLTAGE_DIVIDER_RATIO使得程序计算出的g_voltage_real与万用表测量的电源电压一致。电流校准对于ACS712模块在不接电流时测量其输出引脚电压应为VCC/2如2.5V。将此值赋给程序中的CURRENT_SENSOR_ZERO_VOLTAGE。串联一个精密电阻负载和万用表让电源输出一个已知电流如1.0A。测量此时ACS712的输出电压V_out。根据公式灵敏度 (V_out - 零点电压) / 电流计算实际灵敏度更新程序中的CURRENT_SENSOR_SENSITIVITY。7.2 动态功能测试数据刷新测试系统上电后观察OLED屏幕或串口调试助手数据应每秒更新一次。电压变化响应改变光源强度或使用可调电源模拟观察检测到的电压值是否能快速、平稳地跟随变化。电流变化响应改变负载大小如并联/串联电阻观察电流和功率值的变化。电量累计测试让系统在稳定功率下运行一段时间如5分钟记录程序计算的累计电量E。用公式E_theory P * t其中P为平均功率t为时间小时数计算理论电量。两者应基本吻合误差应在传感器和ADC精度允许范围内。7.3 边界与异常测试超量程测试输入超过传感器量程的电压或电流需谨慎避免损坏观察程序处理是否限幅、报警。稳定性测试长时间运行如1小时观察数据是否有漂移累计电量是否持续稳定增加。通信压力测试连续通过串口发送数据观察是否会出现数据丢失或卡顿。8. 资源占用与性能观察对于STM32F103C8T6来说这个项目的资源占用非常宽松。CPU占用主要开销在1ms一次的定时器中断服务程序ISR中。ISR内完成了ADC启动、读取、转换计算和条件判断。这些操作在72MHz的主频下执行时间极短微秒级CPU利用率极低主循环几乎空闲。内存占用Flash包含HAL库、外设初始化代码和我们的业务逻辑通常不会超过30KB远小于64KB的容量。SRAM全局变量很少几乎可以忽略不计远小于20KB。外设资源使用了1个ADC的2个通道、1个通用定时器、1个USART。STM32F103C8T6有2个ADC、多个定时器和USART资源绰绰有余留有大量扩展空间如增加更多传感器、使用PWM控制负载等。功耗STM32本身功耗很低。系统主要功耗来自传感器模块如ACS712和显示模块OLED。在电池供电的应用中可以通过MCU的睡眠模式、定时唤醒采样来进一步降低功耗。性能优化提示如果采样率要求很高如10kHz使用查询方式HAL_ADC_PollForConversion在中断中处理可能来不及。此时应启用ADC的DMA直接存储器访问模式让ADC自动将转换结果存入内存数组定时器中断中只需读取数组中的值即可大大减少中断服务时间。对ADC采样值进行软件滤波如滑动平均滤波、中值滤波可以有效地抑制噪声使显示数据更稳定。9. 常见问题与排查方法问题现象可能原因排查方式解决方案上电无反应LED不亮1. 电源接反或电压不对。2. 复位电路问题。3. BOOT引脚配置错误。1. 检查电源电压3.3V/5V。2. 测量复位引脚电压。3. 检查BOOT0和BOOT1引脚是否已下拉。1. 确保电源正确。2. 确保复位按钮正常复位引脚在上电后为高电平。3. BOOT0接GNDBOOT1可悬空或接GND。程序已下载但串口无输出1. 串口线接错TX/RX反。2. 波特率不匹配。3. 程序未进入主循环或卡在初始化。1. 检查USB转TTL模块与STM32的TX/RX交叉连接。2. 确认代码和串口助手波特率一致。3. 在程序开始点点亮一个LED测试。1. 正确接线STM32_TX - USB模块_RX。2. 统一设置为常用波特率如115200。3. 使用调试器单步调试或添加LED指示灯代码。ADC采样值始终为0或固定值1. ADC引脚配置错误未设置为模拟输入。2. 外部输入电压超出范围或为0。3. ADC参考电压不正确。4. 采样时间太短。1. 检查CubeMX中引脚配置模式。2. 用万用表测量ADC引脚实际电压。3. 检查VDDA和VSSA是否连接正确。4. 在CubeMX中增加ADC采样周期。1. 在CubeMX中将引脚设为“Analog”。2. 确保传感器电路工作正常信号已接入。3. 确保VDDA接3.3VVSSA接GND。4. 将采样时间设置为最大或较长周期如239.5 Cycles。检测的电压/电流值不准1. 分压电阻比例计算错误或精度不够。2. 电流传感器零点或灵敏度参数错误。3. ADC参考电压不准内部参考或外部LDO精度。1. 用万用表实测分压点电压反推算比例。2. 按照“静态校准测试”步骤重新校准。3. 测量MCU的VREF引脚如果引出或供电电压。1. 使用高精度1%的金属膜电阻并实测阻值计算。2. 更新程序中的转换系数。3. 使用外部精密基准源或在程序中加入软件校准系数。Proteus仿真时程序不运行1..hex文件路径错误或未成功编译。2. STM32模型时钟频率设置错误。3. 仿真电路存在逻辑错误如电源未接。1. 确认.hex文件已生成且路径无中文。2. 检查元件属性中的“Clock Frequency”。3. 使用Proteus的电气规则检查ERC。1. 重新编译工程指定正确路径。2. 设置为与代码一致的频率如72M。3. 补充缺失的电源、地修正短路/断路。电量累计值增长过快或过慢1. 功率计算错误。2. 累计能量时的时间单位换算错误。3. 定时器中断周期设置错误。1. 打印出原始的电压、电流ADC值验证转换公式。2. 检查累计能量代码能量 功率 * (中断周期/3600)。3. 检查定时器预分频器PSC和自动重载值ARR配置。1. 校准电压电流。2. 确认时间单位功率(W) * 时间(h) 能量(Wh)。注意秒到小时的转换。3. 重新计算并配置定时器确保中断周期准确。10. 扩展方向与最佳实践这个基础框架可以很容易地进行扩展使其更实用、更智能。功能扩展建议数据存储加入EEPROM如AT24C02或Flash存储用于掉电保存累计发电量。无线传输接入ESP8266/ESP32 WiFi模块或NB-IoT模块将数据上传到云平台如阿里云、腾讯云实现远程监控。人机交互增加按键和菜单界面可以切换显示内容、设置参数、清零累计电量。最大功率点跟踪MPPT这是一个高级功能。通过实时调整一个DC-DC转换器如Boost电路的占空比使光伏板始终工作在最大功率输出点。这需要更快的采样和PWM控制算法。历史数据记录与显示在OLED上绘制简单的功率-时间曲线。报警功能当电压、电流异常过高、过低时通过LED或蜂鸣器报警。工程实践建议模块化编程将ADC采样与计算、电量累计、数据显示、数据通信等功能写成独立的.c/.h文件提高代码可读性和可维护性。参数可配置将电压分压比、电流传感器参数等校准系数存储在Flash的固定区域甚至通过串口命令在线修改便于生产校准。增加滤波算法在ADC采样后加入数字滤波如一阶低通滤波让显示数据更稳定避免跳动。做好注释与版本管理代码中关键部分添加注释使用Git等工具管理工程版本。安全与鲁棒性在代码中加入看门狗IWDG防止程序跑飞。对计算后的电压、电流值进行合理性判断如范围限制避免显示异常值。这个基于STM32F103C8T6的光伏发电量检测系统从核心板上电到数据稳定显示打通了整个链路。它麻雀虽小五脏俱全涵盖了嵌入式开发中硬件设计、传感器应用、外设驱动、数据处理和系统调试等多个关键环节。通过Proteus仿真你可以在几乎没有成本的情况下验证想法的可行性通过实物搭建和校准你能获得最直接的工程经验。建议你从仿真开始逐步过渡到实物并尝试上述的扩展功能把它打造成属于你自己的新能源监控小项目。