单片机学习笔记---AT24C02(I2C总线)
目录
有关储存器的介绍
存储器的简介
存储器简化模型
AT24C02介绍
AT24C02引脚及应用电路
I2C总线介绍
I2C电路规范
开漏输出模式和弱上拉模式
其中一个设备的内部结构
I2C通信是怎么实现的
I2C时序结构
起始条件和终止条件
发送一个字节
接收一个字节
发送应答和接收应答
I2C数据帧
发送一帧数据
接收一帧数据
先发送再接收数据帧(复合格式)
有关储存器的介绍
存储器的简介
RAM:随机储存,断电丢失数据,存储比较快。
SRAM:是最快的,内部是锁存器,D触发器,用电路来储存数据,一般用于电脑的CPU高速缓存。
DRAM:利用电容的充放电以达到储存数据的目的,充电就是高电平,放完电之后就是低电平,因为电容存在漏电现象,要配一个扫描电路,每隔一段时间就补电,电脑中的内存条和手机里的运行内存是动态RAM。
ROM:只读储存,断电不丢失数据,存储比较慢
Mask ROM:不能写入,只能读取
PROM:升级版Mask ROM,只能写入一次
EPROM:三十分钟紫外线照射可擦除
E2PROM:5V低压电即可擦除
以上四个ROM可以说是一个家族的。
Flash:目前应用最广
硬盘:C盘......(应用磁相关的原理存储)
软盘:以前的A盘和B盘(现在我们电脑上基本没有应用软盘了,所以从C盘开始)
光盘:应用光信号存储数据
存储器简化模型
我们的存储器在内部实际上都是像一种网格的结构。
横向的线称为地址总线,用来选中哪一根线就是我们的哪一个地址;
纵向的线称为数据总线,数据是从下面出来的。
那数据是怎么存的呢?
比如说我们选中了第一行的地址总线,我们给它加上一个高电平1,其他的暂时都不接。然后,先说一下这些网格的交错处是不连接的,我们现在把交错的第一个节点、第二和第三个节点给连上,其他的都不连。那我们现在读取一下下面这八位数据,是怎样的呢?
我们连上了那三个节点后,数据就可以顺着前三根数据总线下来了,它们下来是1,第一行的其他交错节点都没连,所以数据不能下来,因此把它当做0。
这样我们第一行存的数据下来就是11100000,其他种情况同理,这样就可以存储不同的数据。
这就是存储器存储数据的最基本的原理。
我们就知道了如何在这里储存,就是控制我们的节点短路和断路这一个过程。
Mask ROM的内部交错处结构是这样的
如果我们想要存储断开,就是什么都不接,它存的就是0
如果我们想要把它短路,为了它们不相互干扰,就可以接一个二极管(二极管是单向的)。当高电平过来的时候,就可以通过,但是想要从其他地方串过来就不行了。
厂家做Mask ROM的时候,如果你告诉它需要存储某个数据,他们就会连上哪一个节点,这个电路一旦完成,就相当于焊死了,所以不能再改了,所以早期的ROM只能读,不能写。
之后出现了一种PROM,它是升级版的Mask ROM,只能写入一次。
它的内部交错处结构是这样的(把每一个节点都做成这种形状)
两根二极管头对头,即使它过来也通不过去,即使通过了第一个,它也通不过第二个,相当于一种断路。
但是这个蓝色的二极管有个特点就是容易被击穿。二极管有个特性就是它反向是截止的,但是当反向电压超过一定数值之后,它就会被击穿,击穿之后它变成短路了,这就是由断路变成短路的变成状态。
所以如果在这种结构的左边接一个高电压的时候,比如说12V,或者24V等等,然后右边下面我们接一个0V(接GND),这时那个标为蓝色的二极管两端就承受了24V的高电压,所以它就被击穿了。
揭穿之后就相当于变成这种结构(相当于短路)
因此我们可以一次选中,相应击穿就得到我们想要的数据。二极管一旦被击穿之后(烧毁),不能恢复,所以是一次性的,所以只能写入一次。
所以我们平时说下载程序,也可以说是“烧录程序”,因为早期的确是烧录,就是把里面的二极管烧毁。
早期的单片机有一个控制引脚,它在编程的时候需要加一个高电压(编程电压),就是用来击毁里面的这个二极管。
这种情况(击穿相当于短路,不击穿相当于断路)和保险丝比较像,如果我们在这里都接上保险丝的话,它就有一个特点,就是它没有被烧断的时候是短路,但是如果加上大电流,这个保险丝就被烧断了,烧断的时候就是断路,这样也能控制我们的编程。
因此PROM有一种是二极管击穿型,一种是保险丝型。
可以说之后发展出来的可重复多次写入的ROM就是利用一种可以让断路变成短路(起死回生)的材料或者原理方法实现了可逆性击毁,比如可擦除的ROM。
因为在地址总线一次只能选中一行,所以我们一般都会加一个译码器(138译码器),它可以把多位数据(地址)变成输入端只有一位被选中的输出端(串行输入,并行输出)。
总而言之,在译码器之前就是输出我们实际的地址,下面就输出数据。
接下来是本节的主角!
AT24C02介绍
AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息
存储介质:E2PROM(电可擦除可编程ROM )
通讯接口:I2C总线
容量:256字节
AT24C02引脚及应用电路
只要接这个范围内的电压就可以工作1.8V-5.5V。
接WP的这个7号引脚直接接了GND,所以这个芯片没有用到写保护功能,如果需要这个功能的话,可以将这个引脚接在IO口或者开关上。
A0,A1,A2是可以选择的接都到VCC或者接到GND,这里全部接到GND,代表这三个都是0。
SCL和SDA引出去分别接了一个4.7K的上拉电阻。
我们开发板的EEPROM模块的原理图:
VSS=GND,VDD=VCC,E0=A0,E1=A1,E2=A2,WE=写使能(低电平使能,高电平保护),这里SCL和SDA没有接上拉电阻因为我们单片机的每个IO口都已经接了一个上拉电阻。
这一部分是I2C协议规范所需要的
我们看一下EEPROM模块的内部框图
这一块都是和I2C接口协议有关的东西
我们现在讲的是下面标蓝色的这一块
然后这部分是用来数据擦除的部分:
这个是地址寄存器
具体里面的电路是怎么工作的就不具体介绍了,我们主要大概了解到这里是把I2C数据拿进来,通过一些逻辑执行操作就可以了。
本节的重难点来了
I2C总线介绍
I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线
两根通信线:SCL(Serial Clock)、SDA(Serial Data)
同步(因为有同步的时钟线SCL)、半双工(双向分时,因为SDA只有一根线,而且哟啊负责来回通信,所以只能分时地复用一根线),带数据应答(在发送一个字节数据之后,要求对方接收到数据之后给它一个应答,判断是否发送成功,所以I2C总线的检测应答的功能还是比较完备的,而我们之前学习的串口就没有,串口发出数据后没有检测应答,弊端就是不知道对方在不在线)
通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度
上图是常用的I2C设备
所有I2C设备的SCL连在一起,SDA连在一起
设备的SCL和SDA均要配置成开漏输出模式
SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右
开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题
I2C电路规范
所有I2C设备的SCL连在一起,SDA连在一起(不像我们前几节学的串口UART通信的TXD和RXT要交叉连接)
开漏输出模式和弱上拉模式
设备的SCL和SDA均要配置成开漏输出模式(单片机的IO口是弱上拉模式)
开漏输出模式是因为高电平驱动能力弱,相当于断开。
SCL和SDA各添加一个上拉电阻(当有空闲设备不通信时,可能会影响到正在通信的设备,所以需要加上拉电阻,使其空闲设备处于一个高阻态(不是高电平也不是低电平)的情况下,这样空闲设备就会断路),阻值一般为4.7KΩ左右
开漏输出和上拉电阻的共同作用实现了“线与”(有一个低电平就是低电平0)的功能,此设计主要是为了解决多机通信互相干扰的问题
我们知道如果CPU想要和其中一个设备通信的话,那么最好的状态就是其他的设备不要影响它,则其他设备相当于断开。CPU跟其中一个设备通信的时候,其他引脚全部输出1,相当于断开,这样就不会干扰到CPU和它的通信了。因此用开漏模式就可以解决多机通信互相干扰的问题。
如果所有设备用弱上拉模式的话,即使开关断开输出1,还是有一个上拉电阻碍事,虽然也不会有太大影响,但是总归不太好。如果接多了上拉电阻,电阻并联,上拉能力肯定越来越强,会干扰通信。所以所有设备都开漏,那数字1就发送不出去。
所以我们在外面接两个电阻,当所有设备都断开的时候,这两个电阻充当上拉能力。CPU想发0的时候,就把输出口拉到低电平。想发1的时候,就松手不拉了,输出口就会被外部的电阻自动拉到高电平。当其他设备没有进行通信的时候,直接输出1,对我们的电路没有干扰(没有干扰是因为内部没有向外部输出,输出的1是外部上拉提供的,这里上拉电阻是将总线的拉成高电平,当连接在总线上的任意一个设备输出低电平时,总线被拉低就是输出了低电平。)
其中一个设备的内部结构
这幅图是其中一个设备的内部结构
下面这个东西是一个输入的缓存,可以把它想象成一个电压表
它可以检测这个点的电压进行操作,
它的输入阻抗是很大的,所以这个一点就相当于是断开
这个东西就相当于一个电子开关:给低电平相当于它导通,如果给高电平相当于它断开
如果给高电平这个电子开关断开,而旁边这条线路也是断开的,所以这这根引脚就是断开的,就可以不干扰外界。
I2C通信是怎么实现的
下面举一个小例子能够更明白I2C通信是怎么实现的:
比如现在有个弹簧控制着一根杆子的升降,杆子上面左右两边都有一根标尺。在A和B两个人眼前,他们两个人可以通过标尺的升降来判断对方发给自己的数据是1还是0,如果两人是松手的状态,标尺就不动,说明发给对方的数据是1,如果其中一人伸手拉下了杆子,那么标尺就会下降,对方就知道发送过来的数据是0,如果松手,标尺上升则代表发送过来的数据是1。
I2C的标准可以想象成如果再A和B之间再多站几个人的话,这几个人都会被标成一个地址,如果主机想要和他们其中一个通信,那么只需要通过时序去发送地址就找到从机。比如说一开始主机摇摇杆子,所有人看到杆子被摇了,说明有人想要开始了,然后主机开始发1/0的数据(通过松手拉下来松手拉下来)就把地址发送出去,其他人看这个地址跟自己一样,就知道主机在找他,就会默认跟主机构建联系,其他人发现地址和自己的不一样,就什么不管,不会去干扰通信。主机就和地址一样的那个人开始通信(双方拉杆子交流)。
接下来就开始正式介绍I2C时序结构:
I2C时序结构
起始条件和终止条件
起始条件:SCL高电平期间,SDA从高电平切换到低电平(主机开始摇杆子)
终止条件:SCL高电平期间,SDA从低电平切换到高电平
发送一个字节
SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节
注意:SCL高电平期间读取数据位时:
PS:我们的单片机是主机,24C02是从机。主机和从机的程序是不一样的,我们只写主机,从机是主动检测的,从机读取数据的时候是程序自动完成的,我们只需要把主机的时序模拟出来就好了。
接收一个字节
SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA,将SDA置1就相当于释放,释放的时候主机是完全不干扰这个通信线的。换言之就是主机释放掉数据线之后,把对线的控制权交给从机,从机就把它拉下来/松手。如果主机是在拉下来的状态把控制权交给从机的话,那从机不论发啥都是0)
上图SDA紫色部分就是从机控制总线的时候
发送应答和接收应答
发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
主机接收完一个字节后再发送给从机一位数据(1/0),告知从机是否应答
主机发送完一个字节后再接收从机发过来的一位数据(1/0),这位数据表示从机是否应答
I2C数据帧
(基本上所有的传感器的数据帧结构都遵循这三种格式)
发送一帧数据
解析图:
完成任务:向谁发什么(由从机地址的前7位决定发给谁,发还是写由地址的读写位决定,发什么由发送字节数据那一部分决定)
接收一帧数据
解析图:
完成任务:向谁收什么
先发送再接收数据帧(复合格式)
完成任务:向谁收指定的什么
用一个大白话来翻译一下这种复合格式就是:
老师(主机):现在开始听题环节。
老师(主机):小明你来听题。
小明(从机):收到。
老师(主机):第一题......
小明(从机):收到。
老师(主机):第二题......
小明(从机):收到。
......
老师(主机):第N题......
小明(从机):收到。
老师(主机):现在开始答题环节。
老师(主机):小明你来答题。
小明(从机):收到,第一题答案是.....
此时老师(主机)接收小明的答案。
老师(主机):收到。
小明(从机):第二题答案是.....
此时老师(主机)接收小明的答案。
老师(主机):收到。
......
小明(从机):第N题答案是.....
此时老师(主机)接收小明的答案。
老师(主机):收到/(不应答)。
老师(主机):本次的问答环节结束。
几乎所有的I2C都遵循以上这三种数据帧格式
我们看一下I2C如何去适配这些结构的呢?
字节写:在WORD ADDRESS(字地址)处写入数据DATA
随机读:读出在WORD ADDRESS处的数据DATA(这其实是一种复合格式)
AT24C02的固定地址为1010,可配置地址本开发板上为000
所以SLAVE ADDRESS+W为0xA0,SLAVE ADDRESS+R为0xA1
补充一下手册上的数据帧的解析图:
字节写:在“字地址”处写入“数据”
根据我们前面说的时序,可以划分成这样:其实和我们前面看到的是一样的。
随机读:读出在“字地址”处的“数据”
下节开始演示代码!
相关文章:

单片机学习笔记---AT24C02(I2C总线)
目录 有关储存器的介绍 存储器的简介 存储器简化模型 AT24C02介绍 AT24C02引脚及应用电路 I2C总线介绍 I2C电路规范 开漏输出模式和弱上拉模式 其中一个设备的内部结构 I2C通信是怎么实现的 I2C时序结构 起始条件和终止条件 发送一个字节 接收一个字节 发送应答…...

c++恶魔轮盘制造第1期输赢
小常识,恶魔叫DEALER。 赢了很简单 void sheng() { cout<<"你获胜了!";MessageBox(NULL,TEXT("你的钱~~~~~~给你"),TEXT("DEALER"),MB_OK);system("pause");system("cls"); } 输了我用了个选…...

60-JS-Ajax
ajax取数据的一种手段,局部刷新,例如弹幕 1.ajax的使用,创建ajax对象,发起对服务器请求 2.核心对象XMLHttpRequest对象(简称XHR) CSS:Cascading Style Sheets(层叠样式表) HTML:Hypertext Markup Language(超文本标记语言) 3.发起对服务器的请求 浏览器方式请求:打…...

C# Avalonia 折线图
线图开发在C# Avalonia框架中可以通过多种方式实现。由于Avalonia旨在成为跨平台的UI框架,您可以利用多种库和方法来绘制折线图。以下是一个简单的例子,展示了如何在Avalonia应用程序中创建一个基本的折线图。 首先,您需要在Avalonia项目中包…...

Vue3中Setup概述和使用(三)
一、引入Setup 1、Person.Vue 与Vue3编写简单的App组件(二) 中的区别是:取消data、methods等方法,而是将数据和方法定义全部放进setup中。 <template><div class"person"><h1>姓名:{{name}}</h1><h1>年龄:{{age}}</h…...

hexo 博客搭建以及踩雷总结
搭建时的坑 文章置顶 安装一下这个依赖 npm install hexo-generator-topindex --save然后再文章的上面设置 top: number,数字越大,权重越大,也就是越靠顶部 hexo 每次推送 nginx 都访问不到 宝塔自带的 nginx 的 config 里默认的角色是 …...

WordPress后台编辑个人资料页面直接修改用户名插件Change Username
前面跟大家介绍了『如何修改WordPress后台管理员用户名?推荐2种简单方法』一文,但是对于新站长或者有很多用户的站长来说,操作有点复杂,所以今天向大家推荐一款可以直接在WordPress后台编辑个人(用户)资料页…...

ssm+vue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
演示视频: ssmvue的医药垃圾分类管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结…...

LLM大模型基本概念,及其相关问题汇总(1)
什么是涌现?为什么会出现涌现? "大模型的涌现能力"这个概念可能是指大型神经网络模型在某些任务上表现出的出乎意料的能力,超出了人们的预期。出现的原因从结论上来看,是模型不够好,导致的原因主要是&#…...

【已解决】pt文件转onnx后再转rknn时得到推理图片出现大量锚框变花屏
前言 环境介绍: 1.编译环境 Ubuntu 18.04.5 LTS 2.RKNN版本 py3.8-rknn2-1.4.0 3.单板 迅为itop-3568开发板 一、现象 采用yolov5训练并将pt转换为onnx,再将onnx采用py3.8-rknn2-1.4.0推理转换为rknn,rknn模型能正常转换,…...

DevOps文章之 操作手册用户使用说明书
前言 最近主导了几个项目操作手册的编写。有新开发的项目,要重新编写操作手册;有中途接手别的项目,后来功能迭代,需要更新原操作手册;有客户对操作手册有意见,需要调整;零零散散写了数万字的手…...

【RT-DETR进阶实战】利用RT-DETR进行视频划定区域目标统计计数
👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 Hello,各位读者,最近会给大家发一些进阶实战的讲解,如何利用RT-DETR现有的一些功能进行一些实战, 让我们不仅会改进RT-DETR,也能够利用RT-DETR去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是…...

2.11学习总结
有效点对https://www.acwing.com/problem/content/description/5472/ 给定一个 n� 个节点的无向树,节点编号 1∼n1∼�。 树上有两个不同的特殊点 x,y�,�,对于树中的每一个点对 (u,v)(u≠v)(�,…...

以谷歌浏览器为例 讲述 JavaScript 断点调试操作用法
今天来说个比较实用的东西 用浏览器开发者工具 对 javaScript代码进行调试 我们先创建一个index.html 编写代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&…...

Vue前端框架--Vue工程项目问题总结{脚手架 Vue-cli}
Vue脚手架部署问题总结 我所遇到的一共两大问题 只有先执行npm install之后 才能run serve 否则会报错 vue-cli-serve不是内部或者外部的命令,也不是可运行的程序或者批处理文件的错误 1. 运行npm install会报错 2. 运行npm run serve报错 nodejs官网为 https://no…...

Unity2D 学习笔记 0.Unity需要记住的常用知识
Unity2D 学习笔记 0.Unity需要记住的常用知识 前言调整Project SettingTilemap相关(创建地图块)C#脚本相关程序运行函数private void Awake()void Start()void Update() Collider2D碰撞检测private void OnTriggerStay2D(Collider2D player)private void…...

vue3-应用规模化-单文件组件
单文件组件概念 Vue 的单文件组件 (即 *.vue 文件,英文 Single-File Component,简称 SFC) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。下面是一个单文件组件的示例: <script setup…...

Redis -- 渐进式遍历
家,是心的方向。不论走多远,总有一盏灯为你留着。桌上的碗筷多了几双,笑声也多了几分温暖。家人团聚,是最美的风景线。时间:2024年 2月 8日 12:51:20 目录 前言 语法 示例 前言 试想一个场景,那就是在key非常多的…...

使用 C++23 从零实现 RISC-V 模拟器(3):指令解析
指令解析 这章内容进一解析更多的指令,此外将解析指令的过程拆分为一个单独的类,采用表格驱动的方式,将数据和逻辑分离,降低了 if else 嵌套层数过多。 这部分依旧改动不多,只增加了七个指令。此外代码中细碎的变动没…...

CSS Selector—选择方法,和html自动——异步社区的爬取(动态网页)——爬虫(get和post的区别)
这里先说一下GET请求和POST请求: post我们平时是要加data的也就是信息,你会发现我们平时百度之类的 搜索都是post请求 get我们带的是params,是发送我们指定的内容。 要注意是get和post请求!!! 先说一下异…...

C语言 服务器编程-日志系统
日志系统的实现 引言最简单的日志类 demo按天日志分类和超行日志分类日志信息分级同步和异步两种写入方式 引言 日志系统是通过文件来记录项目的 调试信息,运行状态,访问记录,产生的警告和错误的一个系统,是项目中非常重要的一部…...

HarmonyOS 状态管理装饰器 Observed与ObjectLink 处理嵌套对象/对象数组 结构双向绑定
本文 我们还是来说 两个 harmonyos 状态管理的装饰器 Observed与ObjectLink 他们是用于 嵌套对象 或者 以对象类型为数组元素 的数据结构 做双向同步的 之前 我们说过的 state和link 都无法捕捉到 这两种数据内部结构的变化 这里 我们模拟一个类数据结构 class Person{name:…...

windows中的apache改成手动启动的操作步骤
使用cmd解决安装之后开机自启的问题 services.msc 0. 这个命令是打开本地服务找到apache的服务名称 2 .通过服务名称去查看服务的状态 sc query apacheapache3.附加上关掉和启动的命令(换成是你的服务名称) 关掉命令 sc stop apacheapache启动命令 …...

Intellij Idea的数据库工具 DataGrip
DataGrip DataGrip: IDEA自带,非常好用。智能提示很强大,快捷键跟IDEA自身一致。 如果下载不了 DataGrip,也可以直接用 IDEA 自带的。 常用的快捷键 alt8: 打开数据库Service ctrlshiftF10:打开常用的数…...

精品springboot疫苗发布和接种预约系统
《[含文档PPT源码等]精品基于springboot疫苗发布和接种预约系统[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功! 软件开发环境及开发工具: Java——涉及技术: 前端使用技术:…...

Linux快速入门
一. Linux的结构目录 1.1 Linux的目录结构 Linux为免费开源的系统,拥有众多发行版,为规范诸多的使用者对Linux系统目录的使用,Linux基金会发布了FHS标准(文件系统层次化标准)。多数的Linux发行版都遵循这一规范。 注&…...

【图形图像的C++ 实现 01/20】 2D 和 3D 贝塞尔曲线
目录 一、说明二、贝塞尔曲线特征三、模拟四、全部代码如下五、资源和下载 一、说明 以下文章介绍了用 C 计算和绘制的贝塞尔曲线(2D 和 3D)。 贝塞尔曲线具有出色的数学能力来计算路径(从起点到目的地点的曲线)。曲线的形…...

python+flask+django医院预约挂号病历分时段管理系统snsj0
技术栈 后端:python 前端:vue.jselementui 框架:django/flask Python版本:python3.7 数据库:mysql5.7 数据库工具:Navicat 开发软件:PyCharm . 第一,研究分析python技术,…...

《CSS 简易速速上手小册》第9章:CSS 最佳实践(2024 最新版)
文章目录 9.1 维护大型项目的 CSS9.1.1 基础知识9.1.2 重点案例:构建一个可复用的 UI 组件库9.1.3 拓展案例 1:优化现有项目的 CSS 结构9.1.4 拓展案例 2:实现主题切换功能 9.2 BEM、OOCSS 和 SMACSS 方法论9.2.1 基础知识9.2.2 重点案例&…...

Qt QVariant类应用
QVariant类 QVariant类本质为C联合(Union)数据类型,它可以保存很多Qt类型的值,包括 QBrush,QColor,QString等等,也能存放Qt的容器类型的值。 QVariant::StringList 是 Qt 定义的一个 QVariant::type 枚举类型的变量&…...