郭天祥的10天学会51单片机_第六节

全局变量:该变量在主函数外面定义

局部变量:在函数体内部定义

当子函数内部定义的变量,该变量的变量名和全局变量名相同并且类型相同时,在主函数调用该子函数时,该子函数的该变量有效,将全局变量屏蔽掉

D/A,数字量(Digital):例如直接从5V跳到0V;模拟量(Anolog):例如从5V缓慢变化到0V,有个变化的过程。

例子:1111 1111    对应    5v(或50mA)

1000 0000    对应    2.5v(或25mA)

0000 0000    对应    0v(或0mA)

当都接0时,从最右边的电阻依次并联算起,到最左边的2R电阻处再和右边全部的电阻(并联后也为2R)为R,所以Vref/R= I, Io2=1/2 I,Io1=0

当I7接0,其它接1时,I7处的电流为I7,I7右边的电流也为I7,所以Io2=1/2 I

当I7接1,当I6接1,先不看其它支路,Io1=(1/2 )*Vref/R+(1/2 *1/2 ) *Vref/R

以此类推,到最后全接1时Io1=Vref/R(1/2+1/2*1/2+……+1/2的八次方)

DAC0832,这里用直通方式,一种简单的方式会了其它方式照猫画虎就行

 Vref为输入参考电压,这里IOUT2接地,IOUT1作为输出,当需要模拟电压时IOUT1接运算放大器并且连接Rfb(反馈电阻)

类似这样上面有横杠的表示低电平有效;上图中连线上连接与门的圆圈表示取反 

CS表示片选信号,Chip Select

下载数据文档:Datasheet即数据文档网站:www.21ic.com-->左边的IC处填写”DAC0832”,“资料”-->下载Datasheet。www.alldatasheet.com

看资料芯片看串并行方式,接口说明,转换位数和转换速率,操作时序

www.maxim-ic.com,如果是并行的一次把数据都读走,但浪费I/O口

见dac0832资料,P5图,ts指不稳定的输出范围,之后稳定

选取DA时,要先知道设计的产品的运行速度,然后选取DA的转换速率,根据产品的精度选取DA的精度即位

串行MAX531的资料:DIN是数据输入端,SCLK是数据时钟,DOUT是输入电压,VDD是电源,VOUT是输出电压,REFIN是参考电压,AGND是接地

时序图中,网格表示无所谓高低电平,两个箭头包起来的数据表示有效数据,MAX531的资料P8中图Figure1:SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据。

看这种资料主要看各个管脚怎么使用以及时序图

时序图中,阴影表示高低电平都可以;两个箭头包起来的数据表示有效数据,例如DIN

SCLK上升沿读走位(DIN)的数据,八个上升沿就读走八个位数据

DA资料中,看多少位,速度,管脚,时序图,有的接法不同,时序图就不同

找资料,根据资料设计电路,按资料上的器件接法连接,把资料上的电器件(如电阻的阻值,电容的法拉)都表示清楚,然后画Protel图,再做出PCB板子,拿到车间生产焊接再连接单片机就制作出来了。

dac0832PDFP5,图中表示CSILE要先给低电平,然后WR给低电平,随后有效数据就传送过去,经过一小段时间稳定一下,IOUT1IOUT2再进行有效输出

直通连接方式:直接送数据,IOUT1口就输出;结合TX-1C原理图看,赋给相应管脚低电平或高电平,结合DA接口.bmp看,DI0DI7是数据口连接单片机的P0口,其它的为控制口或电源口,CSDA连接单片机的P3.2口(使用时要给低电平),WR连接单片机的P3.6口(使用时要给低电平);IOUT1口输出的P523用跳线帽(又叫短路子)短路,IOUT1输出的电流直接穿过发光二极管到地上,输出的数字量变化,那么输出的模拟量就变化,模拟量的变化体现在流过发光二极管上的电流,发光二极管就有明暗的变化可以判断有没有把DA操作起来,1口可以外接运算放大器;DA输出口的器件,当23短路后直接通过发光二极管接地

赋给低电平

输出最高电压,点亮DA的灯,一上电P0口到P3口就输出最大值,所以开始DA的灯就亮:

#include<reg52.h>

sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别

sbit wr=P3^6;

void main()

{

       csda=0;

       wr=0;

       P0=0xff;//输出最高电压,P0=0时,关闭DA

       while(1);

}

我的随笔程序:证明按照AD的时序图来操作是可以的,可以让片选CSDA高低电平变化,并且WR高低电平的变化:

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

sbit csda=P3^2;//注意csda(数模)和csad(模数)相区别

sbit wr=P3^6;

sbit dula=P2^6;

sbit wela=P2^7;

uchar aa;

void delay(uint z)

{

       uint x,y;

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

              for(y=110;y>0;y--);

}

void main()

{

       while(1)

       {

              dula=0;

              wela=0;

              aa++;

              if(aa==256)

                     aa=0;

              csda=0;

              wr=0;

              P0=aa;//输出最高电压,P0=0时,关闭DA

              delay(5);

              wr=1;

              csda=1;

              delay(5);

       }

}

DA灯由灭到逐渐变到最亮,时间2s,由最亮到逐渐变暗到灭,时间2s

我的程序:

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

sbit csda=P3^2;

sbit wr=P3^6;

sbit wela=P2^7;

uchar flag;

int aa,bb,cc;

void init()

{

       csda=0;

       wr=0;

       P0=0;

       TMOD=0x01;

       TH0=(65536-7812)/256;

       TL0=(65536-7812)%256;

       EA=1;

       ET0=1;

       TR0=1;

       wela=1;

       P0=0xff;

       wela=0;

       bb=255;

}

void main()

{

       init();

       while(1)

       {

              P0=cc;

       }

}

void timer0() interrupt 1

{

       if(flag==0)

       {

              TH0=(65536-7812)/256;

              TL0=(65536-7812)%256;

              aa++;

              if(aa==256)

              {

                     aa=0;

                     flag=1;

              }

              cc=aa;

       }

       if(flag==1)

       {

              TH0=(65536-7812)/256;

              TL0=(65536-7812)%256;

              bb--;

              if(bb==-1)

              {

                     bb=255;

                     flag=0;

              }

              cc=bb;

       }

}

DA灯亮灭变化的同时发光二极管做加法变化:

#include<reg51.h>

sbit wela=P2^7;

sbit dula=P2^6;

sbit dawr=P3^6;

sbit csda=P3^2;

unsigned char a,j,k;

void delay(unsigned char i)

{

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

    for(k=125;k>0;k--);

}

void main()

{

  wela=0;

  dula=0;//因为下面控制P1口,段选和位选给零,不让数码管干扰

  csda=0;

  a=0;

  dawr=0;

  while(1)

      {

         P0=a;

         P1=~a;

         delay(50);

         a++;

}

}

A/D例如把08V电压分成百位就是全部量化分配到0255

用的最多的是逐次逼近式和双积分式

PPTP16VIN模拟量的输入端,EOCEnd Of Convert)转换结束(输出一个信号,告诉转换结束,可以把数据读走),倒三角是比较器,OEOutput Enable)是使能端,D/A转换器有A/D转换的功能

倒三角是比较器,倒三角上面的线(带圆圈的是上面)输出比下面高输出就是1,上面的线输出比下面低输出就是0;图中最右边,从右向左看,先将作为参考电压,这里将八位D/A转换器的最高位先置1,通过D/A转换器后的对应电压是 = /2,输出电压为 = /2,与 比较,如果大,则置1到N位寄存器最高位并传给D/A转换器,如果小,则置0到N位寄存器最高位并传给D/A转换器和锁存缓存器,再在D/A转换器的第二位置1,进行判断,如此类推,进行八次后,EOC口输出一个信号给单片机,告诉转换结束,单片机收到EOC信号后给OE一个低电平再将数据读走

见dac0832资料P1的典型管脚连线图,11到18管脚是数据口(TX-1C型单片机实验板原理图中的DB1到DB8),用来送数据,接单片机的P1口;INTR是中断口,当芯片转换完给单片机一个中断,要接单片机的外部中断(P3.2口或P3.3口),开发板中AD转换器没;使用中断,就是过段时间去读,肯定能转换完;RD和WR接单片机的RD和WR,即单片机的P3.6口和P3.7口;CS即片选,接锁存器(控制数码管位选的那个锁存器)的CSAD;VCC接5V电压;CLK R和CLK IN接管脚19和4是一个RC振荡电路,作用是提供频率让A/D转换;VIN(+)和VIN(-)采集电压,组成差分电路,输出差分信号,两条电路用来比较,可以采集桥式电路(见下图,可以做电子秤,上面的支路的第一个电阻是滑动电阻,两条并联的支路的两个电阻之间的导线连在VIN(+)和VIN(-)上,得到的压差来得出压力值);A GND表示模拟电压地端,D GND表示数字电压地端,之所以分开是防止它俩有干扰;Processor是处理器,即单片机(51,arm等);AD转换器在开发板中的电源灯下面,ADIN在AD转换器的左侧,即有跳线帽的,为了扩展,可能接模拟输入端,开发板中将其1和2短路,上面的滑动变阻器对应开发板中AD转换器的右边,可以调节上面的旋钮,ADIN的1连接着AD转换器的6管脚,6管脚下面的7管脚接地,所以6管脚就能检测到0到5伏之间的变化,ADIN的1管脚和AD转换器的6管脚之间的10k电阻是限流电阻,保护不被击穿,但电压是不会变的;AD转换器的9管脚是 ,开发板上用两个1K电阻分成2.5V

 P5的时序图,第一个图是开始转换,CS给低电平,WRCS低电平期间给个低脉冲,即在CS给低电平之后稍过一段时间WR给个低脉冲,实际内部转换状态(Actual Internal Status Of The Converter)的BUSY表示AD转换过程,转换完INTR给个低电平通知中断,实际内部转换状态和INTR可以不用程序实现,只是表示转换过程;第二个图是读取数据,如果要AD转换器一直工作就让CS一直置0;中断INTR通知后,给RD一个低电平,在RD低电平到高电平变化的瞬间把数据读走,开发板上不用中断,所以不用考虑中断;程序中就让RD为高,变低,再为高,读走数据,即送到P1口;AD转换器的CSAD连接着锁存器,程序中直接控制锁存器就行

开发板中的AD转换器的数据口也连接着发光二极管,设计一个程序,就不停的启动读,数字量变化八个发光二极管就亮灭变化

 

见ad0804的PDF的P18,是内部工作频率,八个数据全转换完需要八个,R=10K,C=145PF,由公式可得,开发板上的C很大,所以程序启动后要等一会再读数字

利用AD转换器动态显示发光二极管:

#include<reg52.h>

#define uchar unsigned char

#define uint unsigned int

sbit wr=P3^6;

sbit rd=P3^7;

void delay(uint z)

{

       uint x,y;

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

              for(y=110;y>0;y--);

}

void init();

void start();

void main()

{

       init();

       while(1)

       {

              start();

              delay(20);

              rd=0;//rd低电平才能读数据,见时序图

        delay(10);//一定要延时一会将数据读走再将rd变高电平,见上面的总结

              rd=1; //rd高电平为了下次变低电平后读数据

              delay(10);

       }    

}

void init()

{

       P0=0;//即将csad赋给0,A/D转换器被选用

}

void start()

{

       wr=1;//0804的资料上的时序图,启动AD转换

       wr=0;

       wr=1;     

}

A/D转换器的数据口接在DB1DB8上,DB1DB8连在发光二极管上,所以A/D转换器的数据口有数据输出,发光二极管也会亮

旋转AD转换器右边的电位器的旋钮,发光二极管的亮度会变化。

TX-1C型单片机实验板原理图中单片机和数码管中间的是USB设备开发芯片,右边是USB下载接口,晶振下面是复位电路,复位电路下面是DS18B20是数字温度传感器,DS18B20下面是串口,串口那,电容处的104表示10* PF(皮法),103是10*PF,180是18*;电阻4K7是4.7K5R85.8欧姆;封装(电阻,电容封装方式):0805,还有1206封装,3216封装,0604封装,0302封装(数字越小封装越小);键盘下面的P6P9是扩展口(下面标明了对应的P0P1P2P3),即开发板上单片机左右的两排针;扩展口的右边是EEPROM,再右边是1602液晶接口,再右边是1280液晶接口;晶振右边是下载程序的指示灯,键盘上面是AD转换器

开发板上,黄色的是电容,黑色的是电阻

课件练习:

AD模拟数字的模拟量读回来,转换成十进制数显示在数码管的前三位上,0255

我的程序:

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

uchar bai,shi,ge,temp;

sbit dula=P2^6;

sbit wela=P2^7;

sbit wr=P3^6;

sbit rd=P3^7;

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71,

0x76,0x79,0x38,0x3f,0

};

void delay(uint z)

{

       uint x,y;

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

              for(y=110;y>0;y--);

}

void start()

{

       wela=1;

       P0=0;

       wr=0;//下面不能加延时程序delay(10),一旦加入延时,wela=1;P0=0;这两句就把数码管//打开,让八个数码管一起显示,而没有延时,刚打开数码管就wela=0关闭就不会出现八个//数码管一起显示

       wr=1;

       P0=0xff;

       delay(10);

       wela=0;

}

void display(uchar aa,uchar bb,uchar cc)

{

       dula=1;

       P0=table[aa];

       dula=0;

       P0=0xff;

       wela=1;

       P0=0xfe;

       wela=0;

       delay(10);

       dula=1;

       P0=table[bb];

       dula=0;

       P0=0xff;

       wela=1;

       P0=0xfd;

       wela=0;

       delay(10);

       dula=1;

       P0=table[cc];

       dula=0;

       P0=0xff;

       wela=1;

       P0=0xfb;

       wela=0;

       delay(10);

}

void init()

{

       P0=0;

}

void main()

{    

       init();

       while(1)

       {

              start();

              delay(20);

              wela=1;//必须有这句,否则会出错,现象是只显示255,因为上次存储器锁存的是//P0=0xff,如果不打开wela,锁存器仍然锁存0xff,而不会把新的P0值存入并显示

              P1=0xff;

              P0=0;

              rd=0;

              temp=P1;

              rd=1;     

              P0=0xff;

              P1=temp;

              delay(20);

              display(temp/100,temp%100/10,temp%10);       

       }

}    

课件的程序:

#include<reg51.h>

#include <intrins.h>

#define uint unsigned int

#define uchar unsigned char

sbit adrd=P3^7;                          //IO口定义

sbit adwr=P3^6;

sbit diola=P2^5;

sbit dula=P2^6;

sbit wela=P2^7;

unsigned char j,k,adval;

void delay(unsigned char i)          //延时程序

{

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

    for(k=125;k>0;k--);

}

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,                            //数码管编码

                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void display(uchar bai_c,uchar sh_c,uchar g_c)                 //显示程序

   P0=table[bai_c];             //显示百位

   dula=1;

   dula=0;

   P0=0xfe;

   wela=1;

   wela=0;

   delay(5);

   dula=0;

   P0=table[sh_c];        //显示十位

   dula=1;

   dula=0;

   wela=0;

   P0=0xfd;

   wela=1;

   wela=0;

   delay(5);

   P0=table[g_c];         //显示个位

   dula=1;

   dula=0;

   P0=0xfb;

   wela=1;

   wela=0;

   delay(5);

}

void main()           //     主程序

{

  uchar a,A1,A2,A2t,A3;

    while(1)

      {

    wela=1;

    P0=0;                       //选通ADCS

    adwr=0;                //AD写入(随便写个什么都行,主要是为了启动AD转换)

    _nop_();

    adwr=1;

    P0=0xff;                    //关闭ADCS

    delay(10);

wela=0;                     //关闭有AD片选信号锁存器的锁存端以防止在操作数

//码管时使AD的片选发生变化

       for(a=20;a>0;a--)        //需要注意的是ADC0804在写和读之间的时间间隔要足够//长否则无法读出数据

    {                           //这里把显示部分放这里的原因也是为了增加写读之间//的时间间隔                                                                                                                                                                                                                           

        display(A1,A2,A3);

     }    //送去显示各位。

     wela=1;                   //重新打开有AD片选信号锁存器的锁存端

     P1=0xff;                    //读取P1口之前先给其写全1

     P0=0;                       //选通ADCS

     adrd=0;                     //AD读使能

     adval=P1;                   //AD数据读取赋给P1

     adrd=1;

     P0=0xff;                     //关闭ADCS

     adwr=0;

     P1=adval;                    //同时把AD的值送八个发光二极显示

     A1=adval/100;            //分出百,十,和个位

     A2t=adval%100;

     A2=A2t/10;

     A3=A2t%10;

   };

}    

AD的值读回来,赋给DA,即调节AD的电位器时,DA对应的发光二极管也会发生变化:

我的程序:

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

sbit adwr=P3^6;

sbit adrd=P3^7;

sbit dula=P2^6;

sbit wela=P2^7;

sbit csda=P3^2;

uchar temp;

void delay(uchar z)

{

       uchar x,y;

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

              for(y=110;y>0;y--);

}

void init()

{

       temp=0;

       P0=0;

}

void start()

{

       P0=0;

       adwr=0;

       adwr=1;

       P0=0xff;

}

void admode()

{

       csda=0;  

       adwr=0;

       //temp=P1;

       delay(1);//调试的时候,由于我不能确定P0是否被赋值为temp,这里可以添加一句//temp=0xfd,再调试中下面的语句csda=1加断点,看看P0是否等于temp,如果是说明AD

//转换器的输出值temp确实被DA转换器读入,并将此值送给P0来控制DA转换器的发光//二极管

       P0=temp;

       csda=1;

       delay(10);

}

void main()

{

       init();

       while(1)

       {

              start();

              delay(10);

              P1=0xff;

              P0=0;

              adrd=0;

              temp=P1;

              adrd=1;

              P0=0xff;

              delay(20);

              P1=temp;//发光二极管亮,可以判断AD转换器是否起作用

              admode();             

       }

}

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值