使用下面代码,可以在51上用P1口模拟I2C。
/* 电平模拟函数和基本读写函数 void IIC_Start(void); void IIC_Stop(void); void SEND_0(void); void SEND_1(void); bit Check_Acknowledge(void); void Write_Byte(uchar b)reentrant; bit Write_N_Bytes(uchar *buffer,uchar n)reentrant; bit Read_N_Bytes(uchar SlaveAdr,uchar n,uchar *buffer); uchar Read_Byte(void)reentrant; */
#include<string.h> #include<reg52.h> #include<intrins.h> #include"aiic_51.h"
sbit SCL=P1^6; sbit SDA=P1^7;
void DELAY(uint t) { while(t!=0) t--; }
void IIC_Start(void) { //启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变 SDA=1; SCL=1; DELAY(DELAY_TIME); SDA=0; DELAY(DELAY_TIME); SCL=0; DELAY(DELAY_TIME); }
void IIC_Stop(void) { //终止I2C总线,当SCL为高电平时使SDA产生一个正跳变 SDA=0; SCL=1; DELAY(DELAY_TIME); SDA=1; DELAY(DELAY_TIME); SCL=0; DELAY(DELAY_TIME); }
void SEND_0(void) { //发送0,在SCL为高电平时使SDA信号为低 SDA=0; SCL=1; DELAY(DELAY_TIME); SCL=0; DELAY(DELAY_TIME); }
void SEND_1(void) { //发送1,在SCL为高电平时使SDA信号为高 SDA=1; SCL=1; DELAY(DELAY_TIME); SCL=0; DELAY(DELAY_TIME); }
bit Check_Acknowledge(void) { //发送完一个字节后检验设备的应答信号 SDA=1; SCL=1; DELAY(DELAY_TIME/2); F0=SDA; DELAY(DELAY_TIME/2); SCL=0; DELAY(DELAY_TIME); if(F0==1) return FALSE; return TRUE; }
void Write_Byte(uchar b)reentrant { //向IIC总线写一个字节 uchar i; for(i=0;i<8;i++) if((b<<i)&0x80) SEND_1(); else SEND_0(); }
bit Write_N_Bytes(uchar *buffer,uchar n)reentrant { //向I2C总线写n个字节 uchar i; IIC_Start();
for(i=0;i<n;i++) { Write_Byte(buffer[i]); if(!Check_Acknowledge()) { IIC_Stop(); return(i==n); } }
IIC_Stop(); return TRUE; }
uchar Read_Byte(void)reentrant { //从I2C总线读一个字节 uchar b=0,i; for(i=0;i<8;i++) { SDA=1; //释放总线 SCL=1; //接受数据 DELAY(10); F0=SDA; DELAY(10); SCL=0; if(F0==1) { b=b<<1; b=b|0x01; } else b=b<<1; } return b; }
bit Read_N_Bytes(uchar SlaveAdr,uchar n,uchar *buffer) { //从I2C总线读n个字节 uchar i; IIC_Start(); Write_Byte(SlaveAdr); //向总线发送接收器地址 if(!Check_Acknowledge()) //等待接收器应答信号 return FALSE; for(i=0;i<n;i++) { buffer[i]=Read_Byte(); if(i!=n) SEND_0(); //发送应答 else SEND_1(); //发送非应答 } IIC_Stop(); return TRUE; } |