赞
踩
AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息
存储介质:E2PROM
通讯接口:I2C总线
容量:256字节
I2C总线(InterICBUS)是由Philips公司开发的一种通用数据总线·两根通信线:SCL(SerialClock)、SDA(SerialData)
同步、半双工,带数据应答
通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议.降低了学习和应用的难度I
所有I2C设备的SCL连在一起,SDA连在一起
设备的SCL和SDA均要配置成开漏输出模式
SCL和SDA各添加一个上拉电阻,阴值一般为4.7K左右
开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题
起始条件:SCL高电平期间,SDA从高电平切换到低电平
终止条件:SCL高电平期间,SDA从低电平切换到高电平
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次.即可发送一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),然后拉高SCL主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次.即可接收一个字节(主机在接收之前,需要释放SDA)
功能:存储数据
#include <REGX52.H> #include "Delay.h" #include "LCD1602.h" #include "Key.h" #include "AT24C02.h" unsigned char KeyNum; unsigned int Num; void main() { LCD_Init(); LCD_ShowNum(1,1,Num,5); while(1) { KeyNum=Key(); if(KeyNum==1) { Num++; LCD_ShowNum(1,1,Num,5); } if(KeyNum==2) { Num--; LCD_ShowNum(1,1,Num,5); } if(KeyNum==3) { AT24C02_WriteByte(0,Num%256); Delay(5); AT24C02_WriteByte(1,Num/256); Delay(5); LCD_ShowString(2,1,"Write OK"); Delay(1000); LCD_ShowString(2,1," "); } if(KeyNum==4) { Num=AT24C02_ReadByte(0); Num|=AT24C02_ReadByte(1)<<8; LCD_ShowNum(1,1,Num,5); LCD_ShowString(2,1,"Read OK"); Delay(1000); LCD_ShowString(2,1," "); } } }
#include <REGX52.H> #include "I2C.h" #define AT24C02_ADDRESS 0xA0 /** * @brief AT24C02写入一个字节 * @param Worddress要写入字节的地址 * @param Worddress要写入字节的数据 * @retval 无 */ void AT24C02_WriteByte(unsigned char WordAddress,Data) { unsigned char Ack; I2C_Start(); I2C_SendByte(AT24C02_ADDRESS); I2C_ReceiveAck(); I2C_SendByte(WordAddress); I2C_ReceiveAck(); I2C_SendByte(Data); I2C_ReceiveAck(); I2C_Stop(); } /** * @brief AT24C02读取一个字节 * @param Worddress要读出字节的地址 * @retval 读出的数据 */ unsigned char AT24C02_ReadByte(unsigned char WordAddress) { unsigned char Data; I2C_Start(); I2C_SendByte(AT24C02_ADDRESS); I2C_ReceiveAck(); I2C_SendByte(WordAddress); I2C_ReceiveAck(); I2C_Start(); I2C_SendByte(AT24C02_ADDRESS|0x01); I2C_ReceiveAck(); Data=I2C_ReceiveByte(); I2C_SendAck(1); I2C_Stop(); return Data; }
#include <REGX52.H> sbit I2C_SCL=P2^1; sbit I2C_SDA=P2^0; /** * @brief I2C开始 * @param 无 * @retval 无 */ void I2C_Start(void) { I2C_SDA=1; I2C_SCL=1; I2C_SDA=0; I2C_SCL=0; } /** * @brief I2C停止 * @param 无 * @retval 无 */ void I2C_Stop(void) { I2C_SDA=0; I2C_SCL=1; I2C_SDA=1; } /** * @brief I2C发送一个字节 * @param Byte要发送的字节 * @retval 无 */ void I2C_SendByte(unsigned char Byte) { unsigned char i; for(i=0;i<8;i++) { I2C_SDA=Byte&(0x80>>i); I2C_SCL=1; I2C_SCL=0; } } //写进内存里面不需要返回值,读出来才要 /** * @brief I2C接收一个字节 * @param 无 * @retval 接收到的一个字节数据 */ unsigned char I2C_ReceiveByte(void) { unsigned char i,Byte=0x00; I2C_SDA=1; for(i=0;i<8;i++) { I2C_SCL=1; if(I2C_SDA){Byte|=(0x80>>i);} I2C_SCL=0; } return Byte; } /** * @brief I2C发送应答 * @param AckBit应答位,0为应答,1为非应 * @retval 无 */ void I2C_SendAck(unsigned char AckBit) { I2C_SDA=AckBit; I2C_SCL=1; I2C_SCL=0; } /** * @brief I2C接收应答 * @param 无 * @retval 接收到的应答位,0为应答,1为非应 */ unsigned char I2C_ReceiveAck(void) { unsigned char AckBit; I2C_SDA=1; I2C_SCL=1; AckBit=I2C_SDA; I2C_SCL=0; return AckBit; }
#include <REGX52.H> #include "Delay.h" #include "Nixie.h" #include "Timer0.h" #include "Key.h" #include "AT24C02.h" unsigned char KeyNum; unsigned char Min,Sec,MiniSec; unsigned char RunFlag; void main() { Timer0_Init(); while(1) { KeyNum=Key(); if(KeyNum==1) { RunFlag=!RunFlag; } if(KeyNum==2) { Min=0;Sec=0;MiniSec=0; } if(KeyNum==3) { AT24C02_WriteByte(0,Min); Delay(5); AT24C02_WriteByte(1,Sec); Delay(5); AT24C02_WriteByte(2,MiniSec); Delay(5); } if(KeyNum==4) { Min=AT24C02_ReadByte(0); Sec=AT24C02_ReadByte(1); MiniSec=AT24C02_ReadByte(2); } Nixie_SetBuf(1,Min/10); Nixie_SetBuf(2,Min%10); Nixie_SetBuf(3,11); Nixie_SetBuf(4,Sec/10); Nixie_SetBuf(5,Sec%10); Nixie_SetBuf(6,11); Nixie_SetBuf(7,MiniSec/10); Nixie_SetBuf(8,MiniSec%10); } } void Sec_Loop(void) { if(RunFlag) { MiniSec++; if(MiniSec>=100) { MiniSec=0; Sec++; if(Sec>=60) { Sec=0; Min++; if(Min>=60) { Min=0; } } } } } void Timer0_Routine() interrupt 1 { static unsigned int Count1,Count2,Count3; TL0 = 0x66; TH0 = 0xFC; Count1++; if(Count1>=20) { Count1=0; Key_Loop(); } Count2++; if(Count2>=2) { Count2=0; Nixie_Loop(); } Count3++; if(Count3>=10) { Count3=0; Sec_Loop(); } }
#include <REGX52.H> #include "Delay.h" unsigned char Key_KeyNumber; unsigned char Key(void) { unsigned char Temp=0; Temp=Key_KeyNumber; Key_KeyNumber=0; return Temp; } unsigned char Key_GetState() { unsigned char KeyNumber=0; if(P3_1==0){KeyNumber=1;} if(P3_0==0){KeyNumber=2;} if(P3_2==0){KeyNumber=3;} if(P3_3==0){KeyNumber=4;} return KeyNumber; } void Key_Loop(void) { static unsigned char NowState,LastState; LastState=NowState; NowState=Key_GetState(); if(LastState==1&&NowState==0) { Key_KeyNumber=1; } if(LastState==2&&NowState==0) { Key_KeyNumber=2; } if(LastState==3&&NowState==0) { Key_KeyNumber=3; } if(LastState==4&&NowState==0) { Key_KeyNumber=4; } }
#include <REGX52.H> #include "Delay.h" unsigned char Nixie_Buf[9]={0,10,10,10,10,10,10,10,10}; unsigned int NixieTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40}; void Nixie_SetBuf(unsigned int Location,Number) { Nixie_Buf[Location]=Number; } void Nixie_Scan(unsigned int Location,Number) { P0=0x00; switch(Location) { case 1:P2_4=1;P2_3=1;P2_2=1;break; case 2:P2_4=1;P2_3=1;P2_2=0;break; case 3:P2_4=1;P2_3=0;P2_2=1;break; case 4:P2_4=1;P2_3=0;P2_2=0;break; case 5:P2_4=0;P2_3=1;P2_2=1;break; case 6:P2_4=0;P2_3=1;P2_2=0;break; case 7:P2_4=0;P2_3=0;P2_2=1;break; case 8:P2_4=0;P2_3=0;P2_2=0;break; } P0=NixieTable[Number]; } void Nixie_Loop(void) { static unsigned char i=1; Nixie_Scan(i,Nixie_Buf[i]); i++; if(i>=9){i=1;} }
代码多,不易理解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。