1 /*************************此部分为I2C总线的驱动程序*************************************/ 2 3 #include<reg52.h> 4 #include <intrins.h> 5 6 //#define NOP() _nop_() /* 定义空指令 */ 7 #define _Nop() _nop_() /*定义空指令*/ 8 9 10 sbit SCL=P2^1; //I2C 时钟 11 sbit SDA=P2^0; //I2C 数据 12 13 bit ack; /*应答标志位*/ 14 15 16 //起动总线函数 17 extern void Start_I2c(); 18 19 //结束总线函数 20 extern void Stop_I2c(); 21 22 //应答子函数 23 extern void Ack_I2c(bit a); 24 25 //字节数据发送函数 26 extern void SendByte(unsigned char c); 27 28 /******************************************************************* 29 起动总线函数 30 函数原型: void Start_I2c(); 31 功能: 启动I2C总线,即发送I2C起始条件. 32 ********************************************************************/ 33 void Start_I2c() 34 { 35 SDA=1; /*发送起始条件的数据信号*/ 36 _Nop(); 37 SCL=1; 38 _Nop(); /*起始条件建立时间大于4.7us,延时*/ 39 _Nop(); 40 _Nop(); 41 _Nop(); 42 _Nop(); 43 SDA=0; /*发送起始信号*/ 44 _Nop(); /* 起始条件锁定时间大于4μs*/ 45 _Nop(); 46 _Nop(); 47 _Nop(); 48 _Nop(); 49 SCL=0; /*钳住I2C总线,准备发送或接收数据 */ 50 _Nop(); 51 _Nop(); 52 } 53 54 /******************************************************************* 55 结束总线函数 56 函数原型: void Stop_I2c(); 57 功能: 结束I2C总线,即发送I2C结束条件. 58 ********************************************************************/ 59 void Stop_I2c() 60 { 61 SDA=0; /*发送结束条件的数据信号*/ 62 _Nop(); /*发送结束条件的时钟信号*/ 63 SCL=1; /*结束条件建立时间大于4μs*/ 64 _Nop(); 65 _Nop(); 66 _Nop(); 67 _Nop(); 68 _Nop(); 69 SDA=1; /*发送I2C总线结束信号*/ 70 _Nop(); 71 _Nop(); 72 _Nop(); 73 _Nop(); 74 } 75 76 /******************************************************************* 77 字节数据发送函数 78 函数原型: void SendByte(UCHAR c); 79 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 80 此状态位进行操作.(不应答或非应答都使ack=0) 81 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 82 ********************************************************************/ 83 void SendByte(unsigned char c) 84 { 85 unsigned char BitCnt; 86 87 for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/ 88 { 89 if((c<<BitCnt)&0x80)SDA=1; /*判断发送位*/ 90 else SDA=0; 91 _Nop(); 92 SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/ 93 _Nop(); 94 _Nop(); /*保证时钟高电平周期大于4μs*/ 95 _Nop(); 96 _Nop(); 97 _Nop(); 98 SCL=0; 99 } 100 101 _Nop(); 102 _Nop(); 103 SDA=1; /*8位发送完后释放数据线,准备接收应答位*/ 104 _Nop(); 105 _Nop(); 106 SCL=1; 107 _Nop(); 108 _Nop(); 109 _Nop(); 110 if(SDA==1)ack=0; 111 else ack=1; /*判断是否接收到应答信号*/ 112 SCL=0; 113 _Nop(); 114 _Nop(); 115 } 116 117 /******************************************************************* 118 字节数据接收函数 119 函数原型: UCHAR RcvByte(); 120 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 121 发完后请用应答函数应答从机。 122 ********************************************************************/ 123 unsigned char RcvByte() 124 { 125 unsigned char retc; 126 unsigned char BitCnt; 127 128 retc=0; 129 SDA=1; /*置数据线为输入方式*/ 130 for(BitCnt=0;BitCnt<8;BitCnt++) 131 { 132 _Nop(); 133 SCL=0; /*置时钟线为低,准备接收数据位*/ 134 _Nop(); 135 _Nop(); /*时钟低电平周期大于4.7μs*/ 136 _Nop(); 137 _Nop(); 138 _Nop(); 139 SCL=1; /*置时钟线为高使数据线上数据有效*/ 140 _Nop(); 141 _Nop(); 142 retc=retc<<1; 143 if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */ 144 _Nop(); 145 _Nop(); 146 } 147 SCL=0; 148 _Nop(); 149 _Nop(); 150 return(retc); 151 } 152 153 /******************************************************************** 154 应答子函数 155 函数原型: void Ack_I2c(bit a); 156 功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定) 157 ********************************************************************/ 158 void Ack_I2c(bit a) 159 { 160 161 if(a==0)SDA=0; /*在此发出应答或非应答信号 */ 162 else SDA=1; 163 _Nop(); 164 _Nop(); 165 _Nop(); 166 SCL=1; 167 _Nop(); 168 _Nop(); /*时钟低电平周期大于4μs*/ 169 _Nop(); 170 _Nop(); 171 _Nop(); 172 SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/ 173 _Nop(); 174 _Nop(); 175 }