51单片机轻松入门—基于STC15W4K系列(C语言版)
李友全 编著:http://www.51hei.com/bbs/dpj-37954-1.html
第6章 单片机IIC通信 1 接口定义 2 程序实例 阅读提示:本章主要讲解过去电路使用较多的24C02- 24C512存储器,对于现在 主流的STC15W系列单片机,通常都具有内部比较器与DataFlash存储器,可 直接代换代换本章各个例程功能(详见第7章) 1 接口定义 I2C总线是两线式串行总线(连同GND为3线),仅需要时钟和数据两根线就可 以进行数据传输,仅需要占用单片机的2个IO引脚,使用时十分方便,I2C总线可 以在同一总线上并接多个器件,每个器件都有自己的器件地址(作为对比:SPI 总线没有器件地址,通过CPU提供片选线确定是否选中芯片),读写操作时需要 先发送器件地址,与该地址相符的器件得到确认后便执行相应的操作,而在同一 总线上的其它器件不做响应,称之为器件寻址。 单片机外围使用I2C接口的器件比较多,最常见的是EEPROM存储器(如: 24C02)与ADC转换芯片(如:MCP3421) 。 24C02与单片机的连接电路如下图所示。
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只电阻即可。
|