51单片机个人学习笔记11(AT24C02-I2C总线)

前言

本篇文章属于STC89C52单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。

[1-1] 课程简介_哔哩哔哩_bilibili

一、存储器介绍

存储器介绍

易失性存储器/RAM(random access memory 随机存储器):掉电会丢失

SRAM:静态RAM速度较快

DRAM:速度不如静态RAM

非易失性存储器/ROM(read only memory 只读存储器):掉电不会丢失

Mask ROM:掩膜ROM,不能写入,只能读取

PROM:可编程ROM,只能写入一次

EPROM:可擦除可编程ROM,紫外线照射30分钟才能擦除数据

EEPROM:电可擦除可编程ROM,可以通过电来迅速擦除


存储器的简化模型

烧录一词的由来:通过烧穿二极管来实现导通

二、AT24C02介绍

引脚及应用电路

内部结构框图

三、I2C总线

1.I2C总线介绍

2.I2C电路规范

单片机的弱上拉模式

要输出低电平0时,闭合开关,无电阻经过,驱动能力较强

要输出高电平1时,断开开关,有电阻经过,驱动能力较弱

开漏输出

把上拉电阻去掉

输出低电平时,闭合开关即可

输出高电平时,断开开关,IO口处于一个浮空的状态

3.I2C时序结构

起始位与终止位

发送一个字节

接受一个字节

从机应答

I2C数据帧

发送

接受

复合格式

AT24C02数据帧

四、实例一(AT24C02数据存储)

I2C.c

#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  接受到的应答位
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char Ackbit;
	I2C_SDA=1;
	I2C_SCL=1;
	Ackbit=I2C_SDA;
	I2C_SCL=0;
	return Ackbit;
}

AT24C02.c --继承I2C的字节帧形成数据帧

#include <REGX52.H>
#include "I2C.h"
 
// SLAVE ADDRESS+W为0xA0,SLAVE ADDRESS+R为0xA1
#define AT24C02_ADDRESS_READ		0xA0
#define AT24C02_ADDRESS_WRITE		0xA1
 
/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS_READ);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}
 
/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS_READ);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	// 读地址
	I2C_SendByte(AT24C02_ADDRESS_WRITE);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

注意:调用AT24C02_WriteByte时要延时5ms,让数据有充分的时间写入

五、实例二(秒表(定时器扫描按键数码管))

在定时器的中断函数中调用按键扫描和数码管扫描的函数,实现定时器的复用
Key.c

#include <REGX52.H>
#include "Delay.h"

unsigned char Key_KeyNum;

unsigned char Key()
{
	unsigned char Temp=0;
	Temp=Key_KeyNum;
	Key_KeyNum=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();
	//Last=1,Now=0检测的是松手,Last=0,Now=1检测的是按下
	if (LastState==1 && NowState==0)
	{
		Key_KeyNum=1;
	}
	if (LastState==2 && NowState==0)
	{
		Key_KeyNum=2;
	}
	if (LastState==3 && NowState==0)
	{
		Key_KeyNum=3;
	}
	if (LastState==4 && NowState==0)
	{
		Key_KeyNum=4;
	}
}

Nixie.c

#include <REGX52.H>
#include "Delay.h"

unsigned char Nixie_Buf[9]={0,10,10,10,10,10,10,10,10};

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};

void Nixie_SetBuf(unsigned char Location,Number)
{
	Nixie_Buf[Location]=Number;
}

void Nixie_Scan(unsigned char 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>8){i=1;}
}

main.c

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

unsigned char KeyNum;
unsigned char Temp;
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()
{
	if (RunFlag)
	{
		MiniSec++;
		if (MiniSec>=100)
		{
			MiniSec=0;
			Sec++;
			if (Sec>=60)
			{
				Sec=0;
				Min++;
				if (Min>=100)
				{
					Min=0;
				}
			}
		}
	}
}

void Timer0_Rountine() interrupt 1
{
	static unsigned int T0Count1,T0Count2,T0Count3;
	TH0=0xFC;   	    
	TL0=0x66;		   
	T0Count1++;
	if (T0Count1==20)       
	{
		T0Count1=0;
		Key_Loop();
	}
	T0Count2++;
	if (T0Count2==2)       
	{
		T0Count2=0;
		Nixie_Loop();
	}
	T0Count3++;
	if (T0Count3==10)
	{
		T0Count3=0;
		Sec_Loop();
	}
}
相关推荐
Moliay7 分钟前
【资料分析】刷题日记2
笔记·公考·行测·常识·资料分析
架构文摘JGWZ41 分钟前
Java 23 的12 个新特性!!
java·开发语言·学习
小齿轮lsl1 小时前
PFC理论基础与Matlab仿真模型学习笔记(1)--PFC电路概述
笔记·学习·matlab
Aic山鱼1 小时前
【如何高效学习数据结构:构建编程的坚实基石】
数据结构·学习·算法
qq11561487071 小时前
Java学习第八天
学习
天玑y2 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯
2301_789985942 小时前
Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)
java·开发语言·学习
橄榄熊2 小时前
Windows电脑A远程连接电脑B
学习·kind
web_learning_3213 小时前
source insight学习笔记
笔记·学习
Lossya3 小时前
【机器学习】参数学习的基本概念以及贝叶斯网络的参数学习和马尔可夫随机场的参数学习
人工智能·学习·机器学习·贝叶斯网络·马尔科夫随机场·参数学习