项目二十三:电阻测量(需要简单的外围检测电路,将电阻转换为电压)测量100,1k,4.7k,10k,20k的电阻阻值,由数码管显示。要求测试误差 <10%
资料查找:
01 方案选择
使用单片机测量电阻有多种方法,以下是一些常见的方法及其原理:
- 串联分压法(ADC)
- 原理:根据串联电路的分压原理,通过测量已知电阻和待测电阻上的电压,计算出待测电阻的阻值。
- 优点:电路简单,易于实现。
- 缺点:测量精度受电源电压稳定性和电压测量精度的影响。
对于89C5x单片机一般需要外接PCF8591(A/D转换芯片)
直流电桥法原理:利用直流电桥的平衡原理,通过调节电位器使电桥平衡,从而计算出待测电阻的阻值。优点:测量精度较高。缺点:电路相对复杂,调节较为麻烦。
恒流源法原理:将恒流源施加到待测电阻上,通过测量电阻两端的电压来计算电阻值。优点:测量精度较高,不受电源电压波动的影响。缺点:需要稳定的恒流源电路,实现相对复杂。
频率法原理:利用RC振荡电路和555定时器电路,将电阻转换为频率信号,通过测量频率来计算电阻值。优点:测量速度快,适用于动态测量。缺点:测量精度受振荡电路稳定性和频率测量精度的影响。
- IO口测量法
- 原理:使用单片机的IO口通过电容充电时间来测量电阻。电容充电时间与电阻成正比,通过测量充电时间来计算电阻值。
- 优点:不需要额外的AD转换电路,利用单片机IO口即可实现。
- 缺点:测量精度受单片机定时器精度和电容稳定性的影响。
以为大部分单片机通用,试了一下,发现STC89C52内部上拉有干扰
2 使用单片机的IO口通过电容充电时间来测量电阻
测量原理
- 使用两个单片机IO口,连接两个电阻,向同一个电容充电。设置一个IO口为输出端口,另一个为输入端口。
- 输出端口通过连接的电阻向电容充电。电容上的电压上升,当超过一定阈值,输入端口逻辑电平就会变成1。
关于阈值可以通过输入三角波得到,但是我们并不需要知道(比值可消)
- 这个充电时间与终止电压、阈值电压以及RC对应的时间常数有关系。具体数值由这个公式决定:

- 对应的时间与R2成正比。因此,两次时间的比值,就等于电阻的比值。如果已知其中一个电阻阻值,另外一个电阻便可以根据时间比值计算出来。12
实验步骤
- 需要一个电容和两个电阻。电容容值为313.8nF,电阻1的阻值为19.545kΩ;电阻2的阻值为4.718kΩ。
- 电容一端接地,另外一端与两个电阻相连。两个电阻分别与单片机的PF0,PF1端口相连。
- 设置PF0为输出端口,PF1为输入端口。周期改变PF0高低电平。分别测量PF0,以及电容上的电压信号。
- 测量软件先将PF0,PF1输出0电平,对于电容进行放电。然后将其中一个设置为输入端口,另外一个置为高电平,对电容充电。同时启动定时器1进行计时。
- 在此过程中,监视输入端口逻辑电平是否为1。当输入端口变为1时,停止定时器,并读取时间。然后再进行放电,更换另外一个端口为输入端口。测试充电时间。1
实验结果
- 测试298个数据进行统计。数据的平均值为4.119,标准方差为0.043。测量平均值比实际电阻比值4.143小了0.6%。1
3 硬件部分

4 软件部分
介绍:
STC89C52的端口P2是一个双向I/O口,每个引脚(如P2.0、P2.1等)
P0=1时为上拉输出,P0=0时为低电平输出
因此在已有上拉输入的条件下,也同样理论可行
最终按照如图思路把代码改出来了,但发现因为单片机太低级了,影响了开发效率
那就准备直接ADC写了算了
main.c
#include <reg52.h>//0.000 001 085069444444444=1
sbit IO1 = P2^2;
sbit IO2 = P2^3;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;void Delay_ms(int ms) //@11.0592MHz
{unsigned char data i, j;do{i = 15;j = 90;do{while (--j);} while (--i);}while (--ms);
}unsigned char code LedChar[] = { //数码管显示字符转换表0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[6] = { //数码管显示缓冲区0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};bit StopwatchRunning = 0; //秒表运行标志
bit StopwatchRefresh = 1; //秒表计数刷新标志
unsigned char DecimalPart = 0; //秒表的小数部分
unsigned int IntegerPart = 0; //秒表的整数部分
unsigned char T0RH = 0; //T0重载值的高字节
unsigned char T0RL = 0; //T0重载值的低字节
unsigned long time_R1, time_R2; // 用于存储充电时间
unsigned long Rx = 0;
float ratio =0;
unsigned char flag1s = 0;
void ConfigTimer0(unsigned int ms);
unsigned long timer_read();
void U_Measure();
void LedScan();
void LCD_paly();
void main()
{EA = 1; //开总中断ENLED = 0; //使能选择数码管ADDR3 = 1;P2 = 0xFE; //P2.0置0,选择第4行按键作为独立按键ConfigTimer0(6); //配置T0定时2mswhile (1){U_Measure();while (1){LedScan();LCD_paly();}}
}void U_Measure()
{// 第一步:放电IO1 = 1;IO2 = 1;TR0 = 0;Delay_ms(20); // 确保电容放电干净// 第二步:测量参考电阻回路上的充电时间IO1 = 0;IO2 = 1;TR0 = 1;while(IO2<=0); // 等待充电结束time_R1 = timer_read(); // 读取计时器值// 第三步:放电IO1 = 1;IO2 = 1;TR0 = 0;Delay_ms(20); // 确保电容放电干净// 第四步:测温度电阻回路上的充电时间IO1 = 1;IO2 = 0;TR0 = 1;while(IO1<=0); // 等待充电结束time_R2 = timer_read(); // 读取计时器值// 第五步:计算电阻比率ratio = ((time_R1*10) / (time_R2*10))/10;Rx=ratio;//flag1s = 1;}
/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)//最大71ms
{unsigned long tmp; //临时变量tmp = 11059200 / 12; //定时器计数频率tmp = (tmp * ms) / 1000; //计算所需的计数值tmp = 65536 - tmp; //计算定时器重载值tmp = tmp + 18; //补偿中断响应延时造成的误差(经验值)
// T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
// T0RL = (unsigned char)tmp;T0RH = 0; //定时器重载值拆分为高低字节T0RL = 0;TMOD &= 0xF0; //清零T0的控制位TMOD |= 0x01; //配置T0为模式1=16位TH0 = T0RH; //加载T0重载值TL0 = T0RL;ET0 = 1; //使能T0中断}
/* 秒表计数显示函数 */
void LedScan()
{// flag1s = 0; //1秒定时标志清零//以下代码将Rx按十进制位从低到高依次提取并转为数码管显示字符LedBuff[0] = LedChar[Rx%10];LedBuff[1] = LedChar[Rx/10%10];LedBuff[2] = LedChar[Rx/100%10];LedBuff[3] = LedChar[Rx/1000%10];LedBuff[4] = LedChar[Rx/10000%10];LedBuff[5] = LedChar[Rx/100000%10];}
void LCD_paly()
{static signed char i;P0 = 0xFF; //显示消隐switch (i){case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;default: break;}}/* 定时停止函数 */
unsigned long timer_read()
{unsigned long tmp1 =0;TR0 = 0; tmp1 = (unsigned char)((TH0-T0RH)<<8)|(unsigned char)(TL0-T0RL); //定时器重载值拆分为高低字节TH0 = T0RH; //重新加载重载值TL0 = T0RL;return tmp1;
}/* T0中断服务函数,完成数码管、按键扫描与秒表计数 */
void InterruptTimer0() interrupt 1
{TH0 = T0RH; //重新加载重载值TL0 = T0RL;
// LedScan(); //数码管扫描显示}
02 使用方法——串联分压法(ADC)测电阻
完整工程代码部分,待课设结束再公开
如果需要技术支持可以加我的QQ交流:
27969203789
02 实验现象

03 硬件部分
金沙滩51单片机+需要测量相近的电阻
04 软件部分
核心部分:
val = (GetADCValue(0)*2.5); //获取ADC通道0的转换值 电压值=转换结果*2.48V/255,式中的25隐含了一位十进制小数
Rx=(val/(6375-val))*R1;
XX 拓展资料(收集资料仅供参考):
虽然STC89C52无法配置上下拉操作,但是一般现代翻新的芯片都可以配置,至于配置方法可能类似如下:


例如:
有些单片机的端口P2的输入和输出模式通过配置端口的P2M0和P2M1寄存器来控制。P2M0和P2M1分别是P2端口的输入/输出模式控制寄存器。
关于P2M1 和 P2M0 寄存器介绍:
P2M1 和 P2M0 寄存器是常见的微控制器(例如 51 系列单片机)中的特定控制寄存器,用于设置端口(特别是端口 2)的功能模式。
通常在 51 系列单片机中,P2M1 和 P2M0 寄存器用于控制端口 2 的工作模式(例如是否作为 I/O 端口,或者是否用于特殊功能)。
1. P2M1 寄存器:
P2M1 寄存器的位数通常是 8 位,每一位对应于端口 2 的各个引脚的模式。具体来说,P2M1 中的每一位控制端口 2 的每一个引脚的工作方式。
位 7 (P2.7):
- 0: 作为 I/O 端口;
- 1: 用于特殊功能。
位 6 (P2.6):
- 0: 作为 I/O 端口;
- 1: 用于特殊功能。
依此类推,P2M1 的每一位控制对应的端口引脚的模式。
2. P2M0 寄存器:
P2M0 寄存器也是 8 位,与 P2M1 配合使用,进一步控制端口 2 的引脚模式。它的每一位也用于设置端口 2 上每个引脚的功能模式。例如:
- 位 7 (P2.7):可以通过设置此位来选择端口引脚的功能(是 I/O,还是其他功能)。
- 位 6 (P2.6):控制端口引脚的工作模式。
P2M1 和 P2M0 的配合:
P2M1 和 P2M0 配合使用,通常具有以下几个常见的工作模式(以位 P2.x 为例):
- 00:作为普通的数字 I/O 端口;
- 01:用于某些特定的功能,如外部中断等;
- 10:用于其他一些特殊功能,例如定时器、串口等;
- 11:也可以用于其他特定功能模式。
总结:
- P2M1 和 P2M0 寄存器通常是 8 位,每一位对应端口 2 上的一个引脚(P2.0 到 P2.7)的功能控制。
- 每一位设置为 0 或 1,控制对应引脚是作为 I/O 端口,还是用于特定的功能模式
| P2 引脚 | P2M1 | P2M0 | 描述 |
|---|---|---|---|
| P2.x | 0 | 0 | 普通输入(无上下拉电阻) |
| P2.x | 0 | 1 | 带下拉电阻输入模式(低电平有效) |
| P2.x | 1 | 0 | 推挽输出模式 |
| P2.x | 1 | 1 | 开漏输出模式 |
一般高级的51单片机的寄存器操作,可以通过P2M1和P2M0的配置来控制P2口的工作模式
配置P2.0为下拉输入模式。我们清除P2M1的对应位(即
P2M1 &= 0xFE),然后设置P2M0的对应位(即P2M0 |= 0x01)来启用下拉电阻。
配置P2.0为推挽输出模式。我们设置P2M1的对应位(即
P2M1 |= 0x01)并清除P2M0的对应位(即P2M0 &= 0xFE)
int IN1(void)
{
// 设置P2.0为下拉输入模式P2M1 &= 0xFE; // P2M1位为0P2M0 |= 0x01; // 设置P2M0位为1,启用下拉输入模式}int IN2(void)
{
// 设置P2.0为下拉输入模式P2M1 &= 0xFD; // P2M1位为0P2M0 |= 0x02; // 设置P2M0位为1,启用下拉输入模式}void ON1(void)
{// 设置P2.0为推挽输出模式P2M1 |= 0x01; // 设置P2M1位为1P2M0 &= 0xFE; // 设置P2M0位为0,设置为推挽输出模式
}void ON2(void)
{// 设置P2.0为推挽输出模式P2M1 |= 0x02; // 设置P2M1位为1P2M0 &= 0xFD; // 设置P2M0位为0,设置为推挽输出模式
}
相关文章:
项目二十三:电阻测量(需要简单的外围检测电路,将电阻转换为电压)测量100,1k,4.7k,10k,20k的电阻阻值,由数码管显示。要求测试误差 <10%
资料查找: 01 方案选择 使用单片机测量电阻有多种方法,以下是一些常见的方法及其原理: 串联分压法(ADC) 原理:根据串联电路的分压原理,通过测量已知电阻和待测电阻上的电压,计算出…...
【NLP 17、NLP的基础——分词】
我始终相信,世间所有的安排都有它的道理;失之东隅,收之桑榆 —— 24.12.20 一、中文分词的介绍 1.为什么讲分词? ① 分词是一个被长期研究的任务,通过了解分词算法的发展,可以看到NLP的研究历程 ② 分词…...
uniapp blob格式转换为video .mp4文件使用ffmpeg工具
前言 介绍一下这三种对象使用场景 您前端一旦涉及到文件或图片上传Q到服务器,就势必离不了 Blob/File /base64 三种主流的类型它们之间 互转 也成了常态 Blob - FileBlob -Base64Base64 - BlobFile-Base64Base64 _ File uniapp 上传文件 现在已获取到了blob格式的…...
【无标题】 [蓝桥杯 2024 省 B] 好数
[蓝桥杯 2024 省 B] 好数 好数 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一…...
Leecode刷题C语言之同位字符串连接的最小长度
执行结果:通过 执行用时和内存消耗如下: bool check(char *s, int m) {int n strlen(s), count0[26] {0};for (int j 0; j < n; j m) {int count1[26] {0};for (int k j; k < j m; k) {count1[s[k] - a];}if (j > 0 && memcmp(count0, cou…...
Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集BIM介绍基本原理算法流程特点应用场景 BIM代码实现BIM算法实现攻击效果 代码汇总bim.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器: Pytorch | 从零构建AlexNet对CIFAR1…...
音频进阶学习八——傅里叶变换的介绍
文章目录 前言一、傅里叶变换1.傅里叶变换的发展2.常见的傅里叶变换3.频域 二、欧拉公式1.实数、虚数、复数2.对虚数和复数的理解3.复平面4.复数和三角函数5.复数的运算6.欧拉公式 三、积分运算1.定积分2.不定积分3.基本的积分公式4.积分规则线性替换法分部积分法 5.定积分计算…...
将4G太阳能无线监控的视频接入电子监控大屏,要考虑哪些方面?
随着科技的飞速发展,4G太阳能无线监控系统以其独特的优势在远程监控领域脱颖而出。这种系统结合了太阳能供电的环保特性和4G无线传输的便捷性,为各种环境尤其是无电或电网不稳定的地区提供了一种高效、可靠的视频监控解决方案。将这些视频流接入大屏显示…...
使用docker拉取镜像很慢或者总是超时的问题
在拉取镜像的时候比如说mysql镜像,在拉取 时总是失败: 像这种就是网络的原因,因为你是连接到了外网去进行下载的,这个时候可以添加你的访问镜像源。也就是daemon.json文件,如果你没有这个文件可以输入 vim /etc/dock…...
Redis数据库笔记
Spring cache 缓存的介绍 在springboot中如何使用redis的缓存 1、使用Cacheable的例子【一般都是在查询的方法上】 /*** 移动端的套餐查询* value 就是缓存的名称* key 就是缓存id ,就是一个缓存名称下有多个缓存,根据id来区分* 这个id一般就是多个查询…...
U盘出现USBC乱码文件的全面解析与恢复指南
一、乱码现象初探:USBC乱码文件的神秘面纱 在数字时代,U盘已成为我们日常生活中不可或缺的数据存储工具。然而,当U盘中的文件突然变成乱码,且文件名前缀显示为“USBC”时,这无疑给用户带来了极大的困扰。这些乱码文件…...
多线程 - 自旋锁
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 概述 原理 优点与…...
vue2 - Day02 -计算属性(computed)、侦听器(watch)和方法(methods)
在 Vue.js 中,计算属性(computed)、侦听器(watch)和方法(methods)都是响应式的数据处理方式 文章目录 1. 方法(Methods)1.1. 是什么1.2. 怎么用示例: 1.3. 特…...
Linux C 程序 【05】异步写文件
1.开发背景 Linux 系统提供了各种外设的控制方式,其中包括文件的读写,存储文件的介质可以是 SSD 固态硬盘或者是 EMMC 等。 其中常用的写文件方式是同步写操作,但是如果是写大文件会对 CPU 造成比较大的负荷,采用异步写的方式比较…...
Liveweb视频汇聚平台支持WebRTC协议赋能H.265视频流畅传输
随着科技的飞速发展和网络技术的不断革新,视频监控已经广泛应用于社会各个领域,成为现代安全管理的重要组成部分。在视频监控领域,视频编码技术的选择尤为重要,它不仅关系到视频的质量,还直接影响到视频的传输效率和兼…...
SQL组合查询
本文讲述如何利用 UNION 操作符将多条 SELECT 语句组合成一个结果集。 1. 组合查询 多数 SQL 查询只包含从一个或多个表中返回数据的单条 SELECT 语句。但是,SQL 也允许执行多个查询(多条 SELECT 语句),并将结果作为一个查询结果…...
方正畅享全媒体新闻采编系统 screen.do SQL注入漏洞复现
0x01 产品简介 方正畅享全媒体新闻生产系统是以内容资产为核心的智能化融合媒体业务平台,融合了报、网、端、微、自媒体分发平台等全渠道内容。该平台由协调指挥调度、数据资源聚合、融合生产、全渠道发布、智能传播分析、融合考核等多个平台组成,贯穿新闻生产策、采、编、发…...
【机器学习】【集成学习——决策树、随机森林】从零起步:掌握决策树、随机森林与GBDT的机器学习之旅
这里写目录标题 一、引言机器学习中集成学习的重要性 二、决策树 (Decision Tree)2.1 基本概念2.2 组成元素2.3 工作原理分裂准则 2.4 决策树的构建过程2.5 决策树的优缺点(1)决策树的优点(2)决策树的缺点(3࿰…...
Flink执行模式(批和流)如何选择
DataStream API支持不同的运行时执行模式(batch/streaming),你可以根据自己的需求选择对应模式。 DataStream API的默认执行模式就是streaming,用于需要连续增量处理并且预计会一直保持在线的无界(数据源输入是无限的)作业。 而batch执行模式则用于有界(输入有限)作业…...
LeetCode:101. 对称二叉树
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:101. 对称二叉树 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...


最终按照如图思路把代码改出来了,但发现因为单片机太低级了,影响了开发效率