国内购物网站案例分析,招生网站建设策划方案,常德网站建设网站优化,电商平台制作公司I2C#xff1a;总线标准或通信协议
EEPROM#xff1a;AT24C02芯片
开发板板载了1个EEPROM模块#xff0c;可实现IIC通信
1、EEPROM模块电路#xff08;AT24C02#xff09; 芯片的SCL和SDA管脚是连接在单片机的P2.1和P2.0上
2、I2C介绍 I2C#xff08;Inter#xff…I2C总线标准或通信协议
EEPROMAT24C02芯片
开发板板载了1个EEPROM模块可实现IIC通信
1、EEPROM模块电路AT24C02 芯片的SCL和SDA管脚是连接在单片机的P2.1和P2.0上
2、I2C介绍 I2CInterIntegrated Circuit总线是由PHILIPS公司开发的两线式串行总线用于连接微控制器MCU及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式具有接口线少控制方式简单器件封装形式小通信速率较高等优点 I2C 总线只有两根双向信号线。一根是数据线SDA另一根是时钟线SCL
2.1 I2C物理层
I2C通信设备常用的连接方式如下图所示 特点了解一下即可
1它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个I2C通讯总线中可连接多个I2C通讯设备支持多个通讯主机及多个通讯从机
2一个I2C总线只使用两条总线线路一条双向串行数据线(SDA)一条串行时钟线(SCL)。数据线即用来表示数据时钟线用于数据收发同步
3每个连接到总线的设备都有一个独立的地址主机可以利用这个地址进行不同设备之间的访问
4总线通过上拉电阻接到电源。当I2C设备空闲时会输出高阻态而当所有设备都空闲都输出高阻态时由上拉电阻把总线拉成高电平
5多个主机同时使用总线时为了防止数据冲突会利用仲裁方式决定由哪个设备占用总线
6具有三种传输模式标准模式传输速率为100kbit/s快速模式为400kbit/s高速模式下可达 3.4Mbit/s但目前大多I2C设备尚不支持高速模式
7连接到相同总线的IC数量受到总线的最大电容400pF限制接5-6个没有问题
2.2 I2C协议层作用于MCU
I2C的协议定义了通信的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节
2.2.1 数据有效性规定
I2C总线进行数据传送时时钟SCL信号为高电平期间数据SDA线上的数据必须保持稳定只有在时钟SCL线上的信号为低电平期间数据SDA线上的高电平或低电平状态才允许变化。如下图所示 每次数据传输都以字节为单位每次传输的字节数不受限制
每一个字节必须保证是8位长度。数据传送时先传送最高位
2.2.1.1 读数据的代码
SCL为高电平时才能读数据 //6、读字节 u8 iic_read_byte(u8 ack){ u8 i0,receive0; for(i0;i8;i){ IIC_SCL0; //开始时SCL为低电平 delay_10us(1); //有一个延时是因为高低电平变化时会有一个变化时间需要延时一下 IIC_SCL1; //往后走变为高电平 receive1; if(IIC_SDA1){ receive; } delay_10us(1); } if(!ack){ iic_ack(); }else{ iic_nack(); } return receive; } 2.2.1.2 写数据的代码 void iic_write_byte(u8 dat){ u8 i0; IIC_SCL0; //为0时数据可以改变 //循环8次将一个字节传出去 //要求先传高位再传低位 for(i0;i8;i){ if((dat0x80)0){ IIC_SDA1; }else{ IIC_SDA0; } dat1; //把次高位变为最高位 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; delay_10us(1); } } 2.2.2 起始和停止信号
起始条件SCL线为高电平期间SDA线由高电平向低电平的变化表示起始信号
终止条件SCL线为高电平期间SDA线由低电平向高电平的变化表示终止信号
如下图所示 2.2.2.1 起始信号 void iic_start(){ IIC_SDA1; IIC_SCL1; delay_10us(1); IIC_SDA0; //SDA先变为低电平先写SDA // delay_10us(1); //可以加也可以不加 IIC_SCL0; //拉低后就准备发送和接收数据 // delay_10us(1); //可以加也可以不加 } 2.2.2.2 停止信号 void iic_stop(){ IIC_SDA0; IIC_SCL1; delay_10us(1); IIC_SDA1; IIC_SCL1; //写不写都可以 } 2.2.3 应答响应
每当发送器件传输完一个字节长度8的数据后后面必须紧跟一个校验位这个校验位是接收端通过控制 SDA数据线来实现的以提醒发送端数据我这边已经接收完成数据传送可以继续进行。这个校验位其实就是数据或地址传输过程中的响应
响应包括“应答(ACK)”和“非应答(NACK)”两种信号 作为数据接收端时当设备无论主从机接收到I2C传输的一个字节数据或地址后若希望对方继续发送数据则需要向对方发送“应答(ACK)”信号即特定的低电平脉冲 发送方会继续发送下一个数据 若接收端希望结束数据传输则向对方发送“非应答(NACK)”信号即特定的高电平脉冲发送方接收到该信号后会产生一个停止信号结束信号传输
应答响应时序图如下图所示 发送应答在接收完一个字节之后主机在下一个时钟发送一位数据数据0表示应答数据1表示非应答
接收应答在发送完一个字节之后主机在下一个时钟接收一位数据判断从机是否应答数据1表示非应答主机在接收之前需要释放SDA
2.2.3.1 应答0 void iic_ack(){ IIC_SCL0; IIC_SDA0; //应答 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; } 2.2.3.2 非应答1 void iic_nack(){ IIC_SCL0; IIC_SDA1; //非应答 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; } 2.2.3.3 等待应答
返回值为0应答返回值为1非应答 u8 iic_wait_ack(){ u8 time_temp0; //注意定义变量时放在上方否则容易出现问题 IIC_SCL1; delay_10us(1); //意外情况没有应答 while(IIC_SDA){ //等待IIC_SDA出现低电平 time_temp; if(time_temp100){ //超时了强制退出 iic_stop(); return 1; } } IIC_SCL0; return 0; } 这些信号中起始信号是必需的结束信号和应答信号都可以不要
2.2.4 总线的寻址方式
1I2C总线寻址按照从机地址位数可分为两种一种是7位另一种是10位。采用7位的寻址字节寻址字节是起始信号后的第一个字节的位定义如下图所示 D7-D1位组成从机的地址。D0位是数据传送方向位为“0”时表示主机向从机写数据为“1”时表示主机由从机读数据
2AT24C02器件地址为7位高4位固定为1010低3位由A0/A1/A2信号线的电平决定。因为传输地址或数据是以字节为单位传送的当传送地址时器件地址占7位还有最后一位最低位R/W用来选择读写方向它与地址无关。其格式如下图所示 如果要对芯片进行写操作时R/W 即为0写器件地址即为0XA0如果要对芯片进行读操作时R/W 即为1此时读器件地址为0XA1
1和2连起来看两个图代表的意思一样
2.2.5 数据传输
在起始信号后必须传送一个从机的地址7位第8位是数据的传送方向位R/W用“0”表示主机发送写数据W“1”表示主机接收读数据R
2.2.5.1 写数据
有阴影部分表示数据由主机向从机传送无阴影部分则表示数据由从机向主机传送。A 表示应答A 非表示非应答高电平。S表示起始信号P表示终止信号 void at24c02_write_one_byte(u8 addr,u8 dat){ //addrat24c02的地址 iic_start(); //S iic_write_byte(0xa0); //1010 0000 //从机地址和0 iic_wait_ack(); //A iic_write_byte(addr); //指定地址 //寄存器at24c02地址 iic_wait_ack(); //A iic_write_byte(dat); //数据 iic_wait_ack(); //A/A非 iic_stop(); //P delay_ms(10); } 2.2.5.2 读数据
有阴影部分表示数据由主机向从机传送无阴影部分则表示数据由从机向主机传送。A 表示应答A 非表示非应答高电平。S表示起始信号P表示终止信号 u8 at24c02_read_one_byte(u8 addr){ //addrat24c02的数据地址 u8 temp0; iic_start(); //S iic_write_byte(0xa0); //1010 0000 //从机地址和0 iic_wait_ack(); //A iic_write_byte(addr); //指定地址 //寄存器at24c02地址 iic_wait_ack(); //A/A非 iic_start(); //S iic_write_byte(0xa1); //1010 0001 //从机地址和1 iic_wait_ack(); //A tempiic_read_byte(1); //读时从当前地址开始读因为上方已经指定过at24c02的地址了所以不需要再次指定at24c02的地址 iic_stop(); //P return temp; } 3、软件设计
3.1 创建多文件工程
3.1.1 创建文件夹
在电脑上创建一个实验文件夹为了与教程配套这里命名为“I2C-EEPROM实验”然后在该文件夹内新建App、Public、User三个文件夹如下图所示 Listings和Objects是软件自动生成的
App文件夹用于存放外设驱动文件如LED、数码管、定时器等24c02、iic、key、smg四个文件夹
Public文件夹用于存放51单片机公共的文件如延时、51头文件、变量类型重定义等。
User文件夹用于存放用户主函数文件如main.c
3.1.2 新建工程
首先打开KEILC51软件新建一个工程将工程命名为template并保存在“I2C-EEPROM实验”文件夹下然后选择芯片类型为“AT89C52”不使用系统创建启动文件 3.1.3 向工程添加文件
1将含有.c文件的文件夹添加到工程中这里我在工程中创建3组User、App、Publi通常在工程组的命名与创建的文件夹名保持一致方便查找到源文件位置 2点击下图中的图标创建新文件CtrlS将文件重命名并保存到对应的文件夹中
例如创建新文件CtrlS将文件重命名为public.c并保存到public文件夹中 3这样每一个文件夹中都有一个.c和一个.h文件文件名和文件夹名一样之后需要将建好的文件添加到1创建的工程中 App24c02.c、iic.c、key.c、smg.c
Publicpublic.c
Usermain.c 3.1.4 配置魔术棒选项卡
1点击下图中的图标 2 点击Output选项卡将CreateHEXFile选项勾上 3点击C51选项卡将前面添加到工程组中的文件路径包括进来否则程序中调用其他文件夹的头文件则会报错找不到头文件路径 3.2 实验代码
要实现的功能是系统运行时数码管右3位显示0按K1键将数据写入到EEPROM内保存按K2键读取EEPROM内保存的数据按K3键显示数据加1按K4键显示数据清零最大能写入的数据是255
一般我们以文件形式存放对应功能的驱动程序时会创建2个文件一个是.c源文件另一个是.h头文件。源文件.c通常存放的是外设的驱动程序比如按键检测函数而头文件.h通常用 来存放管脚定义、变量声明、函数声明
3.2.1 public文件
3.2.1.1 public.h //头文件中放置函数的声明、全局变量的定义#ifndef _public_H#define _public_H #include reg52.h //全局变量 typedef unsigned int u16; typedef unsigned char u8; //两个延迟函数声明 void delay_10us(u16 us); void delay_ms(u16 ms);#endif 在头文件的开头使用“#ifndef”关键字判断标号“_public_H”是否被定义若没有被定义则从“#ifndef”至“#endif”关键字之间的内容都有效
这个头文件public.h文件若被其它文件“#include”它就会被包含到其该文件中且头文件中紧接着使用“#define”关键字定义上面判断的标号“_public_H”。当这个头文件被同一个文件第二次“#include”包含的时候由于有了第一次包含中的“#define _public_H” 定义这时再判断“#ifndef _public_H”判断的结果就是假了从“#ifndef” 至“#endif”之间的内容都无效从而防止了同一个头文件被包含多次编译时就不会出现“redefine重复定义”的错误了
3.2.1.2 public.c #include public.h void delay_10us(u16 us){ while(us--); } void delay_ms(u16 ms){ u16 i0,j0; for(i0;ims;i){ for(j0;j110;j); } } 3.2.2 独立按键
3.2.2.1 key.h文件 #ifndef _key_H#define _key_H #include public.h sbit KEY1P3^1; sbit KEY2P3^0; sbit KEY3P3^2; sbit KEY4P3^3; u16 key_scan(u16 mode);#endif 3.2.2.2 key.c文件 #include key.h u16 key_scan(u16 mode){ static u16 key1; if(mode1){ key1; } if(key1(KEY10||KEY20||KEY30||KEY40)){ delay_10us(1000); key0; if(KEY10){ return 1; }else if(KEY20){ return 2; }else if(KEY30){ return 3; }else if(KEY40){ return 4; } }else if(KEY11KEY21KEY31KEY41){ key1; return 0; } } 3.2.3 动态数码管
3.2.3.1 smg.h #ifndef _smg_H #define _smg_H #include public.h sbit LSAP2^2; sbit LSBP2^3; sbit LSCP2^4; #define SMG_A_DP_PORT P0 extern u8 gsmg_code[]; void smg_display(u8 save_buff[],u8 pos); #endif 3.2.3.2 smg.c #include smg.h u8 gsmg_code[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //save_buff是一个u8类型的数组方便外部传入要显示的数据 //pos是数码管从左开始第几个位置开始显示取值范围是1-8 void smg_display(u8 save_buff[],u8 pos){ u16 i0; u16 pos_temppos-1; for(ipos_temp;i8;i){ //位选 switch(i){ case 0: LSC1,LSB1,LSA1; //7 break; case 1: LSC1,LSB1,LSA0; //6 break; case 2: LSC1,LSB0,LSA1; //5 break; case 3: LSC1,LSB0,LSA0; //4 break; case 4: LSC0,LSB1,LSA1; //3 break; case 5: LSC0,LSB1,LSA0; //2 break; case 6: LSC0,LSB0,LSA1; //1 break; case 7: LSC0,LSB0,LSA0; //0 break; } SMG_A_DP_PORTgsmg_code[save_buff[i-pos_temp]]; //save_buff[?]0、1、2 delay_10us(100); SMG_A_DP_PORT0x00; //消隐 } } 3.2.4 I2C读写字节函数
3.2.4.1 iic.h #ifndef _iic_H #define _iic_H #include public.h //定义管脚 sbit IIC_SCLP2^1; sbit IIC_SDAP2^0; //iic协议层的函数 //1、起始信号 void iic_start(); //2、停止信号 void iic_stop(); //3、应答 void iic_ack(); //4、非应答 void iic_nack(); //5、等待应答 u8 iic_wait_ack(); //6、读字节 u8 iic_read_byte(u8 ack); //7、写字节 void iic_write_byte(u8 dat); #endif 3.2.4.2 iic.c #include iic.h //iic协议层的函数 //1、起始信号 void iic_start(){ IIC_SDA1; IIC_SCL1; delay_10us(1); IIC_SDA0; // delay_10us(1); //可以加也可以不加 IIC_SCL0; //拉低后就准备发送和接收数据 // delay_10us(1); //可以加也可以不加 } //2、停止信号 void iic_stop(){ IIC_SDA0; IIC_SCL1; delay_10us(1); IIC_SDA1; IIC_SCL1; //写不写都可以 } //3、应答 void iic_ack(){ IIC_SCL0; IIC_SDA0; //应答 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; } //4、非应答 void iic_nack(){ IIC_SCL0; IIC_SDA1; //非应答 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; } //5、等待应答返回值为0应答返回值为1非应答 u8 iic_wait_ack(){ u8 time_temp0; //注意定义变量时放在上方否则容易出现问题 IIC_SCL1; delay_10us(1); //意外情况没有应答 while(IIC_SDA){ //等待IIC_SDA出现低电平 time_temp; if(time_temp100){ //超时了强制退出 iic_stop(); return 1; } } IIC_SCL0; return 0; } //6、读字节 u8 iic_read_byte(u8 ack){ u8 i0,receive0; for(i0;i8;i){ IIC_SCL0; delay_10us(1); IIC_SCL1; receive1; if(IIC_SDA1){ receive; } delay_10us(1); } //注意看看测试时和案例是否一样没有区别 if(!ack){ iic_ack(); }else{ iic_nack(); } return receive; } //7、写字节 void iic_write_byte(u8 dat){ u8 i0; IIC_SCL0; //为0时数据可以改变 //循环8次将一个字节传出去 //要求先传高位再传低位 for(i0;i8;i){ if((dat0x80)0){ IIC_SDA1; }else{ IIC_SDA0; } dat1; //把次高位变为最高位 delay_10us(1); IIC_SCL1; delay_10us(1); IIC_SCL0; delay_10us(1); } } 3.2.5 AT24C02读写字节函数
3.2.5.1 at24c02.h #ifndef _at24c02_H #define _at24c02_H #include public.h #include iic.h //写入数据函数 void at24c02_write_one_byte(u8 addr,u8 dat); //读数据函数 u8 at24c02_read_one_byte(u8 addr); #endif 3.2.5.2 at24c02.c #include at24c02.h //写 void at24c02_write_one_byte(u8 addr,u8 dat){ //addrat24c02的地址 iic_start(); iic_write_byte(0xa0); //1010 0000 iic_wait_ack(); iic_write_byte(addr); //指定地址 iic_wait_ack(); iic_write_byte(dat); iic_wait_ack(); iic_stop(); delay_ms(10); } //读 u8 at24c02_read_one_byte(u8 addr){ //addrat24c02的数据地址 u8 temp0; iic_start(); iic_write_byte(0xa0); iic_wait_ack(); iic_write_byte(addr); //指定地址 iic_wait_ack(); iic_start(); iic_write_byte(0xa1); iic_wait_ack(); tempiic_read_byte(1); //读时从当前地址开始读 iic_stop(); return temp; } 3.2.6 main.c #include public.h #include smg.h #include key.h #include iic.h #include at24c02.h #define EEPROM_ADDRESS 0 //不超过255即可 /* 系统运行时数码管右3位显示0 按K1键将数据写入到EEPROM内保存 按K2键读取EEPROM内保存的数据 按K3键显示数据加1最大能写入的数据是2550-255 按K4键显示数据清零 */ void main(){ u8 key_temp0; u8 save_value0; //可以不设为0 u8 save_buff[3]; while(1){ key_tempkey_scan(0); if(key_temp1){ //保存数据写 at24c02_write_one_byte(EEPROM_ADDRESS,save_value); }else if(key_temp2){ //读取数据 save_valueat24c02_read_one_byte(EEPROM_ADDRESS); }else if(key_temp3){ //数据1 save_value; if(save_value255){ save_value255; } }else if(key_temp4){ //数据清零 save_value0; } //save_value是一个十进制的值 //让数码管显示数据需要得到save_value个位、十位和百位的值 save_buff[0]save_value/100; //百位 save_buff[1]save_value/10%10; //十位 save_buff[2]save_value%10; //个位 smg_display(save_buff,6); } }
文章转载自: http://www.morning.gwxsk.cn.gov.cn.gwxsk.cn http://www.morning.tgxrm.cn.gov.cn.tgxrm.cn http://www.morning.litao4.cn.gov.cn.litao4.cn http://www.morning.wngpq.cn.gov.cn.wngpq.cn http://www.morning.clfct.cn.gov.cn.clfct.cn http://www.morning.jcfqg.cn.gov.cn.jcfqg.cn http://www.morning.rhdqz.cn.gov.cn.rhdqz.cn http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn http://www.morning.lywys.cn.gov.cn.lywys.cn http://www.morning.rmxgk.cn.gov.cn.rmxgk.cn http://www.morning.kzyr.cn.gov.cn.kzyr.cn http://www.morning.znsyn.cn.gov.cn.znsyn.cn http://www.morning.znsyn.cn.gov.cn.znsyn.cn http://www.morning.kwqwp.cn.gov.cn.kwqwp.cn http://www.morning.rykmf.cn.gov.cn.rykmf.cn http://www.morning.qswws.cn.gov.cn.qswws.cn http://www.morning.crfyr.cn.gov.cn.crfyr.cn http://www.morning.lxthr.cn.gov.cn.lxthr.cn http://www.morning.tfznk.cn.gov.cn.tfznk.cn http://www.morning.wgkz.cn.gov.cn.wgkz.cn http://www.morning.mjzcp.cn.gov.cn.mjzcp.cn http://www.morning.jkwwm.cn.gov.cn.jkwwm.cn http://www.morning.wfttq.cn.gov.cn.wfttq.cn http://www.morning.pszw.cn.gov.cn.pszw.cn http://www.morning.ykgp.cn.gov.cn.ykgp.cn http://www.morning.dqpd.cn.gov.cn.dqpd.cn http://www.morning.wqbhx.cn.gov.cn.wqbhx.cn http://www.morning.qymqh.cn.gov.cn.qymqh.cn http://www.morning.zbkdm.cn.gov.cn.zbkdm.cn http://www.morning.pqwhk.cn.gov.cn.pqwhk.cn http://www.morning.qxwrd.cn.gov.cn.qxwrd.cn http://www.morning.hgcz.cn.gov.cn.hgcz.cn http://www.morning.pyxwn.cn.gov.cn.pyxwn.cn http://www.morning.hwycs.cn.gov.cn.hwycs.cn http://www.morning.kfwrq.cn.gov.cn.kfwrq.cn http://www.morning.jbtzx.cn.gov.cn.jbtzx.cn http://www.morning.pnmgr.cn.gov.cn.pnmgr.cn http://www.morning.fllx.cn.gov.cn.fllx.cn http://www.morning.tfpqd.cn.gov.cn.tfpqd.cn http://www.morning.iiunion.com.gov.cn.iiunion.com http://www.morning.syhwc.cn.gov.cn.syhwc.cn http://www.morning.pqndg.cn.gov.cn.pqndg.cn http://www.morning.mfbcs.cn.gov.cn.mfbcs.cn http://www.morning.cwgt.cn.gov.cn.cwgt.cn http://www.morning.brscd.cn.gov.cn.brscd.cn http://www.morning.qlhwy.cn.gov.cn.qlhwy.cn http://www.morning.jyznn.cn.gov.cn.jyznn.cn http://www.morning.bzpwh.cn.gov.cn.bzpwh.cn http://www.morning.gjxr.cn.gov.cn.gjxr.cn http://www.morning.rbjf.cn.gov.cn.rbjf.cn http://www.morning.wbfg.cn.gov.cn.wbfg.cn http://www.morning.mynbc.cn.gov.cn.mynbc.cn http://www.morning.gtbjc.cn.gov.cn.gtbjc.cn http://www.morning.syrzl.cn.gov.cn.syrzl.cn http://www.morning.bfrsr.cn.gov.cn.bfrsr.cn http://www.morning.rhdln.cn.gov.cn.rhdln.cn http://www.morning.flqbg.cn.gov.cn.flqbg.cn http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn http://www.morning.jrhmh.cn.gov.cn.jrhmh.cn http://www.morning.fgrcd.cn.gov.cn.fgrcd.cn http://www.morning.kbdjn.cn.gov.cn.kbdjn.cn http://www.morning.qklff.cn.gov.cn.qklff.cn http://www.morning.dkqbc.cn.gov.cn.dkqbc.cn http://www.morning.sxmbk.cn.gov.cn.sxmbk.cn http://www.morning.bqwrn.cn.gov.cn.bqwrn.cn http://www.morning.rkdw.cn.gov.cn.rkdw.cn http://www.morning.ckzjl.cn.gov.cn.ckzjl.cn http://www.morning.lzbut.cn.gov.cn.lzbut.cn http://www.morning.nrchx.cn.gov.cn.nrchx.cn http://www.morning.ztqyj.cn.gov.cn.ztqyj.cn http://www.morning.litao7.cn.gov.cn.litao7.cn http://www.morning.gtqx.cn.gov.cn.gtqx.cn http://www.morning.dnydy.cn.gov.cn.dnydy.cn http://www.morning.xskbr.cn.gov.cn.xskbr.cn http://www.morning.mcjrf.cn.gov.cn.mcjrf.cn http://www.morning.pgkpt.cn.gov.cn.pgkpt.cn http://www.morning.ckhry.cn.gov.cn.ckhry.cn http://www.morning.fwcnx.cn.gov.cn.fwcnx.cn http://www.morning.nypgb.cn.gov.cn.nypgb.cn http://www.morning.znpyw.cn.gov.cn.znpyw.cn