51单片机模拟I2C程序

您所在的位置:网站首页 单片机iic 51单片机模拟I2C程序

51单片机模拟I2C程序

2024-01-11 06:04| 来源: 网络整理| 查看: 265

IIC即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦公司研发出来的。是一种两线式串行总线,两条线可以挂多个参与通信的器件,即多机模式。一般由控制器作为主机。 IIC 有两个双向信号线:一个是数据线SDA,一个是时钟线SCL(IIC是半双工)。主从机之间的数据传输完全依靠这两个信号的配合。同时,只有主机才能进行时钟信号的生成。IIC总线式开漏引脚并联结构,因此需要在外部要添加上拉电阻。对于开漏电路外部加上拉电阻,就组成了线“与”的关系。所有接入的器件保持高点平,这条线才是高电平,而任何一个器件输出一个低电平,那这条线就会保持低电平。 ​​在这里插入图片描述

1、通信起始信号和停止信号:

起始信号和停止信号是两种特殊的信号。SCL为高电平期间,SDA由高电平向低电平变化产生一个下降沿,表示起始信号。SCL为高电平期间,SDA由低电平向高电平变化产生一个上升沿,表示停止信号。起始和停止信号一般是由主机产生。

2、应答/非应答信号:

当主机发送一个字节后,从机需要进行一个应答信号,以此来判断信号是否完成了传输。从机应答主机所需要的时钟仍是主机提供的,每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据应答出现。在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答。

3、数据有效性

I2C使用SDA来传输数据,使用SCL来进行数据同步。每个时钟周期传输1位数据。在SCL时钟线为高电平时,也被称作采样时刻,此时SDA表示的数据有效,即SDA为高电平表示’1’,低电平表示‘0’,同时采样时刻SDA数据线必须保持稳定,因为在SCL高电平时,如果SDA发生动作,那么就会被判定成起始或停止信号。所以在传数据的时候,SCL为高时,SDA必须保持稳定,否则会导致此次数据传输失败。 当SCL时钟线为低电平时,SDA的数据无效,一般在这个时候是进行数据交换,为下次数据做准备。每次数据传输都以字节为单位,每次传输的字节数不受限制。

4、地址及数据方向

I2C总线上的设备,每个都有自己的独立地址。主机发起通讯时,通过SDA数据线发送设备地址来查找从机。I2C协议从机地址可以是7位或10位。在实际应用中,7位地址比较广泛,紧跟设备地址的一个数据位表示数据传输方向,它是数据的方向位(R/W),第8位或第11位。为’0’时,是主机向从机写数据;为‘1’时,是主机读取从机传输来的数据。

下面代码是51单片机的模拟I2C程序,需要注意的是51单片机的IO口是准双向IO。所以SDA引脚在数据传输过程中不需要进行方向的切换。这点需要注意。如果你的单片机GPIO有方向,一定注意切换。 代码如下: iic.c //iic.c #include "reg52.h" #include "type.h" #include "iic.h" #include "intrins.h" #include "delay.h" //#define I2CDelay() {_nop_();_nop_();} void I2C_Start(void) //开始信号 { SDA_H; //I2CDelay(); SCL_H; //I2CDelay(); SDA_L; //I2CDelay(); } void I2C_Stop(void) //停止 { SDA_L; //I2CDelay(); SCL_H; //I2CDelay(); SDA_H; //I2CDelay(); } void send_ACK(bit b_ACK) //主机应答ACK,或不应答 { SCL_L; //I2CDelay(); if(b_ACK) //ACK { SDA_L; } else //NOACK { SDA_H; } //I2CDelay(); SCL_H; //I2CDelay(); SCL_L; //I2CDelay(); } void read_ACK(void) //等待 24C02 回应 ACK { uint8_t t=0; SCL_H; //I2CDelay(); while((I2C_SDA==1)&&(t uint8_t mask; SCL_L; for(mask=0x80;mask!=0;mask>>=1) //从高位到低位依次进行 { if((mask&date)==0) { SDA_L; } else { SDA_H; } //I2CDelay(); SCL_H; //I2CDelay(); SCL_L; } } uint8_t read_byte() //读取一字节,从 24C02 中读取一个字节 { uint8_t i=0,read_data=0; SCL_L; //I2CDelay(); SDA_H; //I2CDelay(); for(i=0;i I2C_Start(); //起始信号 write_byte(0XA0); //发送写指令 read_ACK(); //等待应答 write_byte(address); //发送要写入的地址 read_ACK(); //等待应答 write_byte(date); //发送数据 read_ACK(); //等待应答 I2C_Stop(); //停止信号 } /*void write_MultipleByte(uint8_t address,uint8_t length,uint8_t *date) //连续地址,多数据持续写入 { while(length--) { write_add(address++,*date++); } }*/ void write_MultipleByte(uint8_t address,uint8_t length,uint8_t *date) //数据块写入 { I2C_Start(); write_byte(0XA0); read_ACK(); write_byte(address); read_ACK(); while(length--) { write_byte(*date++); read_ACK(); //I2CDelay(); } I2C_Stop(); } uint8_t read_add(uint8_t address,bit ACK) //从 24C02 中读出数据 { uint8_t date; I2C_Start(); //第一次起始信号 write_byte(0XA0); //发送写指令 read_ACK(); //等待应答 write_byte(address); //发送要读取的地址 read_ACK(); //等待应答 I2C_Start(); //第二次起始信号 write_byte(0XA1); //发送读指令 read_ACK(); //等待应答 date=read_byte(); //读数据 send_ACK(ACK); //主机应答ACK或不应答 I2C_Stop(); //停止信号 return date; } void read_MultipleByte(uint8_t *temp,uint8_t address,uint8_t data_size) //读出多个数据 { I2C_Start(); write_byte(0XA0); read_ACK(); write_byte(address); read_ACK(); I2C_Start(); write_byte(0XA1); read_ACK(); while(data_size--) { *temp++=read_byte(); //I2CDelay(); send_ACK(data_size); //主机应答ACK,当data_size = 0时,发送非应答 主机应答,则继续接受数据;不应答,即表示停止接收 } I2C_Stop(); //return temp; } iic.h //iic.h - 实现相关的头文件 #include "type.h" #ifndef __IIC_H__ #define __IIC_H__ #define SCL_H I2C_SCL=1 #define SCL_L I2C_SCL=0 #define SDA_H I2C_SDA=1 #define SDA_L I2C_SDA=0 sbit I2C_SCL=P2^1; sbit I2C_SDA=P2^0; extern void I2C_Start(void); extern void I2C_Stop(void); extern void read_ACK(void); extern void I2C_init(); extern void write_byte(uint8_t date); extern uint8_t read_byte() ; extern void write_add(uint8_t address,uint8_t date) ; extern uint8_t read_add(uint8_t address,bit ACK); extern void send_ACK(bit ACK); extern void write_MultipleByte(uint8_t address,uint8_t length,uint8_t *date); extern void read_MultipleByte(uint8_t *temp,uint8_t address,uint8_t data_size) ; #endif //!__IIC_H__


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3