您的位置:首页 > 其它

用I2C总线传输数据控制继电器工作

2007-09-11 16:56 423 查看

用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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐