文章目录
前言
💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗
👇🏻 精彩专栏 推荐订阅👇🏻
单片机设计精品实战案例✅
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人
资料获取
文章底部名片,详细资料联系我。
设计介绍
基于单片机的电容测量仪设计是一个综合性的项目,旨在通过单片机技术实现电容的精确测量。以下是对该设计的一个详细介绍:
一、系统概述
基于单片机的电容测量仪利用单片机的控制和处理能力,结合电容测量原理,通过特定的电路设计实现电容值的测量。该设计通常包括硬件设计、软件设计以及必要的仿真验证等环节。
二、硬件设计
-
单片机选择
选择合适的单片机是整个设计的关键。通常,需要选择具有高性能、低功耗特点的单片机,如STC12C5A60S2等,以满足高精度测量的需求。
-
测量电路设计
电容的测量电路通常采用555定时器构成的多谐振荡器。该电路能够将被测电容的容量转换为振荡器输出的频率信号,进而通过单片机的计数和运算求出电容值。此外,为了提高测量精度和范围,还可以使用可变电阻进行调节。
-
信号处理电路
信号处理电路负责将多谐振荡器输出的频率信号进行放大、滤波和转换,以便单片机能够准确识别和处理。这包括必要的放大器、滤波器和AD转换器等。
-
显示模块
显示模块用于将测量结果直观地展示给用户。常见的显示方式有LED数码管显示、液晶显示屏显示等。
-
电源模块
电源模块负责为整个测量仪提供稳定、可靠的电源供应。为了确保测量精度和稳定性,需要选择高效率、低纹波系数的电源模块。
设计程序
/* 预处理区 */
#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;
}
具体实现截图
设计获取
文章下方名片联系我即可~
精彩专栏推荐订阅:在下方专栏👇🏻
收藏关注不迷路!!
🌟文末获取设计🌟