|
51单片机学习网开通新域名www.8951.com啦!速度更快更稳定! |
||||||||||
| 返回主页 | 给我留言 | 单片机教学 | 单片机提高 | 音响技术 | 品质技术 | 技术资料 | 软件下载 | 学液晶 | 产品介绍 | 如何购买 |
|
中南林业科技大学 基于AT89S52单片机的毫欧表电路设计 姓名:
郭海
2007
年 05 月 18 日 摘 要 基于AT89S52单片机的毫欧表设计是采用伏安法测量电阻。采用TLC5615数模转换芯片和LM358运算放大器及三极管TIP41构成的压控恒流源提拱恒定的电流。测量电阻时可选择的电流分别为1mA,10mA,100mA。测量电阻的量程分别为40.00Ω、4000mΩ、400.0mΩ。测量的电压信号通过LM358运算放器放大100倍后经过TLC1549模数芯片传入单片机进行计算处理并在数码管上输出电阻值!
关键字:毫欧表 压控恒流源
目 录:
采用伏安法测电阻,通以恒定的电流,测量电阻上的电压。因为U=R×I 由于电阻为毫欧,如果电流为毫安的话,则所得的电压值很小,难以通过ADC识别出来。可以采用大电流的方法和把电压信号放大的方法来使ADC芯片识别出来并由通过单片机计算得出电阻值。采用大电流的话,由于很多小电阻无法承受较大的电流,通过电阻的电流较大时,产生的热量也多,会带来较大的误差。所以采用把电压信号放大的方法,把微小的电压信号放大后经过AD转换,把信号送入单片机,然后由单片机计算并显示出电阻值。
上图为测试电阻的范围及测量时的电流: 下载本文所涉及到的protel格式电路图:相关的ic资料,相关源程序!
二.方案选择: 2.1电阻测量方案 2.1.1
方案一 比较法测电阻:
在乙图中,K1闭合,K2断开测得U1;K1断开,K2闭合测得U2,使用条件:在乙图中应保证AB间电压恒定。上图中的比较法测量电阻值的阻值非常小时,电阻R0难以选取。并且要用电压表测量两处电阻的电压。其中的导体接触间的电阻也会对测量结果造成一定的误差,并且对电压表的要求高。没有采用此方案。 2.1.2
方案二 替代法测电阻:
①K1打开,K2接1,调节R1为最大,电阻箱R0为最大。 ②闭合K1。调节R1使、指针指在2/3处,读数。 ③K2接2,保持R1不动,调节R-0,使、读数不变。 ④RX=电阻箱读数。 条件:被测量的部份电路电流或电压不变。 上图但不适合于测量小电阻。因为电阻箱的阻值一般都较大。测量的电阻精度低。 2.1.3
方案三 直流电桥测电阻 直流电桥又分直流单电桥和直流双电桥。采用上面的两种方法时要用很多操作需要手动操作,并且对元件选取要求高,是通过数字电位器来改变需要的电阻参数,虽然可以达到数控的目的,但数字电位器的每一级步进电阻比较大,调节困难,需要采用数控电阻,用单片机处理计算杂复并且测量时操作不方便。 2.1.4
方案
采用伏安法测量电阻时,恒流源电路产生恒定的电流源通过被测电阻Rx,只需要测量出Rx上的电压大小,然后用Rx=U / I 即可算出电阻的阻值大小。方便单片机进行处理。实际操作起来相对也比较简单。方案四,操作简单,计算方便。精度比方案一和方案二高,但操作和计算比方安三更简单和方案。所以采用方案四伏安法测电阻。 2.2
压控恒流源方案:
I=U/(R1+R2),若R1>>R2,则电流I约为I=U/R1; 可以采用一个恒定的电压,然后除以一个大电阻,测试时由时所测的电阻很小,基本上可以看作电流是恒定的。但这种方案测量的电阻阻值越大,电流变化较大,电流精度不高。 2.2.2
方案二 采用恒流二极管或者恒流三极管,精度比较高,但这种电路能实现的恒流范围很小,只能达到十几毫安,不能达到题目的要求。 2.2.3
方案三
压控恒流源,通过改变恒流源的外围电压,利用电压的大小来控制输出电流的大小。电压控制电路采用数控的方式,利用单片机送出数字量,经过D/A转换转变成模拟信号,再送到运算放大器和大功率三极管进行放大输出电流。该方案通过软件方法实现输出电流稳定,易于功能的实现,便于操作,故选择此方案。原理图如下面的数控恒流源中的原理图。 3.1 数控恒流源
数控恒流源为电阻测量提供恒定的电流。单片机由测量所需的电流而控制输出恒定电流的大小。 实际电路中采用的三极管为TIP41,三极管本身在这里不具备控制电流大小的作用,但是起到驱动和扩流的作用。前面是一个电压跟随,后面一个负反馈。 R9上的电压为输入的电压Vin。 理论计算
I1=VR1/R1=(Vi-V+)/R1 ; I2=VR2/R2=(V+-Va)/R2 ; 因为I+=0,得I1
= I2 所以Va=(V+-Vi)R2/R1+V+; I3=VR3/R3=V-/R1 ;I4=VR4/R4=(VO-V-)/R4 ; 因为I-=0,得I3 =
I4 所以VO=
V-
(R3/R4+1); 从而可得R5上电压为UR5=VO - Va =(R4/R3)×V-
-
(R2/R1)×V+
+(V--V+)
+ (R2/R1)×Vi ,若R2=R1,R3=R4,且 V-=V+ 则UR5=Vi(输入电压) 假设I5=IL 可得 VA/RL=VI/R5 ,由上式的Va=(V+-V-)R2/R1+V+;及R2=R1;可得 (2V+ - V-)/RL=
Vi / R5 即(2V+/V-)-1= RL/ R5; 当V+<Vi
和RL<R5,R3+R4>>R5, R3+R4>>RL,时可满足RL上电流恒定。 3.2 电压放大模块设计 需要把测量到的直流电压信号放大100倍后,即可传给AD芯片再由单片机处量。原理图如下 通过调节R2与R1的比值即可以改变电压放大倍数。
上图为LM358的PDF里提供的电路原理图,实际电路中采用的电阻R2=1MΩ,R1由3296电位器构成,阻值调成10K。 上图是采用的单个运算放大一百倍。也可以采用两个运算,每个放大十倍。 实际电路制作过程中,上面两种方法都进行测试,发现采用单个运算放大一百倍效果相对要好。所以实际电路中是采用的单个运算放大100倍的方法。 3.3 AD转换与单片机处理
电阻测量所取得的电压信号放大100倍后,通过AD-IN传入ADC转换芯片。再由单片机计算,用所得的电压除以测量时恒定的电流可得电阻的阻值大小,但此时的电阻阻值还不是实际所测得的电阻阻值,因为电压是放大一百倍后所得的。所以结果应缩小100倍即可得到真实的电阻阻值大小。 3.4 DA转换
3.5 按键的输入及数码管的显示输出 采用了串行接口8位LED数码管及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电流的量程,测得电阻阻值如下表
10mA电流的量程,测得电阻阻值如下表
100mA电流的量程,测得电阻阻值如下表
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 本系统如果采如精度更高,温度特性更好的电阻和导线,可提高测量的精度。
在制作毫欧表的过程中,我深切的体会到电路理论与实际相结合的重要。以及用电脑软件仿真与电路理论及电路实际的不同。自己制作过程是先实际再理论最后再实际的过程。自己最初制作的毫欧表是采用的是稳定的电压除以大电阻的恒流源方案。测量的结果不是很稳定。而且每次换量程时还需要手动改变电流,操作繁琐。后面打算单片机通过控制继电器来改变电流开关。需要占用较多的单片机资源。而且成本增加。后面发现了压控恒流源方案来恒定电流,接着花了很长时间查资料学习及实验采用的压控恒流源的方法来提拱恒定的电流。在整个制作过程中,主要是离不开上学期电子培训课上老师所教的知识及提供的条件,让自己学到了更多的知识。其次是网上电子爱好者及电子类的论坛给了自己很大的帮助,在整个制作过程中所遇到的问题大部分是通过网络上虽互不认识但都爱好电子的电子爱好者给予的解答。 用途: 测量直流类
mΩ~数十 Ω 的小电阻,主要用于电动机,扬声器,继电器等线圈的直流电阻,由于它们的直流电阻数值不大,普通万用表实际很难测量到准确读数.使用毫欧表可以解决大部分这种测量.
[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);
// 此时调整 时
第6、7两位设为闪烁显示
p=&hour; }
if(a==2) { write7279(BLINKCTL,0xe7);
// 此时调整 分
第3、4两位设为闪烁显示
p=&minute; }
if(a==3) { write7279(BLINKCTL,0xfc);
// 此时调整 秒
第0、1两位设为闪烁显示
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;
/* a=u1*4; */ 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;
/* a=u1*4; */
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; /*a=a*4;*/
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++)
/*read data */
{ 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;
/*return ad data */ 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);
} } |