返回主页 单片机教程XL2000开发板 单片机学习 自制编程器 单片机资料 软件下载 电子技术产品介绍如何购买 进入论坛

学林杯第二届单片机征文大赛公开评奖稿件 深圳学林电子www.51c51.com 版权所有 转载注明出处   请不要忘了:现在为你喜欢的稿件投票!
作品1:征文-我是怎样开始学习电子的 山西省大同市作品6:多功能自行车测速仪  北京大学       崔健
作品2:数字温度计的设计  杭州电子科技大学     陈智杰作品7:带闹钟智能电子钟 深圳市天安数码城      谢玉平 
作品3:如何使自制的单片机电子钟走时精准       舒新生作品8:电话回拨服务告知装置 武汉市桥口区      詹显德
作品4:宽带数控放大器 陕西省西安通信学院    韩宏伟作品9:单片机应用之摩斯密码电子锁广东省顺德      吴志光
作品5:一些事,一些情 韶关市      冯敬锋作品10:基于aduc842瞬态波形存储器 华中师范大学物理学院     杨程泽
作品11:基于AT89S52单片机的毫欧表电路设计中南林业科技大学涉外学院     郭海

基于AT89S52单片机的毫欧表电路设计

中南林业科技大学涉外学院 

 郭海  

下载本文所涉及到的protel格式电路图:相关的ic资料,相关源程序!

摘 要

基于AT89S52单片机的毫欧表设计是采用伏安法测量电阻。采用TLC5615数模转换芯片和LM358运算放大器及三极管TIP41构成的压控恒流源提拱恒定的电流。测量电阻时可选择的电流分别为1mA10mA100mA。测量电阻的量程分别为40.00Ω4000mΩ400.0mΩ。测量的电压信号通过LM358运算放器放大100倍后经过TLC1549模数芯片传入单片机进行计算处理并在数码管上输出电阻值!

 

关键字毫欧表      压控恒流源


  录:

.总体方案设计:. 4

.方案选择:. 5

2.1.1 方案一 比较法测电阻:. 5

2.1.2 方案二 替代法测电阻:. 5

2.1.3 方案三 直流电桥测电阻. 5

2.1.4 方案四 伏安法测电阻. 6

2.2 压控恒流源方案:. 6

2.2.1 方案一. 6

2.2.2 方案二. 6

2.2.3 方案三. 6

.单元模块设计:. 7

3.1 数控恒流源. 7

3.2 电压放大模块设计. 8

3.3 AD转换与单片机处理. 9

3.4 DA转换. 9

3.5 按键的输入及数码管的显示输出. 9

.软件设计. 11

4.1 主程序流程图. 11

5.1 系统实现的功能,. 12

5.2 测量电阻方法:. 12

5.3 实际测试结果. 13

5.4 对测理结果的分析:. 15

.设计总结. 16

.参考文献. 17

.附:. 18

8.1 电路仿真原理图. 18

9.2 程序: 19

 

.总体方案设计:

采用伏安法测电阻,通以恒定的电流,测量电阻上的电压。因为UR×I

由于电阻为毫欧,如果电流为毫安的话,则所得的电压值很小,难以通过ADC识别出来。可以采用大电流的方法和把电压信号放大的方法来使ADC芯片识别出来并由通过单片机计算得出电阻值。采用大电流的话,由于很多小电阻无法承受较大的电流,通过电阻的电流较大时,产生的热量也多,会带来较大的误差。所以采用把电压信号放大的方法,把微小的电压信号放大后经过AD转换,把信号送入单片机,然后由单片机计算并显示出电阻值。

 

测量范围

测量电流

最大输出电压

电压放大100

40.00Ω

1mA

40mV

4V

4000mΩ

10 mA

40mV

4V

400.0mΩ

100 mA

40mV

4V

 

上图为测试电阻的范围及测量时的电流:

 

 下载本文所涉及到的protel格式电路图:相关的ic资料,相关源程序!


.方案选择:

2.1电阻测量方案

2.1.1 方案一 比较法测电阻:

 

 

 

 

 

在乙图中,K1闭合,K2断开测得U1;K1断开,K2闭合测得U2,使用条件:在乙图中应保证AB间电压恒定。上图中的比较法测量电阻值的阻值非常小时,电阻R0难以选取。并且要用电压表测量两处电阻的电压。其中的导体接触间的电阻也会对测量结果造成一定的误差,并且对电压表的要求高。没有采用此方案。

 

 

2.1.2 方案二 替代法测电阻

步骤:

K1打开,K21,调节R1为最大,电阻箱R0为最大。

②闭合K1。调节R1使、指针指在2/3处,读数。

K22,保持R1不动,调节R-0,使、读数不变。

RX=电阻箱读数。

条件:被测量的部份电路电流或电压不变。

上图但不适合于测量小电阻。因为电阻箱的阻值一般都较大。测量的电阻精度低。

 

2.1.3 方案三 直流电桥测电阻

直流电桥又分直流单电桥和直流双电桥。采用上面的两种方法时要用很多操作需要手动操作,并且对元件选取要求高,是通过数字电位器来改变需要的电阻参数,虽然可以达到数控的目的,但数字电位器的每一级步进电阻比较大,调节困难,需要采用数控电阻,用单片机处理计算杂复并且测量时操作不方便。

 

 

 

2.1.4 方案四 伏安法测电阻

采用伏安法测量电阻时,恒流源电路产生恒定的电流源通过被测电阻Rx,只需要测量出Rx上的电压大小,然后用RxU / I 即可算出电阻的阻值大小。方便单片机进行处理。实际操作起来相对也比较简单。方案四,操作简单,计算方便。精度比方案一和方案二高,但操作和计算比方安三更简单和方案。所以采用方案四伏安法测电阻。

 

 

2.2 压控恒流源方案

2.2.1 方案一 

IU/R1+R2,R1>>R2,则电流I约为IU/R1

可以采用一个恒定的电压,然后除以一个大电阻,测试时由时所测的电阻很小,基本上可以看作电流是恒定的。但这种方案测量的电阻阻值越大,电流变化较大,电流精度不高。

 

 

2.2.2 方案二

采用恒流二极管或者恒流三极管,精度比较高,但这种电路能实现的恒流范围很小,只能达到十几毫安,不能达到题目的要求。

 

 

2.2.3 方案三

       压控恒流源,通过改变恒流源的外围电压,利用电压的大小来控制输出电流的大小。电压控制电路采用数控的方式,利用单片机送出数字量,经过D/A转换转变成模拟信号,再送到运算放大器和大功率三极管进行放大输出电流。该方案通过软件方法实现输出电流稳定,易于功能的实现,便于操作,故选择此方案。原理图如下面的数控恒流源中的原理图。

 

.单元模块设计:

3.1 数控恒流源

      

 

数控恒流源为电阻测量提供恒定的电流。单片机由测量所需的电流而控制输出恒定电流的大小。

实际电路中采用的三极管为TIP41,三极管本身在这里不具备控制电流大小的作用,但是起到驱动和扩流的作用。前面是一个电压跟随,后面一个负反馈。

R9上的电压为输入的电压Vin

 

理论计算

I1=VR1/R1=(Vi-V+)/R

I2=VR2/R2=(V+-Va)/R

因为I+=0,I1 =I2

所以Va=(V+-Vi)R2/R1+V+

I3=VR3/R3=V-/RI4=VR4/R4=(VO-V-)/R

因为I-=0,I3 = I4 所以VO=V- (R3/R4+1)

从而可得R5上电压为UR5VO - Va =R4/R3)×V-  - R2/R1)×V+  +(V--V++ R2/R1)×Vi R2=R1,R3=R4, V-V+UR5Vi输入电压

假设I5=IL 可得 VA/RLVI/R5 由上式的Va=(V+-V-)R2/R1+V+R2=R1可得 (2V+ - V-/RLVi / R5 (2V+/V--1 RL/ R5

V+<Vi RL<R5R3+R4>>R5,  R3+R4>>RL,时可满足RL上电流恒定。

 

3.2 电压放大模块设计

需要把测量到的直流电压信号放大100倍后,即可传给AD芯片再由单片机处量。原理图如下 通过调节R2R1的比值即可以改变电压放大倍数。

上图为LM358PDF里提供的电路原理图,实际电路中采用的电阻R21MΩ,R13296电位器构成,阻值调成10K

上图是采用的单个运算放大一百倍。也可以采用两个运算,每个放大十倍。

实际电路制作过程中,上面两种方法都进行测试,发现采用单个运算放大一百倍效果相对要好。所以实际电路中是采用的单个运算放大100倍的方法。

3.3 AD转换与单片机处理

电阻测量所取得的电压信号放大100倍后,通过AD-IN传入ADC转换芯片。再由单片机计算,用所得的电压除以测量时恒定的电流可得电阻的阻值大小,但此时的电阻阻值还不是实际所测得的电阻阻值,因为电压是放大一百倍后所得的。所以结果应缩小100倍即可得到真实的电阻阻值大小。

 

3.4 DA转换

由单片机控制DAC5615芯片分别产生40mV400mV4000mV的电压即可获得需要测量的电流分别为1mA (40mV/40Ω)10mA (400mV/40Ω)100mA (4000mV/40Ω)。实际电路中只需要选择好相应的电阻测量范围即可。不需要手机选择测试电流,电流将由单片机控制电压控制电流源电路输出所需要的电流。

3.5 按键的输入及数码管的显示输出

采用了串行接口8LED数码管及64键键盘智能控制芯片HD7279芯片来处理按键的输入及8位数码管的输出显示。本电路只采用了4×4的按键及8位数码管显示输出。

 

.软件设计

4.1 主程序流程图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


.系统功能,指标参数

5.1 系统实现的功能

1) 电阻的测量,测量电阻范量为0.1mΩ40Ω(理论值可达到0.1mΩ)

2) 产生方波,正弦波,方波,锯齿波。

3) 时钟的显示功能。并可调整时间。

4) 测量0-4V间的直流电压值。

5) 压控恒流源 输入0-4V的电压,产生恒定的电流为0-100mA

5.2 测量电阻方法

用小鳄鱼夹接好电阻,选估计被测电阻的范围,再按下按键来选择测试的电流。其中,在100mA电流(按键3)中设了自动调零技术。可以选用把测试导线直接短接后,选按下数字键3,再按一下自动调零按键(数字0)即可。测量出的电阻显示的是,测量值减去导线间的电阻值。

注意:1,必须在测试之前,确定被测电阻可以安全流过最大测试电流!尤其在使用 0.4Ω 100mA)档时!

      2,调零时,先把两根测试导线短接。按下要用的量程键(数字键3)之后,再按下调零键(数字键0)。此时,数码管会显示出当前导线间的电阻值一秒钟并保存。再按下量程键(数字键3)即可进行测量。

 

5.3 实际测试结果

被测电阻全部为四色坏的碳膜电阻。0.24Ω2Ω2.2Ω3.9Ω

由于测试时电阻有限,所以下面测试中部分电阻阻值是采用以上电阻串联或并联起来作为一个被测电阻。三个量程测试的数据分别如下:

 

1mA电流的量程,测得电阻阻值如下表

量程

电阻标称值Ω

测量电阻值Ω

绝对误差

相对误差 %

1mA 40Ω

1

0.99

0.01

1.00

1mA 40Ω

2

2.11

0.11

5.50

1mA 40Ω

2.2

2.06

0.14

6.36

1mA 40Ω

3.9

3.88

0.02

0.51

1mA 40Ω

4

4.04

0.04

1.00

1mA 40Ω

6

6.28

0.28

4.67

1mA 40Ω

8

8.45

0.45

5.62

1mA 40Ω

10

10.56

0.56

5.60

1mA 40Ω

12

12.88

0.88

7.33

1mA 40Ω

14

13.94

0.06

0.43

1mA 40Ω

16

16.34

0.34

2.13

1mA 40Ω

18

18.82

0.82

4.56

1mA 40Ω

20

20.74

0.74

3.70

1mA 40Ω

22

22.78

0.78

3.55

平均

3.71

 

10mA电流的量程,测得电阻阻值如下表

量程

电阻标称值Ω

测量电阻值Ω

绝对误差

相对误差 %

10mA 4Ω

0.12

0.12

0

0.00

10mA 4Ω

0.24

0.24

0

0.00

10mA 4Ω

0.48

0.508

0.028

5.83

10mA 4Ω

0.72

0.768

0.048

6.67

10mA 4Ω

1

1.024

0.024

2.40

10mA 4Ω

2

2.052

0.052

2.60

10mA 4Ω

2.2

2.216

0.016

0.73

10mA 4Ω

3.9

3.928

0.028

0.72

10mA 4Ω

4

4.048

0.048

1.20

平均

2.24

 

100mA电流的量程,测得电阻阻值如下表

量程

电阻标称值mΩ

测量电阻值mΩ

绝对误差

相对误差 %

100mA 0.4Ω

60

61.4

1.4

2.33

100mA 0.4Ω

80

83.5

3.5

4.38

100mA 0.4Ω

120

125.4

5.4

4.50

100mA 0.4Ω

240

255.8

15.8

6.58

平均

4.45

 

 

5.4 对测理结果的分析

1 在采用1mA电流测试时,当被测电阻小于2Ω时,所得的测试结果平均比电阻标称值要小0.23Ω。当被测的电阻大于14欧时,所得的测试结果平均比电阻标称值要大1.38Ω。在编程中对上面问题进行了软件修正。

2 分析原因,当测量电流为1mA,电阻小于2欧时,产生的电压也小于2mV。由于LM358器件原因,而使得输出结果小0.23Ω。被测电阻大于14欧时,所得结果偏大的原因,估计由时测试时的14Ω,16Ω,18Ω,20Ω,22Ω的电阻都是由一单独阻值为2Ω的碳膜电阻串联而成的。在两电阻间的接触处没有用电烙铁等工具焊接起来,而且直接用把电阻引脚绑定在一起。每个电阻连结处的电阻给测量结果带来的较大的偏差。

 

3 测试结果表明,所测得的电阻在一定程度上与电阻本身标称值相同,当工作电流太小,或在比较大的电流范围时误差有所增加。引起这些误差的因素是多方面的,主要由测量仪器的系统误差以及电阻采用的是四环的碳膜电阻受温度影响较大,电流源工作在大电流时受温度影响所致。

 

4 本系统如果采如精度更高,温度特性更好的电阻和导线,可提高测量的精度。

 

.设计总结

       在制作毫欧表的过程中,我深切的体会到电路理论与实际相结合的重要。以及用电脑软件仿真与电路理论及电路实际的不同。自己制作过程是先实际再理论最后再实际的过程。自己最初制作的毫欧表是采用的是稳定的电压除以大电阻的恒流源方案。测量的结果不是很稳定。而且每次换量程时还需要手动改变电流,操作繁琐。后面打算单片机通过控制继电器来改变电流开关。需要占用较多的单片机资源。而且成本增加。后面发现了压控恒流源方案来恒定电流,接着花了很长时间查资料学习及实验采用的压控恒流源的方法来提拱恒定的电流。在整个制作过程中,主要是离不开上学期电子培训课上老师所教的知识及提供的条件,让自己学到了更多的知识。其次是网上电子爱好者及电子类的论坛给了自己很大的帮助,在整个制作过程中所遇到的问题大部分是通过网络上虽互不认识但都爱好电子的电子爱好者给予的解答。

 

用途:测量直流类~数十 Ω 的小电阻,主要用于电动机,扬声器,继电器等线圈的直流电阻,由于它们的直流电阻数值不大,普通万用表实际很难测量到准确读数.使用毫欧表可以解决大部分这种测量.

 

.参考文献

[1]:周尘.单片机C语言轻松入门.北京航空航一大学出版社.2006

[2]:康华光,陈大钦编.电子技术基本.高等教育出版社.2004

[3]:周润景.张丽娜.基于PROTEUSR的电路及单片机系统设计与仿真.2006

[4]:http://www.jldz08.cn/0606/2711houb.htm 杰龙电子 单片机毫欧表

[5]: http://www.ednchina.com/blog/user_default.aspx?u=asyun&page=3

 

.附:

8.1 电路仿真原理图

proteus电路仿真软件中的仿真的压控恒流源电路原理图如下:

 

 

Multisim 9电路仿真软件中的仿真的压控恒流源电路原理图如下:

 

9.2 程序:

#include <reg51.h>

#include<intrins.h>

void write7279(unsigned char, unsigned char);//写入到HD7279

unsigned char read7279(unsigned char);    //HD7279读出

void send_byte(unsigned char);     //发送一个字节

unsigned char receive_byte(void); //接收一个字节

void delay10ms(unsigned char time);    //延时程序

void short_delay(void); //短延时

unsigned int adc1549(void);     //ADC TLC1549的驱动程序

void DaConv(unsigned int DaDat);   //DAC TLC5615的驱动程序

unsigned int lubo(void); //滤波程序

void zhenxianbo(void);   //正弦波

void sanjiaobo(void);    //三角波

void juchibo(void);      //锯齿波

void fangbo(void);       //方波

void displaytime();      //显示时钟

void adc(void);      //显示测量出的电压值

void resistance1mA();                     //1mA  计算电阻值

void resistance10mA();                    //10mA  计算电阻值

void resistance100mA();                   //100mA 计算电阻值

void ABC();   // 计算导线间的电阻值

void overflow(unsigned char d3,unsigned char d2,unsigned char d1,unsigned char d0);        // 溢出显示1

 

//**************** HD7279A指令************

#define CMD_RESET 0xa4

#define CMD_TEST 0xbf

#define DECODE0 0x80

#define DECODE1 0xc8

#define CMD_READ 0x15

#define UNDECODE 0x90

#define RTL_CYCLE 0xa3

#define RTR_CYCLE 0xa2

#define RTL_UNCYL 0xa1

#define RTR_UNCYL 0xa0

#define ACTCTL 0x98

#define SEGON 0xe0

#define SEGOFF 0xc0

#define BLINKCTL 0x88

 

//**************** 键盘按键代码************

#define one 0x3a

#define    two 0x39

#define    three 0x38

#define    four 0x32

#define five 0x31

#define six 0x30

#define seven 0x2a

#define eight 0x29

#define nine 0x28

#define Esc 0x22

#define zero 0x21

#define Enter 0x20

#define up 0x3f

#define left 0x37

#define right 0x2f

#define down 0x27

#define uint unsigned int

#define uchar unsigned char

 

//************* 变量及I/O口定义******************

unsigned char key_number,hour=0,minute=0,second=0;

unsigned int tmr;

unsigned int u1=0,u=0,res=0,DaDate;

sbit cs=P0^3;        // HD7279

sbit clk=P0^2;       // HD7279

sbit dat=P0^0;       // HD7279

sbit key=P0^1;       // HD7279

sbit  ad_clk =P2^2;    //ADC1549

sbit  ad_cs=P2^0;      //ad

sbit  ad_dout=P2^1;    //ad

sbit DIN=P2^3;           //DAC5615              

sbit DaCS=P2^4;          //da

sbit DaSCLK=P2^5;    //da

 

 

void da5615(unsigned int);

void fangbo(void);

void juchibo(void);

void sanjiaobo(void);

void zhenxianbo(void);

void set_time (void);

code unsigned char TAB[]={

          0x80,0x83,0X86,0X89,0X8D,0X90,0X93,0X96,0X99,0X9C,0X9F,0XA2,0XA5,0XA8,0XAB,0XAE,

          0XB1,0XB4,0XB7,0XBA,0XBC,0XBF,0XC2,0XC5,0XC7,0XCA,0XCC,0XCF,0XD1,0XD4,0XD6,0XD8,

          0XDA,0XDD,0XDF,0XE1,0XE3,0XE5,0XE7,0XE9,0XEA,0XEC,0XEF,0XF1,0XF2,0XF3,0XF4,0XF5,

          0XF6,0XF7,0XF8,0XF9,0XFA,0XFB,0XFC,0XFD,0XFE,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,

          0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFE,0XFD,0XFC,0XFB,0XFA,0XF9,0XF8,0XF7,0XF6,

          0XF5,0XF4,0XF2,0XF1,0XEF,0XEE,0XEC,0XEA,0XE9,0XE7,0XE5,0XE3,0XE1,0XDE,0XDD,0XDA,

          0XD8,0XD6,0XD4,0XD1,0XCF,0XCC,0XCA,0XC9,0XC5,0Xc2,0XBF,0XBC,0XBA,0XB7,0XB4,0XB1,

          0XAE,0XAB,0XA8,0XA5,0XA2,0X9F,0X9C,0X99,0X96,0X93,0X90,0X8D,0X89,0X86,0X83,0X80,

          0X80,0X7C,0X79,0X76,0X72,0X6F,0X6C,0X69,0X66,0X63,0X60,0X5D,0X5A,0X57,0X55,0X51,

          0X4E,0X4C,0X48,0X45,0X43,0X40,0X3D,0X3A,0X38,0X35,0X33,0X30,0X2E,0X2B,0X29,0X27,

          0X25,0X22,0X20,0X1E,0X1C,0X1A,0X18,0X16,0X15,0X13,0X11,0X10,0X0E,0X0D,0X0B,0X0A,

          0X09,0X08,0X07,0X06,0X05,0X04,0X03,0X02,0X02,0X01,0X00,0X00,0X00,0X00,0X00,0X00,

          0X00,0X00,0X00,0X01,0X00,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0A,0X0B,0X0D,

          0X0E,0X10,0X11,0X13,0X15,0X16,0X18,0X1A,0X1C,0X1E,0X20,0X22,0X25,0X27,0X29,0X2B,

          0X2E,0X30,0X33,0X35,0X38,0X3A,0X3D,0X40,0X43,0X45,0X48,0X4C,0X4E,0X51,0X55,0X57,

          0X5A,0X5D,0X60,0X63,0X66,0X69,0X6C,0X6F,0X72,0X76,0X79,0X7C,0X80};

 

             

main()

{  unsigned char a,*p;

while(1)

{    

  for (tmr=0;tmr<0x2000;tmr++); //上电延时

      send_byte(CMD_RESET); //复位HD7279A

      cs=1;            

      delay10ms(10);

      key_number=0xff;

 

    TMOD=0x01;//定时器0 工作方式1

    TH0=0xdc; //定时时间=(65536-56320)*(1/11.0592)*12=10ms  fosc=11.0592

    TL0=0x00;    

    ET0=1;

    TR0=1;

 

if (!key) //如果有键按下

{

 key_number=read7279(CMD_READ);        //读出键码

 tmr=key_number;

 

    switch(tmr)

    {   case one: do{resistance1mA(); delay10ms(100);//1mA 电流时测得 电阻值              

                     DaConv(11);   }while(key);break;

 

       case two:do{resistance10mA(); delay10ms(100);//10mA 电流时测得 电阻值                   

                     DaConv(100);  }while(key);break;

 

       case three:do{resistance100mA();delay10ms(100);//100mA 电流时测得 电阻值            

                      DaConv(1000);    }while(key);break;

 

       case zero: ABC();delay10ms(100);   //计算导线间的电阻值

                 break;

 

       case four:do{adc();delay10ms(100);    //显示电压值          

                     DaConv(1000);    }while(key);break;   

                

        case seven: EA=0; //关总中断 时钟暂停,进入调整   

                     a++;

                     if(a==1) {  write7279(BLINKCTL,0x3f); // 此时调整 时67两位设为闪烁显示 

                                p=&hour;   }                                                   

                     if(a==2) { write7279(BLINKCTL,0xe7); // 此时调整 分  34两位设为闪烁显示                             

                                p=&minute;}                                 

                     if(a==3) { write7279(BLINKCTL,0xfc); // 此时调整 秒      01两位设为闪烁显示

                                p=&second;}                                              

                     if(a>3){a=0; write7279(BLINKCTL,0xff); //清除闪烁设置

                                }

                     displaytime();    //显示时钟

                     DaConv(0);              

                     delay10ms(100);

                     break;

 

       case eight:   *p=*p+1;

                  if(second>59||minute>59){*p=0;}    //当 分 或 秒 显示为59时变为0

                  if(hour>23){*p=0;}   //当 时 显示为23时变为0                    

                  displaytime();       //显示时钟              

                  delay10ms(100); DaConv(0);;break;

 

       case nine:     do{EA=1;//开总中断                   

                       displaytime();   //显示时钟            

                      delay10ms(100); DaConv(0); }while(key);break;

                 

       case up:do{zhenxianbo();   //正弦波                  

                   }while(key);break;

 

       case left:do{sanjiaobo();      //三角波              

                   }while(key);break;

 

       case right:do{  juchibo();      //锯齿波                  

                    }while(key);break;

 

       case down:do{  fangbo();    //方波             

                    }while(key);break;

 

       }

 

 }

 

}

}

 

/************* 定时器0中断************/

void timer0() interrupt 1 //定时器0中断

{   static Count=0;  //静态变量计数器

    TH0=0xdc;

    TL0=0x00;

    Count++;            

    if(Count>=100){   Count=0; second=second+1;  } //判断时间是否到1s 了?         

    if(second>=60){   second=0; minute+=1; }

    if(minute>=60){   minute=0;  hour+=1;   }

    if( hour>=23 && minute>=59 && second>=59){second=0; minute=0; hour=0;}

  }

 

/************* 显示时钟************/

void displaytime()   //显示时钟

{

    write7279(DECODE0+1,second/10);    //显示 秒的 十位

    write7279(DECODE0+0,second%10);    //显示 秒的 个位

    write7279(DECODE0+2,10);

    write7279(DECODE0+4,minute/10);    //显示 分的 十位

    write7279(DECODE0+3,minute%10);    //显示 分的 个位

    write7279(DECODE0+5,10);

    write7279(DECODE0+7,hour/10);      //显示 时的 十位

    write7279(DECODE0+6,hour%10);      //显示 时的 个位

 }

 

/************* ADC数码管显示转换后的电压值数值************/

void adc(void)

{

   unsigned char d0,d1,d2,d3;

   unsigned int a;

       u1=lubo();

       a=u1<<2;    

      

       d3=a/1000;d3=d3|0x80;          //显示小数点

       d2=a/100%10;

       d1=a/10%10;

       d0=a%10;

 

       write7279(DECODE0+3,d3);

       write7279(DECODE0+2,d2);

       write7279(DECODE0+1,d1);

       write7279(DECODE0+0,d0);

   }

 

/************* 1mA 计算电阻值************/

void resistance1mA()                            

{   unsigned char d0,d1,d2,d3;

    unsigned int a;

 

    u1=lubo();

    a=u1*40;

 

    if(a>200&&a<2000){a=a+230;}   //修正电阻值    当电阻值小于2欧姆时,显示结果为测量值加0.23

    if(a>14000&&a<40770){a=a-1380;}//修正电阻值  当电阻值大于14欧姆时,显示结果为测量值减去1.38

 

       d3=a/10000;  

       d2=a/1000%10;    

       d2=d2|0x80;  //显示小数点      

       d1=a/100%10;

       d0=a/10%10;

       overflow(d3,d2,d1,d0);

}

 

/************* 10mA 计算电阻值************/

void resistance10mA()                           

{   unsigned char d0,d1,d2,d3;

    unsigned int a;

       u1=lubo();

       a=u1<<2;     /* a=u1*4; */

 

       d3=a/1000;

       d2=a/100%10;

       d1=a/10%10;  

       d0=a%10;  

      

       overflow(d3,d2,d1,d0);

}

 

/************* 100mA 计算电阻值************/

void resistance100mA()                   

{  unsigned char d0,d1,d2,d3;

   unsigned int a;

 

    u1=lubo();   

    a=u1<<2;    

 

    if(a!=4092){     

        a=a-res;

          

       d3=a/1000;

       d2=a/100%10;

       d1=a/10%10;     d1=d1|0x80;            //显示小数点 

       d0=a%10;

   

       write7279(DECODE0+7,d3);        //    第八位数码管

       write7279(DECODE0+6,d2);        //    第七位数码管

       write7279(DECODE0+5,d1);        //        第六位数码管

       write7279(DECODE0+4,d0);        //        第五位数码管         

                   }

    else{        

 

       write7279(DECODE0+7,1);             //       超出范转显示1

       write7279(DECODE0+6,0x0f);         //    第七位数码管 空

       write7279(DECODE0+5,0x0f);          //        第六位数码管  

       write7279(DECODE0+4,0x0f);          //        第五位数码管 空

                    

   

      

       }  

}

 

/************* 溢出显示1************/

void overflow(unsigned char d3,unsigned char d2,unsigned char d1,unsigned char d0)

{

   if(d3==4 && d1==9)           //    超出范转显示1

 

     {  write7279(DECODE0+7,1);             //       超出范转显示1

       write7279(DECODE0+6,0x0f);         //    第七位数码管 空

       write7279(DECODE0+5,0x0f);          //        第六位数码管  

       write7279(DECODE0+4,0x0f);          //        第五位数码管 空

        } 

    else

       {

       write7279(DECODE0+7,d3);        //    第八位数码管

       write7279(DECODE0+6,d2);        //    第七位数码管

       write7279(DECODE0+5,d1);        //        第六位数码管

       write7279(DECODE0+4,d0);        //        第五位数码管

       }

 

}

 

/************* 计算导线间的电阻值************/

void ABC()

{  unsigned int a;

   unsigned char d0,d1,d2,d3;

 

        a=lubo();

       a=a<<2;      

 

       d3=a/1000;

       d2=a/100%10;

       d1=a/10%10;  

       d0=a%10;

 

 

   if(a>=3000){   res=0;

               write7279(DECODE0+3,d3);          //    第八位数码管

               write7279(DECODE0+2,d2);          //    第七位数码管

               write7279(DECODE0+1,d1);           //        第六位数码管

               write7279(DECODE0+0,d0);           //        第五位数码管

              }

 

   else{   res=a;    

           write7279(DECODE0+3,d3);        //    第八位数码管

           write7279(DECODE0+2,d2);        //    第七位数码管

           write7279(DECODE0+1,d1);        //        第六位数码管

           write7279(DECODE0+0,d0);        //        第五位数码管         

           }

 

  delay10ms(100);

 }

 

 //*************A/DC1549转换子程序**************

unsigned int adc1549(void)

{uchar i;

  ad_cs=0;

  ad_clk=0;

  ad_dout=1;

  u=0;

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

     {   ad_clk=0;

       short_delay();

        u=u*2;

        if (ad_dout==1)

        {

            u ++ ;

        }

        ad_clk =1 ;              //上升沿接受数据

       short_delay();

        }

   ad_dout=1;

   ad_cs=1;

   return u;           

   short_delay();

  }

 

//*************滤波程序*************************

unsigned int lubo(void)         //滤波程序

{unsigned char i;

  unsigned  int a[10],sum=0,value;

 

  for(i=0;i<10;i++)      //取值

    {  a[i]=adc1549(); short_delay();}

          

  for(i=0;i<10;i++)     //求和

    {  sum=sum+a[i];    }

   value=sum/10;     //计算平均值

   return value;

  }

 

//**************TLC5615转换子程序*******************

void DaConv(uint DaDat)  //TLC5615的驱动程序,命令:DAConv

{

  uchar i=0;

  DaCS=1;

  _nop_();

  _nop_();

  DIN=0;

  DaSCLK=0;

  DaCS=0;

  _nop_();

  _nop_();

 

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

  {

    DaDat=_irol_(DaDat,1);

 

     if((DaDat&0x0400)!=0)

        DIN=1;

     else

         DIN=0;

 

     DaSCLK=1;

      _nop_();

      _nop_();

      DaSCLK=0;

      _nop_();

      _nop_();

    }

 

  DaCS=1;

  DIN=0;

  DaSCLK=0;

}

 

void send_byte( unsigned char out_byte)//发送一个命令字

{    unsigned char i;

clk=0;

cs=0;

short_delay();

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

{  clk=0;

  if (out_byte&0x80)

       {dat=1;}

  else {dat=0;}

 

clk=1;

short_delay();

out_byte=out_byte*2;

 }

dat=1;

}

 

unsigned char receive_byte(void) //接收一个命令字

{   unsigned char i, in_byte;

 cs=0;

    clk=0;

     dat=1; //设为输入状态

     short_delay();

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

{   clk=0;

in_byte=in_byte*2;

clk=1;

if (dat==1)

{in_byte=in_byte|0x01;}

 }

dat=1;

//cs=1;

return (in_byte);

}

 

void write7279(unsigned char cmd, unsigned char dta)

{   send_byte (cmd);

    send_byte (dta);

cs=1;}

 

unsigned char read7279(unsigned char command)

{  send_byte(command);

cs=1;

return(receive_byte()); }

 

void short_delay(void) //短延时

{  unsigned char i;

for (i=0;i<8;i++);}

 

// ********************* n*10ms 延时**********************

void delay10ms(unsigned char time)

{   unsigned char i;

    unsigned int j;

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

 {  for(j=0;j<0x390;j++);

   }

}

 

void fangbo(void)

{uint j;

delay10ms(100);

 while(key)

 

 {for(j=0;j<2;j++)

  {if(j<1)

  DaConv(0x0fff);

  else

  DaConv(0x0000);

 }

  }

     }

void juchibo(void)

{uint i,j;

  i=0;

  j=0;

  delay10ms(100);

 while(key)

 

 {

   if(i<500)

    {i=i+30;  //周期

     j=j+3;   //幅值

    DaConv(j*40);}

   else

    {i=0;

    j=0;}

 }

  }

 

void sanjiaobo(void)

{uint i,j,k;

  i=0;

  j=0;

  delay10ms(100);

 while(key)

 {for(i=0;i<1;i++) //周期

    {if(j<200)

      {k=200;

      j=j+10;

      DaConv(j*10);}

      else

     {

        if(k<1)

        j=0;

        else

      {DaConv(k*10);

        k=k-10;}

      }

    }

 }

   }

void zhenxianbo(void)

{uint i;

delay10ms(100);

  while(key)

  {

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

 

    DaConv(TAB[i]*6);

 

   }

  }