服务器建站,360度全景街景地图,网站项目建设的必要性,学雷锋做美德少年网站目录 #x1f381;I2C总线
编辑
#x1f381;代码
#x1f3f3;️#x1f308;main.c
#x1f3f3;️#x1f308;i2.c
#x1f386;代码分析 #x1f381;I2C总线
I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线#xff0c;主要用于近距…目录 I2C总线
编辑
代码
️main.c
️i2.c
代码分析 I2C总线
I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线主要用于近距离、低速的芯片之间的通信I2C总线有两根双向的信号线一根数据线SDA用于收发数据一根时钟线SCL用于通信双方时钟的同步I2C总线硬件结构简单简化了PCB布线降低了系统成本提高了系统可靠性因此在各个领域得到了广泛应用。 代码
️main.c
/**************************************************************************************
* EEPROM-IIC实验 *
实现现象下载程序后数码管后4位显示0按K1保存显示的数据按K2读取上次保存的数据按K3显示数据加一按K4显示数据清零。最大能写入的数据是255.注意事项由于P3.2口跟红外线共用所以做按键实验时为了不让红外线影响实验效果最好把红外线先取下来。
***************************************************************************************/#include reg52.h //此文件中定义了单片机的一些特殊功能寄存器
#include i2c.h typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;sbit LSAP2^2;
sbit LSBP2^3;
sbit LSCP2^4;sbit k1P3^1;
sbit k2P3^0;
sbit k3P3^2;
sbit k4P3^3; //定义按键端口char num0;
u8 disp[4];
u8 code smgduan[10]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数i1时大约延时10us
*******************************************************************************/
void delay(u16 i)
{while(i--);
}/*******************************************************************************
* 函数名 :Keypros()
* 函数功能 :按键处理函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Keypros()
{if(k10){delay(1000); //消抖处理if(k10){At24c02Write(1,num); //在地址1内写入数据num}while(!k1);}if(k20){delay(1000); //消抖处理if(k20){numAt24c02Read(1); //读取EEPROM地址1内的数据 保存 在num中}while(!k2);}if(k30){delay(100); //消抖处理if(k30){num; //数据 加1if(num255)num0;}while(!k3);}if(k40){delay(1000); //消抖处理if(k40){num0; //数据 清零}while(!k4);}
}/*******************************************************************************
* 函数名 :datapros()
* 函数功能 :数据处理函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void datapros()
{disp[0]smgduan[num/1000];//千位disp[1]smgduan[num%1000/100];//百位disp[2]smgduan[num%1000%100/10];//个位disp[3]smgduan[num%1000%100%10];
}/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能 :数码管显示函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void DigDisplay()
{u8 i;for(i0;i4;i){switch(i) //位选选择点亮的数码管{case(0):LSA0;LSB0;LSC0; break;//显示第0位case(1):LSA1;LSB0;LSC0; break;//显示第1位case(2):LSA0;LSB1;LSC0; break;//显示第2位case(3):LSA1;LSB1;LSC0; break;//显示第3位 }P0disp[i];//发送数据delay(100); //间隔一段时间扫描 P00x00;//消隐}
}/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{ while(1){Keypros(); //按键处理函数datapros(); //数据处理函数DigDisplay();//数码管显示函数 }
}
️i2.c
#includei2c.h/*******************************************************************************
* 函数名 : Delay10us()
* 函数功能 : 延时10us
* 输入 : 无
* 输出 : 无
*******************************************************************************/void Delay10us()
{unsigned char a,b;for(b1;b0;b--)for(a2;a0;a--);}
/*******************************************************************************
* 函数名 : I2cStart()
* 函数功能 : 起始信号在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入 : 无
* 输出 : 无
* 备注 : 起始之后SDA和SCL都为0
*******************************************************************************/void I2cStart()
{SDA1;Delay10us();SCL1;Delay10us();//建立时间是SDA保持时间4.7usSDA0;Delay10us();//保持时间是4usSCL0; Delay10us();
}
/*******************************************************************************
* 函数名 : I2cStop()
* 函数功能 : 终止信号在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入 : 无
* 输出 : 无
* 备注 : 结束之后保持SDA和SCL都为1表示总线空闲
*******************************************************************************/void I2cStop()
{SDA0;Delay10us();SCL1;Delay10us();//建立时间大于4.7usSDA1;Delay10us();
}
/*******************************************************************************
* 函数名 : I2cSendByte(unsigned char dat)
* 函数功能 : 通过I2C发送一个字节。在SCL时钟信号高电平期间保持发送信号SDA保持稳定
* 输入 : num
* 输出 : 0或1。发送成功返回1发送失败返回0
* 备注 : 发送完一个字节SCL0,SDA1
*******************************************************************************/unsigned char I2cSendByte(unsigned char dat)
{unsigned char a0,b0;//最大255一个机器周期为1us最大延时255us。 for(a0;a8;a)//要发送8位从最高位开始{SDAdat7; //起始信号之后SCL0所以可以直接改变SDA信号datdat1;Delay10us();SCL1;Delay10us();//建立时间4.7usSCL0;Delay10us();//时间大于4us }SDA1;Delay10us();SCL1;while(SDA)//等待应答也就是等待从设备把SDA拉低{b;if(b200) //如果超过2000us没有应答发送失败或者为非应答表示接收结束{SCL0;Delay10us();return 0;}}SCL0;Delay10us();return 1;
}
/*******************************************************************************
* 函数名 : I2cReadByte()
* 函数功能 : 使用I2c读取一个字节
* 输入 : 无
* 输出 : dat
* 备注 : 接收完一个字节SCL0,SDA1.
*******************************************************************************/unsigned char I2cReadByte()
{unsigned char a0,dat0;SDA1; //起始和发送一个字节之后SCL都是0Delay10us();for(a0;a8;a)//接收8个字节{SCL1;Delay10us();dat1;dat|SDA;//由低位开始存Delay10us();SCL0;Delay10us();}return dat;
}/*******************************************************************************
* 函数名 : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能 : 往24c02的一个地址写入一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/void At24c02Write(unsigned char addr,unsigned char dat)
{I2cStart();I2cSendByte(0xa0);//发送写器件地址 0为写 1为读I2cSendByte(addr);//发送要写入内存地址I2cSendByte(dat); //发送数据I2cStop();
}
/*******************************************************************************
* 函数名 : unsigned char At24c02Read(unsigned char addr)
* 函数功能 : 读取24c02的一个地址的一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/unsigned char At24c02Read(unsigned char addr)
{unsigned char num;I2cStart();I2cSendByte(0xa0); //发送写器件地址I2cSendByte(addr); //发送要读取的地址I2cStart();I2cSendByte(0xa1); //发送读器件地址numI2cReadByte(); //读取数据I2cStop();return num;
}
代码分析 void At24c02Write(unsigned char addr,unsigned char dat) { I2cStart(); I2cSendByte(0xa0);//发送写器件地址 0为写 1为读 I2cSendByte(addr);//发送要写入内存地址 I2cSendByte(dat); //发送数据 I2cStop(); } 如下图所示器件地址的高四位是固定的是0x 下面三位接了地为0
最后一位如果是0那么为写如果是1那么为读 unsigned char At24c02Read(unsigned char addr) { unsigned char num; I2cStart(); I2cSendByte(0xa0); //发送写器件地址 I2cSendByte(addr); //发送要读取的地址 I2cStart(); I2cSendByte(0xa1); //发送读器件地址 numI2cReadByte(); //读取数据 I2cStop(); return num; } 代码At24c02Read(1); 传入了1作为At24c02Read(unsigned char addr)的参数addr
addr进入 At24c02Read函数后作为I2cSendByte(addr);//发送要写入内存地址
为什么addr是一个十进制的数但是可以作为地址呢
AT24C02 EEPROM 芯片支持 8 位地址编址其中低 5 位用于指示要读写的具体存储单元。因此addr 参数可以设置为 1对应的二进制数是 0000 0001