51单片机基于I2C总线的秒表模拟应用

————————————————————————————————————————————

参考地址:

http://blog.csdn.net/junyeer/article/details/46480863

http://blog.csdn.net/bob_fly1984/article/details/22690381

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

硬件结构:

  • SDA数据线
  • SCL时间线
  • 上拉电阻

    p.s. 当总线空闲状态时,两根线被上拉电阻拉高,保持高电平。连接总线上的任一器件输出的低电平都将使总线的信号变低

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

总线特征:

  • I2C总线上的每一个设备都可以作为主设备或从设备
  • 每个设备会对应一个唯一的地址,主从设备之间通过地址来确定与哪个器件通信

    p.s. 地址分为7位或10位,此处只介绍7位

  • 通常情况下,把CPU带有I2C总线接口的模块作为主设备,其他挂在总线上的作为从设备
  • 主从设备之间以字节为单位进行双向数据传输

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

工作方式:

  • 主从工作方式:主器件启动数据的发送,产生时钟信号,发出停止信号

    p.s. 是没有I2C总线硬件接口的单片机采用软件模拟I2C总线常用的工作方式

  • 多主工作方式:需要总线竞争或仲裁

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

通信时序(主从工作方式):

  • 空闲状态:

    • SCL和SDA保持高电平状态
  • 忙状态:

    p.s. SDA线必须在SCL时钟的高电平周期才能保持稳定,SDA数据线的高或低电平状态只能在SCL低电平时才能改变

    • 起始条件 S:

      • SCL为高电平,SDA下降沿1→0时,主器件产生起始信号
      • 起始信号产生后,总线处于忙状态,其他I2C器件无法访问总线
    • 停止条件 P:
      • SCL为高电平,SDA上升沿0→1时,主器件产生停止信号

        p.s. 非应答信号规定:当主机为接收设备,主机对最后一个字节不应答,以向发送设备表示数据传送结束

      • 停止条件产生后,主从设备释放总线,总线再次处于空闲状态

    • 传输过程:
      • 主设备在传输有效数据之前先指定从设备的地址,设备地址为7位时,再加一个最低位表示数据传输的方向,0表示主设备→从设备写数据,1表示主设备读数据。

        7位地址码:其中DA3~DA0(硬件出厂时固有的地址编码)及A2~A0(用户设定)为从机地址

      • 主设备在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个bit
      • 当一个字节按数据位从高到低顺序传输完之后,接收设备将SDA拉为低电平,表示数据传输正确,回传给主设备一个应答位。一个字节传输完毕。

        p.s. 并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备回传一个非应答位

        在一次传输中可以传输多个字节,图中只画出首字节

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  • 当主机向从机发送1字节数据时

    p.s. 实际上主从机的SDA信号是在同一根线上的,分开画有助于理解各自的行为

  • 当主机从从机接收1字节数据时

————————————————————————————————————————————

AT24C02

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

主要型号:

ATMEL公司生产的AT24C系列EEPROM中具有I2C总线接口。

这类芯片可以解决掉电而造成的数据丢失的问题,可以保存数据100年,擦写100w次以上。

芯片地址固定部分为1010


型号


存储容量


AT24C01


128*8


AT24C02


256*8


AT24C04


512*8


AT24C08


1024*4


AT24C16


2048*8

芯片特性:略

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

引脚描述:

  • A0/A1/A2是3条地址线,用于确定芯片的硬件地址,在上图系统中均接地,选择000
  • 第4脚和第8脚为正负电源
  • 第5脚为SDA串行数据输入/输出,与单片机P3.5相连
  • 第6脚为SCL串行时钟输入线,与单片机P3.6相连
  • SDA和SCL都需要与正电源间接一个5.1k欧上拉电阻
  • 第7脚写保护功能接地
  • 24C02中带有片内地址寄存器,每写入或读出一个数据字节后,该地址寄存器自动+1,实现对下一个存储单元的读写。为降低总的写入时间,一次操作可以写入多达8个字节的数据。

————————————————————————————————————————————

AT24C02应用实例

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

设计要求:

  • 采用定时中断方式,设计一个0~59s变化的秒表,将每次显示在数码管上的时间存入AT24C02中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

设计思路:

  • 通过定时器50ms触发中断,每次触发中断时中断计数,到达1s时flag标识为1
  • 在死循环中始终显示当前秒数
  • 每次秒数变化时写入flag清零并写入AT24C02中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

硬件清单及连线情况:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

实现代码:

  1 #include <reg51.h>
  2 typedef unsigned char uchar;
  3 typedef unsigned int uint;
  4 sbit scl = P3 ^ 0;
  5 sbit sda = P3 ^ 1;
  6 uchar second = 0;
  7 uchar count = 0;
  8 bit flag = 0;
  9 uchar code table[] =
 10 {
 11     0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0xEE, 0x3E, 0x9C, 0x7A, 0x9E, 0x8E
 12 };
 13 void Init(); //初始化总线
 14 void Start(); //开始
 15 void Stop(); //停止
 16 void Respons(); //响应位
 17 uchar ReadByte(); //读数据
 18 uchar ReadAddress(uchar address); //读地址
 19 void WriteByte(uchar dat); //写字节
 20 void WriteAddress(uchar address, uchar dat); //写地址
 21 void Display(); //显示数码管
 22 void Delay1ms(uchar m); //延时1ms
 23 void Delay(); //延时2个机器周期
 24 void main()
 25 {
 26     /* 初始化总线 */
 27     Init();
 28     /* 初始化LED */
 29     P1 = 0xff;
 30     /* 设置定时器 */
 31     TMOD = 0x01;
 32     TH0 = (65536 - 50000) / 256;
 33     TL0 = (65536 - 50000) % 256;
 34     /* 中断初始化 */
 35     EA = 1;
 36     ET0 = 1;
 37     /* 定时器开始 */
 38     TR0 = 1;
 39     /* 显示数码管并写入 */
 40     while(1)
 41     {
 42         if (flag == 1)
 43         {
 44             flag = 0;
 45             WriteAddress(2, second);
 46         }
 47         Display();
 48     }
 49
 50 }
 51 void Init()
 52 {
 53     //空间状态时SCL与SDA均保持高电平
 54     sda = 1;
 55     Delay();
 56     scl = 1;
 57     Delay();
 58 }
 59 void Start()
 60 {
 61     //SCL高电平情况下,SDA下降沿启动
 62     sda = 1;
 63     Delay();
 64     scl = 1;
 65     Delay();
 66     sda = 0;
 67     Delay();
 68 }
 69 void Stop()
 70 {
 71     //SCL高电平情况下,SDA上升沿停止
 72     sda = 0;
 73     Delay();
 74     scl = 1;
 75     Delay();
 76     sda = 1;
 77     Delay();
 78 }
 79 void Respons()
 80 {
 81     //在SCL位为高电平时产生响应信号,数据传输正确时产生应答且SDA拉低
 82     uchar i;
 83     scl = 1; //此处scl拉高后在while循环中降低,参照时序图
 84     Delay();
 85     while ((sda == 1) && (i < 255))
 86     {
 87         //SDA拉低时跳出循环,表示数据传输正确,产生应答.如果在一段时间内未收到应答,则不再等待跳出循环
 88         i++;
 89         scl = 0;
 90         Delay();
 91     }
 92 }
 93 void WriteAddress(uchar address, uchar dat)
 94 {
 95     Start(); //开始
 96     WriteByte(0xA0); //写入 1010 0000 高4位为固定值,5-7位为A0 A1 A2,最低位0为写操作标识
 97     Respons();
 98     WriteByte(address); //写入 0000 0010
 99     Respons();
100     WriteByte(dat); //写入数据(秒数)
101     Respons();
102     Stop(); //停止
103 }
104 void WriteByte(uchar dat)
105 {
106     uchar i, temp;
107     temp = dat; //将dat读入temp
108     for (i = 0; i < 8; ++i)
109     {
110         temp = temp << 1; //temp左移,最高位移入CY
111         scl = 0; //SCL复位,等待最高位存入SDA后置位
112         Delay();
113         sda = CY; //CY在头文件中已规定,通过SDA发送bit
114         Delay();
115         scl = 1; //SCL置位,延迟2个机器周期后复位
116         Delay();
117     }
118     scl = 0; //为最后一个SCL高电平复位
119     Delay();
120     sda = 1; //一个字节数据发送完毕后置位准备响应
121     Delay();
122 }
123 uchar ReadAddress(uchar address)
124 {
125     uchar byte;
126     Start();
127     WriteByte(0xA0);
128     Respons();
129     WriteByte(address);
130     Respons();
131     Start();
132     WriteByte(0xA1); //写入地址 1010 0001,读写标志位1为读
133     Respons();
134     byte = ReadByte();
135     Stop();
136     return byte;
137 }
138 uchar ReadByte()
139 {
140     uchar i, k;
141     scl = 0;
142     Delay();
143     sda = 1;
144     Delay();
145     for (i = 0; i < 8; ++i)
146     {
147         scl = 1;
148         Delay();
149         k = (k << 1) | sda;
150         scl = 0;
151         Delay();
152     }
153     return k;
154 }
155 void Display()
156 {
157     P2 = 0xfe;
158     P1 = table[second % 10];
159     Delay1ms(1);
160     P2 = 0xfd;
161     // P1 = table[second / 10 %10];
162     P1 = table[second / 10];
163     Delay1ms(1);
164     // P2 = 0xfb;
165     // P1 = table[second / 100];
166     // Delay1ms(5);
167 }
168 void Delay()
169 {
170     ;;
171 }
172 void Delay1ms(uchar m) //使用1ms时二极管闪烁,此处将y=110改成y=50
173 {
174     uchar x, y;
175     for (x = m; x > 0; ++x)
176         for (y = 50; y > 0; --y)
177             ;
178 }
179 void time()interrupt 1
180 {
181     TH0 = (65536 - 50000) / 256;
182     TL0 = (65536 - 50000) % 256;
183     count++;
184     if (count == 20)
185     {
186         count = 0;
187         flag = 1;
188         second++;
189         if (second == 60)
190             second = 0;
191     }
192 }

时间: 2024-10-10 17:28:13

51单片机基于I2C总线的秒表模拟应用的相关文章

51单片机的仿真栈(模拟栈/可重入栈)

51单片机的仿真栈(又叫模拟栈.或者可重入栈). 首先来看,51的系统栈(又叫系统栈,或者硬件栈),就是SP所指向的栈,他是一个满增栈(注释1),位于片内RAM的128 bytes之中,上电之后系统堆栈指针SP的初值等于多少呢?这个要从51的启动文件来分析,启动文件中有这样的汇编代码: ?STACK SEGMENT IDATA ;定义一个片内数据段,段名:?STACK RSEG ?STACK ;选择之前定义过的一个可重定位的段?STACK,下面的汇编语句将会被放置到该段,直到遇到下一个段定位指令

【转】I2C总线协议

I2C总线(Inter Integrated-Circuit)是由PHILIPS公司在上世纪80年代发明的一种电路板级串行总线标准,通过两根信号线--时钟线SCL和数据线SDA--即可完成主从机的单工通信.总线硬件连接极其简单,不同I2C设备挂接在总线上,只需在信号线安装上拉电阻即可完成硬件线路的搭建.另外,I2C总线采用器件地址的硬件设置方法,通过软件寻址方式完全避免了片选寻址的弊端,从而使硬件系统扩展更为灵活. 由于简单有效,I2C在业界得到广泛应用.基于I2C衍生出来的标准有SMBus.P

(4)I2C总线的7bit从机地址

时钟拉伸(Clock stretching)clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.clock stretching是可选的,实际上大多数从设备不包括SCL驱动,所以它们不能stretch时钟.从字节级来看,一个设备可能在快速模式下接受数据,但是需要更多的时间来存储接收到的字节或者准备将要传输的另一个字节.从机可以以一种握手的处理方式在接受和应答字节后将SCL线拉低来强制使得主机进入wait状态知道从机准备好下一个字节的传输.从

51单片机课程设计:基于DS18B20的温度报警器

51单片机课程设计:基于DS18B20的温度报警器 本程序用于读取DS18B20温度,同时具备报警功能,工程分为3个文件,main.c.temp.c.temp.h,经本人修改部分代码,适用于吉林农业大学51开发板,其他朋友亦可移植到其他型号开发板.工程文件在文章最下方. 1.main.c文件 /*********************************说明****************************************** 本程序用于读取温度检测模块DS18B20数值,并

[51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]

这里把EEPROM 24c02封装起来,今后可以直接调用,其连线方式为:SDA-P2.1;SCL-P2.0;WP-VCC >_<:i2c.c 1 /*----------------------------------------------- 2 名称:IIC协议 3 内容:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 一定的修改....(本例是1us机器 4 周期,即晶振频率要小于12MHZ) 5 ---------------------------------------

[原创]基于51单片机的红外遥控课程设计

[注]: 一眨眼,大学接近尾声,具有找工作需要,所以把大学做的电子设计“劣作”放上来.希望考研失意,还能赶上“好工作”的春招班车.如果大伙有什么工作推荐也可以联系我哦,因为一年考研少接触了这方面,所以难免有些生疏.但请相信我!给我机会我会很认真学的! 邮箱:[email protected] 转载请注明出处呀! 基于51单片机的红外遥控课程设计 目录 第一章 设计简介... 3 第二章 系统方案... 3 一.设计方案对比... 3 二.方案设计... 4 第三章 硬件设计... 5 一.红外遥

51单片机课程设计:基于MQ-3的酒精浓度报警器

51单片机课程设计:基于MQ-3的酒精浓度报警器 本程序用于将MQ-3上读取到的模拟信号转换为对应的数字信号,经51单片机处理后,在数码管显示,同时具有报警功能,当检测值高于预警值,蜂鸣器报警.除了可以检测MQ-3酒精浓度模块的AD值,也适用于MQ系列的其他模块,原理基本都相同,都是将读取到的AD值转换为数字信号,程序修改后,如果接线方法正确,可以在吉林农业大学51开发板上完美运行,相关工程文件见最下方附件. /*************************************说明***

51单片机GPIO口模拟串口通信

51单片机GPIO口模拟串口通信 标签: bytetimer终端存储 2011-08-03 11:06 6387人阅读 评论(2) 收藏 举报 本文章已收录于: 分类: 深入C语言(20) 作者同类文章X 1 #include "reg52.h" 2 #include "intrins.h" 3 #include "math.h" 4 #include "stdio.h" 5 sbit BT_SND =P1^5; 6 sbit

基于51单片机的万年历(算法实现)

基于51单片机的万年历,用到了单片机独立键盘.数码管.LED灯模块实现. 想要简单还是DS1302好用. 1 /************************************************** 2 3 作者:纟彖氵戋 博客:http://www.cnblogs.com/yllinux/ 4 5 时间:2017年6月7日 6 7 目标:利用单片机独立键盘.数码管.LED灯模块实现万年历(算法实现) 8 9 ************************************