C51学习归纳9 --- I2C通讯学习(重点)

        首先,我自己学习过以后的直观感觉,通信协议是单片机的灵魂之一,只有规定好了通信协议我们才能够正确的接收到信息,才能实现更加深入的研究。所以这一部分是需要好好学习的。

        本节借助一个可存储的芯片AT24C02,进行在I2C协议上的读取,实现掉电不丢失,永久存储数据并读取的工作。

一、I2C通信协议原理

        24C02的通讯方式是I2C,所以这个芯片端口的连接直接按照I2C所需直接预留出来。WE是写入使能,即可以存储内容。P2_1,2是控制我们写入时机,和内容的控制端口。后续讲完I2C通讯流程,大家应该就懂了。E0~2直接接地,是I2C的地址。

        上图是I2C通信协议开始和结束的信号标志。

        开始标志:在SCL高电平的时候,将数据线SDA下拉,从高电平到低电平。随后SCL拉低       

        结束标志:在SCL高电平的时候,将数据线SDA上拉,从低电平到高电平。 SCL提前拉高

         在收到开始信号以后,我们就可以发送数据了,现在讲数据怎么发送的。

        开始信号后,SCL=0,SDA=0。在SCL=0的期间,我们将数据放在SDA上,在下一次SCL=1时,从机读取数据。

       在讲数据怎么接收的。

       开始前SCL=0,SDA=0。在SCL=0的期间,从机将数据放在SDA上,在下一次SCL=1时,主机读取刚才SDA写入的数据。注意,这里需要主机释放SDA线。

         这一步其实是为了,确定从机是否接受,和确定从机是否发送完毕。保证系统通信的连贯和正确。        

         主机发送开始位,然后发送从机地址和设置为写模式,随后监听从机的接收应答,如果接收了,返回RA信号。然后主机开始发送数据,从机应答,以此往复,直到最后主机发送结束位。本次通信结束。

        地址,前四位是厂家定的,加下来三位由电路板的连接确定,电路板全部连地,所以就是000.最后一位是1为读,0为写。

         主机发送开始位,然后发送从机地址和设置为读模式,随后监听从机的接收应答,如果接收了,返回RA信号。然后从机开始发送数据,从机发送发送应答,以此往复,最后遇到SA=1时主机发送结束位。本次通信结束。

         这个就是将前两个组合起来,发送尾部去掉停止信号,直接加上接受操作。

         这里就是在指定位置写入、读取。

二、利用AT24C02 进行数据存储和读取

        那么我们要借助I2C通信,我们就要写I2C的底层函数。

#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;
}

        这一段代码看着很长,但是你如果只看大的模块,其实我们就是把刚才的开启、停止、发送、接收、发送应答、接收应答的时序逻辑表示出来了而已 。这些就是I2C的通信协议

#include <REGX52.H>
#include "I2C.h"#define AT24C02_ADDRESS		0xA0/*** @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();
}/*** @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;
}

         有了I2C的通信协议之后,我们的AT24C02就可以借助I2C的通信格式,编写自己的读写功能。这个也是刚才的逻辑图。

#include <REGX52.H>
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"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,"        ");}}
}

        编写了底层的代码之后,我们在主函数里只需要,直接调用就好了。

三、利用定时器实现秒表

        之前也实现了类似的功能,但是以前按键按下以后是阻塞的,不利于芯片的运行,现在使用定时器对按键扫描,克服以前的不足。

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include "Nixie.h"
#include "Delay.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)			//K1按键按下{RunFlag=!RunFlag;	//启动标志位翻转}if(KeyNum==2)			//K2按键按下{Min=0;				//分秒清0Sec=0;MiniSec=0;}if(KeyNum==3)			//K3按键按下{AT24C02_WriteByte(0,Min);	//将分秒写入AT24C02Delay(5);AT24C02_WriteByte(1,Sec);Delay(5);AT24C02_WriteByte(2,MiniSec);Delay(5);}if(KeyNum==4)			//K4按键按下{Min=AT24C02_ReadByte(0);	//读出AT24C02数据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);}
}/*** @brief  秒表驱动函数,在中断中调用* @param  无* @retval 无*/
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 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count1++;if(T0Count1>=20){T0Count1=0;Key_Loop();	//20ms调用一次按键驱动函数}T0Count2++;if(T0Count2>=2){T0Count2=0;Nixie_Loop();//2ms调用一次数码管驱动函数}T0Count3++;if(T0Count3>=10){T0Count3=0;Sec_Loop();	//10ms调用一次数秒表驱动函数}
}

        我们先看主要的逻辑,中断中,1、每次产生中断都要重新赋值;2、我们每20ms对独立按键进行扫描,判断当下的按键值;3、每2ms对数码管进行顺序刷新显示;4、每10ms,因为我们的毫秒只显示2位,所以我们每10ms显示依次新的毫秒数字,并并进位。

        讲完了中断,我们关注一下主函数的内容,每当我们扫描得到了键码值以后,我们针对不同的键码值做不同的工作。按键一:修改计时器开始。按键二:数据清理。按键三:写入。案件四:从芯片读出,显示在数码表。

        随后讲一下优势:

        1、使用定时器,避免了延时函数占用CPU,从而提高效率。

        2、使用定时器,定时扫描数码管,显示效果更好

void Nixie_Scan(unsigned char Location,Number)
{P0=0x00;				//段码清0,消影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];	//段码输出
}/*** @brief  数码管驱动函数,在中断中调用* @param  无* @retval 无*/
void Nixie_Loop(void)
{static unsigned char i=1;Nixie_Scan(i,Nixie_Buf[i]);i++;if(i>=9){i=1;}
}

        3、使用定时器,可以消除按键抖动,配合如下代码

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;}
}

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

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

相关文章

C语言怎样初始化图形模式?

一、问题 在C语⾔中&#xff0c;initgraph( ) 函数⽤于初始化图形模式。初始化时&#xff0c;那么多参数都是⼲什么的&#xff1f;怎样设置&#xff1f; 二、解答 initgraph( ) 函数⽤于初始化图形模式&#xff0c;其语法格式如下。 void far initgraph(int far * gdriver, i…

对象存储OSS 客户端签名直传的安全风险和解决方法

1. 前言 阿里云对象存储OSS&#xff08;Object Storage Service&#xff09;是一款海量、安全、低成本、高可靠的云存储服务&#xff0c;可提供99.9999999999%&#xff08;12个9&#xff09;的数据持久性&#xff0c;99.995%的数据可用性。多种存储类型供选择&#xff0c;全面…

11.链表

数组的分类&#xff1a;便于遍历 静态数组&#xff1a;int arr[10]数据过多造成空间溢出&#xff0c;数据过小空间浪费 动态数组&#xff1a;malloc calloc realloc 合理利用空间不能快捷的插入或删除数据&#xff08;会涉及到大量的数据移动&#xff09; 知识点一&#xff1…

玉米粒计数检测数据集VOC+YOLO格式107张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;107 标注数量(xml文件个数)&#xff1a;107 标注数量(txt文件个数)&#xff1a;107 标注类别…

二分#背包#快排#LCS详解

二分#背包#快排#LCS详解 文章目录 二分#背包#快排#LCS详解1. 二分搜索2. 01背包问题3. 快速排序4. 最长公共子序列 1. 二分搜索 在处理大规模数据集时&#xff0c;查找操作的效率显得尤为重要。二分搜索是一种在有序数组中查找目标值的高效算法&#xff0c;其时间复杂度为O(lo…

【python报错】关于 xlrd.biffh.XLRDError: Excel xlsx file; not supported 解决方法【已解决】

【Python报错】关于xlrd.biffh.XLRDError: Excel xlsx file; not supported解决方法【已解决】 在使用Python进行数据分析时&#xff0c;经常需要处理Excel文件。xlrd库是一个流行的用于读取Excel文件的库&#xff0c;但如果你在使用xlrd打开.xlsx文件时遇到了xlrd.biffh.XLRDE…

区块链(Blockchain)调查研究(一)

文章目录 1. 区块链是什么&#xff1f;2. 区块链分类和特点3. 区块链核心关键技术3.1 共识机制3.2 密码学技术3.4 分布式存储3.5 智能合约 4. 区块链未来发展趋势5. 区块链能做什么、不能做什么&#xff1f;5.1 第一部分5.2 第二部分5.3 第三部分&#xff08;结论&#xff09; …

新书推荐:2.3 消息机制

Windows程序的消息机制是指在Windows操作系统下&#xff0c;应用程序与操作系统之间的一种通信方式。通过消息机制&#xff0c;应用程序可以接收来自操作系统的各种事件和请求&#xff0c;以便做出相应的响应和处理。 在Windows程序中&#xff0c;消息机制的实现是基于消息队列…

用 Axios 封装一个双 token 无感刷新

为什么要用双Token无感刷新&#xff0c;它解决了什么问题&#xff1f; 为了保证安全性&#xff0c;后端设置的Token不可能长期有效&#xff0c;过了一段时间Token就会失效。而发送网络请求的过程又是需要携带Token的&#xff0c;一旦Token失效&#xff0c;用户就要重新登陆&…

欢乐打地鼠小游戏html源码

这是一款简单的js欢乐打地鼠游戏&#xff0c;挺好玩的&#xff0c;老鼠出来用鼠标点击锤它&#xff0c;击中老鼠获得一积分。 欢乐打地鼠小游戏html源码

kopf,一个实用的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个实用的 Python 库 - kopf。 Github地址&#xff1a;https://github.com/nolar/kopf 在 Kubernetes 中&#xff0c;Operator 是一种用于扩展 Kubernetes 功能的强大工具。Operator 可以自动化应…

MySQL的group by与count(), *字段使用问题

文章目录 问题group by到底做了什么举个例子简单来说为什么select字段&#xff0c;count()不能和*共同使用总结 问题 这是一段摘抄自MySQL官网的文字。其大致意思是MySQL拓展了group by的使用&#xff0c;MySQL允许选择没有出现在group by中的字段。换句话说&#xff0c;标准SQ…

【QT5.14.2】编译MQTT库example的时候报No such file or directory

【QT5.14.2】编译MQTT库example的时候报No such file or directory 前几天导师让跑一下MQTT库&#xff0c;用的5.14.2版本的QT&#xff0c;于是就上网搜了一个教程&#xff1a;https://www.bilibili.com/video/BV1dH4y1e7hG/?spm_id_from333.337.search-card.all.click&v…

Fedora的远程桌面

要在 Fedora 40 上开启远程桌面功能。 首先&#xff0c;要确保已安装 gnome-remote-desktop 和 vino 包。 这些软件包通常默认安装在 Fedora 的 GNOME 桌面环境中。 可以按照以下步骤操作&#xff1a; 1、判断电脑是否安装了 gnome-remote-desktop 和 vino 包: tomfedora:…

第十三周 5.28 三个修饰符知识点

一、abstract[抽象的] 1.abstract可以修饰类: (1&#xff09;被abstract修饰的类称为抽象类 (2) 语法:abstract class 类名{} (3) 特点:抽象类只能声明引用&#xff0c;不能创建对象 (4) 抽象类中可以定义属性和成员方法、构造方法 2.abstr…

【Linux】匿名管道的应用场景 --- 进程池

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

Qt qtpropertybrowser使用实例(1)

属性界面实例&#xff1a; 代码如下&#xff1a; #include <QDate> #include <QLocale> #include "qtpropertymanager.h" #include "qtvariantproperty.h" #include "qttreepropertybrowser.h" int main(int argc, char *argv[]) {…

nginx mirror流量镜像详细介绍以及实战示例

nginx mirror流量镜像详细介绍以及实战示例 1.nginx mirror作用2.nginx安装3.修改配置3.1.nginx.conf3.2.conf.d目录下添加default.conf配置文件3.3.nginx配置注意事项3.3.nginx重启 4.测试 1.nginx mirror作用 为了便于排查问题&#xff0c;可能希望线上的请求能够同步到测试…

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台。通过搜索结果&#xff0c;我们可以了解到 TalkingData 的一些关键特性和市场情况&#xff0c;并将其与同类型产品进行比较。 TalkingData 产品特性 数据统计与分析&#xff1a;提供专业的数…

【每日算法】

算法第15天| (二叉树part02)层序遍历、226.翻转二叉树(优先掌握递归)、101. 对称二叉树(优先掌握递归) 文章目录 算法第15天| (二叉树part02)层序遍历、226.翻转二叉树(优先掌握递归)、101. 对称二叉树(优先掌握递归)一、层序遍历二、226. 翻转二叉树(优先掌握递归)三、101. 对…