zoukankan      html  css  js  c++  java
  • 实验5 IIC通讯与AD/接DA接口

    1.利用单片机控制PCF8591AD转换,控制AD0AD1电位器,在数码光上显示DA转换的值。

    2.利用单片机控制PCF8591DA转换,让发光二极管D1由暗到亮变化,整个过程时间差不多2s左右,再由亮到暗变化,循环变化。

     

    以下代码将12实验合并成一个实验。

    Lab6.1

    #include<reg51.h>

    #include <I2C.H>

     

    #define  PCF8591 0x90    //PCF8591 地址

    #define uchar unsigned char

    #define uint unsigned int

    #define ulong unsigned long

     

     

     

    //=========全局变量区============================================

    unsignedchar AD_CHANNEL;

    unsignedint  D[5];

            

    sbit high=P2^4;

    sbit mid=P2^3;

    sbit low=P2^2;

    uint code NumTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数字的编码

     

     

    //=========全局变量区结束========================================

     

     

     

     

    //=========函数区============================================

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

        延时

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

    void delay_1ms(uint x){

        uint i=x;

        uint j;

        for(;i>0;--i){

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

        }

    }

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

        在数码管上显示对应的值

    参数说明:

      Num 要显示的数字

      withDot 是否带点,如果要带点的话,那么传入0x80。不带点,传入0

     

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

    void display(uchar Num,uchar withDot)

    {

     

        P0=NumTable[Num]|withDot;

        delay_1ms(1);

        P0=0;      //送完段选信号后,进行消影的处理

    }

     

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

        控制数码管显示,并分解计数值

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

    void DisplayNumByOrder(uint left,uint right){

           low=0; mid=0; high=0;  display(left%10000/1000,0);         //left

            low=1; mid=0; high=0;  display(left%1000/100,0);               

            low=0; mid=1; high=0;  display(left%100/10,0x80);

           low=1; mid=1; high=0;  display(left%10,0);

                                                 //right

           low=0; mid=0; high=1;  display(right%10000/1000,0);

           low=1; mid=0; high=1;  display(right%1000/100,0);

           low=0; mid=1; high=1;  display(right%100/10,0x80);

           low=1; mid=1; high=1;  display(right%10,0);

    }

     

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

    DAC 变换, 转化函数              

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

    bit DACconversion(unsignedchar sla,unsignedchar c,  unsignedchar Val)

    {

       Start_I2c();              //启动总线

       SendByte(sla);            //发送器件地址

       if(ack==0)return(0);

       SendByte(c);              //发送控制字节

       if(ack==0)return(0);

       SendByte(Val);            //发送DAC的数值 

       if(ack==0)return(0);

       Stop_I2c();               //结束总线

       return(1);

    }

     

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

    ADC发送字节[命令]数据函数              

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

    bit ISendByte(unsignedchar sla,unsignedchar c)

    {

       Start_I2c();              //启动总线

       SendByte(sla);            //发送器件地址

       if(ack==0)return(0);

       SendByte(c);              //发送数据

       if(ack==0)return(0);

       Stop_I2c();               //结束总线

       return(1);

    }

     

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

    ADC读字节数据函数              

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

    unsignedchar IRcvByte(unsignedchar sla)

    {  unsignedchar c;

     

       Start_I2c();          //启动总线

       SendByte(sla+1);      //发送器件地址

       if(ack==0)return(0);

       c=RcvByte();          //读取数据0

     

       Ack_I2c(1);           //发送非就答位

       Stop_I2c();           //结束总线

       return(c);

    }

     

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

    main()

    { 

         while(1)

         {

           /********以下AD-DA处理*************/ 

           //因为PCF8591读取的是前一个时刻AD转换的值,所以读取的值在第5个时钟才是正常的值,相当于

           //swith经历了一轮case 0~4后,程序里面读取到的AD转换的值才是正常的。

           switch(AD_CHANNEL)    // A/D信道,通过这个函数,4个信道的数值都能读到

           {

                case0: ISendByte(PCF8591,0x41);

                       D[0]=IRcvByte(PCF8591)*2;  //ADC0 模数转换1  放大2倍显示

                       break; 

            

                case1: ISendByte(PCF8591,0x42);

                       D[1]=IRcvByte(PCF8591)*2;  //ADC1  模数转换2

                       break; 

     

                case2: ISendByte(PCF8591,0x43);

                       D[2]=IRcvByte(PCF8591)*2;  //ADC2  模数转换3

                       break; 

     

                case3: ISendByte(PCF8591,0x40);

                       D[3]=IRcvByte(PCF8591)*2;  //ADC3   模数转换4

                       break; 

                case4: DACconversion(PCF8591,0x40, D[4]);//DAC  数模转换

                   break;

           }

                  D[4]=D[0];  //   把模拟输入采样的信号通过数模转换输出,最终改变灯泡亮度

           if(++AD_CHANNEL>4) AD_CHANNEL=0;

           DisplayNumByOrder(D[0],D[1]);//AD的值送到LED数码管显示

         } 

    }

     

    //=========函数结束区============================================

     

     

     

     

    /*************************此部分为I2C总线的驱动程序*************************************/

    I2c.c

    #include<reg51.h>

    #include <intrins.h>

    #include <I2C.H>

     

    #define  NOP()   _nop_()   /* 定义空指令 */

    #define  _Nop()  _nop_()   /*定义空指令*/

     

     

    sbit     SCL=P2^1;       //I2C  时钟

    sbit     SDA=P2^0;       //I2C  数据

    bit ack;                 /*应答标志位*/

      

     

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

                         起动总线函数              

    函数原型: void  Start_I2c(); 

    功能:     启动I2C总线,即发送I2C起始条件. 

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

    void Start_I2c()

    {

      SDA=1;         /*发送起始条件的数据信号*/

      _Nop();

      SCL=1;

      _Nop();        /*起始条件建立时间大于4.7us,延时*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();   

      SDA=0;         /*发送起始信号*/

      _Nop();        /* 起始条件锁定时间大于4μs*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();      

      SCL=0;       /*钳住I2C总线,准备发送或接收数据 */

      _Nop();

      _Nop();

    }

     

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

                          结束总线函数              

    函数原型: void  Stop_I2c(); 

    功能:     结束I2C总线,即发送I2C结束条件. 

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

    void Stop_I2c()

    {

      SDA=0;      /*发送结束条件的数据信号*/

      _Nop();       /*发送结束条件的时钟信号*/

      SCL=1;      /*结束条件建立时间大于4μs*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();

      _Nop();

      SDA=1;      /*发送I2C总线结束信号*/

      _Nop();

      _Nop();

      _Nop();

      _Nop();

    }

     

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

                     字节数据发送函数              

    函数原型: void  SendByte(UCHAR c);

    功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对

              此状态位进行操作.(不应答或非应答都使ack=0)    

               发送数据正常,ack=1; ack=0表示被控器无应答或损坏。

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

    void  SendByte(unsignedchar  c)

    {

     unsignedchar  BitCnt;

     

     for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8*/

        {

         if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/

           else  SDA=0;               

         _Nop();

         SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/

          _Nop();

          _Nop();             /*保证时钟高电平周期大于4μs*/

          _Nop();

          _Nop();

          _Nop();        

         SCL=0;

        }

       

        _Nop();

        _Nop();

        SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/

        _Nop();

        _Nop();  

        SCL=1;

        _Nop();

        _Nop();

        _Nop();

        if(SDA==1)ack=0;    

           else ack=1;        /*判断是否接收到应答信号*/

        SCL=0;

        _Nop();

        _Nop();

    }

     

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

                     字节数据接收函数              

    函数原型: UCHAR  RcvByte();

    功能:        用来接收从器件传来的数据,并判断总线错误(不发应答信号)

              发完后请用应答函数应答从机。 

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

    unsignedchar   RcvByte()

    {

      unsignedchar  retc;

      unsignedchar  BitCnt;

     

      retc=0;

      SDA=1;                     /*置数据线为输入方式*/

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

          {

            _Nop();          

            SCL=0;                  /*置时钟线为低,准备接收数据位*/

            _Nop();

            _Nop();                 /*时钟低电平周期大于4.7μs*/

            _Nop();

            _Nop();

            _Nop();

            SCL=1;                  /*置时钟线为高使数据线上数据有效*/

            _Nop();

            _Nop();

            retc=retc<<1;

            if(SDA==1)retc=retc+1;  /*读数据位,接收的数据位放入retc */

            _Nop();

            _Nop();

          }

      SCL=0;   

      _Nop();

      _Nop();

      return(retc);

    }

     

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

                         应答子函数

    函数原型:  void Ack_I2c(bit a);

    功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)

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

    void Ack_I2c(bit a)

    {

     

      if(a==0)SDA=0;              /*在此发出应答或非应答信号 */

      else SDA=1;

      _Nop();

      _Nop();

      _Nop();     

      SCL=1;

      _Nop();

      _Nop();                    /*时钟低电平周期大于4μs*/

      _Nop();

      _Nop();

      _Nop(); 

      SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/

      _Nop();

      _Nop();   

    }

     

     

     

     

    I2c.h

    clip_image002

  • 相关阅读:
    10.16作业
    day0402作业
    day04作业
    10.13作业
    JVM原理最全、清晰、通俗讲解
    Java的SimpleDateFormat,DateTimeFormatter:YYYY与yyyy
    从源码层面理解 ArrayList 扩容策略
    哈夫曼树
    面向对象三大基本特性,五大基本原则
    数据结构
  • 原文地址:https://www.cnblogs.com/kissazi2/p/3174446.html
Copyright © 2011-2022 走看看