51单片机中iic
2016-09-23 23:04
357 查看
/*========================================================================== 名称:IIC协议 编写:aiken 修改:无 内容:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作一定的修改 (本例是1us机器周期,即晶振频率要小于12MHZ)============================================================================*/ #include <reg52.h>#include "iic.h" bit ack; /*================================================= 启动总线==================================================*/void iic_start(){ SDA = 1; //发送起始条件的数据信号 SCL = 1; delay_us(1); //起始条件建立时间大于4.7us,延时 SDA = 0; //发送起始信号 delay_us(1); //起始条件锁定时间大于4μ SCL = 0; //钳住I2C总线,准备发送或接收数据} /*================================================= 结束总线==================================================*/void iic_stop(){ SDA = 0; //发送结束条件的数据信号 SCL = 1; delay_us(1); //结束条件建立时间大于4μ SDA = 1; //发送I2C总线结束信号 delay_us(1); SCL = 0;} /*===================================================================== 发送一个字节数据 函数原型: bit iic_send_byte(unsigned char byte);功能: 将数据byte发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0 假) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。======================================================================*/bit iic_send_byte(unsigned char byte){ unsigned char i; for(i = 0; i < 8; i++) //要传送的数据长度为8位 { SDA = byte & 0x80; //判断发送位 SCL = 1; //置时钟线为高,通知被控器开始接收数据位 delay_us(1); //保证时钟高电平周期大于4μ SCL = 0; byte <<= 1; } SCL = 1; SDA = 1; //8位发送完后释放数据线,准备接收应答位 delay_us(1); if(0 == SDA) //判断是否接收到应答信号 { ack = 1; } else { ack = 0; } SCL = 0; return ack;} /*=================================================================================== 接受一个字节数据 函数原型: unsigned char iic_receive_byte();功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数。 ====================================================================================*/ unsigned char iic_receive_byte(){ unsigned char i; unsigned char a; unsigned char temp = 0; SDA = 1; //置数据线为输入方式 for(i = 0; i < 8; i++) { SCL = 0; //置时钟线为低,准备接收数据位 delay_us(1); //时钟低电平周期大于4.7us SCL = 1; //置时钟线为高使数据线上数据有效 if(SDA) { a = 1; } else { a = 0; } temp |= (a << (7 - i)); //读数据位,接收的数据位放入retc中 delay_us(1); } SCL = 0; return temp;} /*=============================================================== 应答子函数================================================================*/void iic_ack(){ SDA = 0; SCL = 1; delay_us(1); //时钟低电平周期大于4μ SCL = 0; //清时钟线,钳住I2C总线以便继续接收} /*================================================================ 非应答子函数=================================================================*/void iic_noack(){ SDA = 1; SCL = 1; delay_us(1); //时钟低电平周期大于4μ SCL = 0; //清时钟线,钳住I2C总线以便继续接收} /*=========================================================================================== 向有子地址器件发送多字节数据函数 函数原型: bit iic_send_str(unsigned char sla, unsigned char suba, unsigned char *str, unsigned char len); 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程。 从器件地址sla,子地址suba,发送内容是str指向的内容,发送len个字节。 如果返回1表示操作成功,否则操作有误。注意:使用前必须已结束总线。=============================================================================================*/bit iic_send_str(unsigned char sla, unsigned char suba, unsigned char *str, unsigned char len){ unsigned char i; iic_start(); //启动总线 iic_send_byte(sla); //发送器件地址 if(0 == ack) { return ERR; } iic_send_byte(suba); //发送器件子地址 if(0 == ack) { return ERR; } for(i = 0; i < len; i++) { iic_send_byte(*str); //发送数据 delay_us(1); //必须延时等待芯片内部自动处理数据完毕 if(0 == ack) { return ERR; } str++; } iic_stop(); //结束总线 return SUCC;} /*=========================================================================================== 向有子地址器件读取多字节数据函数 函数原型: bit iic_receive_str(unsigned char sla, unsigned char suba, unsigned char *str, unsigned char len); 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程。 从器件地址sla,子地址suba,读出的内容放入str指向的存储区,读len个字节。 如果返回1表示操作成功,否则操作有误。注意:使用前必须已结束总线。=============================================================================================*/bit iic_receive_str(unsigned char sla, unsigned char suba, unsigned char *str, unsigned char len){ unsigned char i; iic_start(); //启动总线 iic_send_byte(sla); //发送器件地址 if(0 == ack) { return ERR; } iic_send_byte(suba); //发送器件子地址 if(0 == ack) { return ERR; } iic_start(); iic_send_byte(sla + 1); if(0 == ack) { return ERR; } for(i = 0; i < len - 1; i++) { *str = iic_receive_byte(); //发送数据 iic_ack(); //发送就答位 str++; } *str = iic_receive_byte(); iic_noack(); //发送非应位 iic_stop(); //结束总线 return SUCC;}
相关文章推荐
- 用Proteus学习51单片机之I2C(IIC)总线
- 用Proteus学习51单片机之I2C(IIC)总线
- 51单片机之IIC&EEPROM的驱动程序
- 51单片机之IIC通信原理及软件仿真
- 基于proteus的51单片机仿真实例四十一、C语言的一维数组
- 51单片机的idata,xdata,pdata,data的详解
- 基于proteus的51单片机仿真实例四十六、C语言的枚举类型演示实例
- 51单片机常见问题
- 基于proteus的51单片机仿真实例五十六、定时器/计数器T0的外部计数实例
- 51单片机开发系列三_数码管动态扫描显示
- 51单片机复习程序例举001
- 51单片机时钟
- 51单片机操作系统开发中的问题与技巧
- 51单片机之大杂烩
- MCS-51 8位单片机(80C,87C/31,51,52,54,58)
- 单片机MCS-51系列指令快速记忆法
- 51单片机中EA对于RTX51的作用
- 单片机:IIC总线通信
- 51、AVR、PIC、MSP430、ARM五大单片机全解析
- 第一篇:51单片机的中断和定时