单片机数字万用表课程设计

2024-08-13

单片机数字万用表课程设计(精选6篇)

单片机数字万用表课程设计 篇1

目:

基于单片机的数字多用表设计

业:

电力系统及其自动化

级:

本自动化

名:

学号:

指导老师:

小组成员:

成绩:

摘要

本次设计采用单片机芯片

AT89S51与ADC0809设计一个数字电压表,能够测量0-5V之间的直流电压值,四位数码显示,但要求使用的元器件数目最少。为使系统更加稳定,使系统的整体精度得以保障,本电路使用了ADC0809数据转换芯片,单片机系统设计采用AT89S51作1

为主控芯片,配以RC上电复位电路和震荡电路,程序每执行周期耗时缩到最短,这样保证了系统的实时性。

关键词

数字万用表

AT89S51单片机

AD转换与控制

目录

摘要„„„„„„„„„„„„„„„„„„„„„„„„„2 关键词„„„„„„„„„„„„„„„„„„„„„„„„2 绪论

1.数字万用表设计背景„„„„„„„„„„„„„„„„„4 1.1 数字万用表的设计目的和意„„„„„„„„„„„„„

41.2 数字万用表的设计依据…………………………………….4

1.3 数字万用表设计重点解决的问题„„„„„„„„„„„„4

2.数字万用表总体设计方案……………………………………5 2.1数字万用表的基本原理……………………..…….…….5 2

2.2芯片选择及功能简介………………………………………..2.3电路原理图及仿真图……………………………………..……….2.4系统板上硬件连线………………………………..………..…… 2.5程序设计内容………………………………..………..…… 2.6C语言源程序………………………………..………..…… 总结……………………………………….….………… 4心得体会 参考文献……………………………..…….………..13

绪论

数字万用表亦称数字多用表,简称

DMM(Digtial Multimeter)。它是采用数字化测量技术,把连续的模拟量转换成不连续的,离散的数字形式并加以显示的仪表。传统的指针式万用表功能单精度低,不能满足数字化时代的需求,采用单片机的数字万用表,已被广泛用于电子及工业测量、工业自动化仪表、自动测试系统等智能测量领域,显示出强大的生命力。数字万用表具有以下几点优势:(1)显示清晰直观,计数准确

为了提高观察的清晰度,新型的手势式数字万用表已普遍采用字高为26mm的大屏幕LCD(液晶显示器)。有些数字万用表还增加了背光源,以便于夜间观察读数。(2)显示位数

数字万用表的显示位数通常为3位到8位半。

(3)准确度高

准确度是测量结果中系统误差与随机误差的综合。它表示测量结果与真值的一致程度,也反映了测量误差的大小,准确度愈高,测量误差愈小。数字万用表的准确度远优于指针万用表。

(4)

分辨力高

数字万用表在最低电压量程上末位1个字所代表的电压值,称作仪表的分辨率,宏观世界反映了仪表灵敏度的高低,分辨率随显示位数的增加而提高。(5)

测试功能强

数字万用表不止可以测量直流电压,直流电流,电阻二3

极管正向压降等等。(6)测量范围宽

数字万用表可满足常规电子测量的需要,智能数字万用表的测量范围更宽广。

(7)测量速率快

数字万用表在每秒中内对被电压的测量次数称为测量速率,单位是次/秒。它主要取决于A/D转换器的转换速率。一般数字万用表的测量速率为2到5次/秒。有的呢过达到20次/秒以上,另外有的比这个还要高得多。数字万用表可满足不同用户对测量速率的需要。

(8)

输入阻抗高

数字万用表电压档具有很高的输入阻抗,通常为10至10000M欧姆,从被测电路上吸取的电流小,不会影响被测信号源的工作状态,能减小由信号源内阻引起的测量误差。(9)保护功能完善,抗干扰能力强

数字万用表具有比价完善的保护电路,过载能力强,新型的数字万用表还增加了高压保护器件,能防止浪涌电压。

本设计就是居于这个设计理念一个基于单片机的数字万用表。该设备具有直观简单的优点。并且能深入的说明 万用表的测量原理。能直观的了解万用表各个部分的结构和测试原则。

1数字万用表的设计背景

在本章中主要介绍了系统的设计原则和总体方案及其系统概述等。

1.1数字万用表的设计目的和意义

数字万用表是当前电子、电工、仪器、仪表和测量领域大量使用的一种基本测量,已被广泛应用于电子及电工测量、工业自动化仪表、自动测试系统等智能化测量领域,示出强大的生命力。随着时代科技的进步,数字万用表的功能越来越强大,把电量及非电量的测量技术提高到崭新水平。

1.2 数字万用表的设计依据

根据数字万用表的原理,结合以下的设计要求:“设计一个数字万用表,能够测量直流电压值,直流电流、直流电阻。实现多级量程的直流电压测量,其量程范围是200mv、2v ,20v,200v和500v.实现多级量程的直流电流测量,其量程范围是2mA,20mA,200mA、2A和20A.实现多级量程的电阻测量,其量程范围是200、2k ,20k,200k和2M。由此设想出以下的解决方法,即数字万用表的系统由分流电阻、分压电阻、基准电阻、电容测试芯片电路、51单片机最小系统、显示部分、报警部分、AD转换和控制部分组成。为使系统更加稳定,使系统整体精度得以保障。

1.3数字万用表设计重点解决的问题

本设计重点要解决的问题是对不同量程的各种测量内容的转换,还有就是各部分电路组合成一个完整的数字万用表,而难点解决的问题就是程序的设计,要保正其可行性从而保证设计的正确性。数字万用表总体设计方案 2.1数字万用表的基本原理

数字万用表的最基本功能是能够测量直流电压,直流电流,还有能够测电量阻。

下面我们分别介绍各个部分的组成:(1)、模数(A/D)转换与数字显示电路

常见的物理量都是幅值(大小)连续变化的所谓模拟量(模拟信号)。指针式仪表可以直接对模拟电压、电流进行显示。而对数字式仪表,需要把模拟电信号(通常是电压信号)转换成数字信号,再进行显示和处理(如存储、传输、打印、运算等)。数字信号与模拟信号不同,其幅值(大小)是不连续的。这种情况被称为是”量化的"。若最小量化单位(量化台阶)为,则数字信号的大小一定是的整数倍,该整数可以用二进制数码表示。但为了能直观地读出信号大小的数值,需经过数码变换(译码)后由数码管或液晶屏显示出来。(2)、多量程数字电压表原理

在基准数字电压表头前面加一级分压电路(分压器),可以扩展直流电压测量的量程。

(3)多量程数字电流表原理 测量电流的原理是:根据欧姆定律,用合适的取样电阻把待测电流转换为相应的电压,再进行测量。

(4)电阻测量原理

数字万用表中的电阻档采用的是比例测量法。

由稳压管ZD提供测量基准电压,流过标准电阻和被测电阻的电流基本相等

2.2芯片选择及功能简介

这次的课程设计中,我们这一种选择了芯片AT89S51和ADC0809。

AT89S51是一个低功耗,高性能CMOS 8位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,功能强大的微型计算机的AT89S51可为许多嵌入式控制应用系统提供高性价比的解决方案。

AT89S51有PDIP、PLCC、TQFP三种封装方式,其中最常见的就是采用40Pin封装的双列直接PDIP封装,芯片共有40个引脚,引脚的排列顺序为从靠芯片的缺口左边那列引脚逆时针数起,依次为1、2、3、4、„、40,其中芯片的1脚5

顶上有个凹点。在单片机的40个引脚中,电源引脚2根,外接晶体振荡器引脚2根,控制引脚4根以及4组8位可编程I/O引脚32根。

1、主电源引脚(2根)VCC(Pin40):电源输入,接+5V电源GND(Pin20):接地线

2、外接晶振引脚(2根)XTAL1(Pin19):片内振荡电路输入端XTAL2(Pin20):片内振荡电路输出端

3、控制引脚(4根)RST/VPP(Pin9):复位引脚,出现2个机器周期的高电平将使单片机复位。ALE/PROG(Pin30):地址锁存允许信号PSEN(Pin29):外部存储器读选通信号EA/VPP(Pin31):程序存储器的内外部选通,接低电平从外部程序存储器读指令,如果接高电平则从内部程序存储器读指令。

4、可编程输入/输出引脚(32根)AT89S51单片机有4组8位的可编程I/O口,分别位P0、P1、P2、P3口,每个口有8位(8根引脚),共32根。PO口(Pin39~Pin32):8位双向I/O口线,名称为P0.0~P0.7P1口(Pin1~Pin8):8位准双向I/O口线,名称为P1.0~P1.7P2口(Pin21~Pin28):8位准双向I/O口线,名称为P2.0~P2.7P3口(Pin10~Pin17):8位准双向I/O口线,名称为P3.0~P3.7。AT89S51的主要性能参数:与MCS-51产品指令系统完全兼容

4k字节在系统编程(ISP)Flash闪速存储器

1000次擦写周期

4.0-5.5V的工作电压范围 全静态工作模式:0Hz-33MHz 三级程序加密锁

128×8字节内部RAM

32个可编程I/O口线 2个16位定时/计数器 6个中断源 全双工串行UART通道

低功耗空闲和掉电模式

中断可从空闲模唤醒系统 看门狗(WDT)及双数据指针 掉电标识和快速编程特性 灵活的在系统编程(ISP字节或页写模式)ADC0809是美国国家半导体公司生产的CMOS工艺8通道,8位逐次逼近式A/D模数转换器。其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。是目前国内应用最广泛的8位通用A/D芯片 1.主要特性

1)8路输入通道,8位A/D转换器,即分辨率为8位。

2)具有转换起停控制端。

3)转换时间为100μs(时钟为640kHz时),130μs(时钟为500kHz时)

4)单个+5V电源供电

5)模拟输入电压范围0~+5V,不需零点和满刻度校准。

6)工作温度范围为-40~+85摄氏度

7)低功耗,约15mW。2.内部结构

ADC0809是CMOS单片型逐次逼近式A/D转换器,内部结构如图所示,它由8路模拟开关、地址锁存与译码器、比较器、8位开关树型A/D转换器、逐次逼近寄存器、逻辑控制和定时电路组成。3.外部特性(引脚功能)

ADC0809芯片有28条引脚,采用双列直插式封装,如图所示。下面说明各引脚功能。

IN0~IN7:8路模拟量输入端。

2-1~2-8:8位数字量输出端。

ADDA、ADDB、ADDC:3位地址输入线,用于选通8路模拟输入中的一路

ALE:地址锁存允许信号,输入,高电平有效。

START: A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。

EOC: A/D转换结束信号,输出,当A/D转换结束时,此端输出一个高电平(转换期间一直为低电平)。

OE:数据输出允许信号,输入,高电平有效。当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。

CLK:时钟脉冲输入端。要求时钟频率不高于640KHZ。

REF(+)、REF(-):基准电压。

Vcc:电源,单一+5V。

GND:地。ADC0809的工作过程

首先输入3位地址,并使ALE=1,将地址存入地址锁存器中。此地址经译码选通8路模拟输入之一到比较器。START上升沿将逐次逼近寄存器复位。下降沿启动 A/D转换,之后EOC输出信号变低,指示转换正在进行。直到A/D转换完成,EOC变为高电平,指示A/D转换结束,结果数据已存入锁存器,这个信号可用作中断申请。当OE输入高电平时,输出三态门打开,转换结果的数字量输出到数据总线上。

转换数据的传送 A/D转换后得到的数据应及时传送给单片机进行处理。数据传送的关键问题是如何确认A/D转换的完成,因为只有确认完成后,才能进行传送。为此可采用下述三种方式。

(1)定时传送方式

对于一种A/D转换器来说,转换时间作为一项技术指标是已知的和固定的。例如ADC0809转换时间为128μs,相当于6MHz的MCS-51单片机共64个机器周期。可据此设计一个延时子程序,A/D转换启动后即调用此子程序,延迟时间一到,转换肯定已经完成了,接着就可进行数据传送。

(2)查询方式

A/D转换芯片由表明转换完成的状态信号,例如ADC0809的EOC端。因此可以用查询方式,测试EOC的状态,即可确认转换是否完成,并接着进行数据传送。

(3)中断方式

把表明转换完成的状态信号(EOC)作为中断请求信号,以中断方式进行数据传送。

不管使用上述哪种方式,只要一旦确定转换完成,即可通过指令进行

数据传送。首先送出口地址并以信号有效时,OE信号即有效,把转换数据送上数据总线,供单片机接受。

2.3电路原理图

2.4系统板上硬件连接

a)把“单片机系统”区域中的P1.0-P1.7与“动态数码显示”区域中的ABCDEFGH端口用8芯排线连接。

b)把“单片机系统”区域中的P2.0-P2.7与“动态数码显示”区域中的S1S2S3S4S5S6S7S8端口用8芯排线连接。

c)把“单片机系统”区域中的P3.0与“模数转换模块”区域中的ST端子用导线相连接。

d)把“单片机系统”区域中的P3.1与“模数转换模块”区域中的OE端子用导线相连接。

e)把“单片机系统”区域中的P3.2与“模数转换模块”区域中的EOC端子用导线相连接。

f)把“单片机系统”区域中的P3.3与“模数转换模块”区域中的CLK端子用导线相连接。

g)把“模数转换模块”区域中的A2A1A0端子用导线连接到“电源模块”区域中的GND端子上。

h)把“模数转换模块”区域中的IN0端子用导线连接到“三路可调电压模块”区域中的VR1端子上。

i)把“单片机系统”区域中的P0.0-P0.7用8芯排线连接到“模数转换模块”区域中的D0D1D2D3D4D5D6D7端子上。

2.5程序设计内容

1.由于ADC0809在进行A/D转换时需要有CLK信号,而此时的ADC0809的CLK是接在AT89S51单片机的P3.3端口上,也就是要求从P3.3输出CLK信号供ADC0809使用。因此产生CLK信号的方法就得用软件来产生了。

2.由于ADC0809的参考电压VREF=VCC,所以转换之后的数据要经过数据处理,在数码管上显示出电压值。实际显示的电压值(D/256*VREF)

2.6C语言源程序

#include

unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f};

unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,0x00};unsigned char dispbuf[8]={10,10,10,10,10,0,0,0};unsigned char dispcount;unsigned char getdata;unsigned int temp;

long int i;

代替原来的unsigned char i;

sbit ST=P3^0;sbit OE=P3^1;sbit EOC=P3^2;sbit CLK=P3^3;

void main(void){

ST=0;

OE=0;

ET0=1;

ET1=1;

EA=1;

TMOD=0x12;

TH0=216;

TL0=216;

TH1=(65536-5000)/256;

TL1=(65536-5000)%256;

TR1=1;

TR0=1;

ST=1;

ST=0;

while(1)

{

if(EOC==1)

{

OE=1;

getdata=P0;

OE=0;

i=getdata*196;

dispbuf[5]=i/10000;

i=i%10000;

dispbuf[6]=i/1000;

i=i%1000;

dispbuf[7]=i/100;

ST=1;

ST=0;

}

} }

void t0(void)interrupt 1 using 0

{

CLK=~CLK;}

void t1(void)interrupt 3 using 0

{

TH1=(65536-6000)/256;

TL1=(65536-6000)%256;

P1=dispcode[dispbuf[dispcount]];

P2=dispbitcode[dispcount];

if(dispcount==5)

/*原来的:

temp = getdata * 235;

temp=temp/128;

i=5;

dispbuf[0]=10;dispbuf[1]=10;dispbuf[2]=10;dispbuf[3]=10;dispbuf[4]=10;dispbuf[5]=0;dispbuf[6]=0;dispbuf[7]=0;while(temp/10)

{

dispbuf[i]=temp%10;

temp=temp/10;

i++;

} dispbuf[i]=temp;*/

//定时器0 中断服务

//定时器1 中断服务

{

P1=P1 | 0x80;

}

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

3.总结

设计结果综述:

(1)、数字万用表完成的功能主要是对电压、电流、电阻的测量,它主要由分流电阻、分压电阻、基准电阻、51单片机最小系统、显示部分、报警部分、AD转换和控制部分组成。(2)、数字万用表属于一种测量工具,其本身的好坏直接影响到测量结果,因此上面的设计在实物上只可以测直流电压,在仿真上可以测出直流电压电流和电阻。(3)、单片机部分跟AD转换部分是整个设计的核心,ADC0809的参考电压VREF=VCC,所以转换之后的数据要经过数据处理,在数码管上显示出电压值。实际显示的电压值(D/256*VREF);AT89S51单片机作为主控芯片,配以RC上电复位电路和震荡电路,使系统稳定运行。(4)、在本次软件设计过程中,采用的是C语言程序。

4心得体会

两周的课程设计结束了,在这次的课程设计中不仅检验了我所学习的知识,也培养了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情。通过此次课程设计,使我更加扎实的掌握了有关单片机方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的仿真环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所12

在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!通过这次的课程设计,使我更加透彻的了解到我在单片机这方面的知识的浅薄,从而促进了握要更加了解单片机知识的决心。

5参考文献

C语言程序设计第三版

51单片机开发与应用基础教程13

C语言版)

单片机数字万用表课程设计 篇2

关键词:STM32单片机,数字式,万用表

制作一台功能齐全, 精度较高, 测量范围较广的数字式万用表, 电路可能会比较复杂, 为了更好的完成设计, 我们采用模块化的思想, 将整个系统分成控制器、电阻测量电路、电感测量电路、电容测量电路、显示电路五个部分。其模块图如图1所示。

一、控制器的选择

要测电阻、电容、电感的值的大小, 并且要能够自动切换量程, 不用一个微处理器, 电路可能会非常复杂, 制作成本也会很高, 为了简化电路, 降低成本, 并且使该表具有更大的灵活性, 我们决定采用单片机来作为总控制器, 协调各个模块的工作, 使系统有条不紊地进行各项测量工作, 并将结果准确无误的显示出来。

市场的的单片机种类繁多, 功能各不相同。STM32核心控制模块基于高性能、低成本、低功耗的ARM Cortex-M3内核, 按照MIPS值计算, Cortex M3的STM32有更丰富和灵活的外设, 且有多个串口, CAP和PWM。STM32作频率为可达72MHz, 内置高速存储器, 高达512K字节的闪存和64K字节的SRAM, 丰富的增强I/O端口和联接到两条APB总线的外设。STM32包含3个12位的ADC、4个通用16位定时器和2个PWM定时器, 还包含标准和先进的通信接口:多达2个I2C接口、3个SPI接口、2个I2S接口、1个SDIO接口、5个USART接口、一个USB接口和一个CAN接口。STM32可工作于-40°C至+105°C的温度范围, 供电电压5V, 一系列的省电模式满足低功耗应用的要求。

二、电感测量电路

电感的测量也有比较多的方法, 常见的有阻抗法、振荡测频率法。阻抗法的操作较为复杂, 对电路要求高, 测量精度较低。振荡测频率法是采用三点式LC谐振电路来使电路发生谐振, 对产生的正弦波进行整形, 形成方波, 再通过单片机对整形之后的信号进行频率测量, 根据频率f的大小, 基准电容的C0大小, 则可得电感值Lx的大小 待测电感与基准电感的差距越小, 测量就越准确, 因此对于不同电感值电感, 应当采用不同的基准电感。电路的切换仍然用继电器来控制, 在此为避免重复, 继电器部分不再重述, 与切换电阻的方法是完全一样的。为了简化电路, 我们采用两个量级的基准电感10m H和10UH。电路如图2所示。

理论上, 以上测量是比较准确的, 但是, 也存在非线性的误差, 即用公式计算出来的结果不是完全准确的, 并且随着待测电感与基准电感差距的增大, 误差累积增大。

三、电容测量电路

对于一般的电容电容的测量方法也很多。常见的有脉宽法、充电测电压法、充电测时间 (频率) 法、容抗法、振荡测频率法等等。利用待测电容与74LS14组成多谐振荡器, 使施密特触发器不断翻转, 输出端就可以得到一个一定频率的方波信号。不同的电容得到的方波频率不同, 且电容的大小同频率成正比。所以, 我们可以测基准电容C0的振荡频率f0, 再测出待测电容的振荡频率fx, 则

电路如图3所示。

四、电阻测量电路

对于电阻的测量, 人类过去的几百年的历史中, 总结出了许多种方法。对于不同阻值的电阻, 为了达到较高的测量精度, 也有不同的测量方法, 比如:分压法、伏安法, 恒流源测小电阻法, 小电流测大电阻法。对于一般电阻, 我们采用分压法, 将待测电阻与基准电阻串联起来, 再将基准电压加在两者之上, 用ADC测量待测电阻分得电压值, 则待测电阻Rx为ADC值, ADC的满量程值ADCREF, 基准电阻R0的函数为:

(一) 基准电压的获取。

MC1403可以产生2.5V的基准电压, 只需在产生的基准电压的基础上用变阻器进行分压, 即可得到2V的基准电压。

(二) 自动切换量程。

在电阻的测量过程中, 待测电阻阻值越接近基准电阻阻值, 所测得的结果就越准确。所以为了使各个量级上的电阻都测得比较准确, 在测量过程中需要切换量程, 也就是采用不同的基准电阻。电阻切换电路需要在导通时电阻很小, 断开时电阻很大, 以避免对基准电阻产生影响。综合各方面的因素, 切换电路采用电磁继电器。其在导通时电阻只有几十毫欧, 断开时电阻无穷大, 很符合要求。电磁继电器需要用达林顿管来驱动。其切换控制电路如图4。

五、结语

经过测试, 我们可以测量电阻的误差在0.5%以内, 电感的误差在1%以内, 电感的误差在2%以内。本系统误差主要由恒流源、AD真有效值转换、双积分ADC器件等几个方面所带来的误差。AD真有效值转换, 在误差允许的范围内可以将所测交流电压转换成对应的真有效值, 但不可避免地受到环境温度的影响, 造成转换时可能引起误差;由于环境温度的改变, 在用恒流法测电阻时, 会引起恒流源不为一个定值, 导致所测电阻流过恒流源所产生的电压有所偏差, 特别是在测小电阻时, 插槽与被测小电阻之间的接触电阻会引起测量的较大误差;双积分ADC器件与前端处理电路同样受到温度、电磁场、工频干扰的影响, 会引起数据的不稳定。

参考文献

[1].杨旭, 裴元庆, 王兆安.开关电源技术[M].北京:机械工业出版社, 2004, 1:61~125

[2].王兆安, 黄俊.电力电子技术[M].北京:机械工业出版社, 2000, 第4版:170~178

单片机数字万用表课程设计 篇3

关键词:数字万用表 MSP430F149 单片机

中图分类号:TM933文献标识码:A文章编号:1674-098X(2012)09(b)-0041-02

1 数字万用表的工作原理

数字万用表的最基本功能是测量直流电压、直流电流、交流电压、电阻、温度、电容及频率,其基本组成见图1。

通过功能量程的选择把被测物理量连接到相应的参数转换电路上,经过电路转换成电压或频率使单片机能够直接测量,单片机通过拨位开关得到被测物理量的类型,再通过cpu计算出被测物理量的大小,然后控制液晶显示测量结果。

2 MSP430F149芯片简介

MSP430F149单片机是美国TI公司推出的16位高性能单片机,具有丰富的片内资源,包括时钟模块、捕获/比较模块、Flash模块、看门狗定时器模块、定时器模块、以及通用I/O口模块等。

3 参数转换电路

3.1 直流电压测量电路

直流电压电路如图2所示,可选择3个档位0~3V,0~30V,0~300V。通过电阻分压把被测电压调整到AD的量程(0~3.3V)内。本设计AD转换使用单片机片内集成AD,AD参考电压为3.3V。图中1M电阻和104电容组成低通滤波器可以滤除表笔与被测物体接触时产生的高频信号和空间的电磁干扰使得测量结果更加稳定[1]。

电阻计算:由于电压表要求接到电路上时对电路的电压影响要下,所以输入阻抗越大越好,本设计选择输入阻抗Ro=10M。

3.2 直流电流测量电路

测量电流的原理是根据欧姆定律,用合适的取样电阻把待测电流转换为相应的电压,再进行测量,被测电流Ii=Ui/R,Ui=IiR。从图3可以看出,测量电路图中有2A保险丝管,电流过大时会快速熔断,起过流保护作用,由于测量电流是可能会有大电流通过采样电阻所以要考虑采样电阻的功率,所以R4采用1W的电阻,R3、R2采用2W的绕线电阻。图中1M电阻和104电容组成低通滤波器可以滤除表笔与被测物体接触时产生的高频信号和空间的电磁干扰使得测量结果更加稳定[2]。

各档分流电阻的阻值是这样计算的,先计算最大电流档的分流电阻R4,,再计算下一档的R3,,依次可计算出R2和R1。

3.3 电阻测量电路

数字万用表中的电阻档采用的是比例测量法,其电阻测量电路见图4。由稳压芯片提供测量基准电压3.3V,流过标准电阻Ro和被测电阻Rx的电流基本相等,数字表头的输入阻抗很高,其取用的电流可忽略不计,图中1M电阻和104电容组成低通滤波器可以滤除表笔与被测物体接触时产生的高频信号和空间的电磁干扰使得测量结果更加稳定。A/D转换器的测量电压和测量基准电压具有如下关系:即:。

电阻计算:当被测电阻阻值在200Ω以下是用100Ω的电阻做分压电阻,;

以此类推…

可计算出。

3.4 交流电压测量电路

交流电压测量是通过二极管1N4007把被测电压进行半波整流,再通过分压电阻把电压降低,再通过电阻和电容组成低通滤波器滤成直流,再经过AD转化成数字值,再经过cpu计算出电压有效值,由于1N4007是普通整流二极管,反向恢复速度较慢所以不能测量高频交流电压[3]。

电阻计算:为了使200V档的分压比为100左右所以R1取9k;750V档的分压比为300所以R2取3k;(图5)

3.5 温度测量电路

(1)LM35简述

LM35系列是精密集成电路温度传感器,其输出的电压线性地与摄氏温度成正比。因此,LM35比按绝对温标校准的线性温度传感器优越感得多。LM35系列传感器生产制作时已经过校准,输出电压与摄氏温度一一对应,使用极为方便。灵敏度为10.0mV/℃,精度在0.4~0.8℃(-55~+150℃溫度范围内),重复性好,低输出阻抗,线性输出和内部精密校准使其与读出或控制电路接口简单和方便,可单电源和正负电源工作[4]。(图6)

(2)应用电路

3.6 频率和电容测量电路

(1)频率测量

频率测量主要是软件设计,单片机I/O口有电平判决功能,所以无论是,正弦波、三角波、还是锯齿波,只需把被测信号接到单片机I/O口上就可以测量,为了防止被测信号的驱动能力过强损坏单片机,在被测信号与单片机之间接上27k电阻防止电流过大。软件设置I/O口下降沿中断,每来一个下降沿计数加1,再用定时器B定时1秒,每次定时中断时读出计数结果并且清零计数。

(2)电容测量电路

电容测量是把电容转化成频率再测量频率来算出电容大小,电容频率变换电路利用lf356高速放大器和电阻电容产生自激振荡,频率。电容频率变换电路如图7所示。其中R为图中R1,R2或R3。因为本设计中单片机测量频率不能高于20kHz,所以要根据上面公式计算出各个电容档对应的电阻,使得振荡产生的频率在单片机测量范围内。例如:当测量nf级电容式对应电阻为27k时,产生的频率范围是168Hz~16.8kHz,满足频率测量范围。

4 系统软件流程

软件设计是设计中最难的部分,它需要把所有的功能综合在一起,由于本设计的功能比较多,要让多种测量方式之间能正常转换,需要设置多种中断,要控制各种中断的开启时间和关闭时间,软件设计包括,AD转换,测量结果转换,LCD显示驱动。系统总体流程图如图8所示,系统开机后,首先进行LCD初始化,ADC初始化,定时器初始化,I/O口中断初始化,开总中断,然后根据按键的输入状态,执行相应处理。

5 结语

本论文结合数字万用表项目,主要论述了各种物理量的测量原理、硬件和软件的设计等。选用了具有较大的片内存储空间的高性能16位微处理器MSP430F149作为控制核心,利用片内高速12位AD转换器做AD转换,利用拨位开关选择测量物理量,利用LCD作静态显示。本文所讨论的数字万用表着眼于低硬件成本、高稳定可靠性、使用方便。具有极高的推广价值。

参考文献

[1]魏小龙.MSP430系列单片机接口技术及系统设计实例[M].北京.北京航空航天大学出版社.2002.45-47.

[2]常健生.检测与转换技术[M].机械工业出版社.2000.180-183.

[3]童诗白.模拟电子技术基础[M].高等教育出版社.2001.13-21.

单片机数字万用表课程设计 篇4

题:

基于51单片机数字温度计设计

业:

电子信息工程

级:

号:

名:

指导教师:

设计日期:

成绩:

XX大学XX学院电气学院

基于51单片机数字温度计设计

一、设计目的1、掌握单片机电路的设计原理、组装与调试方法。

2、掌握LED数码显示电路的设计和使用方法。

3、掌握DS18B20温度传感器的工作原理及使用方法。

二、设计要求

1、本次单片机课程设计要求以51系列单片机为核心,以开发板为平台。

2、设计一个数字式温度计,要求使用DS18B20温度传感器测量温度。

3、经单片机处理后,要求用4位一体共阴LED数码管来设计显示电路,以显示测量的温度值。

4、另外还要求在设计中加入报警系统,如果我们所设计的系统用来监控某一设备,当设备的温度超过或低于我们所设定的温度值时,系统会产生报警。

5、要求在设计中加入上下限警报温度设置电路。

三、设计的具体实现

1数字温度计设计的方案

在做数字温度计的单片机电路中,对信号的采集电路大多都是使用传感器,这是非常容易实现的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。采集之后,通过使用51系列的单片机,可以对数据进行相应的处理,再由LED显示电路对其数据进行显示。

2系统设计框图

温度计电路设计总体设计方框图如下图所示,控制器采用单片机AT89C51,温度传感器采用DS18B20,用4位一体共阴LED数码管以串口传送数据实现温度显示。此外,还添加了报警系统,对温度实施监控。

3主控器AT89C51芯片

对于单片机的选择,可以考虑使用8031与8051系列,由于8031没有内部RAM,系统又需要大量内存存储数据,因而不适用。AT89C51

以低价位单片机可为提供许多高性价比的应用场合,可灵活应用于各种控制领域,对于简单的测温系统已经足够。单片机AT89C51具有低电压供电和体积小等特点,四个端口只需要两个口就能满足电路系统的设计需要该器件是INTEL公司生产的MCS一5l系列单片机中的基础产品,采用了可靠的CMOS工艺制造技术,具有高性能的8位单片机,属于标准的MCS—51的CMOS产品。

AT8951的管脚如下图所示:

AT89C51芯片管脚图

4时钟电路

80C51时钟有两种方式产生,即内部方式和外部方式。80C51中有一个构成内部震荡器的高增益反向放大器,引脚XTAL1和XTAL2分别是该放大器的输入端和输出端。本次采用内部震荡电路,瓷片电容采用22PF,晶振为12MHZ。

晶体震荡电路图

复位电路

单片机系统的复位电路在这里采用的是上电+按钮复位电路形式,其中电阻R采用10KΩ的阻值,电容采用10μF的电容值。

复位电路

温度传感电路

DALLAS

最新单线数字温度传感器DS18B20是一种新型的“一线器件”,其体积更小、更适用于多种场合、且适用电压更宽、更经济。DALLAS

半导体公司的数字化温度传感器DS18B20是世界上第一片支持“一线总线”接口的温度传感器。温度测量范围为-55~+125

摄氏度,可编程为9位~12

位转换精度,测温分辨率可达0.0625摄氏度,分辨率设定参数以及用户设定的报警温度存储在EEPROM

中,掉电后依然保存。被测温度用符号扩展的16位数字量方式串行输出。

DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。DS18B20的管脚排列、各种封装形式,DQ

为数据输入/输出引脚。开漏单总线接口引脚。当被用着在寄生电源下,也可以向器件提供电源;GND为地信号;VDD为可选择的VDD引脚。当工作于寄生电源时,此引脚必须接地,如下图所示。

DS18B20管脚图

显示电路

对于数字温度的显示,我们采用4位一体共阴LED数码管。足够显示0~100中各位数,并且还能显示一位小数部分。

4位LED数码显示管

温度报警电路

对于数字温度计的设计,除了温度的数字显示功能外还加入了报警系统,当测量的温度超过或低于我们所设定的温度值时,系统会产生报警并亮红灯报警。

其电路图如下所示。

蜂鸣器红灯报警系统电路图

源程序:

/********************************************************************

*

程序名;

基于51单片机的温度计

*

能:

实时测量温度,超过上下限报警,报警温度可手动调整。K1是用来

*

进入上下限调节模式的,当按一下K1进入上限调节模式,再按一下进入下限

*

调节模式。在正常模式下,按一下K2进入查看上限温度模式,显示1s左右自动

*

退出;按一下K3进入查看下限温度模式,显示1s左右自动退出;按一下K4消除

*

按键音,再按一下启动按键音。在调节上下限温度模式下,K2是实现加1功能,*

K1是实现减1功能,K3是用来设定上下限温度正负的。

*********************************************************************/

#include

#include//将intrins.h头文件包含到主程序(调用其中的_nop_()空操作函数延时)

#define

uint

unsigned

int

#define

uchar

unsigned

char

uchar

max=0x00,min=0x00;

//max是上限报警温度,min是下限报警温度

bit

s=0;

//s是调整上下限温度时温度闪烁的标志位,s=0不显示200ms,s=1显示1s左右

bit

s1=0;

//s1标志位用于上下限查看时的显示

void

display1(uint

z);

#include“ds18b20.h“

#include“keyscan.h“

#include“display.h“

/******************************************************/

/*

主函数

/

/*****************************************************/

void

main()

{

beer=1;

//关闭蜂鸣器

led=1;

//关闭LED灯

timer1_init(0);

//初始化定时器1(未启动定时器1)

get_temperature(1);

//首次启动DS18B20获取温度(DS18B20上电后自动将EEPROM中的上下限温度复制到TH和TL寄存器)

while(1)

{

keyscan();

get_temperature(0);

display(temp,temp_d*0.625);

alarm();

}

}

/**********************************************************************

*

程序名;

ds18b20数码管动态显示头文件

*

能:

通过定时器0延时是数码管动态显示

**********************************************************************/

#ifndef

__ds18b20_display_H__

#define

__ds18b20_display_H__

#define

uint

unsigned

int

//变量类型宏定义,用uint表示无符号整形(16位)

#define

uchar

unsigned

char

//变量类型宏定义,用uchar表示无符号字符型(8位)

sbit

wei1=P2^4;

//可位寻址变量定义,用wei1表示P2.4口

sbit

wei2=P2^5;

//用wei2表示P2.5口

sbit

wei3=P2^6;

//用wei3表示P2.6口

sbit

wei4=P2^7;

//用wei4表示P2.7口

uchar

num=0;

//定义num为全局无符号字符型变量,赋初值为‘0’

uchar

code

temperature1[]={

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//定义显示码表0~9

uchar

code

temperature2[]={

0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

//带小数点的0~9.uchar

code

temperature3[]={

0x00,0x80,0x40,0x76,0x38};//依次是‘不显示’‘.’‘-’‘H’‘L’

/******************************************************/

/

延时子函数

/

/*****************************************************/

void

display_delay(uint

t)

//延时1ms左右

{

uint

i,j;

for(i=t;i>0;i--)

for(j=120;j>0;j--);

}

/******************************************************/

/*

定时器1初始化函数

/

/*****************************************************/

void

timer1_init(bit

t)

{

TMOD=0x10;

TH0=0x3c;

TL0=0xb0;

EA=1;

ET1=1;

TR1=t;

//

局部变量t为1启动定时器1,为0关闭定时器1

}

/******************************************************/

/*

定时器1中断函数

/

/*****************************************************/

void

timer1()

interrupt

{

TH0=0x3c;

//重新赋初值,定时50ms

TL0=0xb0;

num++;

//每进入一次定时器中断num加1(每50ms加1一次)

if(num<5)

{s=1;if(w==1){beer=1;led=1;}else{beer=1;led=1;}}

else

//进入4次中断,定时200ms时若报警标志位w为‘1’则启动报警,不为‘1’不启动

//实现间歇性报警功能

{s=0;if(w==1){beer=0;led=0;}else{beer=1;led=1;}}

if(num>20)

//进入20次中断,定时1s

{

num=0;

//num归0,重新定开始定时1s

s1=0;

//定时1s时间到时自动关闭报警上下限显示功能

v1=1;

//定时1s时间到时自动关闭报警上下限查看功能

}

}

/******************************************************/

/*

调整报警上下限选择函数

/

/*****************************************************/

void

selsct_1(uchar

f,uchar

k)

//消除百位的0显示,及正负温度的显示选择

{

if(f==0)

//若为正温度,百位为0则不显示百位,不为0则显示

{

if(k/100==0)

P0=temperature3[0];

else

P0=temperature1[k/100];

}

if(f==1)

//若为负温度,若十位为0,百位不显示,否则百位显示‘-’

{

if(k%100/10==0)

P0=temperature3[0];

else

P0=temperature3[2];

}

}

void

selsct_2(bit

f,uchar

k)

//消除十位的0显示,及正负温度的显示选择

{

if(f==0)

//若为正温度,百位十位均为0则不显示十位,否则显示十位

{

if((k/100==0)&&(k%100/10==0))

P0=temperature3[0];

else

P0=temperature1[k%100/10];

}

if(f==1)

//若为负温度,若十位为0,十位不显示,否则十位显示‘-’

{

if(k%100/10==0)

P0=temperature3[2];

else

P0=temperature1[k%100/10];

}

}

/******************************************************/

/*

主函数显示

/

/*****************************************************/

void

display(uchar

t,uchar

t_d)

//用于实测温度、上限温度的显示

{

uchar

i;

for(i=0;i<4;i++)

//依次从左至右选通数码管显示,实现动态显示

{

switch(i)

{

case

0:

//选通第一个数码管

wei2=1;

//关第二个数码管

wei3=1;

//关第三个数码管

wei4=1;

//关第四个数码管

wei1=0;

//开第一个数码管

if(a==0){selsct_1(f,t);}

//若a=0则在第一个数码管上显示测量温度的百位或‘-’

if(a==1)

{

P0=temperature3[3];

//若a=1则在第一个数码管上显示‘H’

}

if(a==2)

{

P0=temperature3[4];

//若a=2则在第一个数码管上显示‘L’

}

break;

case

1:

//选通第二个数码管

wei1=1;

wei3=1;

wei4=1;

wei2=0;

if(a==0){selsct_2(f,t);}

//若a=0则在第二个数码管上显示测量温度的十位或‘-’

if(a==1)

//若a=1则在第二个数码管上显示上限报警温度的百位或‘-’

{

if(s==0)

selsct_1(f_max,max);//若s=0则显示第二个数码管,否则不显示

else

P0=temperature3[0];

//通过s标志位的变化实现调节上下限报警温度时数码管的闪烁

if(s1==1)

selsct_1(f_max,max);//若s1=1则显示第二个数码管(s1标志位用于上下限查看时的显示)

}

if(a==2)

//若a=2则在第二个数码管上显示下限报警温度的百位或‘-’

{

if(s==0)

selsct_1(f_min,min);

else

P0=temperature3[0];

if(s1==1)

selsct_1(f_min,min);

}

break;

case

2:

//选通第三个数码管

wei1=1;

wei2=1;

wei4=1;

wei3=0;

if(a==0){P0=temperature2[t%10];}//若a=0则在第三个数码管上显示测量温度的个位

if(a==1)

//若a=1则在第三个数码管上显示上限报警温度的十位或‘-’

{

if(s==0)

selsct_2(f_max,max);//若s=0则显示第三个数码管,否则不显示

else

P0=temperature3[0];

if(s1==1)

selsct_2(f_max,max);//若s1=1则显示第三个数码管

}

if(a==2)

//若a=2则在第三个数码管上显示下限报警温度的十位或‘-’

{

if(s==0)

selsct_2(f_min,min);

else

P0=temperature3[0];

if(s1==1)

selsct_2(f_min,min);

}

break;

case

3:

//选通第四个数码管

wei1=1;

wei2=1;

wei3=1;

wei4=0;

if(a==0){P0=temperature1[t_d];}//若a=0则在第四个数码管上显示测量温度的小数位

if(a==1)

//若a=1则在第四个数码管上显示上限报警温度的个位

{

if(s==0)

P0=temperature1[max%10];//若s=0则显示第四个数码管,否则不显示

else

P0=temperature3[0];

if(s1==1)

P0=temperature1[max%10];//若s1=1则显示第四个数码管

}

if(a==2)

//若a=2则在第四个数码管上显示下限报警温度的个位

{

if(s==0)

P0=temperature1[min%10];

else

P0=temperature3[0];

if(s1==1)

P0=temperature1[min%10];

}

break;

}

display_delay(10);

//每个数码管显示3ms左右

}

}

/******************************************************/

/*

开机显示函数

/

/*****************************************************/

void

display1(uint

z)

//用于开机动画的显示

{

uchar

i,j;

bit

f=0;

for(i=0;i

//‘z’是显示遍数的设定

{

for(j=0;j<4;j++)

//依次从左至右显示‘-’

{

switch(j)

{

case

0:

wei2=1;

wei3=1;

wei4=1;

wei1=0;

break;

P0=temperature3[2];//第一个数码管显示

case

1:

wei1=1;

wei3=1;

wei4=1;

wei2=0;break;

P0=temperature3[2];//第二个数码管显示

case

2:

wei1=1;

wei2=1;

wei4=1;

wei3=0;break;

P0=temperature3[2];//第三个数码管显示

case

3:

wei1=1;

wei2=1;

wei3=1;

wei4=0;break;

P0=temperature3[2];//第四个数码管显示

}

display_delay(400);

//每个数码管显示200ms左右

}

}

}

#endif

/********************************************************************

*

程序名;

DS18B20头文件

*

明:用到的全局变量是:无符号字符型变量temp(测得的温度整数部分),temp_d

*

(测得的温度小数部分),标志位f(测量温度的标志位‘0’表示“正温度”‘1’表

*

示“负温度”),标志位f_max(上限温度的标志位‘0’表示“正温度”、‘1’表

*

示“负温度”),标志位f_min(下限温度的标志位‘0’表示“正温度”、‘1’表

*

示“负温度”),标志位w(报警标志位‘1’启动报警‘0’关闭报警)。

*********************************************************************/

#ifndef

__ds18b20_h__

//定义头文件

#define

__ds18b20_h__

#define

uint

unsigned

int

#define

uchar

unsigned

char

sbit

DQ=

P2^3;

//DS18B20接口

sbit

beer=P1^0;

//用beer表示P1.0

sbit

led=P1^1;

//用led表示P1.1

uchar

temp=0;

//测量温度的整数部分

uchar

temp_d=0;

//测量温度的小数部分

bit

f=0;

//测量温度的标志位,0’表示“正温度”

‘1’表示“负温度”)

bit

f_max=0;

//上限温度的标志位‘0’表示“正温度”

‘1’表示“负温度”)

bit

f_min=0;

//下限温度的标志位‘0’表示“正温度”、‘1’表示“负温度”)

bit

w=0;

//报警标志位‘1’启动报警‘0’关闭报警

/******************************************************/

/*

延时子函数

/

/*****************************************************/

void

ds18b20_delayus(uint

t)

//延时几μs

{

while(t--);

}

void

ds18b20_delayms(uint

t)

//延时1ms左右

{

uint

i,j;

for(i=t;i>0;i--)

for(j=120;j>0;j--);

}

/******************************************************/

/*

DS18B20初始化函数

/

/*****************************************************/

void

ds18b20_init()

{

uchar

c=0;

DQ=1;

DQ=0;

//控制器向DS18B20发低电平脉冲

ds18b20_delayus(80);

//延时15-80μs

DQ=1;

//控制器拉高总线,while(DQ);

//等待DS18B20拉低总线,在60-240μs之间

ds18b20_delayus(150);

//延时,等待上拉电阻拉高总线

DQ=1;

//拉高数据线,准备数据传输;

}

/******************************************************/

/*

DS18B20字节读函数

/

/*****************************************************/

uchar

ds18b20_read()

{

uchar

i;

uchar

d=0;

DQ

=

1;

//准备读;

for(i=8;i>0;i--)

{

d

>>=

1;

//低位先发;

DQ

=

0;

_nop_();

_nop_();

DQ

=

1;

//必须写1,否则读出来的将是不预期的数据;

if(DQ)

//在12us处读取数据;

d

|=

0x80;

ds18b20_delayus(10);

}

return

d;

//返回读取的值

}

/******************************************************/

/*

DS18B20字节写函数

/

/*****************************************************/

void

ds18b20_write(uchar

d)

{

uchar

i;

for(i=8;i>0;i--)

{

DQ=0;

DQ=d&0x01;

ds18b20_delayus(5);

DQ=1;

d

>>=

1;

}

}

/******************************************************/

/*

获取温度函数

/

/*****************************************************/

void

get_temperature(bit

flag)

{

uchar

a=0,b=0,c=0,d=0;

uint

i;

ds18b20_init();

ds18b20_write(0xcc);

//向DS18B20发跳过读ROM命令

ds18b20_write(0x44);

//写启动DS18B20进行温度转换命令,转换结果存入内部RAM

if(flag==1)

{

display1(1);

//用开机动画耗时

}

else

ds18b20_delayms(1);

ds18b20_init();

ds18b20_write(0xcc);

ds18b20_write(0xbe);

a=ds18b20_read();

//读内部RAM

(LSB)

b=ds18b20_read();

//读内部RAM

(MSB)

if(flag==1)

//局部位变量f=1时读上下线报警温度

{

max=ds18b20_read();

//读内部RAM

(TH)

min=ds18b20_read();

//读内部RAM

(Tl)

}

if((max&0x80)==0x80)

//若读取的上限温度的最高位(符号位)为‘1’表明是负温度

{f_max=1;max=(max-0x80);}

//将上限温度符号标志位置‘1’表示负温度,将上限温度装换成无符号数。

if((min&0x80)==0x80)//若读取的下限温度的最高位(符号位)为‘1’表明是负温度

{f_min=1;min=(min-0x80);}

//将下限温度符号标志位置‘1’表示负温度,将下限温度装换成无符号数。

i=b;

i>>=4;

if

(i==0)

{

f=0;

//i为0,正温度,设立正温度标记

temp=((a>>4)|(b<<4));

//整数部分

a=(a&0x0f);

temp_d=a;

//小数部分

}

else

{

f=1;

//i为1,负温度,设立负温度标记

a=~a+1;

b=~b;

temp=((a>>4)|(b<<4));

//整数部分

a=(a&0x0f);

//小数部分

temp_d=a;

}

}

/******************************************************/

/*

存储极限温度函数

/

/*****************************************************/

void

store_t()

{

if(f_max==1)

//若上限温度为负,将上限温度转换成有符号数

max=max+0x80;

if(f_min==1)

//若下限温度为负,将上限温度转换成有符号数

min=min+0x80;

ds18b20_init();

ds18b20_write(0xcc);

ds18b20_write(0x4e);

//向DS18B20发写字节至暂存器2和3(TH和TL)命令

ds18b20_write(max);

//向暂存器TH(上限温度暂存器)写温度

ds18b20_write(min);

//向暂存器TL(下限温度暂存器)写温度

ds18b20_write(0xff);

//向配置寄存器写命令,进行温度值分辨率设置

ds18b20_init();

ds18b20_write(0xcc);

ds18b20_write(0x48);

//向DS18B20发将RAM中2、3字节的内容写入EEPROM

}

//DS18B20上电后会自动将EEPROM中的上下限温度拷贝到TH、TL暂存器

/******************************************************/

/*

温度超限报警函数

/

/*****************************************************/

void

alarm()

{

//若上限值是正值

if(f_max==0)

{

if(f_min==0)

//若下限值是正值

{

if(f==0)

//若测量值是正值

{

if(temp<=min||temp>=max)

{w=1;TR1=1;}

//当测量值小于最小值或大于最大值时报警

if((tempmin))

{w=0;}

//当测量值大于最小值且小于最大值时不报警

}

if(f==1){w=1;TR1=1;}

//若测量值是负值时报警

}

if(f_min==1)

//若下限值是负值

{

if(f==0)

//若测量值是正值

{

if(temp>=max)//当测量值大于最大值时报警

{w=1;TR1=1;}

if(temp

{w=0;}

}

if(f==1)

//若测量值是负值

{

if(temp>=min)//当测量值大于最小值时报警

{w=1;TR1=1;}

if(temp

{w=0;}

}

}

}

if(f_max==1)

//若下限值是负值

{

if(f_min==1)

//若下限值是负值

{

if(f==1)

//若测量值是负值

{

if((temp<=max)||(temp>=min))

{w=1;TR1=1;}

//当测量值小于最大值或大于最小值时报警

if((tempmax))

{w=0;}

//当测量值小于最小值且大于最大值时不报警

}

if(f==0){w=1;TR1=1;}

//若测量值是正值时报警

}

}

}

#endif

/********************************************************************

*

程序名;

基于51单片机的温度计

*

能:

实时测量温度,超过上下限报警,报警温度可手动调整。K1是用来

*

进入上下限调节模式的,当按一下K1进入上限调节模式,再按一下进入下限

*

调节模式。在正常模式下,按一下K2进入查看上限温度模式,显示1s左右自动

*

退出;按一下K3进入查看下限温度模式,显示1s左右自动退出;按一下K4消除

*

按键音,再按一下启动按键音。在调节上下限温度模式下,K2是实现加1功能,*

K1是实现减1功能,K3是用来设定上下限温度正负的。

*********************************************************************/

#include

#include

//将intrins.h头文件包含到主程序(调用其中的_nop_()空操作函数延时)

#define

uint

unsigned

int

#define

uchar

unsigned

char

uchar

max=0x00,min=0x00;

//max是上限报警温度,min是下限报警温度

bit

s=0;

//s是调整上下限温度时温度闪烁的标志位,s=0不显示200ms,s=1显示1s左右

bit

s1=0;

//s1标志位用于上下限查看时的显示

void

display1(uint

z);

//声明display1()函数(display.h头文件中的函数,ds18b20.h要用应先声明)

#include“ds18b20.h“

#include“keyscan.h“

#include“display.h“

/******************************************************/

/*

主函数

/

/*****************************************************/

void

main()

{

beer=1;

//关闭蜂鸣器

led=1;

//关闭LED灯

timer1_init(0);

//初始化定时器1(未启动定时器1)

get_temperature(1);

//首次启动DS18B20获取温度(DS18B20上电后自动将EEPROM中的上下限温度复制到TH和TL寄存器)

while(1)

{

keyscan();

get_temperature(0);

display(temp,temp_d*0.625);

alarm();

}

}

/**********************************************************************

*

程序名;

ds18b20keyscan函数

*

能:

通过键盘设定设定上下限报警温度

**********************************************************************/

#ifndef

__keyscan_H__

//定义头文件

#define

__keyscan_H__

sbit

key1=P2^2;

sbit

key2=P2^1;

sbit

key3=P2^0;

sbit

key4=P3^3;

uchar

i=0;

//定义全局变量i用于不同功能模式的选择,‘0’正常模式,‘1’上限调节模式,‘2’下限调节模式

uchar

a=0;

//定义全局变量a用于不同模式下数码管显示的选择

bit

k4=0;

//K4按键双功能选择位,k4=0时K4按键选择消按键音的功能,k4=1时K4按键选择正负温度设定功能

bit

v=0;

//K2、K3按键双功能选择位,v=0时选择上下限查看功能,v=1时选择上下限温度加减功能

bit

v1=0;

//v1=1时定时1250ms时间到自动关闭报警上下限查看功能

bit

v2=0;

/消按键音功能调整位,为‘0’时开按键音,为‘1’时关按键音

/******************************************************/

/*

读键盘延时子函数

/

/*****************************************************/

void

keyscan_delay(uint

z)

//延时1ms左右

{

uint

i,j;

for(i=z;i>0;i--)

for(j=120;j>0;j--);

}

/******************************************************/

/*

温度调节函数

/

/*****************************************************/

int

temp_change(int

count,bit

f)

//上下限温度调整

{

if(key2==0)

//判断K2是否按下

{

if(v2==0)beer=0;

//v2=0开按键音,否则消按键音

keyscan_delay(10);

//延时10ms

if(key2==0)

//再次判断K2是否按下(实现按按键时消抖)

{

beer=1;

//K2按下关按键音

if(f==0)

//若温度为正

{

count++;

//每按一下K2温度上调1

if(a==1){if(count>125)

count=125;}//当温度值大于125时不上调

if(a==2){if(count>125)

count=125;}

}

if(f!=0)

//若温度为负

{

count++;

//每按一下K2温度下调1

if(a==1){if(count>55)

count=55;}//当温度值小于-55时不再下调

if(a==2){if(count>55)

count=55;}

}

}

while(key2==0);

//K2松开按键时消抖

keyscan_delay(10);

}

if(key3==0)

{

if(v2==0)beer=0;

keyscan_delay(10);

if(key3==0)

//K3按按键时消抖

{

beer=1;

count--;

//每按一下K3温度为正时下调1,为负时上调1

if(a==1){if(count<0)

count=0;}//当温度值达到0时不再调

if(a==2){if(count<0)

count=0;}

}

while(key3==0);

keyscan_delay(10);

//K3松开按键时消抖

}

return

count;

}

/******************************************************/

/*

读键盘函数

/

/*****************************************************/

void

keyscan()

{

if(key1==0)

{

if(v2==0)beer=0;

keyscan_delay(10);

if(key1==0)

//K1按按键时消抖

{

beer=1;

TR1=1;

//开定时器1,通过s标志位的变化,实现在上下限温度调整时温度显示时闪烁的功能

k4=1;

//在上下温度调节功能模式下选择K4的调整上下限温度正负的功能

v=1;

//在上下温度调节功能模式下选择K2、K3的温度加减功能

i++;

//K1按一下i加1,i=‘0’进入正常模式,i=‘1’进入调上限模式,i=‘2’进入调下限模式

if(i>2)

//K1按下三次后退出调节模式

{

i=0;

//进入正常模式

TR1=0;

//关定时器1

k4=0;

//在正常模式下选择K4的消按键音功能

v=0;

//在正常模式下选择K2、K3的查看上下限报警温度功能

store_t();

//存储调整后的上下限报警温度

}

switch(i)

//显示选择

{

case

0:a=0;break;

//a=0选择显示测得的温度

case

1:a=1;break;

//a=1选择显示上限温度

case

2:a=2;break;

//a=2选择显示下限温度

default:break;

}

}

while(key1==0);

//K1松按键时消抖

keyscan_delay(10);

}

if(a==1&&v==1)

//a=1选择显示上限温度且v=1时选择上下限温度加功能

{led=0;max=temp_change(max,f_max);}//显示上限温度

else

if(a==2&&v==1)

//a=2选择显示下限温度且v=1时选择上下限温度减功能

{led=1;min=temp_change(min,f_min);}

else;

if(k4==1)

//k4=1时K4按键选择正负温度设定功能

{

if(key4==0)

{

if(v2==0)beer=0;

keyscan_delay(5);

if(key4==0)

{

beer=1;

if(a==1)

{if(max>55)

f_max=0;else

f_max=~f_max;}//当温度大于55度时,只能设定为正温度

if(a==2)

{if(min>55)

f_max=0;else

f_min=~f_min;}//当温度大于55度时,只能设定为正温度

}

while(key4==0);

keyscan_delay(10);

}

}

if(v==0)

//v=0时选择上下限查看功能

{

if(key2==0)

{

if(v2==0)beer=0;

keyscan_delay(10);

if(key2==0)

{

beer=1;

a=1;

//选择上限显示

TR1=1;

//开定时器1开始定时一分钟左右

s1=1;

//上限显示不闪烁,显示一分钟左右自动退出

}

while(key2==0);

keyscan_delay(10);

}

if(key3==0)

{

if(v2==0)beer=0;

keyscan_delay(10);

if(key3==0)

{

beer=1;

a=2;

//选择下限显示

TR1=1;

//开定时器1开始定时1s

s1=1;

//下限显示不闪烁,显示1s自动退出

}

while(key3==0);

keyscan_delay(10);

}

if(v1==1)

//v1=1时定时1s时间到自动关闭报警上下限查看功能

{a=0;v1=0;TR1=0;}

//a=0显示实测温度,v1清零,关定时器1

if(k4==0)

//k4=0时K4按键选择消按键音的功能

{

if(key4==0)

{

if(v2==0)beer=0;

keyscan_delay(10);

if(key4==0)

{

beer=1;

v2=~v2;

//为‘0’时开按键音,为‘1’时关按键音

}

while(key4==0);

keyscan_delay(10);

}

}

}

}

#endif

四、总结

单片机的学习与应用相关的总结与体会。在课设过程中,我们不仅巩固了平时所学习的单片机知识,而且通过不断查阅相关资料,学习新的知识,可以说,通过这次单片机的实践学习,我们学到了很多,而且对单片机的有关知识以及其在现实生活中的多方面应用有了更深层次的认识,这对于我们以后的学习和步入社会后参加工作都有很大的帮助。

在此次课程设计的进程中,我们遇到了很多问题,例如,一开始我们在确定课设题目后,在编写程序时,由于思路不太清晰,而且设计要求中需要使用新器件DS18B20智能测温,而其相关知识我们很模糊甚至可以说一无所知,不过后来,我们通过查找一些相关的资料书以及寻求辅导老师的帮助,又经过我们的主动思考,理清思路,终于将程序修改正确。在仿真时,由于我们有了之前的数模电课设仿真经验,所以此时我们课设进行的很顺利,并没有受到什么大的阻碍。

通过此次单片机课程设计,我们明白了很多,理论指导实践,但是理论也需要实践给予证明,不能盲目的相信书本,凡事都要通过自己的思考推敲,否则自己不会取的大的进步。而且在平时的学习生活中应该多和周围的同学相互学习,交流经验,遇到不会的东西时,切忌焦躁,首先要经过自己的独立思考,有了一定想法后,可以去查找相关的资料书刊或者找同学讨论,如果实在解释不了,再去找辅导老师,在这个遇到问题解决问题的过程中,不断加强自我的动脑能力,进而去指导动手能力,也只有这样,在思路清晰,条理顺畅的时候,再去进行软件编写和硬件操作工作,才有可能起到事半功倍的效果。

五、附录

系统硬件原理电路图

数字温度计设计器材表

单片机STC89C52

DS18B20

晶振12M

三极管8850

电容30PF

电解电容10UF/25V

小蜂鸣器

LED

ø5红

电阻10k,3k,2k,1k,510,330

各5

4位一体共阴数码管

AC/DC(5V/1A)电源

IC插座40

9X15cm万用板

六、参考文献

单片机数字万用表课程设计 篇5

课程设计

资料袋

电气与信息工程学院学年第学期

课程名称单片机系统课程设计指导教师凌云职称教授学生姓名专业班级测控101学号题目数字钟(C51版)成绩起止日期 2012年12 月 10日~ 2012年 12 月 28 日

目录清单

湖南工业大学

课程设计任务书

2012 —2013 学年第1 学期

电气与信息工程学院测控技术与仪器专业101班 课程名称:单片机系统课程设计设计题目:数字钟(C51版)完成期限:自2012年12 月 17日至2012年12 月28日共2周单片机系统课程设计说明书 起止日期:

数字万用表应该怎么使用 篇6

电阻档Ω,红表笔插在v/Ω插口,黑色表笔插在COM插口。测量电路或器件两端。(不能带电,否则烧坏万用表。)

直流电压档,同电阻档测量方式。

交流电压档,同电阻档测量方式。

MA或10A插口,黑色表笔插在COM插口。将万用表串入电路测量。

直流电流档,红表笔插在MA或10A插口,黑色表笔插在COM插口。将万用表串入电路测量。

二极管档位,同电阻档测量。

万用表

一:测二极管,如万用表显示1,交换表笔再次测量,这时万用表显示零点几,表示这个二极管是好的。这个数值是该管的正向压降。硅0.6V左右,锗材料0.2V左右。如果两次测量的值一样的话,那么该管是坏的。

上一篇:宣传类面试方式下一篇:端午节发给父母的问候语