日志档案

发表于 2008-4-29 8:24:29

3

标签: I2C  总线  传输  数据  控制  继电器  

用I2C总线传输数据控制继电器工作---很使用哦

用I2C总线传输数据控制继电器工作---很使用哦

直接看程序吧,好的就哈~~~~~~~~~~~

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define dig_num P2
#define dig_seg P0
#define ADD_t1 0x10
#define ADD_t2 0x20
#define somenop();   _nop_();_nop_();_nop_();_nop_();_nop_();

bit ACK;             /*应答标志位*/
sbit jdq="P3"^7;
sbit key="P3"^3;
sbit led3=P1^2;
sbit led1=P1^0;
sbit sw1=P2^7;
sbit sw2=P2^6;
sbit sw3=P2^5;
sbit sw5=P2^3;
sbit sw6=P2^2;
sbit beep="P2"^0;
bit f_run,f_run_t;
sbit SDA="P3"^4;
sbit SCL="P3"^2;

uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
uchar data count_1s;
uchar data buff_t1,buff_t2,t1,t2;
uchar data buff_led1,buff_led2,buff_led5,buff_led6,buff;
uchar dig_num0;
uchar data SLA _at_ 0x2e;
uchar data MTD _at_ 0x2f;
uchar data MRD _at_ 0x30;

void INT_0(void);
void delay(uint t);
void key_down(void);
void Input_I2C(uchar add,uchar add_t,uchar dat);
void Start_I2c();
void Stop_I2c();
void SendByte(uchar c);
void Ack_I2c(bit a);
uchar RcvByte(void);
//***********************************************************
void main(void)
{
 sw1=0;sw2=0;sw3=0;sw5=0;sw6=0;key=1;
 TMOD=0x01;
 TH0=0xf0;TL0=0x60;
 TCON=0x10;           //TR0=1,IE0=0;          
 IE=0x82;             //EA=1,EX0=1,ET0=1;

 Start_I2c();
 SLA=0xAE;
 SendByte(SLA);
 while(!ACK)SendByte(SLA);
 SendByte(ADD_t1);
 while(!ACK)SendByte(ADD_t1);
 Start_I2c();
 SLA=0xAF;
 SendByte(SLA);
 while(!ACK)SendByte(SLA);
 t1=RcvByte();
 Ack_I2c(ACK);
 Stop_I2c();
 buff_t1=t1;

 Start_I2c();
 SLA=0xAE;
 SendByte(SLA);
 while(!ACK)SendByte(SLA);
 SendByte(ADD_t2);
 while(!ACK)SendByte(ADD_t2);
 Start_I2c();
 SLA=0xAF;
 SendByte(SLA);
 while(!ACK)SendByte(SLA);
 t2=RcvByte();
 Ack_I2c(ACK);
 Stop_I2c();
 buff_t2=t2;
 
 while(1)
   {
    if(!key)key_down();            
    if(f_run_t==0){f_run=0;buff_t1=t1;buff_t2=t2;}
    }
 }
//***************************************************************
//***************************************************************
void key_down(void)
{
  if(sw1==0)     //加1
    {if(t1>=99){t1=0;
             beep="0";
    delay(30000);
    beep=1;}
        else{t1++;
             beep="0";
          delay(30000);
          beep="1";}
 buff_t1=t1;
 Input_I2C(0xae,ADD_t1,t1);
 delay(30000);
 }      
  else if(sw2==0)     //减1
         {if(t1==0){t1=99;
                 beep="0";
           delay(30000);
           beep="1";}
            else{t1--;
                 beep="0";
              delay(30000);
              beep="1";}
      buff_t1=t1;
      Input_I2C(0xae,ADD_t1,t1);
         }
        else if(sw3==0)
               {f_run=1;f_run_t=1;beep=0;delay(30000);beep=1;led1=0;}
 
             else if(sw5==0)
            {if(t2>=10){t2=0;         //加1
                              beep="0";
                        delay(30000);
                     beep="1";}
                          else{t2++;       //减1
                               beep="0";
                            delay(30000);
                            beep="1";}
                    buff_t2=t2;
                    Input_I2C(0xae,ADD_t2,t2);
                    }
                   else if(sw6==0)         
                          {if(t2==0){t2=10;
                                  beep="0";
                            delay(30000);
                            beep="1";}
                              else{t2--;
                                   beep="0";
                                delay(30000);
                                beep="1";}
                                   buff_t2=t2;
                         Input_I2C(0xae,ADD_t2,t2);
                         }
}   
//**************************************************************
void Input_I2C(uchar add,uchar add_t,uchar dat)
{
 Start_I2c();
 SLA=add;
 SendByte(SLA);
 while(!ACK)SendByte(SLA);
 SendByte(add_t);
 while(!ACK)SendByte(add_t);
 SendByte(dat);
 while(!ACK)SendByte(dat);
 Stop_I2c();
 }
/**********************************************************************************/
/**********************************************************************************/
 void INT_0(void)interrupt 1
 {TH0=0xf0;TL0=0x60;
  if(f_run){                          //有按键3按下,灯1亮,t1秒后,灯3亮?
            if(count_1s==250){count_1s=0;    //三秒后全部灭掉,数码管显示变化的时间
                              if(buff_t1==0){led3=0;jdq=1;
                                             if(buff_t2==0){led1=1;led3=1;jdq=0;f_run_t=0;}
                                             else buff_t2--;
                                             }
                              else buff_t1--;                                                                                       
                              }
                         else count_1s++;
            buff_led1=buff_t1/10;buff_led2=buff_t1%10;
            buff_led5=buff_t2/10;buff_led6=buff_t2%10;
            dig_num0=count_1s%4;
            switch(dig_num0)
              {case 0:dig_num=0x7f;
             dig_seg=table[buff_led1];
       break;
               case 1:dig_num=0xbf;
             dig_seg=table[buff_led2];
       break;
               case 2:dig_num=0xf7;
             dig_seg=table[buff_led5];
       break;
               case 3:dig_num=0xfb;
             dig_seg=table[buff_led6];
       break;
               default:break;   
               }     
            }
  else {led3=1;led1=1;              //未按键,灯不亮,数码管显示初始值1
        if(count_1s==250)count_1s=0;                                       
        else count_1s++;
        buff_led1=buff_t1/10;
  buff_led2=buff_t1%10;
        buff_led5=buff_t2/10;
  buff_led6=buff_t2%10;
        dig_num0=count_1s%4;
        switch(dig_num0)
          {case 0:dig_num=0x7f;
            dig_seg=table[buff_led1];
      break;
           case 1:dig_num=0xbf;
            dig_seg=table[buff_led2];
      break;
           case 2:dig_num=0xf7;
            dig_seg=table[buff_led5];
      break;
           case 3:dig_num=0xfb;
            dig_seg=table[buff_led6];
      break;
           default:break;
           }     
        }
  }

void delay(uint t)
{
  while(--t);
 }
/*************************I2C FUNCTION*******************************/
/*******************************************************************
                     起动总线函数
函数原型: void  Start_I2c();
功能:       启动I2C总线,即发送I2C起始条件.

********************************************************************/
void Start_I2c()
{
  SDA="1";        /*发送起始条件的数据信号*/
  _nop_();
  SCL="1";
  somenop();    /*起始条件建立时间大于4.7us,延时*/
  SDA="0";        /*发送起始信号*/
  somenop();    /* 起始条件锁定时间大于4μs*/
  SCL="0";        /*钳住I2C总线,准备发送或接收数据 */
  _nop_();
  _nop_();
}
/*******************************************************************
                      结束总线函数
函数原型: void  Stop_I2c();
功能:       结束I2C总线,即发送I2C结束条件.

********************************************************************/
void Stop_I2c()
{
  SDA="0";       /*发送结束条件的数据信号*/
  _nop_();     /*发送结束条件的时钟信号*/
  SCL="1";       /*结束条件建立时间大于4μs*/
  somenop();
  SDA="1";       /*发送I2C总线结束信号*/
  somenop();
}
/*******************************************************************
                 字节数据传送函数
函数原型: void  SendByte(uchar c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)
     发送数据正常,ack=1; ack="0表示被控器无应答或损坏"。
********************************************************************/
void  SendByte(uchar c)
{
 uchar BitCnt;
 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
     if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/
       else  SDA="0";
     _nop_();
     SCL="1";                       /*置时钟线为高,通知被控器开始接收数据位*/
     somenop();                   /*保证时钟高电平周期大于4μs*/
     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_();
}

 

/********************************************************************
                     应答子函数
原型:  void Ack_I2c(bit a);

功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(bit a)
{
  if(a==0)SDA=0;           /*在此发出应答或非应答信号 */
     else SDA="1";
  _nop_();
  _nop_();
  _nop_();
  SCL="1";
  somenop();               /*时钟低电平周期大于4μs*/
  SCL="0";                   /*清时钟线,钳住I2C总线以便继续接收*/
  _nop_();
  _nop_();
}
/*******************************************************************
                 字节数据传送函数
函数原型: uchar  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。
********************************************************************/
 uchar RcvByte(void)
{
  uchar BitCnt;
  uchar retc;
  retc="0";
  SDA="1";             /*置数据线为输入方式*/
  _nop_();
  _nop_();
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        _nop_();
        SCL="0";       /*置时钟线为低,准备接收数据位*/
        somenop();         /*时钟低电平周期大于4.7μs*/
        SCL="1";       /*置时钟线为高使数据线上数据有效*/
        _nop_();
        _nop_();
        retc="retc"<<1;
        if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
        _nop_();
        _nop_();
      }
  SCL="0";
  _nop_();
  _nop_();
  return (retc);
}

系统分类: 单片机   |   用户分类: 单片机   |   来源: 原创   |   【推荐给朋友】

    阅读(451)    回复(3)  

投一票您将和博主都有获奖机会!

  • mianyang

    2008-4-29 13:33:06

    谢谢楼主 我正需要的 真是万分感谢

  • wormchen

    2008-4-30 8:56:00

    用I2C总线控制继电器,你的继电器支持I2C总线?

  • mycaibo

    2008-5-2 8:25:50

    可以呀