三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

基于51单片机的LC振荡法电感测量:原理、电路与代码实现

基于51单片机的LC振荡法电感测量:原理、电路与代码实现

在嵌入式开发中,我们常常需要测量电阻、电容等无源器件的值,但对于电感,很多初学者会觉得无从下手。网上关于使用51单片机测量电感的方案相对零散,要么电路复杂,要么代码晦涩。本文将分享一种基于51单片机的简易电感测量方法,其核心思想是利用LC振荡电路将电感值转换为频率进行测量。这种方法电路简单,成本低廉,非常适合电子爱好者、学生课程设计或对精度要求不高的应用场景。下面,我们将从原理到实践,完整拆解整个设计过程,并提供可直接复用的代码和电路连接图。

1. 背景与核心概念

在开始动手之前,我们首先要理解几个关键概念:什么是电感?为什么要测量它?以及我们采用的测量原理是什么。

电感是导线内通过电流时,其周围会产生磁场的特性。当电流变化时,磁场也会变化,这个变化的磁场又会产生感应电动势来阻碍电流的变化,这种特性就是电感,单位是亨利(H)。在电路中,电感常用于滤波、振荡、延迟等。

测量电感的挑战在于,它不像电阻可以用万用表直接测量。专业LCR电桥价格昂贵。因此,我们需要一种基于常见微控制器(如51单片机)的间接测量方法。

本文采用的原理是LC振荡法。其核心思想是:将一个待测电感(Lx)和一个已知容值的电容(C)组成一个LC并联或串联振荡回路。这个回路会产生一个固有的谐振频率。频率(f)与电感(L)、电容(C)满足公式:f = 1 / (2π√(LC))由此可知,在电容C固定的情况下,振荡频率f仅由电感L决定。L越大,频率f越低;L越小,频率f越高。因此,只要我们能用单片机测出这个LC回路的振荡频率,就能反推出电感值。

我们的任务就是:用51单片机生成一个激励信号,触发LC回路振荡,然后测量其振荡频率,最后通过计算得到电感值并显示出来。

2. 系统设计与核心组件

在搭建具体电路和编写代码前,我们需要规划好整个系统的框架。

2.1 系统整体框架

一个完整的简易电感测量系统通常包含以下部分:

  1. MCU控制核心:采用常见的STC89C52RC单片机,负责产生激励、测量频率、进行计算和控制显示。
  2. LC振荡电路:由待测电感Lx和标准电容C组成,是整个测量的传感器部分。
  3. 信号调理电路:因为LC回路产生的正弦波振荡信号幅度较小且非数字信号,需要经过放大和整形,转换为单片机可以识别的方波信号。
  4. 频率测量模块:利用单片机的定时器/计数器功能,对整形后的方波信号进行计数,从而得到频率。
  5. 人机交互界面:通常使用LCD1602液晶显示屏来显示测量出的电感值和单位,也可以使用数码管,但显示信息量较少。

2.2 关键组件选型说明

  • 单片机:STC89C52RC,工作电压5V,拥有3个定时器/计数器,完全满足需求。其IO口直接驱动能力较强,简化了电路。
  • 标准电容C:建议选用高精度、低温漂的CBB或NPO电容,例如102 (1000pF) 或 222 (2200pF)。电容的精度直接决定了最终测量的精度。本文示例采用1000pF (1nF)。
  • 信号调理电路:可以使用一个三极管(如S8050)构成共射极放大电路,配合施密特触发器(如74HC14)进行整形,也可以使用一个高速电压比较器(如LM311)实现放大和整形一体化。为了简化,后续电路将展示一种利用单片机IO口配合三极管的简易方法。
  • 显示模块:LCD1602,能够显示两行16个字符,可以清晰地显示“L=120.5uH”这样的信息。

3. 硬件电路设计

电路是测量的基础,一个稳定可靠的电路至关重要。

3.1 核心振荡与检测电路

下图展示了一种简化的LC振荡信号检测电路连接方式:

+5V | R1 (10kΩ) | P1.0 (MCU)---|<----| Lx (待测电感) | | | === C (标准电容,1nF) | | | | GND GND

工作过程(概念性描述)

  1. 单片机从P1.0引脚输出一个短暂的高电平脉冲。
  2. 这个脉冲通过电阻R1对LC回路(Lx和C并联)进行充电。
  3. 当脉冲结束后,P1.0变为高阻态或输入模式,LC回路开始自由振荡,在P1.0引脚上会产生一个衰减的正弦波电压信号。
  4. 这个正弦波信号通过一个由三极管或电压比较器构成的整形电路(图中未画出具体器件),转换为同频率的方波。
  5. 方波信号被连接到单片机的某个具有外部计数功能的引脚(如P3.4/T0)。

注意:上述是一个原理示意图。在实际制作中,需要在P1.0和LC回路之间增加隔离(如一个小电阻),并在检测点增加保护(如钳位二极管),防止高压损坏单片机。更稳健的做法是使用一个独立的比较器电路。

3.2 基于比较器的推荐电路

这里给出一个使用LM311电压比较器的推荐电路设计:

+5V | R2 (10kΩ) | +---| VCC LM311 |---+ +5V | | | | Output ----> P3.4/T0 (To MCU) | | | | +----|---| IN+ | | | | | | | | +---| GND | | | |___________| | | | | +5V | | | | | R3 (10kΩ) | | | | | +---| IN- | | | | P1.0 (MCU)---|<|----/\/\/----+ | (激励脉冲) R4 (1kΩ) | | | | Lx | | ~~~~~~~ | | | | | === C (1nF) | | | | GND GND GND

电路解释

  • 激励部分:单片机P1.0发出脉冲,通过R4注入LC回路。
  • 振荡信号:LC回路在P1.0脉冲结束后产生振荡,信号出现在LM311的同相输入端(IN+)。
  • 参考电压:由R2和R3分压,在LM311的反相输入端(IN-)建立一个约2.5V的参考电压。
  • 比较整形:LM311将振荡的正弦波与2.5V参考电压进行比较。当正弦波电压高于2.5V时,输出高电平;低于2.5V时,输出低电平。从而将正弦波转换为方波。
  • 输出:方波信号送入单片机的T0引脚(P3.4),用于频率计数。

3.3 单片机最小系统与显示连接

  • 单片机最小系统:包括STC89C52RC、复位电路(10uF电容+10k电阻)、晶振电路(12MHz晶振+两个30pF电容)。
  • LCD1602连接:采用8位数据线并口模式连接。
    • RS -> P2.0
    • RW -> P2.1 (接地,始终写操作)
    • E -> P2.2
    • D0-D7 -> P0.0-P0.7
    • VSS接地,VDD接5V,VEE接电位器中心抽头调节对比度。

4. 软件程序设计

软件是系统的灵魂,负责控制流程、测量频率和进行计算。

4.1 程序流程总览

  1. 初始化:配置定时器、计数器、LCD等。
  2. 主循环: a. 发出激励脉冲。 b. 启动定时器T1定时一个精确的闸门时间(如100ms)。 c. 在闸门时间内,启动计数器T0对来自LM311的方波进行计数。 d. 闸门时间到,停止计数,读取计数值N。 e. 计算频率f = N / 闸门时间。 f. 根据公式Lx = 1 / ( (2πf)^2 * C )计算电感值。 g. 将电感值转换为合适的单位(uH, mH)并显示在LCD上。 h. 延时一段时间,重复测量。

4.2 核心代码实现

4.2.1 头文件与引脚定义
#include <reg52.h> // 包含51单片机寄存器定义头文件 #include <intrins.h> // 包含_nop_()函数 #include <math.h> // 包含数学函数,如pow() // LCD1602引脚定义 sbit LCD_RS = P2^0; sbit LCD_RW = P2^1; // 通常接地,这里定义为引脚但程序中置低 sbit LCD_E = P2^2; #define LCD_Data P0 // 数据端口 // 激励脉冲输出引脚 sbit Pulse_Pin = P1^0; // 频率计数引脚(连接LM311输出) sbit Freq_In = P3^4; // T0引脚,用作计数器输入 // 常量定义 #define GATE_TIME_MS 100 // 闸门时间,单位毫秒 #define CRYSTAL_FREQ 12000000UL // 晶振频率 12MHz #define STANDARD_CAP 1e-9 // 标准电容值,1nF = 1e-9 F #define PI 3.141592653589793
4.2.2 LCD1602驱动函数

这部分是标准代码,用于初始化LCD和显示字符/字符串。

void LCD_Delay(unsigned int t) { while(t--); } void LCD_WriteCmd(unsigned char cmd) { /* 写命令代码 */ } void LCD_WriteData(unsigned char dat) { /* 写数据代码 */ } void LCD_Init(void) { /* 初始化LCD */ } void LCD_SetCursor(unsigned char x, unsigned char y) { /* 设置光标位置 */ } void LCD_ShowStr(unsigned char x, unsigned char y, unsigned char *str) { /* 显示字符串 */ } // 具体实现代码较长,此处省略,可参考任何51单片机LCD1602教程。
4.2.3 频率测量函数

这是最核心的函数,负责产生激励、开启定时闸门、计数并返回频率值。

// 产生一个短暂的激励脉冲 void Generate_Pulse(void) { Pulse_Pin = 1; _nop_(); _nop_(); _nop_(); _nop_(); // 短暂延时,约4us Pulse_Pin = 0; } // 测量频率,返回单位为Hz的频率值 unsigned long Measure_Frequency(void) { unsigned int count_high, count_low; unsigned long total_count; // 1. 产生激励脉冲,触发LC振荡 Generate_Pulse(); // 稍作延时,等待振荡稳定(根据实际电路调整) LCD_Delay(100); // 2. 配置T0为计数器模式,方式1(16位计数),对T0引脚(P3.4)下降沿计数 TMOD &= 0xF0; // 清除T0的模式位 TMOD |= 0x05; // 设置T0为模式1,计数器 TH0 = 0; // 计数器从0开始计数 TL0 = 0; TR0 = 1; // 启动T0计数器 // 3. 配置T1为定时器模式,方式1,用于产生精确的闸门时间 TMOD &= 0x0F; // 清除T1的模式位 TMOD |= 0x10; // 设置T1为模式1,定时器 // 计算100ms需要的定时器初值 (12MHz, 12T模式) // 机器周期 = 12 / 12MHz = 1us // 100ms = 100000us // 需要计数次数 = 65536 - 100000,但65536不够,需要中断配合 // 这里采用50ms中断一次,中断两次为100ms的方法 TH1 = (65536 - 50000) / 256; // 50ms初值高8位 TL1 = (65536 - 50000) % 256; // 50ms初值低8位 ET1 = 1; // 开启T1中断 EA = 1; // 开启总中断 TR1 = 1; // 启动T1定时器 // 4. 等待闸门时间到达(通过T1中断标志或软件查询) // 这里使用一个全局变量作为闸门时间到达标志 gate_time_flag = 0; while(gate_time_flag < 2); // 等待两次50ms中断,即100ms // 5. 闸门时间到,停止计数 TR0 = 0; TR1 = 0; ET1 = 0; // 6. 读取计数值 count_high = TH0; count_low = TL0; total_count = (count_high << 8) + count_low; // 7. 计算频率:频率 = 计数值 / 时间 // 时间 = GATE_TIME_MS / 1000 秒 return (total_count * 1000UL / GATE_TIME_MS); } // T1中断服务函数,用于标记闸门时间 unsigned char gate_time_flag = 0; void Timer1_ISR(void) interrupt 3 { TH1 = (65536 - 50000) / 256; // 重装初值 TL1 = (65536 - 50000) % 256; gate_time_flag++; // 中断次数加1 }
4.2.4 电感计算与显示函数

根据测得的频率计算电感值,并格式化为字符串显示。

void Calculate_and_Display_Inductance(unsigned long freq) { double inductance; char disp_buf[16]; if(freq == 0 || freq > 2000000) { // 频率异常处理 LCD_ShowStr(0, 1, "Freq Error! "); return; } // 计算公式: L = 1 / ( (2 * π * f)^2 * C ) inductance = 1.0 / ( pow(2.0 * PI * (double)freq, 2) * STANDARD_CAP ); // 单位转换和显示 if(inductance < 1e-6) { // 小于1uH,显示nH sprintf(disp_buf, "L=%7.2fnH", inductance * 1e9); } else if(inductance < 1e-3) { // 小于1mH,显示uH sprintf(disp_buf, "L=%7.2fuH", inductance * 1e6); } else if(inductance < 1) { // 小于1H,显示mH sprintf(disp_buf, "L=%7.2fmH", inductance * 1e3); } else { // 大于等于1H,显示H sprintf(disp_buf, "L=%7.2f H", inductance); } LCD_ShowStr(0, 1, disp_buf); // 在LCD第二行显示 }
4.2.5 主函数
void main(void) { unsigned long frequency; LCD_Init(); // 初始化液晶 LCD_ShowStr(0, 0, "Inductor Meter"); // 显示标题 while(1) { frequency = Measure_Frequency(); // 测量频率 Calculate_and_Display_Inductance(frequency); // 计算并显示电感 // 延时一段时间再进行下一次测量,避免刷新过快 Delay_ms(500); } }

5. 系统校准与精度提升

由于电容误差、电路分布参数、单片机计数器误差等因素,直接测量结果可能存在偏差。因此,校准是提高测量精度的关键步骤。

5.1 校准方法

  1. 准备标准电感:获取一个或多个已知精确值的电感,例如100uH ±1%的工字电感。
  2. 测量与记录:将标准电感接入测量系统,记录LCD显示的值L_measure
  3. 计算校准系数:校准系数K = L_standard / L_measure。其中L_standard是标准电感的标称值。
  4. 软件修正:在计算电感值的公式中乘以校准系数K。
    // 在Calculate_and_Display_Inductance函数中,计算后加入 inductance = inductance * CALIBRATION_FACTOR; // CALIBRATION_FACTOR 是校准系数
  5. 多点校准:如果测量范围较宽,可以在不同量程(如10uH, 100uH, 1mH)分别进行校准,然后在程序中根据测量值大小选择不同的校准系数。

5.2 影响精度的因素及优化

  • 标准电容精度:使用精度高、温度稳定性好的电容(如C0G/NPO)。
  • 闸门时间精度:依赖于单片机定时器的精度。使用更高精度的外部晶振(如11.0592MHz或22.1184MHz,并注意机器周期计算)可以提高时间基准精度。
  • 电路布局与噪声:LC回路和比较器部分应紧凑布局,远离数字电路(如单片机、LCD)。电源需加滤波电容。
  • 单片机计数误差:对于高频信号,51单片机(12T模式)的最高计数频率约为晶振频率的1/24,12MHz时约为500kHz。测量更高频率的电感(小电感)时,需考虑此限制。可考虑使用1T模式的新型51单片机(如STC15系列)或增加预分频电路。
  • 软件滤波:连续测量多次,取平均值或中位值,可以抑制随机误差。

6. 常见问题与排查思路

在制作和调试过程中,你可能会遇到以下问题:

问题现象可能原因排查思路与解决方案
LCD无显示或显示乱码1. 电源或接线错误。
2. 对比度调节不当。
3. 初始化时序不对。
4. 总线冲突。
1. 检查VCC/GND,确认电压5V。
2. 调节VEE电位器,改变对比度。
3. 检查初始化代码延时是否足够。
4. 确认P0口是否接了上拉电阻(10k排阻)。
测量结果始终为0或显示“Freq Error!”1. LC回路未起振。
2. 比较器电路工作不正常。
3. 单片机未检测到脉冲信号。
4. 激励脉冲太弱。
1. 检查电感电容是否焊接良好,用示波器探头(或万用表AC档)测LC节点是否有振荡波形。
2. 检查LM311供电、参考电压,用示波器看输出引脚是否有方波。
3. 检查T0引脚(P3.4)连接,程序是否配置为计数器模式。
4. 尝试减小R4电阻(如改为100Ω),增大激励电流。
测量结果不稳定,数值跳动大1. 电源噪声大。
2. 外部电磁干扰。
3. 接触不良。
4. 软件未做滤波。
1. 在单片机、比较器电源引脚就近加104(0.1uF)和10uF滤波电容。
2. 让LC回路远离电源变压器、电机等干扰源。
3. 检查所有接线和焊点。
4. 在软件中增加多次测量取平均的算法。
测量值存在固定偏差1. 标准电容容值不准。
2. 电路存在固定分布电容或电感。
3. 未进行校准。
1. 使用电容表测量实际使用的电容值,并更新代码中的STANDARD_CAP
2. 通过校准来补偿系统误差。
3.必须进行校准,这是提高精度的最重要步骤。
测量小电感(如<10uH)不准1. 振荡频率过高,接近或超过单片机计数极限。
2. 寄生参数影响占比大。
1. 增大并联电容C的值(如用2.2nF),降低振荡频率。
2. 尽量缩短LC回路的引线长度。
测量大电感(如>10mH)不准1. 振荡频率过低,在闸门时间内计数值太小,相对误差大。
2. 电感内阻大,振荡衰减快。
1. 减小并联电容C的值(如用470pF),提高振荡频率。
2. 延长闸门时间(如改为500ms或1s),增加计数值。
3. 选择高品质(Q值高)的电感。

7. 项目优化与扩展方向

这个简易测量仪是一个很好的起点,你可以在此基础上进行多种优化和功能扩展:

  1. 量程自动切换:根据首次粗略测量的频率值,自动切换不同容值的标准电容(通过模拟开关如CD4051控制),从而实现更宽范围的精确测量。
  2. 更高精度时钟:采用外部有源温补晶振(TCXO)为单片机提供时钟,大幅提高定时闸门的精度。
  3. 使用更先进的MCU:采用STC15、STC8等1T单片机,其计数频率和运行速度远超传统51,可以测量更高频率,实现更复杂的数字滤波算法。
  4. 增加测量模式:通过继电器或模拟开关切换电路,使系统既能测电感,也能用类似原理测电容,一机两用。
  5. 上位机通信与记录:添加串口通信功能(如MAX232芯片),将测量数据发送到电脑,利用上位机软件进行数据记录、分析和曲线绘制。
  6. 改进人机交互:使用按键和菜单,允许用户手动输入校准值、选择量程、查看历史数据等。
  7. 低功耗设计:在电池供电场景下,可以优化程序,让单片机大部分时间处于休眠模式,定时唤醒进行测量,以延长续航。

通过这个项目,你不仅学会了如何测量电感,更深入理解了LC振荡原理、单片机定时器/计数器应用、模拟数字信号混合电路设计以及系统校准的重要性。这些知识和技能在嵌入式系统开发中具有广泛的适用性。

← 返回列表