基于单片机电容测量仪仿真设计

news2024/11/18 3:23:15

文章目录

  • 前言
  • 资料获取
  • 设计介绍
  • 设计程序
  • 具体实现截图
  • 设计获取


前言

💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗
👇🏻 精彩专栏 推荐订阅👇🏻
单片机设计精品实战案例
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人

资料获取

文章底部名片,详细资料联系我。

设计介绍

基于单片机的电容测量仪设计是一个综合性的项目,旨在通过单片机技术实现电容的精确测量。以下是对该设计的一个详细介绍:

一、系统概述
基于单片机的电容测量仪利用单片机的控制和处理能力,结合电容测量原理,通过特定的电路设计实现电容值的测量。该设计通常包括硬件设计、软件设计以及必要的仿真验证等环节。

二、硬件设计

  1. 单片机选择
    选择合适的单片机是整个设计的关键。通常,需要选择具有高性能、低功耗特点的单片机,如STC12C5A60S2等,以满足高精度测量的需求。

  2. 测量电路设计
    电容的测量电路通常采用555定时器构成的多谐振荡器。该电路能够将被测电容的容量转换为振荡器输出的频率信号,进而通过单片机的计数和运算求出电容值。此外,为了提高测量精度和范围,还可以使用可变电阻进行调节。

  3. 信号处理电路
    信号处理电路负责将多谐振荡器输出的频率信号进行放大、滤波和转换,以便单片机能够准确识别和处理。这包括必要的放大器、滤波器和AD转换器等。

  4. 显示模块
    显示模块用于将测量结果直观地展示给用户。常见的显示方式有LED数码管显示、液晶显示屏显示等。

  5. 电源模块
    电源模块负责为整个测量仪提供稳定、可靠的电源供应。为了确保测量精度和稳定性,需要选择高效率、低纹波系数的电源模块。

设计程序

/*      预处理区    */
#include<reg52.h>   //加载"reg52.h"头文件
#include<math.h>    //加载"math.h"头文件

/*  宏定义   */
#define unchar unsigned char    //无符号字符型
#define unint unsigned int      //无符号整型
#define N 10                    //延时参数

/*      数组常量定义  */
unchar code row1[] = ">>Capacitance:<<";    //液晶输出的第一行显示编码
unchar code row2[] = {"0123456789"};        //液晶的0~9编码
unchar code tip_1[] = "Please lini cap";    //液晶输出行
unchar code tip_2[] = "then push'start'";   //液晶输出行
/*  位定义   */
sbit lcd_rs = P2 ^ 0;   //液晶的数据命令选择端
sbit lcd_rw = P2 ^ 1;   //液晶的读写选择端
sbit lcd_en = P2 ^ 2;   //液晶的使能端
sbit show = P1 ^ 0;     //开始按键
sbit clear = P1 ^ 1;    //清屏按键
sbit led = P1 ^ 2;      //电源灯
/*      变量定义    */
unint flag = 0;             //标志位
double count = 0;           //计数
double final = 0;           //高电平时间
double cx = 0;              //电容数值
unint w1, w2, w3, w4, i;    //变量定义 百位,十位,个位,十分位,循环计数位。

/*  自定义函数声明   */
void init();            //初始化函数
void delay(unint);      //延时函数
void write_com(unchar); //液晶写指令
void write_data(unchar);//液晶写数据
void firstline();       //液晶第一行显示
void display();         //电容大小输出函数
void tip();             //初始显示函数
void chose();           //判断按键函数


/*  主函数   */
void main()
{
    init();                 //初始化
    tip();                  //初始显示
    firstline();            //显示 ">>Capacitance:<<"
    display();              //初始输出"000.0"
    while (1)               //死循环
        chose();            //按键判断
}


/*      自定义函数定义区    */
void init()             //初始化函数定义
{
    lcd_rw = 0;         //液晶读写选择端置0,默认只写不读
    write_com(0x38);    //液晶设置16*2显示,5*7点阵,8位数据接口
    write_com(0x0c);    //液晶设置开显示,不显示光标
    write_com(0x06);    //液晶写一个字符后地址指针加一
    write_com(0x01);    //液晶显示清0,数据指针清0
    EX0 = 1;            //开启外部中断0
    IT0 = 1;            //外部中断0采用边沿触发,下降沿有效
    PX0 = 1;            //外部中断0设高优先级
    TMOD = 0x01;        //定时器0工作方式1
    TH0 = 0;            //装初值0
    TL0 = 0;
    ET0 = 1;            //开启定时器中断
    TR0 = 0;            //关闭定时器0
    EA = 1;             //开启总中断
    led = 0;            //开电源指示灯
}

void delay(unint a)                 //延迟函数定义
{
    unint b;                        //定义变量
    for (; a > 0; a--)              //外层循环,由用户定义
        for (b = 0; b < 10; b++);   //内层循环,固定10次
}

void write_com(unchar data1)    //液晶写命令函数
{
    lcd_rs = 0;                 //选择写命令模式
    delay(N);                   //稍作延时
    lcd_en = 1;                 //使能端置给高脉冲
    P0 = data1;                 //将要写的命令字送到数据总线上
    delay(N);                   //稍作延时以待数据稳定
    lcd_en = 0;                 //将使能端置0以完成高脉冲
}

void write_data(unchar data2)   //液晶数据函数
{
    lcd_rs = 1;                 //选择写数据模式
    delay(N);                   //稍作延时
    lcd_en = 1;                 //时能端给高脉冲
    P0 = data2;                 //将要写的数据字送到数据总线上
    delay(N);                   //稍作延时以待数据稳定
    lcd_en = 0;                 //将使能端置0以完成高脉冲
}


void firstline()                //液晶显示第一行
{
    write_com(0x80);            //定位液晶第一行
    for (i = 0; i < 16; i++)    //循环选择光标位
        write_data(row1[i]);    //输出字符
}

void display()              //电容大小输出函数
{
    write_com(0x80 + 0x40); //定位液晶第二行
    write_data(' ');        //显示"空格"
    write_data(' ');        //显示"空格"
    write_data(' ');        //显示"空格"
    write_data(' ');        //显示"空格"
    write_data(row2[w1]);   //显示电容大小"百位"
    write_data(row2[w2]);   //显示电容大小"个位"
    write_data(row2[w3]);   //显示电容大小"十位"
    write_data('.');        //显示"小数点"
    write_data(row2[w4]);   //显示电容大小"十分位"
}

void tip()                      //初始化显示
{
    write_com(0x80);            //定位液晶第一行
    for (i = 0; i < 15; i++)    //循环选择光标位
    {
        write_data(tip_1[i]);   //输出字符"Please lini cap"
        delay(5);               //稍作延时
    }
    write_com(0x80 + 0x40);     //定位液晶第二行
    for (i = 0; i < 16; i++)    //循环选择光标位
    {
        write_data(tip_2[i]);   //输出字符"then push'start'"
        delay(5);               //稍作延时
    }
    delay(20000);               //初始化提示停留时间
    write_com(0x01);            //液晶清屏
}

void chose()                            //按键选择
{
    if (show == 0)                      //判断"开始键"是否按下
    {
        delay(5);                       //延时去键抖
        if (show == 0)                  //砍断"开始建"是否按下
        {
            final = 65536 * count + 256 * TH0 + TL0;    //高电平时间计算
            cx = final / log(2) / 2 / 1.5;              //电容值计算
            if (final > 2000)           //电容"uF"和"nF"区间判断
                cx = cx / 1000;         //自动切换量程
            w1 = (unint)cx / 100;       //提取百位
            w2 = ((unint)cx / 10) % 10; //提取十位
            w3 = (unint)cx % 10;        //提取个位
            w4 = (unint)(cx * 10) % 10; //提取十分位
            display();                  //输出电容值
            if (final > 2000)           //电容"uF"和"nF"区间判断
            {
                write_data('(');        //输出字符"("
                write_data('u');        //输出字符"u"
                write_data('F');        //输出字符"F"
                write_data(')');        //输出字符")"
            }
            if (final <= 2000)          //电容"uF"和"nF"区间判断
            {
                write_data('(');        //输出字符"("
                write_data('n');        //输出字符"u"
                write_data('F');        //输出字符"F"
                write_data(')');        //输出字符")"
            }
        }
    }
    if (clear == 0)             //判断"清0键"是否按下
    {
        delay(5);               //延时去键抖
        if (clear == 0)         //判断"清0键"是否按下
        {
            write_com(0x01);    //清屏
            firstline();        //显示第一行">>Capacitance:<<"
            w1 = 0;             //百位清0
            w2 = 0;             //十位清0
            w3 = 0;             //个位清0
            w4 = 0;             //十分位清0
            display();          //输出"000.0"
        }
    }
}

void int1() interrupt 0 //外部中断0服务函数
{
    flag++;             //改变旗帜位
    if (flag == 1)      //判断旗帜位
        TR0 = 1;        //开启定时器
    if (flag == 2)      //判断旗帜位
    {
        TR0 = 0;        //关闭定时器
        EX0 = 0;        //关闭外部中断0
        EA = 0;         //关闭总中断
        flag = 0;       //旗帜置0
    }
}

void timer() interrupt 1    //定时器0中断服务函数
{
    count++;                //中断次数计数
    TH0 = 0;                //定时器重新赋初值
    TL0 = 0;
}

具体实现截图

在这里插入图片描述
请添加图片描述
请添加图片描述
请添加图片描述

设计获取

文章下方名片联系我即可~

精彩专栏推荐订阅:在下方专栏👇🏻

毕业设计精品实战案例

收藏关注不迷路!!

🌟文末获取设计🌟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch 8.16 和 JDK 23 中的语言环境变化

作者&#xff1a;来自 Elastic Simon Cooper 随着 JDK 23 即将发布&#xff0c;语言环境信息中有一些重大变化&#xff0c;这将影响 Elasticsearch 以及你提取和格式化日期时间数据的方式。首先&#xff0c;介绍一些背景知识。 什么是语言环境&#xff1f; 每次 Java 程序需要…

【Java】static-静态变量、静态方法、工具类、注意事项、args数组的使用

文章目录 一、静态变量特点调用方式 二、静态方法特点调用方式 三、类的类型1.Javabean类2.测试类3.工具类 四、注意事项从代码方面解释1. 上下文清晰2. 静态变量的访问例子注意 3. 静态方法中没有this关键字原因 4. 静态方法只能访问静态变量和静态方法错误原因解决方法 4.非静…

如何获取钉钉webhook

第一步打开钉钉并登录 第二步创建团队 并且 添加自定义 机器人 即可获取webhook

【流计算】流计算概论

前言 作者在之前写过一个大数据的专栏&#xff0c;包含GFS、BigTable、MapReduce、HDFS、Hadoop、LSM树、HBase、Spark&#xff0c;专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12631789.html?fromshareblogcolumn&sharetypeblogcolumn&sharerI…

待办事项应用SideQuests

赶在国庆长假前&#xff0c;自驾&#x1f697;出去玩了几天。 国庆前的错峰出游简直是太香了&#xff01;一路上&#x1f6e3;️畅通无阻&#xff0c;停车&#x1f17f;️不用抢&#xff0c;吃饭&#x1f354;不用等&#xff0c;景点&#x1f3de;️不用排队&#xff0c;拍照&…

Flume实战--Flume中的拦截器详解与操作

在处理大规模数据流时&#xff0c;Apache Flume 是一款功能强大的数据聚合工具&#xff0c;它可以通过拦截器在运行时对Event进行修改或丢弃。本文将详细讲解Flume中的拦截器&#xff0c;包括时间戳拦截器、Host添加拦截器、静态拦截器以及如何自定义拦截器。 拦截器 拦截器的…

《HelloGitHub》第 102 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

LeetCode - #124 二叉树中的最大路径和(Top 100)

文章目录 前言1. 描述2. 示例3. 答案关于我们前言 本题为 LeetCode 前 100 高频题 我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新到 123 期…

Electron 隐藏顶部菜单

隐藏前&#xff1a; 隐藏后&#xff1a; 具体设置代码&#xff1a; 在 main.js 中加入这行即可&#xff1a; // 导入模块 const { app, BrowserWindow ,Menu } require(electron) const path require(path)// 创建主窗口 const createWindow () > {const mainWindow ne…

Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作并通过uboot进行挂载启动

文章目录 1、AB分区镜像制作2、uboot修改3、镜像启动 在上一篇 Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动中&#xff0c;我们通过buildroot制作了根文件系统&#xff0c;并通过 SD卡的形式将其挂载到设备并成功进行了启动&#xff0c;但上一章中&#xff0c;我们的…

启动 Ntopng 服务前需先启动 redis 服务及 Ntopng 常用参数介绍

启动Ntopng服务之前需要先启动redis服务&#xff0c;因为Ntopng服务依赖于redis服务的键值存储。 服务重启 服务启动 Ntopng常用参数&#xff1a; -d 将 Ntopng 进程放入后台执行。默认情况下&#xff0c;Ntop 在前台运行。 -u 指定启动Ntopng执行的用户&#xff0c;默认为…

[论文精读]TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor

期刊名称&#xff1a;IEEE Transactions on Information Forensics and Security 发布链接&#xff1a;TorWard: Discovery, Blocking, and Traceback of Malicious Traffic Over Tor | IEEE Journals & Magazine | IEEE Xplore 中文译名&#xff1a;TorWard&#xff1a;…

2024大二上js高级+ES6学习9.26(闭包,递归函数)

9.26.2024 1.闭包 什么是闭包&#xff1a; 闭包的作用&#xff1a; Return 的函数作为fn的子函数&#xff0c;可以使用fn的局部变量num&#xff0c;局部变量num要等所有使用它的函数调用完毕后才销毁 2.闭包的案例 点击li会发现输出4 在 JavaScript 中&#xff0c;事件处理器&…

C语言 | Leetcode C语言题解之第443题压缩字符串

题目&#xff1a; 题解&#xff1a; void swap(char *a, char *b) {char t *a;*a *b, *b t; }void reverse(char *a, char *b) {while (a < b) {swap(a, --b);} }int compress(char *chars, int charsSize) {int write 0, left 0;for (int read 0; read < charsSi…

软考论文《论模型驱动架构设计方法及其应用》精选试读

论文真题 模型驱动架构设计是一种用于应用系统开发的软件设计方法&#xff0c;以模型构造、模型转换和精化为核心&#xff0c;提供了一套软件设计的指导规范。在模型驱动架构环境下&#xff0c;通过创建出机器可读和高度抽象的模型实现对不同问题域的描述&#xff0c;这些模型…

【HTTP(3)】(状态码,https)

【认识状态码】 状态码最重要的目的&#xff0c;就是反馈给浏览器:这次请求是否成功&#xff0c;若失败&#xff0c;则出现失败原因 常见状态码: 200:OK&#xff0c;表示成功 404:Not Found&#xff0c;浏览器访问的资源在服务器上没有找到 403:Forbidden&#xff0c;访问被…

你还在用Java8吗?

Java 11 在企业中&#xff0c;Java的不同版本使用情况随着时间在不断变化。根据最新的数据报告&#xff0c;以下是一些关键点&#xff1a; Java 11 和 Java 17 成为企业中最常用的长期支持&#xff08;LTS&#xff09;版本&#xff0c;使用率分别为 48% 和 45%&#xff0c;而 …

rtp协议:rtp固定头部介绍

前言&#xff1a; 大家好&#xff0c;今天开始给大家分享rtp协议的相关详细介绍&#xff0c;关于rtsp的介绍&#xff0c;大家可以暂时看官方的文档&#xff1a; https://datatracker.ietf.org/doc/html/rfc2326 本文主要是介绍rtp协议&#xff0c;也就是在开发rtsp过程进行传输…

微积分-反函数6.3(对数函数)

如果 b > 0 b > 0 b>0 且 b ≠ 1 b \neq 1 b1&#xff0c;则指数函数 f ( x ) b x f(x) b^x f(x)bx 不是递增就是递减&#xff0c;因此它是通过水平线测试的单调函数。所以它具有反函数 f − 1 f^{-1} f−1&#xff0c;称为以 b b b 为底的对数函数&#xff…

【数据结构】链表(2)

【LinkedList的模拟实现】 这是java中的一个集合类&#xff0c;可以当成链表来使用&#xff0c;作为链表时&#xff0c;它视为包含三个域&#xff0c;是一个双向链表 【构建LinkedList框架】 public class MyLinkedList {static class ListNode{public int val;public ListNo…