(学习日记)2023.04.23

news/2025/1/20 2:52:07/

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2023.04.23

  • 一、元件:AT24C02——E2PROM存储器
  • 二、51:I2C总线
  • 三、51:AT24C02数据存储(I2C总线)
    • 1. 编写`I2C总线`函数
    • 2. 编写`AT24C02数据存储`函数
    • 3. 编写`main`函数

一、元件:AT24C02——E2PROM存储器

  1. 存储器介绍
    在这里插入图片描述
    在这里插入图片描述

详细可看计算机三级嵌入式系统开发 知识点笔记

  1. AT24C02介绍
    在这里插入图片描述
  2. 引脚及应用电路(SCL、SDA需要上拉电阻)
    在这里插入图片描述

(此处写保护为高电平有效,但我用的是低电平有效的存储器)

  1. 内部结构框图
    在这里插入图片描述

二、51:I2C总线

  1. I2C总线介绍
    在这里插入图片描述

详细可看计算机三级嵌入式系统开发 知识点笔记
在这里插入图片描述

  1. I2C电路规范
    在这里插入图片描述

上拉电阻
将一个不确定的信号(高或低电平),通过一个电阻与电源VCC相连,固定在高电平。
一般说法是上拉增大电流,下拉电阻是用来吸收电流。
在这里插入图片描述
上拉电阻阻值的选择原则:
1、从节约功耗及芯片的灌电流能力考虑应当足够大;电阻大,电流小。
2、从确保足够的驱动电流考虑应当足够小;电阻小,电流大。
3、对于高速电路,过大的上拉电阻可能边沿变平缓。
综合考虑以上三点,通常在 1K 到 10K 之间选取。对下拉电阻也是类似道理。

开漏输出(Open Drain Output)
常说的与推挽输出相对的就是开漏输出,对于开漏输出和推挽输出的区别最普遍的说法就是开漏输出无法真正输出高电平,即高电平时没有驱动能力,需要借助外部上拉电阻完成对外驱动。
在这里插入图片描述

  1. I2C时序结构
    在这里插入图片描述
    起始条件触发后,SCL开始产生时钟信号
    在这里插入图片描述
    SDA发送一个二进制,SCL拉高一次
    如果在SCL低电平切换SDA,不会有任何影响
    在这里插入图片描述
    和发送相同,不过拉高SCL和放置SDA的变成了从机
    在这里插入图片描述
    主机发送字节后,从机在下一时钟发送应答
    主机接收字节后,主机在下一时钟发送应答

  2. I2C数据帧
    在这里插入图片描述
    第一个字节中前7位为地址,第8位为读取或写入(1是read,0是write),如果器件只有A0~A2三个引脚,那么A3~A6为固定位(查手册)
    在这里插入图片描述
    如果在SCL低电平时切换SDA,认为触发了起始条件或终止条件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

三、51:AT24C02数据存储(I2C总线)

1. 编写I2C总线函数

  1. 寻找I2C对应引脚,很明显是P20P21
    在这里插入图片描述
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;
  1. 编写I2C发送开始信号函数
/*** @brief  I2C开始* @param  无* @retval 无*/
void I2C_Start(void)
{I2C_SDA=1;I2C_SCL=1;I2C_SDA=0;I2C_SCL=0;
}
  • 将I2C总线的数据线(SDA)置为高电平(1)。
  • 将I2C总线的时钟线(SCL)置为高电平(1)。
  • 将I2C总线的数据线(SDA)置为低电平(0),表示发送开始信号。
  • 将I2C总线的时钟线(SCL)置为低电平(0),完成发送开始信号。

通过执行这段代码,可以在I2C总线上产生一个开始信号,该信号用于启动I2C通信过程。开始信号的形式是先将数据线(SDA)保持高电平,然后将时钟线(SCL)从高电平变为低电平,表示I2C通信的起始。

  1. 编写I2C发送停止信号函数
/*** @brief  I2C停止* @param  无* @retval 无*/
void I2C_Stop(void)
{I2C_SDA=0;I2C_SCL=1;I2C_SDA=1;
}
  • 将I2C总线的数据线(SDA)置为低电平(0)。
  • 将I2C总线的时钟线(SCL)置为高电平(1)。
  • 将I2C总线的数据线(SDA)置为高电平(1),表示发送停止信号。

通过执行这段代码,可以在I2C总线上产生一个停止信号,该信号用于结束I2C通信过程。停止信号的形式是先将数据线(SDA)变为低电平,然后将时钟线(SCL)从高电平变为低电平,最后将数据线(SDA)变为高电平,表示I2C通信的结束。停止信号通常用于表示一次完整的数据传输完成。

  1. 编写I2C发送一个字节数据函数
/*** @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;}
}
  • 函数接受一个无符号字符类型的参数Byte,表示要发送的字节数据。
  • 进入一个循环,循环执行8次,每次发送一个bit的数据。
  • 在每次循环中,通过按位与操作(Byte & (0x80 >> i))来获取要发送的bit的值。
  • 将得到的bit值设置到I2C总线的数据线(SDA)上,通过将I2C_SDA变量赋值为该bit值。
  • 将I2C总线的时钟线(SCL)置为高电平(1),表示准备发送数据。
  • 然后将I2C总线的时钟线(SCL)置为低电平(0),完成一个bit的发送。
  • 循环结束后,函数完成了一个字节数据的发送。

该函数用于通过I2C总线发送数据时,通过连续发送8个bit来传输一个字节数据。具体的工作流程是根据要发送的字节数据,按位设置I2C总线的数据线(SDA)的状态,并通过控制I2C总线的时钟线(SCL)来实现数据的发送。

  1. 编写I2C接收一个字节数据函数
/*** @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;
}
  • 首先声明了一个无符号字符类型的变量iByte,并将Byte初始化为0x00,用于存储接收到的字节数据。
  • 将I2C总线的数据线(SDA)置为高电平(1),表示准备接收数据。
  • 进入一个循环,循环执行8次,每次接收一个bit的数据。
  • 在每次循环中,首先将I2C总线的时钟线(SCL)置为高电平(1),表示准备接收数据。
  • 然后通过判断I2C总线的数据线(SDA)的状态,来确定接收到的bit是0还是1。如果SDA为高电平,则将对应的bit位置为1(Byte的对应bit位根据循环次数递减),如果SDA为低电平,则对应的bit位置为0。
  • 最后,将I2C总线的时钟线(SCL)置为低电平(0),完成一个bit的接收。
  • 循环结束后,函数返回接收到的一个字节数据(Byte)。

该函数用于从I2C总线接收数据时,通过连续接收8个bit来组成一个字节数据。具体的工作流程是根据I2C总线的时钟和数据线状态来逐位接收数据,并将其组装成一个完整的字节数据。

  1. 编写I2C发送应答信号函数
/*** @brief  I2C发送应答* @param  AckBit 应答位,0为应答,1为非应答* @retval 无*/
void I2C_SendAck(unsigned char AckBit)
{I2C_SDA=AckBit;I2C_SCL=1;I2C_SCL=0;
}
  • 将I2C总线的数据线(SDA)设置为应答位(AckBit),其中0表示应答,1表示非应答。
  • 将I2C总线的时钟线(SCL)置为高电平(1)。
  • 将I2C总线的时钟线(SCL)置为低电平(0),完成应答信号的发送。

通过执行这段代码,可以在I2C总线上发送应答信号,用于确认接收到的数据或指示拒绝接收数据。应答信号通常在主设备向从设备发送数据后,从设备进行响应,以指示是否成功接收数据。

  1. 编写I2C接收应答信号函数
/*** @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;
}
  • 将I2C总线的数据线(SDA)置为高电平(1)。
  • 将I2C总线的时钟线(SCL)置为高电平(1)。
  • 将接收到的应答位(AckBit)设置为I2C总线的数据线(SDA)的状态。
  • 将I2C总线的时钟线(SCL)置为低电平(0),完成应答信号的接收。

通过执行这段代码,可以在I2C总线上接收从设备发送的应答信号,并将其作为函数的返回值返回。应答信号通常由从设备发送给主设备,用于确认接收到的数据或指示拒绝接收数据。函数返回的应答位为0表示应答,为1表示非应答。

2. 编写AT24C02数据存储函数

  1. 确定固定地址
    因为器件只有E0~E2三个引脚,那么E3~E6为固定位(1010)
    在这里插入图片描述

在这里插入图片描述

#define AT24C02_ADDRESS		0xA0
  1. 编写 向AT24C02芯片写入一个字节数据 的函数
/*** @brief  AT24C02写入一个字节* @param  WordAddress 要写入字节的地址* @param  Data 要写入的数据* @retval 无*/
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Stop();
}
  • 参数WordAddress表示要写入字节的地址。
  • 参数Data表示要写入的数据。
  • 函数首先发送开始信号(I2C_Start()),然后发送AT24C02芯片的地址(AT24C02_ADDRESS)并接收应答信号(I2C_ReceiveAck())。
  • 接下来,发送要写入的字节的地址(WordAddress)并接收应答信号。
  • 最后,发送要写入的数据(Data)并接收应答信号。
  • 最后发送停止信号(I2C_Stop())结束通信。
  1. 编写 从AT24C02芯片读取一个字节数据 的函数
/*** @brief  AT24C02读取一个字节* @param  WordAddress 要读出字节的地址* @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;
}
  • 参数WordAddress表示要读取字节的地址。
  • 函数首先发送开始信号(I2C_Start()),然后发送AT24C02芯片的地址(AT24C02_ADDRESS)并接收应答信号。
  • 接下来,发送要读取的字节的地址(WordAddress)并接收应答信号。
  • 然后再次发送开始信号,发送AT24C02芯片地址的读取位(AT24C02_ADDRESS | 0x01)并接收应答信号。
  • 接下来,从AT24C02芯片读取一个字节数据(Data = I2C_ReceiveByte())。
  • 最后发送非应答信号(I2C_SendAck(1))表示读取结束,并发送停止信号(I2C_Stop())结束通信。
  • 函数返回读取到的数据。

3. 编写main函数

unsigned char KeyNum;
unsigned int Num;void main()
{LCD_Init();LCD_ShowNum(1,1,Num,5);while(1){KeyNum=Key();if(KeyNum==1)	//K1按键,Num自增{Num++;LCD_ShowNum(1,1,Num,5);}if(KeyNum==2)	//K2按键,Num自减{Num--;LCD_ShowNum(1,1,Num,5);}if(KeyNum==3)	//K3按键,向AT24C02写入数据{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)	//K4按键,从AT24C02读取数据{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,"        ");}}
}

main函数通过按键控制一个数字变量Num的增减以及与AT24C02 EEPROM芯片的读写操作。

下面是代码的执行流程:

  1. 首先,调用LCD_Init()函数初始化LCD显示器。
  2. 调用LCD_ShowNum()函数在LCD上显示Num的当前值。
  3. 进入一个无限循环,程序将不断检测按键状态。
  4. 使用Key()函数获取当前按下的按键编号,并将其存储在KeyNum变量中。
  5. 如果按下的是K1按键(KeyNum等于1),则将Num自增,并使用LCD_ShowNum()函数在LCD上显示更新后的Num的值。
  6. 如果按下的是K2按键(KeyNum等于2),则将Num自减,并使用LCD_ShowNum()函数在LCD上显示更新后的Num的值。
  7. 如果按下的是K3按键(KeyNum等于3),则将Num的低8位写入AT24C02的地址0,并将Num的高8位写入AT24C02的地址1。然后,在LCD上显示"Write OK"消息,并进行延迟等待一段时间后清除显示。
  8. 如果按下的是K4按键(KeyNum等于4),则从AT24C02的地址0读取一个字节,并将其存储在Num的低8位中,然后从地址1读取一个字节,并将其存储在Num的高8位中。最后,使用LCD_ShowNum()函数在LCD上显示读取到的Num的值,并显示"Read OK"消息,并进行延迟等待一段时间后清除显示。
  9. 回到步骤3,继续等待按键操作。

这段代码演示了如何使用按键控制一个变量的增减,并将该变量的值写入和从EEPROM芯片读取。


http://www.ppmy.cn/news/120474.html

相关文章

西门子6SE70交流变频器的详细介绍

西门子6SE70交流变频器主要由隔爆箱、变频器铁芯和热管组成。隔爆箱采用双设备室双接线室的方式&#xff0c;为矩形双门结构。左室为进线室&#xff0c;配有接触器、进线电抗器和辅助变压器。右腔室为变频器主腔室&#xff0c;配有变频器核心和控制系统。本产品采用先进的交-直…

青少年戴助听器有什么危害助听器副作用

世界那么大 一起去看看&#xff5e; 一起去打雪仗堆雪人&#xff5e; 人活一生不容易&#xff0c;要躲过那么多的&#xff0c;人老了想看什么就看什么&#xff0c;想去那就去哪&#xff0c;不要犹豫&#xff0c;肯定有一天你会想走走不了了&#xff0c;到那时一切后悔都晚了。要…

西门子s7 200smart与3台台达VFD-M变频器通讯目标:用触摸屏和西门子smart 控制3台台达变频器通讯

西门子s7 200smart与3台台达VFD-M变频器通讯目标&#xff1a;用触摸屏和西门子smart 控制3台台达变频器通讯 器件&#xff1a;西门子s7 200 smart PLC&#xff0c;3台台达VFD-M变频器&#xff0c;昆仑通态触摸屏(带以太网)&#xff0c;中途可以加路由器 控制方式&#xff1a;触…

西门子1200与台达MS300变频器通讯程序

西门子1200与台达MS300变频器通讯程序 器件&#xff1a;西门子1200 PLC&#xff0c;台达ms300变频器&#xff0c;西门子KTP700 Basic Pn触摸屏&#xff0c;昆仑通态触摸屏(带以太网)&#xff0c;中途可以加路由器 控制方式&#xff1a;触摸屏与plc以太网通讯&#xff0c;PLC与…

助听器牌子重要吗?一文教你如何验配助听器

随着WHO首份《世界听力报告》的颁布&#xff0c;大家对“听力障碍”也重视起来&#xff0c;越来越多的人开始关注助听器。这是一个好现象&#xff0c;但随之而来的问题也不少。 比如说&#xff0c;有些人直接在网上买了助听器&#xff0c;到手发现外界的声音确实被放大了&#…

资深助听器验配师告诉你,助听器是“验配”不是买!

随着WHO&#xff08;世界卫生组织&#xff09;在2021年3月3日发布了首份《世界听力报告》&#xff0c;重视听力情况的人也逐渐多了起来。大家知道&#xff0c;不再是老人才会出现听力损失的情况&#xff0c;受很多外界、遗传因素的影响&#xff0c;不少年轻人甚至儿童&#xff…

爱美人士的福音,这款超小型助听器get一下!

提起超小型助听器&#xff0c;大家联想到的是不是耳道式助听器&#xff1f;因为它比起很多传统耳背式&#xff0c;确实要小巧、美观很多。 但耳道式助听器有着诸多不便之处&#xff0c;比如它的功率不够大&#xff0c;比较适用于轻中度听力受损的朋友&#xff1b;它容易堵耳&am…

常戴助听器有什么危害副作用

绿荷多少并且&#xff0c;对于初次绿荷多少验配的患绿荷多少者&#xff0c;验配绿荷多少师会将放大渺渺孤城有所保留&#xff0c;不会调到极大渺渺孤绿荷多少城绿荷多少音量。待其适应一段时间后 戴助听器有什么危害和副作用 1、助听器外观&#xff1a;助听器实际上是一部微型扩…