标签:
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);
}
系统分类:
单片机 | 用户分类:
单片机 | 来源:
原创 | 【推荐给朋友】