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

news2024/9/23 11:16:47

前言

本篇文章属于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();
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2117247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海外域名有多好用?怎么购买海外域名?Namecheap+虚拟卡购买步骤详解

前言 为什么要用海外域名&#xff1f; 首先&#xff0c;博主要介绍一下为什么要使用海外域名&#xff0c;使用国内的域名不好吗&#xff1f;主要是出于以下几个原因供大家参考&#xff0c;主要是涵盖了品牌保护、市场拓展、灵活性和创新性等多个方面&#xff1a; 1.品牌保护&…

智慧环保解决方案

1. 建设背景与环境问题 随着经济和工业的快速发展&#xff0c;环境问题如污染和资源短缺日益严重&#xff0c;引起了国家层面的高度重视。政策密集出台&#xff0c;旨在加强大气污染防治&#xff0c;推动区域联合防治&#xff0c;实施大气污染物和温室气体的协同控制。 2. 环…

springboot 整合swagger

没有多余废话&#xff0c;就是干 spring-boot 2.7.8 springfox-boot-starter 3.0.0 结构 POM.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/…

PhotoZoom Pro 9.0.4中文特别版软件介绍

PhotoZoom Pro 9.0.4中文特别版软件介绍 PhotoZoom Pro 9.0.4中文特别版是一个十分强大的图片无损放大(图片放大不失真)软件。 它是一款采用国际领先插值算法的新颖的、技术上具有革命性的对数码图片无损放大的工具。 一般情况我们用通常的工具对数码图片进行放大时&#xff…

kali2023安装docker

在root用户下运行 先运行更新&#xff0c;然后升级 apt update apt upgrade -y 安装docker依赖包 apt install apt-transport-https ca-certificates curl software-properties-common -y 添加docker官方的GPG密钥 echo deb https://download.docker.com/linux/debian s…

华为OD机试真题 - 考古学家 - 递归(Python/JS/C/C++ 2024 D卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

检查Index对象是否单调递减pandas.Index.is_monotonic_decreasing

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 检查Index对象是否单调递减 pandas.Index.is_monotonic_decreasing [太阳]选择题 题目代码中输出结果是&#xff1f; import pandas as pd idx1 pd.Index([1, 2, 3, 4, 5]) idx2 pd.Index…

抢鲜体验 PolarDB PG 15 开源版

unsetunsetPolarDB 商业版unsetunset 8 月&#xff0c;PolarDB PostgreSQL 版兼容 PostgreSQL 15 版本&#xff08;商业版&#xff09;正式发布上线。 当前版本主要增强优化了以下方面&#xff1a; 改进排序功能&#xff1a;改进内存和磁盘排序算法。 增强SQL功能&#xff1a;支…

SprinBoot+Vue餐饮连锁店管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

基于聚类与LSTM对比特币价格深度分析与预测

1.项目背景 比特币作为全球最具影响力的加密货币之一&#xff0c;其价格受到多种复杂因素的共同作用&#xff0c;包括市场情绪、政策变化、大型机构的投资行为等&#xff0c;这些因素在不同的市场阶段对比特币价格波动产生直接或间接的影响。通过对比特币市场的深入分析&#…

在java中使用网易邮箱发送邮件保姆级教程,从零开始,完美避开各种坑

背景,开源工作流引擎AntFlow,gitcode地址通知系统需要配置一个邮箱地址才能供用户展示发送邮件通知功能.最初在开发阶段我使用的是个人163邮箱,本来没什么问题.然而当注册一个新的网易邮箱并在配置里替换掉原来个人邮箱后,竟然出现535 Error: authentication failed 异常,经过网…

【orin-nx Linux下创建简单C++项目 CMake构建编译系统】

【注意】&#xff1a;需要安装gcc 和 cmake 安装视频 #.sh 文件添加权限 chmod x cmake-3.30.3-linux-aarch64.sh1、在root下创建一个文件夹testaubo 2、在testaubo文件夹下创建5个文件夹以及一个cmake文件 2.1、【src】 文件夹存放C的 .cpp文件2.2、【include】 文件夹存…

【计算机网络】TCP协议(下)

上篇我们介绍了三次握手四次挥手&#xff0c;这次继续来进行tcp的介绍。 1 TINE_WAIT与CLOSE_WAIT 我们先使用客户端作为左端&#xff0c;服务端作为右方 当我们客户端close时&#xff0c;就会发起两次挥手&#xff0c;此时服务端就会进入CLOSE_WAIT状态&#xff0c;只要服务端…

链表算法题(下)

在链表算法题&#xff08;上&#xff09;长中我们已经学习了一系列的链表算法题&#xff0c;那么在本篇中我们将继续来学习链表的算法题&#xff0c;接下来就继续来破解链表的算法题吧&#xff01; 1.相交链表 160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 通过以上…

基于yolov8的人脸检测计数系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的人脸检测计数系统是一种利用深度学习技术的先进解决方案&#xff0c;它以其高效、准确的特点在人脸检测领域脱颖而出。该系统以YOLOv8为核心算法&#xff0c;该算法作为YOLO系列的最新迭代&#xff0c;不仅继承了前代算法的优点&#xff0c;还在实时…

YOLOv8-obb训练自己的数据集

一、YOLO OBB 格式 YOLO OBB 格式通过四个角点指定边界框&#xff0c;其坐标在 0 和 1 之间归一化&#xff1a; class_index x1 y1 x2 y2 x3 y3 x4 y4 YOLO 在内部处理损失和产出。 xywhr 格式&#xff0c;表示边界框的中心点&#xff08;xy&#xff09;、宽度、高度和旋转角度…

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派5 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下&#xff1a; 今天就水一篇文章&#xff0c;用树莓派摄像头&…

NISP 一级 | 2.4 访问控制

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 0x01&#xff1a;访问控制基本概念 访问控制是针对越权使用资源的防御措施。 其目标是防止对任何资源&#xff08;如计算资源、通信资源或信息资源&#xff09;进行未授权的访问&#xff0c;从而…

BLIP3技术小结(xGen-MM (BLIP-3): A Family of Open Large Multimodal Models)

paperhttps://www.arxiv.org/abs/2408.08872githubhttps://github.com/salesforce/LAVIS/tree/xgen-mmOrg.Salesforce AI Research个人博客地址http://myhz0606.com/article/blip3 前置阅读&#xff1a;BLIP系列总结 核心思路 虽然过去BLIP系列对LMM发展起到至关重要的作用&…

Redis缓存常用的读写策略

缓存常用的读写策略 缓存与DB的数据不一致问题&#xff0c;大多数都是指DB的数据已经修改&#xff0c;而缓存中的数据还是旧数据的情况。 旁路缓存模式 对于读操作&#xff1a;基本上所有模式都是先尝试从缓存中读&#xff0c;没有的话再去DB读取&#xff0c;然后写到缓存中…