扫盲教程:单片机IIC基础通信

单片机IIC基础通信

1 接口定义
2 程序实例

阅读提示:本章主要讲解过去电路使用较多的24C02- 24C512存储器,对于现在 主流的STC15W系列单片机,通常都具有内部比较器与DataFlash存储器,可 直接代换代换本章各个例程功能(详见第7章)
1 接口定义

I2C总线是两线式串行总线(连同GND为3线),仅需要时钟和数据两根线就可 以进行数据传输,仅需要占用单片机的2个IO引脚,使用时十分方便,I2C总线可 以在同一总线上并接多个器件,每个器件都有自己的器件地址(作为对比:SPI 总线没有器件地址,通过CPU提供片选线确定是否选中芯片),读写操作时需要 先发送器件地址,与该地址相符的器件得到确认后便执行相应的操作,而在同一 总线上的其它器件不做响应,称之为器件寻址。

单片机外围使用I2C接口的器件比较多,最常见的是EEPROM存储器(如:
24C02)与ADC转换芯片(如:MCP3421) 。
24C02与单片机的连接电路如下图所示。
在这里插入图片描述
2 程序实例
24C系列芯片既然作为存储器使用,我们最关心的就是如何将数据写入芯片及 写入成功的数据如何读取出来。

例6.2 使用IAP15W4K58S4单片机的硬件仿真功能仿真观察24C02芯片读写结果
(也可用24C01/04/08/16) 。本例无页面限制,快速,适合连续读写多个字 节,本程序先向芯片写入一组数据,然后读出,若读出的数据与写入的数据相同 则表明实验结果是正确的。

为了简化,我们直接移植成熟的程序代码(配套例程中提供)。
① 除主程序MAIN.C外,其余*.C与*.H文件全部复制到你自己的文件夹并将*.C文 件加入工程,如图所示。
在这里插入图片描述
② 根据实际硬件连接修改引脚定义。在IIC.H中有如下语句,可设置为任意IO口,注
意上拉。

sbit SCL=P3^7; // 串行时钟(代码包必须)

sbit SDA=P4^1; // 串行数据(代码包必须)

③ 根据硬件修改从机地址。在24C01_02.H中有:#define SlaveADDR 0xA0 // 从机 地址格式为:1010 ***0。其中的***对应器件引脚 A2A1A0,,用于设置器件地 址,当硬件上A2A1A0接GND时, ***=000。
④ 在要求严格的情况下,根据R/C时钟频率修改延时函数参数。myfun.c中的延时函 数delay1ms()和delay10ms()延时参数由第1章介绍的软件计算得出。

⑤ 根据R/C时钟频率修改宏定义。IIC.H中的语句 “#define tt 26”的常数26对应
myfun.c中的延时函数void delay (unsigned char t)中的参数t,此常数值确定
5uS延时时间,延时可以更长,不能短,时钟频率为22.1184MHz时t=26。
⑥ 这里的例子使用的是24C02芯片,若换用24C04/08/16,为了提高多字节数据跨页 写入速度,则需要对24C01_02.C中函数WrToRomPageB内部常数0x07改为0x0f。

主程序代码如下(注意是硬件仿真观察实验结果):

#include “STC15W4K.H” // 注意宏定义后面没分号
#include “24C01_02.H”
#include “myfun.h” void main()
{
u8 i;
u8 test_data[20]={0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,
0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81,0x91,0xa1};
port_mode(); // 所有IO口设为准双向弱上拉方式。 WrToRomB(SlaveADDR, 5,test_data,20);
// 器件地址、存储单元地址、数据指针、写入字节数
for(i=0;i<20;i++)
{
test_data[ i ]=0;
}
RdFromROM(SlaveADDR, 5,test_data,20); // 连续读取20个字节数据
while(1);
}
例6.5利用24C02记录单片机上电次数(使用工作组方式)

头文件代码如下:

#define E2P_RECORD_ADDR 0x00 // 存储单元地址

#define POWER_UP_MARK 0xAB // 第一次使用标记

struct POWER_UP

{
u32 times;

u8 flag;

};
// 主程序代码如下:

#include “PowerUP.H”

#include “24C01_02.H”

#include “myfun.h”

struct POWER_UP Power_up;
void main()
{

RdFromROM(SlaveADDR,E2P_RECORD_ADDR,(u8*)&Power_up,sizeof(struct POWER_UP));

// 芯片硬件地址、存储单元地址、数据组、写入字节数

if (Power_up.flag != POWER_UP_MARK) // 存储器第一次使用
{

}
else
{

}

Power_up.flag = POWER_UP_MARK; Power_up.times = 1;

Power_up.times++;
WrToRomB(SlaveADDR, E2P_RECORD_ADDR,(u8 *)&Power_up,sizeof(struct POWER_UP));

// 芯片硬件地址、存储单元地址、数据组、写入字节数 UART_init(); UART_Send_StrNum(“上电次数:”,Power_up.times);
// 串口输出上电次数,波特率:9600 /22.1184MHZ
while(1);
}
结果如图所示。
在这里插入图片描述

例6.6 利用24C02断电瞬间存储数据。断电存储就是在系统断电瞬间保存RAM中的重要数据 到EEPROM,在下次系统上电时再读出EEPROM中的数据并运行,断电检测电路原理如图所 示。
在这里插入图片描述
利用单片机外中断检测交流电源的有无,交流供电正常时INT2每10mS进入一次中断,在中断
程序中重装定时器T1初值让定时器一直不产生溢出中断,交流断电时,定时器计数值不断增 加直到溢出,溢出中断程序中单片机立即保存数据到EEPROM 。定时器定时时间要求大于
10mS即可,比如取12或15mS,另外特别注意单片机外中断引脚必须外接上拉电阻。
对于现在主流的STC15W系列单片机,通常都具有内部比较器与DataFlash存储器,可直接 代换24C系列存储器使用,断电检测电路更加简单,如上图单片机VCC与GND间接2只电阻即可。

发布了72 篇原创文章 · 获赞 159 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_44212493/article/details/104334099
今日推荐