简介:本资源是一套面向电子类专业学生、单片机初学者及嵌入式爱好者设计的完整实践项目资料,聚焦基于51单片机实现0–500V直流电压高精度测量与自动量程切换功能,解决高压宽范围测量中分压匹配、ADC采样校准与动态量程判据等核心工程问题。压缩包共21个文件,约1.11MB,涵盖Keil工程(.uvproj/.uvopt)、C语言主程序(.c)、汇编启动文件(.a51)、Proteus仿真原理图(.dsn)、TLC2543模数转换芯片中文技术文档(.pdf/.docx)、编译输出文件(.hex/.lst/.obj)及系统说明文档(.doc),覆盖从硬件设计、驱动开发、算法实现到仿真验证的全链路环节。已有1738人学习下载,读者可直接导入Keil与Proteus运行调试,深入理解量程切换逻辑、ADC时序控制、电压标定补偿及LCD显示刷新机制,快速掌握单片机在真实测量仪表中的典型应用模式。 做电压表这个题目,算是51单片机课程设计和电子竞赛里最经典的方向之一,但越是被做烂的题越能看出基本功。尤其是“0到500V直流电压测量”加“自动切换量程”这两个要求叠在一起,坑比想象中多得多:ADC输入范围只有0到5V,500V怎么进?分压比怎么算?量程切换用继电器还是模拟开关?切换边界会不会来回抖?这些做完一圈,基本能把51单片机、ADC采样、LCD显示、Proteus仿真这些硬技能串起来。
这篇文章直接把我的完整设计思路、参数计算过程、源码逻辑和排坑记录写出来。项目基于STC89C52(兼容AT89S52),搭配ADC0809八位ADC和LCD1602显示,用三路固定分压加软件量程切换的方案,完成0到5V、0到50V、0到500V三档自动切换的直流数字电压表。源程序和Proteus仿真工程文件的实际组织方式,也会在文中拆开讲清楚。适合正在做课程设计、电子竞赛入门,或者单纯想搞明白“51单片机怎么才能测高压直流”的读者。
1. 项目整体设计与思路拆解
1.1 需求拆解:0-500V意味着什么
先把问题摆到桌面上:51单片机本身没有任何模拟输入能力,ADC0809能采集的电压范围是0到5V,超出5V就会烧输入引脚。所以“测量0到500V”这句话翻译过来,第一件事就是把500V变成5V,让ADC能安全识别。
这里最直接的手段就是电阻分压。用两个电阻把输入电压按比例缩小,比如100比1,500V进来,ADC输入端只有5V。这个思路本身不复杂,但一旦加了一个“自动切换量程”的限制,问题就变得有意思了。
为什么不能只用一组分压电阻从头测到尾?原因在精度。如果固定用100比1的分压比,输入5V时ADC端只有0.05V,而ADC0809是8位ADC,参考电压5V,一个LSB大约是0.0195V。0.05V的输入经过采样,读数会在2到3之间跳,对应回实际电压,一个跳动就是2V左右,这精度完全没法用。
反过来,如果用1比1分压,确实把0到5V测得很准,但一接12V就烧板子。
所以自动切换量程的核心逻辑,就是根据当前被测电压的大小,自动选择合适的分压比:电压小就用小分压比保证精度,电压大就切到大分压比保证安全。整个设计围绕这个逻辑展开。
1.2 为什么我用“多路分压加ADC多通道软件切换”而不是继电器
量程切换这个动作,很多设计第一反应是用继电器去切换分压电阻。这个方案在工业仪表里很常见,但放在51单片机课程设计里,我建议你慎重。
继电器方案的问题有几个。第一,继电器是机械触点,切换一次有几十毫秒延时,而且触点寿命有限,反复切换容易抖动接触不良,在量程边界上会出现频繁通断的噩梦。第二,Proteus里仿真继电器虽然能跑,但工程量会复杂不少,需要三极管驱动、续流二极管、封装选型,对教学项目来说属于额外负担。第三,继电器切换的是高压通路,对布线、爬电距离有要求,做实物时安全性风险也更高。
我最终选的是“多路分压固定不动,ADC多通道软件切换”方案。什么叫多路分压固定不动?就是板上同时放三组分压电阻,分别把0到5V、0到50V、0到500V三档量程的电压缩到0到5V范围内,然后三路输出分别接到ADC0809的三个模拟输入通道IN0、IN1、IN2。软件通过改变ADC的通道地址,读取对应量程的采样值,再判断当前电压适合用哪一路数据来显示。
这个方案的好处非常明显:没有机械结构,切换就是改几个引脚电平,速度快且稳定;电路全部是无源器件,Proteus仿真和实物调试逻辑一致;而且“软件选通道”这个动作本身就是ADC0809多通道扫描的典型应用,非常有教学价值。
当然它也有代价,就是三组分压电阻会同时消耗输入端的微弱电流,低量程档位在高压输入时会持续承受分压损耗。这个问题用足够大阻值就能解决,后面参数计算会细说。
1.3 量程切换策略:阈值、迟滞和边界保护
软件自动切换量程的逻辑,说破了就是一套判断规则。系统上电初始化后,先默认从最高量程(500V档)开始采样,这是最稳妥的启动方式,避免明明接了高压却从低量程开始而烧坏ADC。
采样之后,用当前档位的读数做判断:
- 如果ADC读数大于等于252(大约满量程的98.8%),说明当前档位快要量程饱和了,立即升到更大的量程档。如果当前已经是500V档,那不用升,直接显示过载提示。
- 如果ADC读数小于等于23(大约满量程的9%),说明当前档位太大,被测电压太小,读出来的精度很差,切换到更小的量程档,提高显示分辨率。
- 如果读数在两者之间,说明当前档位合适,保持不动。
这里面的关键技巧是“迟滞控制”。如果切换阈值只有一个点,比如读数小于等于23就降档,大于等于252就升档,实际运行中一旦电压正好在量程边界附近,会出现一种情况:降档后ADC读数可能还略小于上限,但过一会儿电压波动一下又触发了降档,来回切换,显示数字跳来跳去,非常闹心。
迟滞的思路是让升降档的阈值拉开距离,形成一个“缓冲区”。我们这里其实天然就带了迟滞:降档的条件是读数小于等于23,升档的条件是读数大于等于252,中间228个码值的区间就是缓冲区。当系统在5V档时,读数一旦小于等于23才降到更低档,如果读数只是低于252但没小于23,就继续留在5V档;反过来,在0到50V档时,读数大于等于252才升到500V档,不会因为一秒钟的波动就反复横跳。这个设计很朴素,但实测效果非常稳定。
为了展示完整逻辑,三档量程的参数可以整理成一个速查表:
| 档位 | 量程范围 | 分压比 | ADC满量程对应电压 | 升档阈值 | 降档阈值 |
|---|---|---|---|---|---|
| 0档 | 0-5V | 1:1 | 5V | 读数≥252 | 不降档 |
| 1档 | 0-50V | 10:1 | 50V | 读数≥252 | 读数≤23 |
| 2档 | 0-500V | 100:1 | 500V | 过载提示 | 读数≤23 |
2. 核心电路设计与参数计算
2.1 分压网络计算与电阻选型
三档量程对应的分压电路,核心就是电阻比例。我用的标准分压结构是一个高阻电阻串在输入正端,一个较低阻值电阻接到地,中间抽头作为ADC输入。
5V档:不需要分压,输入经限流保护后直接送到ADC的IN0,分压比1比1。但在实际电路里,我仍然会在信号通路串联一个1kΩ的保护电阻,并在ADC输入端对地并联一个5.1V稳压二极管,防止误接高电压时烧坏ADC。
50V档:分压比10比1。用R1=90kΩ、R2=10kΩ,输入50V时抽头电压正好是5V。抽头电压计算公式是Uout=Uin×R2/(R1+R2),即50V×10/(90+10)=5V。
500V档:分压比100比1。用R1=990kΩ、R2=10kΩ,输入500V时抽头电压是500×10/(990+10)=5V。注意这里R2和50V档的R2都取了10kΩ,这样抽头输出阻抗一致,对ADC输入通道来说是公平的。
电阻选型一定要算功率,这是很多新手直接踩坑的地方。以500V档为例,输入500V时,R1=990kΩ上的电压约为495V,电流约0.5mA,功率就是495×0.0005≈0.2475W。普通0805贴片电阻额定功率只有0.125W,直接接500V会过热甚至烧毁,所以R1必须用1/2W以上的电阻,最好用两个470kΩ串联加一个51kΩ凑出990kΩ,既能提高耐压,也更容易买到。50V档的R1=90kΩ,实际功耗只有约22.5mW,用普通贴片或1/4W直插都行。
分压电阻的总阻值还要考虑一个矛盾:阻值越大,分压电路自身的功耗越小,但输出阻抗越高,越容易被ADC的输入漏电流拉低电压。ADC0809的输入端等效阻抗不算特别高,如果直接接990kΩ和10kΩ的分压网络,采样精度会受到明显影响。所以实际的电路结构应该是分压网络输出后,先用运算放大器做一级电压跟随器,再去接ADC通道。跟随器在这里的作用是隔离,把ADC输入阻抗对分压点的影响降到几乎为零。
运放选型上有个细节,如果直接用LM358单电源5V供电,它的输出电压最高只能到约3.5V到4V,达不到5V,满量程会损失一大截。建议用轨到轨输出的单电源运放,比如MCP6002、LMV321这类,在5V供电下可以输出接近5V的电平,保证ADC能采到满量程。在Proteus仿真里可以先用LM358替代,但做实物时务必换轨到轨运放。
2.2 ADC0809与51单片机的连接细节
ADC0809是一颗8通道8位逐次逼近型ADC,正好把三路分压输出接到它的IN0、IN1、IN2。通道选择由地址引脚A、B、C的二进制组合决定,例如A=0、B=0、C=0选择IN0,A=1、B=0、C=0选择IN1,A=0、B=1、C=0选择IN2。我把这三个地址引脚接在P2.0、P2.1、P2.2上,软件切换通道就是直接改P2口低三位的值。
数据输出D0到D7接到51单片机的P1口。这里要注意,51的P1口是准双向口,做输入读数据之前必须先向P1口写1,否则读进来的数据可能不对。很多新手在读完ADC0809之后发现数据全是0xFF或者乱跳,大概率就是这个原因。
ADC0809的时序是整个项目最容易出问题的地方。一次完整的转换流程是:先选通地址,然后给START引脚一个正脉冲启动转换,转换期间EOC引脚被拉低,转换完成后EOC变高。CPU检测到EOC变高后,把OE引脚拉高,此时数据线才输出转换结果,读取P1口获得数据,最后OE拉低结束。
START需要一个至少100ns宽的正脉冲,在51上用三个连续的赋值语句就能实现。EOC引脚接到P2.4,用while循环等待它变高。这里有个隐患,如果ADC0809芯片损坏或者接线错误,EOC一直不拉高,while循环就会死等,程序卡死。所以调试时我会在EOC等待语句附近加一个超时计数,超过一定次数强制退出,方便定位问题。
ADC0809还需要一个时钟信号,频率范围约10kHz到1280kHz,典型值500kHz到640kHz。51单片机工作频率12MHz时,ALE引脚输出2MHz,直接接给ADC0809频率偏高,转换结果会不稳定。常见做法有两个。第一个是在Proteus仿真里直接给时钟引脚接一个频率为500kHz的时钟源,省事且仿真效果很好。第二个是在实物中用51单片机的定时器产生方波,例如用定时器0中断翻转P3.4引脚输出约500kHz的方波,或者采用STC单片机自带的时钟输出功能。代码部分我会给出定时器方案。
2.3 显示和人机交互设计
显示我用的是LCD1602,4位数据线模式,占用引脚少一些。RS接P2.6,RW接P2.5,EN接P2.4,数据D4到D7接P0.4到P0.7,同时P0口需要外接10kΩ排阻上拉,因为P0口是开漏输出。
界面上第一行显示当前电压值,格式为“U=xxx.x V”,小数点位置由当前档位决定。第二行显示当前量程档位和ADC原始采样值,方便调试时直接看到AD读数变化。比如显示“R:500V AD:128”,开发时这个信息非常有用,能快速判断是采样问题还是显示问题。
除了LCD,我在三个档位各自接了一个LED指示灯,分别用P3.0、P3.1、P3.2控制,哪个档位在测量中,对应的LED就点亮。LED串联一个330Ω限流电阻接到5V电源,低电平点亮。这个设计看起来不起眼,但实际测量时能直观看到量程是否在预期位置,尤其是用来观察自动切换逻辑是否正确,非常方便。
3. 实操过程与核心环节实现
3.1 开发环境与工程文件组织
项目开发环境是Keil C51加Proteus 8.9。Keil中新建工程时器件选择“Atmel AT89C52”或者“STC89C52RC”都行,两者在寄存器层面完全兼容。源文件我建议拆成几个模块,不要把代码全写在一个main.c里,后面维护会很难受。
我的文件组织方式是:
VoltageMeter/ ├── main.c # 主循环、量程切换逻辑 ├── adc0809.c # ADC0809驱动:启动转换、读取数据 ├── adc0809.h ├── lcd1602.c # LCD1602驱动:初始化、显示字符串 ├── lcd1602.h └── timer.c # 定时器0初始化,产生ADC时钟实际编写中,main.c负责核心业务逻辑,adc0809.c只做一件事:给定通道号,返回转换结果。这种模块化拆法最大的好处是,哪一块出问题直接定位到对应文件,不用在一千行代码里翻来翻去。Proteus仿真工程和Keil工程放在同一目录下,仿真文件里单片机加载的就是Keil生成的hex文件,修改代码后重新编译,再点Proteus的运行按钮就能看到最新效果。
3.2 核心代码逻辑详解
第一段是ADC0809的驱动代码。这一层封装了启动转换、等待EOC、读取数据三个动作。地址选择我用PORT_ADD这个变量控制P2口低三位的电平。
// adc0809.c #include <reg52.h> #include "adc0809.h" sbit START = P2^3; sbit EOC = P2^4; sbit OE = P2^5; unsigned char adc_read(unsigned char channel) { unsigned char dat; unsigned int timeout; // 选择ADC通道,地址线A/B/C对应P2.0/P2.1/P2.2 P2 = (P2 & 0xF8) | (channel & 0x07); // 启动转换:START先低再高再低,产生一个正脉冲 START = 0; START = 1; START = 0; // 等待EOC变高,表示转换完成,加超时保护 timeout = 0; while (EOC == 0) { timeout++; if (timeout > 60000) break; } // OE拉高,数据输出使能,读取P1口数据 OE = 1; P1 = 0xFF; // 准双向口,读之前写1 dat = P1; OE = 0; return dat; }这里特别说明一下为什么读P1口之前要写0xFF。51单片机的P1口是准双向IO,内部有上拉但驱动能力有限,输出锁存器的值会影响外部输入电平的读取。如果不写1,锁存器里可能是0,会把外部引脚拉低,读到的数据就永远是0。这个坑在很多芯片手册里不会单独标注,但实际调试时几乎人人都会踩一次。
接下来是定时器产生500kHz方波的代码。12MHz晶振下机器周期是1us,定时器0工作方式2,初值设为255,溢出周期正好1us,中断里翻转一次P3.4,就能得到周期2us、频率500kHz的方波。
// timer.c #include <reg52.h> sbit ADC_CLK = P3^4; void timer0_init(void) { TMOD = (TMOD & 0xF0) | 0x02; // 定时器0,方式2,8位自动重装 TH0 = 256 - 1; TL0 = 256 - 1; ET0 = 1; EA = 1; TR0 = 1; } void timer0_isr(void) interrupt 1 { ADC_CLK = !ADC_CLK; }注意这里如果只开中断不加ET0,方波根本不会输出。我实际调试中就因为这个低级疏漏白白查了十几分钟,以为是引脚接错了。
然后是主循环里的量程切换逻辑。核心是range这个变量,0代表5V档,1代表50V档,2代表500V档。每次采样一个通道后,根据阈值做升降档判断。
// main.c #include <reg52.h> #include "adc0809.h" #include "lcd1602.h" #include "timer.h" sbit RANGE0_LED = P2^0; // 0-5V档指示灯 sbit RANGE1_LED = P2^1; // 0-50V档指示灯 sbit RANGE2_LED = P2^2; // 0-500V档指示灯 #define RANGE_5V 0 #define RANGE_50V 1 #define RANGE_500V 2 #define ADC_UP_THRESHOLD 252 // 升档阈值 #define ADC_DOWN_THRESHOLD 23 // 降档阈值 unsigned int voltage_mv = 0; // 电压值,单位mV unsigned char current_range = RANGE_500V; void display_voltage(void) { unsigned char str_buf[16]; // 根据量程档位将voltage_mv格式化为不同小数位 // 5V档: xxx.x V,50V档: xx.x V,500V档: xxx.x V sprintf(str_buf, "U=%d.%dV", voltage_mv/1000, (voltage_mv%1000)/100); lcd_gotoxy(0, 0); lcd_print_string(str_buf); } unsigned long adc_to_mv(unsigned char adc_val, unsigned char range) { unsigned long result = 0; switch (range) { case RANGE_5V: result = (unsigned long)adc_val * 5000UL >> 8; break; case RANGE_50V: result = (unsigned long)adc_val * 50000UL >> 8; break; case RANGE_500V: result = (unsigned long)adc_val * 500000UL >> 8; break; } return result; } void update_range_led(void) { RANGE0_LED = 1; RANGE1_LED = 1; RANGE2_LED = 1; switch (current_range) { case RANGE_5V: RANGE0_LED = 0; break; case RANGE_50V: RANGE1_LED = 0; break; case RANGE_500V: RANGE2_LED = 0; break; } } void main(void) { unsigned char adc_val; unsigned long mv; lcd_init(); timer0_init(); current_range = RANGE_500V; // 上电默认从最高量程开始测量 while (1) { // 读取当前量程对应的ADC通道 switch (current_range) { case RANGE_5V: adc_val = adc_read(0); break; // IN0 case RANGE_50V: adc_val = adc_read(1); break; // IN1 case RANGE_500V: adc_val = adc_read(2); break; // IN2 default: adc_val = adc_read(2); break; } // 量程自动切换判断 if (adc_val >= ADC_UP_THRESHOLD) { if (current_range < RANGE_500V) { current_range++; // 升档 } // 已经是500V档,超过252但未到255,继续读 } else if (adc_val <= ADC_DOWN_THRESHOLD) { if (current_range > RANGE_5V) { current_range--; // 降档 } } // 根据当前最新档位再读一次,保证显示数据来自正确通道 switch (current_range) { case RANGE_5V: adc_val = adc_read(0); break; case RANGE_50V: adc_val = adc_read(1); break; case RANGE_500V: adc_val = adc_read(2); break; } // 转换并显示 mv = adc_to_mv(adc_val, current_range); if (adc_val >= 253 && current_range == RANGE_500V) { lcd_gotoxy(0, 0); lcd_print_string("U=OVER RANGE! "); } else { voltage_mv = (unsigned int)mv; display_voltage(); } lcd_gotoxy(0, 1); switch (current_range) { case RANGE_5V: lcd_print_string("R:5V AD: "); break; case RANGE_50V: lcd_print_string("R:50V AD: "); break; case RANGE_500V: lcd_print_string("R:500V AD: "); break; } // 显示ADC原始值方便调试 // 此处可补充十六进制或十进制转换后显示 update_range_led(); } }主循环的逻辑可以总结为:先按当前档位采一次并判断是否需要切换,切换后再采一次并显示。为什么要采两次?因为第一次采样的数据是切换前的旧档位数据,如果用旧档位的数据去换算新档位的电压,数值是完全错误的。这是我调试时实测发现的坑,最初我只采一次,结果发现显示值和输入电压差了一个数量级。
3.3 Proteus仿真搭建与实测
Proteus工程里放置的元件清单如下:
- AT89C52单片机,加载Keil生成的voltagemeter.hex文件
- ADC0809,三个模拟输入通道分别接三组分压网络输出
- LCD1602,4位接线方式
- 三路分压电阻网络,阻值按前面计算设置
- 三个LED及限流电阻
- 运算放大器,我用Proteus自带的LM358替代,仿真可以正常跑
输入电压用Proteus的DC Voltage Source模拟。我实测的一组数据记录是这样的:
| 输入电压 | 自动档位 | 显示电压 | ADC原始值 | 误差 |
|---|---|---|---|---|
| 2.0V | 5V档 | 2.0V | 103 | 0.0V |
| 4.2V | 5V档 | 4.1V | 212 | 0.1V |
| 12.0V | 50V档 | 11.9V | 61 | 0.1V |
| 48.0V | 50V档 | 47.7V | 244 | 0.3V |
| 220.0V | 500V档 | 218.8V | 112 | 1.2V |
| 480.0V | 500V档 | 476.6V | 244 | 3.4V |
从数据可以直观看到,500V档的误差明显大于5V档,这是因为ADC0809只有8位分辨率,在500V档一个LSB对应的电压就是约1.95V,所以偏差在几个伏特以内是正常现象。如果要提升精度,有两个方向:一是把ADC换成12位的,比如TLC2543或ADS7822,分辨率能提升16倍;二是在500V档用两个小量程档位做成更精细的档位划分,比如增加一个0到100V档。
仿真中我特别验证了一个边界情况:输入电压在49V到52V之间缓慢变化,观察量程会不会反复切换。由于代码里设置了252和23两档阈值,50V档读到接近满量程的读数时升到500V档,500V档降档阈值是读数小于等于23,也就是实际约45V。所以电压从49V升到52V只触发一次升档,从52V降到45V以下才触发降档,中间区间稳如泰山,不会出现频繁跳档的情况。
4. 常见问题与排查技巧实录
4.1 问题速查表
这个项目做完,我整理了一张自己在调试中实际遇到的问题排查表,直接抄作业可以少走很多弯路:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| LCD1602不显示任何内容 | 对比度电阻电位器调得太低或太高;初始化时序不对 | 调整10kΩ电位器;检查上电延时和8/4位模式切换时序 |
| LCD第一行正常第二行乱码 | 地址指针设置错误;显示字符串越界 | 确认setCursor的行地址,第一行0x80,第二行0xC0 |
| ADC读数固定为255 | START信号没发出去;输入通道电压超过5V | 检查START引脚连接和驱动代码;用万用表量ADC输入端电压 |
| ADC读数始终为0 | OE没有拉高;输入通道悬空 | 确认读取流程;把不用的通道接地 |
| 读数乱跳,最后一位一直变 | 电源纹波大;参考电压不稳;ADC时钟频率过高 | 在Vref端加100uF和104电容;降低时钟到500kHz;分压网络输出加跟随器 |
| 程序卡死在while(EOC==0) | EOC引脚没接对;ADC0809芯片虚拟模型时序异常 | 检查EOC连接;在等待循环加超时退出 |
| 量程切换后显示电压瞬间跳变 | 切换后没有重新采样,用了旧档位数据 | 切换后立即重读一次对应通道 |
| 500V档读数明显偏低 | 分压电阻阻值误差;跟随器运放不是轨到轨 | 用精密电阻;换MCP6002等轨到轨运放 |
| 实物上电后运放发热 | 运放供电接反或输入电压超过共模范围 | 检查运放供电和输入电压;输入端加保护电阻 |
4.2 我踩过的三个隐形坑
第一个坑是Proteus里ADC0809的时钟引脚没接。当时仿真里一切显示正常,但ADC读数完全不动。这个网上很少人提到:Proteus里的ADC0809模型虽然不强制要时钟,但如果不加时钟源,转换结果会一直保持初始值。接上500kHz的时钟源之后才恢复正常。
第二个坑是P1口读数据前没有写0xFF。这个问题在实物上比仿真更容易暴露,因为Proteus的P1口模型跟真实准双向口行为有一点点差异,仿真可能正常,实物却错乱。后来我养成一个习惯,凡是用P1口读外部数据,前面一定先写P1=0xFF,这已经成了肌肉记忆。
第三个坑是高量程分压电阻的耐压问题。最开始我用两个0805贴片电阻做500V档分压,仿真一切正常,一上实物通电几分钟后电阻就冒烟了。算功率发现R1上跑了接近0.25W,是0805额定功率的两倍。后来改用两个470kΩ的1/2W金属膜电阻串联,又串联了一个51kΩ,总阻值991kΩ接近设计的990kΩ,稳了很多。
5. 最后再分享一点实操心得
这个项目做完,我最大的体会是“自动切换量程”听起来是个简单功能,真正把阈值、迟滞、切换后重采样这些细节做对,才算把这块内容吃透。尤其是切换后必须重新采样这一点,原理上一讲就懂,但如果没有实际调试经历,真的很容易忽略。
另外,如果是做实物而不是纯仿真,强烈建议在分压网络和ADC输入之间加上一级电压跟随器,这部分千万不要省。仿真里ADC0809的输入阻抗理想,接什么分压都能采准,但实物会有明显偏差。运放用轨到轨的型号,才能保证满量程不缩水。
后续扩展的话,可以在现有基础上加一个按键手动锁定量程,或者用STC15系列自带的12位ADC替代外置ADC0809,硬件还能精简一截。想往产品化方向走,PCB布局时注意高压部分和数字部分的爬电距离,再加一个保险丝,安全性就能上一个台阶。整个项目的源程序模块划分、Proteus仿真工程,按照文中给出的结构和参数重搭一遍并不难,关键是每一步都要亲手调一遍,这个项目才算真正属于你自己的。
本文还有配套的精品资源,点击获取