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


前言

💗博主介绍:✌全网粉丝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;
}

具体实现截图

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

设计获取

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

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

毕业设计精品实战案例

收藏关注不迷路!!

🌟文末获取设计🌟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值