【51单片机】AT24C02-存储器

RAM : 易失性存储器 (高速存储)

  • SRAM:静态RAM,电脑中的CPU,高速缓存,容量少,成本高
  • DRAM:动态RAM,使用电容存储,电容容值小,需要补电能,成本相较于SRAM更低,容量更大

ROM:非易失性存储器

  • Mask ROM(掩膜ROM),只能读,不能写
  • PROM:可编程ROM,可以写,但是只能写入一次
  • EPROM:可擦除可编程ROM,可以编程,也可以清除(30分钟紫外线)
  • E2PROM: 电可擦除可编程ROM,5V电可擦除,掉电不丢失
  • Flash(闪存):
  • 硬盘、软盘、光盘等:磁介质、光信号
    在这里插入图片描述
    单片机烧录的由来:早期通过编程储存数据,实际上是将特殊的二极管击穿,相当于“烧毁”(PROM)。

AT24C02介绍
在这里插入图片描述
I2C总线介绍:

为什么要开漏输出模式?

  • 输出端浮空,电平易受外界干扰,不稳定

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a446e82c166b462bb6128a982ee637da.png在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
I2C不同的流程模块:

  • 起始条件
  • 中止条件
  • 发送一个字节
  • 接收一个字节
  • 接收应答
  • 发送应答

实验: 给AT24C02写入数据

实验现象:AT24C02掉电不丢失

代码:

#include <REGX52.H>
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"

unsigned char Data;
void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"Hello World");
	//AT24C02_WriteByte(1,123);
	Delay(5);//AT21C02写一个序列的有效停止条件开始至内部写周期结束的时间
	Data=AT24C02_ReadByte(1);
	LCD_ShowNum(2,1,Data,3);
	while(1)
	{
		
	}
}

完善代码:

#include <REGX52.H>
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"

unsigned char KeyNum;
//unsigned char Num; 这里要用到整型
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)//读的时候不需要Delay
		{
			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,"        ");//延时清除
		}
	
	}
}

为什么要写?

			AT24C02_WriteByte(0,Num%256);//低八位
			Delay(5);
			AT24C02_WriteByte(1,Num/256);//高八位

因为:int类型最高65535,对应的二进制为16位

实验:定时器按键扫描实例1

实验结果:如果直接让Nixie在判断键码后显示Keynum值,只能显示一瞬间,数码管的显示方式不同于LCD1602,所以需要一个缓存量Temp

		Temp=Key();
		if(KeyNum)//显示结果只在一瞬间显示
		{
			Nixie(1,KeyNum);
		}
		if(Temp)
		{
			KeyNum=Temp;
		}
		Nixie(1,KeyNum);

实验:定时器按键扫描实列2

#include <REGX52.H>
#include "Key.h"
#include "AT24C02.h"
#include "Timer0.h"
#include "Nixie.h"
#include "Delay.h"
unsigned char KeyNum;
void main()
{
	Timer0_Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum)
		{
			Nixie_SetBuf(1,KeyNum);
			Nixie_SetBuf(2,KeyNum);
			Nixie_SetBuf(3,KeyNum);
			Delay(1000);
		}
	}
}

void Timer0_Routine() interrupt 1 //中断子程序
{
		static unsigned int T0Count1,T0Count2;//静态局部变量,保证退出函数之后不销毁
		TL0 = 0x66;				//设置定时初始值
		TH0 = 0xFC;				//设置定时初始值	
		T0Count1++;//每次进入中断子程序,秒控制器自加一
		if(T0Count1>=20)//每隔20ms,按键函数会被调用一次
		{
			T0Count1=0;
			Key_Loop(); 
		}
		T0Count2++;
		if(T0Count2>=2)
		{
			 T0Count2=0;
			 Nixie_Loop();
		}
}

实验结果:
请添加图片描述
请添加图片描述
这时,按下按键,数码管显示会延时一秒改变,可见,使用定时器扫描按键,不会被延时函数影响,相较于延时函数使单片机的工作更具有可靠性

秒表源代码:
操作方式:

  • 按键1暂停
  • 按键2清零
  • 按键3通过AT24C02写入数据
  • 按键4通过AT24C02读取数据
#include <REGX52.H>
#include "Key.h"
#include "AT24C02.h"
#include "Timer0.h"
#include "Nixie.h"
#include "Delay.h"


unsigned char KeyNum;
unsigned char Min,Sec,MiniSec;//单位:分,秒,1/100s=10ms
unsigned char RunFlag;//启动暂定标志位

void main()
{
	P2_5=0;//蜂鸣器关闭
	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 T0Count1,T0Count2,T0Count3;//静态局部变量,保证退出函数之后不销毁
		TL0 = 0x66;				//设置定时初始值
		TH0 = 0xFC;				//设置定时初始值	
		T0Count1++;//每次进入中断子程序,秒控制器自加一
		if(T0Count1>=20)//每隔20ms,按键函数会被调用一次
		{
			T0Count1=0;
			Key_Loop(); 
		}
		T0Count2++;
		if(T0Count2>=2)
		{
			 T0Count2=0;
			 Nixie_Loop();
		}
		T0Count3++;
		if(T0Count3>=10)//10ms
		{
			 T0Count3=0;
			 Sec_Loop();
		}
}
  • 题外话: 6-1矩阵键盘密码锁:为什么密码不能设置为0开头?
    因为0开头代表八进制,比如0123实际上对应的十进制数是83
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值