IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【正点原子Linux连载】第二十三章 DDR3实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0 -> 正文阅读

[嵌入式]【正点原子Linux连载】第二十三章 DDR3实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

1)实验平台:正点原子阿尔法Linux开发板
2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434
2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html
3)对正点原子Linux感兴趣的同学可以加群讨论:935446741
4)关注正点原子公众号,获取最新资料更新
在这里插入图片描述

第二十三章 DDR3实验

I.MX6U-ALPHA开发板上带有一个256MB/512MB的DDR3内存芯片,一般Cortex-A芯片自带的RAM很小,比如I.MX6U只有128KB的OCRAM。如果要运行Linux的话完全不够用的,所以必须要外接一片RAM芯片,I.MX6U支持LPDDR2、LPDDR3/DDR3,I.MX6U-ALPHA开发板上选择的是DDR3,本章就来学习如何驱动I.MX6U-ALPHA开发板上的这片DDR3。

23.1 DDR3内存简介
在正式学习DDR3内存之前,我们要先了解一下DDR内存的发展历史,通过对比SRAM、SDRAM、DDR、DDDR2和DDR3的区别,有助于我们更加深入的理解什么是DDR。在看DDR之前我们先来了解一个概念,那就是什么叫做RAM?
23.1.1 何为RAM和ROM?
相信大家在购买手机、电脑等电子设备的时候,通常都会听到RAM、ROM、硬盘等概念,很多人都是一头雾水的。普通用户区分不清楚RAM、ROM到可以理解,但是作为一个嵌入式Linux开发者,要是不清楚什么是RAM、什么是ROM就绝对不行!RAM和ROM专业的解释如下:
RAM:随机存储器,可以随时进行读写操作,速度很快,掉电以后数据会丢失。比如内存条、SRAM、SDRAM、DDR等都是RAM。RAM一般用来保存程序数据、中间结果,比如我们在程序中定义了一个变量a,然后对这个a进行读写操作,示例代码如下:
示例代码23.1.1.1 RAM中的变量
1 int a;
2 a = 10;
a是一个变量,我们需要很方便的对这个变量进行读写操作,方法就是直接“a”进行读写操作,不需要在乎具体的读写过程。我们可以随意的对RAM中任何地址的数据进行读写操作,非常方便。
ROM:只读存储器,笔者认为目前“只读存储器”这个定义不准确。比如我们买手机,通常会告诉你这个手机是4+64或6+128配置,说的就是RAM为4GB或6GB,ROM为64G或128GB。但是这个ROM是Flash,比如EMMC或UFS存储器,因为历史原因,很多人还是将Flash叫做ROM。但是EMMC和UFS,甚至是NAND Flash,这些都是可以进行写操作的!只是写起来比较麻烦,要先进行擦除,然后再发送要写的地址或扇区,最后才是要写入的数据,学习过STM32,使用过WM25QXX系列的SPI Flash的同学应该深有体会。可以看出,相比于RAM,向ROM或者Flash写入数据要复杂很多,因此意味着速度就会变慢(相比RAM),但是ROM和Flash可以将容量做的很大,而且掉电以后数据不会丢失,适合用来存储资料,比如音乐、图片、视频等信息。
综上所述,RAM速度快,可以直接和CPU进行通信,但是掉电以后数据会丢失,容量不容易做大(和同价格的Flash相比)。ROM(目前来说,更适合叫做Flash)速度虽然慢,但是容量大、适合存储数据。对于正点原子的I.MX6U-ALPHA开发板而言,256MB/512MB的DDR3就是RAM,而512MB NANF Flash或8GB EMMC就是ROM。
23.1.2 SRAM简介
为什么要讲SRAM呢?因为大多数的朋友最先接触RAM芯片都是从SRAM开始的,因为大量的STM32单片机开发板都使用到了SRAM,比如F103、F407等,基本都会外扩一个512KB或1MB的SRAM的,因为STM32F103/F407内部RAM比较小,在一些比较耗费内存的应用中会出现内存捉紧的情况,比如emWin做UI界面。我们简单回顾一下SRAM,如果想要详细的了解SRAM请阅读正点原子STM32F103战舰开发板的开发指南。
SRAM的全称叫做Static Random-Access Memory,也就是静态随机存储器,这里的“静态”说的就是只要SRAM上电,那么SRAM里面的数据就会一直保存着,直到SRAM掉电。对于RAM而言需要可以随机的读取任意一个地址空间内的数据,因此采用了地址线和数据线分离的方式,这里就以STM32F103/F407开发板常用的IS62WV51216这颗SRAM芯片为例简单的讲解一下SRAM,这是一颗16位宽(数据位为16位)、1MB大小的SRAM,芯片框图如图23.1.2.1所示:
在这里插入图片描述

图23.1.2.1 IS62WV51216框图
图23.1.2.1主要分为三部分,我们依次来看一下这三部分:
①、地址线
这部分是地址线,一共A0~A18,也就是19根地址线,因此可访问的地址大小就是2^19=524288=512KB。不是说IS62WV51216是个1MB的SRAM吗?为什么地址空间只有512KB?前面我们说了IS62WV51216是16位宽的,也就是一次访问2个字节,因此需要对512KB进行乘2处理,得到512KB*2=1MB。位宽的话一般有8位/16位/32位,根据实际需求选择即可,一般都是根据处理器的SRAM控制器位宽来选择SRAM位宽。
②、数据线
这部分是SRAM的数据线,根据SRAM位宽的不同,数据线的数量要不同,8位宽就有8根数据线,16位宽就有16根数据线,32位宽就有32根数据线。IS62WV51216是一个16位宽的SRAM,因此就有16根数据线,一次访问可以访问16bit的数据,也就是2个字节。因此就有高字节和低字节数据之分,其中IO0IO7是低字节数据,IO8IO15是高字节数据。
③、控制线
SRAM要工作还需要一堆的控制线,CS2和CS1是片选信号,低电平有效,在一个系统中可能会有多片SRAM(目的是为了扩展SRAM大小或位宽),这个时候就需要CS信号来选择当前使用哪片SRAM。另外,有的SRAM内部其实是由两片SRAM拼接起来的,因此就会提供两个片选信号。
OE是输出使能信号,低电平有效,也就是主控从SRAM读取数据。
WE是写使能信号,低电平有效,也就是主控向SRAM写数据。
UB和LB信号,前面我们已经说了,IS62WV51216是个16位宽的SRAM,分为高字节和低字节,那么如何来控制读取高字节数据还是低字节数据呢?这个就是UB和LB这两个控制线的作用,这两根控制线都是低电平有效。UB为低电平的话表示访问高字节,LB为低电平的话表示访问低字节。关于IS62WV51216的简单原理就讲解到这里。
那么SRAM有什么缺点没有?那必须有的啊,要不然就不可能有本章教程了,SRAM最大的缺点就是成本高!价格高,大家可以在淘宝上搜索一下IS62WV51216这个仅仅只有 1MB大小的SRAM售价为多少,大概为5,6块钱。大家再搜索一下32MB的SDRAM多钱,以华邦的W9825G6KH为例,大概4,5块钱,可以看出SDRAM比SRAM容量大,但是价格更低。SRAM突出的特点就是无需刷新(SDRAM需要刷新,后面会讲解),读写速度快!所以SRAM通常作为SOC的内部RAM使用或Cache使用,比如STM32内存的RAM或I.MX6U内部的OCRAM都是SRAM。
23.1.3 SDRAM简介
前面给大家简单讲解了SRAM,可以看出SRAM最大的缺点就是价格高、容量小!但是应用对于内存的需求越来越高,必须提供大内存解决方案。为此半导体厂商想了很多办法,提出了很多解决方法,最终SDRAM应运而生,得到推广。SDRAM全称是Synchronous Dynamic Random Access Memory,翻译过来就是同步动态随机存储器,“同步”的意思是SDRAM工作需要时钟线,“动态”的意思是SDRAM中的数据需要不断的刷新来保证数据不会丢失,“随机”的意思就是可以读写任意地址的数据。
与SRAM相比,SDRAM集成度高、功耗低、成本低、适合做大容量存储,但是需要定时刷新来保证数据不会丢失。因此SDRAM适合用来做内存条,SRAM适合做高速缓存或MCU内部的RAM。SDRAM目前已经发展到了第四代,分别为:SDRAM、DDR SDRAM、DDR2 SDRAM、DDR3 SDRAM、DDR4 SDRAM。STM32F429/F767/H743等芯片支持SDRAM,学过STM32F429/F767/H743的朋友应该知道SDRAM,这里我们就以STM32开发板最常用的华邦W9825G6KH为例,W9825G6KH是一款16位宽(数据位为16位)、32MB的SDRAM、速度一般为133MHz、166MHz或200MHz。W9825G6KH框图如图23.1.3.1所示:
在这里插入图片描述

图23.1.3.1 W9825G6KH框图
①、控制线
SDRAM也需要很多控制线,我们依次来看一下:
CLK:时钟线,SDRAM是同步动态随机存储器,“同步”的意思就是时钟,因此需要一根额外的时钟线,这是和SRAM最大的不同,SRAM没有时钟线。
CKE:时钟使能信号线,SRAM没有CKE信号。
CS:片选信号,这个和SRAM一样,都有片选信号。
RAS:行选通信号,低电平有效,SDRAM和 SRAM的寻址方式不同,SDRAM按照行、列来确定某个具体的存储区域。因此就有行地址和列地址之分,行地址和列地址共同复用同一组地址线,要访问某一个地址区域,必须要发送行地址和列地址,指定要访问哪一行?哪一列?RAS是行选通信号,表示要发送行地址,行地址和列地址访问方式如图23.1.3.2所示:
在这里插入图片描述

图23.1.3.2 SDRAM行列寻址方式
CAS:列选通信号,和RAS类似,低电平有效,选中以后就可以发送列地址了。
WE:写使能信号,低电平有效。
②、A10地址线
A10是地址线,那么这里为什么要单独将A10地址线给提出来呢?因为A10地址线还有另外一个作用,A10还控制着Auto-precharge,也就是预充电。这里又提到了预充电的概念,SDRAM芯片内部会分为多个BANK,关于BANK我们稍后会讲解。SDRAM在读写完成以后,如果要对同一个BANK中的另一行进行寻址操作就必须将原来有效的行关闭,然后发送新的行/列地址,关闭现在工作的行,准备打开新行的操作就叫做预充电。一般SDSRAM都支持自动预充电的功能。
③、地址线
对于W9825G6KH来说一共有A0A12,共13根地址线,但是我们前面说了SDRAM寻址是按照行地址和列地址来访问的,因此这A0A12包含了行地址和列地址。不同的SDRAM芯片,根据其位宽、容量等的不同,行列地址数是不同的,这个在SDRAM的数据手册里面会也清楚的。比如W9825G6KH的A0A8是列地址,一共9位列地址,A0A12是行地址,一共13位,因此可寻址范围为:29*213=4194304B=4MB,W9825G6KH为16位宽(2个字节),因此还需要对4MB进行乘2处理,得到42=8MB,但是W9825G6KH是一个32MB的SDRAM啊,为什么算出来只有8MB,仅仅为实际容量的1/4。不要急,这个就是我们接下来要讲的BANK,8MB只是一个BANK的容量,W9825G6KH一共有4个BANK。
④、BANK选择线
BS0和BS1是BANK选择信号线,在一片SDRAM中因为技术、成本等原因,不可能做一个全容量的BANK。而且,因为SDRAM的工作原理,单一的BANK会带来严重的寻址冲突,减低内存访问效率。为此,人们在一片SDRAM中分割出多块BANK,一般都是2的n次方,比如2,4,8等。图23.1.1.2中的⑤就是W9825G6KH的4个BANK示意图,每个SDRAM数据手册里面都会写清楚自己是几BANK。前面我们已经计算出来了一个BANK的大小为8MB,那么四个BANK的总容量就是8MB
4=32MB。
既然有4个BANK,那么在访问的时候就需要告诉SDRAM,我们现在需要访问哪个BANK,BS0和BS1就是为此而生的,4个BANK刚好2根线,如果是8个BANK的话就需要三根线,也就是BS0~BS2。BS0、BS1这两个线也是SRAM所没有的。
⑤、BANK区域
关于BANK的概念前面已经讲过了,这部分就是W9825G6KH的4个BANK区域。这个概念也是SRAM所没有的。
⑥、数据线
W9825G6KH是16位宽的SDRAM,因此有16根数据线,DQ0~DQ15,不同的位宽其数据线数量不同,这个和SRAM是一样的。
⑦、高低字节选择
W9825G6KH是一个16位的SDRAM,因此就分为低字节数据和高字节数据,LDQM和UDQM就是低字节和高字节选择信号,这个也和SRAM一样。
23.1.4 DDR简介
终于到了DDR内存了,DDR内存是SDRAM的升级版本,SDRAM分为SDR SDRAM、DDR SDRAM、DDR2 SDRAM、DDR3 SDRAM、DDR4 SDRAM。可以看出DDR本质上还是SDRAM,只是随着技术的不断发展,DDR也在不断的更新换代。先来看一下DDR,也就是DDR1,人们对于速度的追求是永无止境的,当发现SDRAM的速度不够快的时候人们就在思考如何提高SDRAM的速度,DDR SDRAM由此诞生。
DDR全称是Double Data Rate SDRAM,也就是双倍速率SDRAM,看名字就知道DDR的速率(数据传输速率)比SDRAM高1倍!这1倍的速度不是简简单单的将CLK提高1倍,SDRAM在一个CLK周期传输一次数据,DDR在一个CLK周期传输两次数据,也就是在上升沿和下降沿各传输一次数据,这个概念叫做预取(prefetch),相当于DDR的预取为2bit,因此DDR的速度直接加倍!比如SDRAM速度一般是133200MHz,对应的传输速度就是133200MT/s,在描述DDR速度的时候一般都使用MT/s,也就是每秒多少兆次数据传输。133MT/S就是每秒133M次数据传输,MT/s描述的是单位时间内传输速率。同样133200MHz的频率,DDR的传输速度就变为了266400MT/S,所以大家常说的DDR266、DDR400就是这么来的。
DDR2在DDR基础上进一步增加预取(prefetch),增加到了4bit,相当于比DDR多读取一倍的数据,因此DDR2的数据传输速率就是533~800MT/s,这个也就是大家常说的DDR2 533、DDR2 800。当然了,DDR2还有其他速度,这里只是说最常见的几种。
DDR3在DDR2的基础上将预取(prefetch)提高到8bit,因此又获得了比DDR2高一倍的传输速率,因此在总线时钟同样为266400MHz的情况下,DDR3的传输速率就是10661600MT/S。
I.MX6U的MMDC外设用于连接DDR,支持LPDDR2、DDR3、DDR3L,最高支持16位数据位宽。总线速度为400MHz(实际是396MHz),数据传输速率最大为800MT/S。这里我们讲一下LPDDR3、DDR3和DDR3L的区别,这三个都是DDR3,但是区别主要在于工作电压,LPDDR3叫做低功耗DDR3,工作电压为1.2V。DDR3叫做标压DDR3,工作电压为1.5V,一般台式内存条都是DDR3。DDR3L是低压DDR3,工作电压为1.35V,一般手机、嵌入式、笔记本等都使用DDR3L。
正点原子的I.MX6U-ALPHA开发板上接了一个256MB/512MB的DDR3L,16位宽,型号为NT5CC128M16JR/MT5CC256M16EP,nanya公司出品的,分为对应256MB和512MB容量。EMMC核心板上用的512MB容量的DDR3L,NAND核心板上用的256MB容量的DDR3L。本讲解我们就以EMMC核心板上使用的NT5CC256M16EP-EK为例讲解一下DDR3。可以到nanya官网去查找一下此型号,信息如图23.1.4.1所示:
在这里插入图片描述

图23.1.4.1 NT5CC256M16EP-EK信息
从图23.1.4.1可以看出,NT5CC256M16EP-EK是一款容量为4Gb,也就是512MB大小、16位宽、1.35V、传输速率为1866MT/S的DDR3L芯片。NT5CC256M16EP-EK的数据手册没有在nanya官网找到,但是找到了NT5CC256M16ER-EK数据手册,在官网上没有看出这两个有什么区别,因此我们就直接用NT5CC256M16ER-EK的数据手册。数据手册已经放到了开发板光盘中,路径为:6、硬件资料-》1、芯片资料-》NT5CC256M16EP-EK.pdf。但是数据手册并没有给出DDR3L对的结构框图,这里我就直接用镁光MT41K256M16数据手册里面的结构框图了,都是一样的,DDR3L结构框图如图23.1.4.2所示:
在这里插入图片描述

图23.1.4.2 DDR3L结构框图
从图23.1.4.2可以看出,DDR3L和SDRAM对的结构框图很类似,但是还是有点区别。
①、控制线
ODT:片上终端使能,ODT使能和禁止片内终端电阻。
ZQ:输出驱动校准的外部参考引脚,此引脚应该外接一个240欧的电阻到VSSQ上,一般就是直接接地了。
RESET:复位引脚,低电平有效。
CKE:时钟使能引脚。
A12:A12是地址引脚,但是有也有另外一个功能,因此也叫做BC引脚,A12会在READ和WRITE命令期间被采样,以决定burst chop是否会被执行。
CK和CK#:时钟信号,DDR3的时钟线是差分时钟线,所有的控制和地址信号都会在CK对的上升沿和CK#的下降沿交叉处被采集。
CS#:片选信号,低电平有效。
RAS#、CAS#和WE#:行选通信号、列选通信号和写使能信号。
②、地址线
A[14:0]为地址线,A0A14,一共15根地址线,根据NT5CC256M16ER-EK的数据手册可知,列地址为A0A9,共10根,行地址为A0~A14,共15根,因此一个BANK的大小就是210*2152=32MB2=64MB,根据图23.1.4.2可知一共有8个BANK,因此DDR3L的容量就是64*8=512MB。
③、BANK选择线
一片DDR3有8个BANK,因此需要3个线才能实现8个BANK的选择,BA0~BA2就是用于完成BANK选择的。
④、BANK区域
DDR3一般都是8个BANK区域。
⑤、数据线
因为是16位宽的,因此有16根数据线,分别为DQ0~DQ15。
⑥、数据选通引脚
DQS和DQS#是数据选通引脚,为差分信号,读的时候是输出,写的时候是输入。LDQS(有的叫做DQSL)和LDQS#(有的叫做DQSL#)对应低字节,也就是DQ07,UDQS(有的叫做DQSU)和UDQS#(有的叫做DQSU#),对应高字节,也就是DQ815。
⑦、数据输入屏蔽引脚
DM是写数据输入屏蔽引脚。
关于DDR3L的框图就讲解到这里,想要详细的了解DDR3的组成,请阅读相应对的数据手册。
23.2 DDR3关键时间参数
大家在购买DDR3内存的时候通常会重点观察几个常用的时间参数:
1、传输速率
比如1066MT/S、1600MT/S、1866MT/S等,这个是首要考虑的,因为这个决定了DDR3内存的最高传输速率。
2、tRCD参数
tRCD全称是RAS-to-CAS Delay,也就是行寻址到列寻址之间的延迟。DDR的寻址流程是先指定BANK地址,然后再指定行地址,最后指定列地址确定最终要寻址的单元。BANK地址和行地址是同时发出的,这个命令叫做“行激活”(Row Active)。行激活以后就发送列地址和具体的操作命令(读还是写),这两个是同时发出的,因此一般也用“读/写命令”表示列寻址。在行有效(行激活)到读写命令发出的这段时间间隔叫做tRCD,如图23.2.1所示:
在这里插入图片描述

图23.2.1 tRCD
一般DDR3数据手册中都会给出tRCD的时间值,比如正点原子所使用的NT5CC256M16EP-EK这个DDR3,tRCD参数如图23.2.2所示:
在这里插入图片描述

图23.2.2 tRCD时间参数
从图23.2.2可以看出,tRCD为13.91ns,这个我们在初始化DDR3的时候需要配置。有时候大家也会看到“13-13-13”之类的参数,这个是用来描述CL-tRCD-TRP的,如图23.2.3所示:
在这里插入图片描述

图23.2.3 CL-TRCD-TRP时间参数
从图23.2.3可以看出,NT5CC256M16ER-EK这个DDR3的CL-TRCD-TRP时间参数为“13-13-13”。因此tRCD=13,这里的13不是ns数,而是CLK时间数,表示13个CLK周期。
3、CL参数
当列地址发出以后就会触发数据传输,但是数据从存储单元到内存芯片IO接口上还需要一段时间,这段时间就是非常著名的CL(CAS Latency),也就是列地址选通潜伏期,如图23.2.4所示:
在这里插入图片描述

图23.2.4 CL
CL参数一般在DDR3的数据手册中可以找到,比如NT5CC256M16EP-EK的CL值就是13个时钟周期,一般tRCD和CL大小一样。
4、AL参数
在DDR的发展中,提出了一个前置CAS的概念,目的是为了解决DDR中的指令冲突,它允许CAS信号紧随着RAS发送,相当于将DDR中的CAS前置了。但是读/写操作并没有因此提前,依旧要保证足够的延迟/潜伏期,为此引入了AL(Additive Latency),单位也是时钟周期数。AL+CL组成了RL(Read Latency),从DDR2开始还引入了写潜伏期WL(Write Latency),WL表示写命令发出以后到第一笔数据写入的潜伏期。引入AL以后的读时序如图23.2.5所示:
在这里插入图片描述

图23.2.5 加入AL后的读时序图
图32.2.5就是镁光DDR3L的读时序图,我们依次来看一下图中这四部分都是什么内容:
①、tRCD,前面已经说过了。
②、AL。
③、CL。
④、RL为读潜伏期,RL=AL+CL。
5、tRC参数
tRC是两个ACTIVE命令,或者ACTIVE命令到REFRESH命令之间的周期,DDR3L数据手册会给出这个值,比如NT5CC256M16EP-EK的tRC值为47.91ns,参考图23.2.2。
6、tRAS参数
tRAS是ACTIVE命令到PRECHARGE命令之间的最小时间,DDR3L的数据手册同样也会给出此参数,NT5CC256M16EP-EK的tRAS值为34ns,参考图23.2.2。
23.3 I.MX6U MMDC控制器简介
23.3.1 MMDC控制器
学过STM32的同学应该记得,STM32的FMC或FSMC外设用于连接SRAM或SDRAM,对于I.MX6U来说也有DDR内存控制器,否则的话它怎么连接DDR呢?MMDC就是I.MX6U的内存控制器,MMDC是一个多模的DDR控制器,可以连接16位宽的DDR3/DDR3L、16位宽的LPDDR2,MMDC是一个可配置、高性能的DDR控制器。MMDC外设包含一个内核(MMDC_CORE)和PHY(MMDC_PHY),内核和PHY的功能如下:
MMDC内核:内核负责通过AXI接口与系统进行通信、DDR命令生成、DDR命令优化、读/写数据路径。
MMDC PHY:PHY负责时序调整和校准,使用特殊的校准机制以保障数据能够在400MHz被准确捕获。
MMDC的主要特性如下:
①、支持DDR3/DDR3Lx16、支持LPDDR2x16,不支持LPDDR1MDDR和DDR2。
②、支持单片256Mbit~8Gbit容量的DDR,列地址范围:8-12位,行地址范围11-16bit。2个片选信号。
③、对于DDR3,最大支持8bit的突发访问。
④、对于LPDDR2最大支持4bit的突发访问。
⑤、MMDC最大频率为400MHz,因此对应的数据速率为800MT/S。
⑥、支持各种校准程序,可以自动或手动运行。支持ZQ校准外部DDR设备,ZQ校准DDR I/O引脚、校准DDR驱动能力。
23.3.2 MMDC控制器信号引脚
我们在使用STM32的时候FMC/FSMC的IO引脚是带有复用功能的,如果不接SRAM或SDRAM的话FMC/FSMC是可以用作其他外设IO的。但是,对于DDR接口就不一样了,因为DDR对于硬件要求非常严格,因此DDR的引脚都是独立的,一般没有复用功能,只做为DDR引脚使用。I.MX6U也有专用的DDR引脚,如图23.3.2.1所示:
在这里插入图片描述

图23.3.2.1 DDR信号引脚
由于图23.3.2.1中的引脚是DDR专属的,因此就不存在所谓的DDR引脚复用配置,只需要设置DDR引脚的电气属性即可,注意,DDR引脚的电气属性寄存器和普通的外设引脚电气属性寄存器不同!
23.3.3 MMDC控制器时钟源
前面说了很多次,I.MX6U的DDR或者MDDC的时钟频率为400MHz,那么这400MHz时钟源怎么来的呢?这个就要查阅I.MX6ULL参考手册的《Chapter 18 Clock Controller Module(CCM)》章节。MMDC时钟源如图23.3.3.1所示:
在这里插入图片描述

图23.3.3.1 MMDC时钟源
图23.3.3.1就是MMDC的时钟源路径图,主要分为4部分,我们依次来看一下每部分所组的工作:
①、pre_periph2时钟选择器,也就是periph2_clkd的前级选择器,由CBCMR寄存器的PRE_PERIPH2_CLK_SEL位(bit22:21)来控制,一共有四种可选方案,如表23.3.3.1所示:
PRE_PERIPH2_CLK_SEL(bit22:21) 时钟源
00 PLL2
01 PLL2_PFD2
10 PLL2_PFD0
11 PLL4
表23.3.3.1 pre_periph2时钟源
从表23.3.3.1可以看出,当PRE_PERIPH2_CLK_SEL为0x1的时候选中PLL2_PFD2为pre_periph2时钟源。在前面的《第十六章 主频和时钟配置》中我们已经将PLL2_PFD2设置为396MHz(约等于400MHz),I.MX6U内部boot rom就是设置PLL2_PFD2作为MMDC的最终时钟源,这就是I.MX6U的DDR频率为400MHz的原因。
②、periph2_clk时钟选择器,由CBCDR寄存器的PERIPH2_CLK_SEL位(bit26)来控制,当为0的时候选择pll2_main_clk作为periph2_clk的时钟源,当为1的时候选择periph2_clk2_clk作为periph2_clk的时钟源。这里肯定要将PERIPH2_CLK_SEL设置为0,也就是选择pll2_main_clk作为periph2_clk的时钟源,因此periph2_clk=PLL2_PFD0=396MHz。
③、最后就是分频器,由CBCDR寄存器的FABRIC_MMDC_PODF位(bit5:3)设置分频值,可设置07,分别对应18分频,要配置MMDC的时钟源为396MHz,那么此处就要设置为1分频,因此FABRIC_MMDC_PODF=0。
以上就是MMDC的时钟源设置,I.MX6U参考手册一直说DDR的频率为400MHz,但是实际只有396MHz,就和NXP宣传自己的I.MX6ULL有800MHz一样,实际只有792MHz。
23.4 ALPHA开发板DDR3L原理图
ALPHA开发板有EMMC和NAND两种核心板,EMMC核心板使用的DDR3L的型号为NT5CC256M16EP-EK,容量为512MB。NAND核心板使用的DDR3L型号为NT5CC128M16JR-EK,容量为256MB,这两种型号的DDR3L封装一摸一样,有人可能就有疑问了,容量不同的话地址线是不同的,比如行地址和列地址线数就不同,没错!但是DDR3L厂商为了方便选择将不同容量的DDR3封装做成一样,没有用到的地址线DDR3L芯片会屏蔽掉。而且,根据规定,所有厂商的DDR芯片IO一摸一样,不管是引脚定义还是引脚间距,但是芯片外形大小可能不同。因此只要做好硬件,可以在不需要修改硬件PCB的前提下,随意的更换不同容量、不同品牌的DDR3L芯片,极大的方便了我们的芯片选型。
正点原子ALPHA开发板EMMC和NAND核心板的DDR3L原理图一样,如图23.4.1所示:
在这里插入图片描述

图23.4.1 DDR3L原理图
图23.4.1中左侧是DDR3L原理图,可以看出图中DDR3L的型号为MT41K256M16TW,这个是镁光的512MB DDR3L。但是我们实际使用的512MB DDR3L型号为NT5CC256M16EP-EK,不排除以后可能会更换DDR3L型号,更换DDR3L芯片是不需要修改PCB。图23.4.1中右边的是I.MX6U的MMDC控制器IO。
23.5 DDR3L初始化与测试
23.5.1 ddr_stress_tester简介
NXP提供了一个非常好用的DDR初始化工具,叫做ddr_stress_tester。此工具已经放到了开发板光盘中,路径为:5、开发工具->5、NXP官方DDR初始化与测试工具->ddr_stress_tester_v2.90_setup.exe.zip,我们简单介绍一下ddr_stress_tester工具,此工具特点如下:
①、此工具通过USB OTG接口与开发板相连接,也就是通过USB OTG口进行DDR的初始化与测试。
②、此工具有一个默认的配置文件,为excel表,通过此表可以设置板子的DDR信息,最后生成一个.inc结尾的DDR初始化脚本文件。这个.inc文件就包含了DDR的初始化信息,一般都是寄存器地址和对应的寄存器值。
③、此工具会加载.inc表里面的DDR初始化信息,然后通过USB OTG接口向板子下载DDR相关的测试代码,包括初始化代码。
④、对此工具进行简单的设置,即可开始DDR测试,一般要先做校准,因为不同的PCB其结构肯定不同,必须要做一次校准,校准完成以后会得到两个寄存器对应的校准值,我们需要用这个新的校准值来重新初始化DDR。
⑤、此工具可以测试板子的DDR超频性能,一般认为DDR能够以超过标准工作频率10%~20%稳定工作的话就认定此硬件DDR走线正常。
⑥、此工具也可以对DDR进行12小时的压力测试。
我们来看一下正点原子开发板光盘里面5、开发工具->6、NXP官方DDR初始化与测试工具目录下的文件,如图23.5.1.1所示:
在这里插入图片描述

图23.5.1.1 NXP官方DDR初始化与测试工具目录下的文件
我们依次来看一下图23.5.1.1中的这些文件的作用:
①、ALIENTEK_256MB.inc和ALIENTEK_512MB.inc,这两个就是通过excel表配置生成的,针对正点原子开发板的DDR配置脚本文件。
②、ddr_stress_tester_v2.90_setup.exe.zip就是我们要用的ddr_stress_tester软件,大家自行安装即可,一定要记得安装路径。
③、I.MX6UL_DDR3_Script_Aid_V0.02.xlsx就是NXP编写的针对I.MX6UL的DDR初始化execl文件,可以在此文件里面填写DDR的相关参数,然后就会生成对应的.inc初始化脚本。
④、最后两个PDF文档就是关于I.MX6系列的DDR调试文档,这两个是NXP编写的。
23.5.2 DDR3L驱动配置
1、安装ddr_stress_tester
首先要安装ddr_stress_testr软件,安装方法很简单,这里就不做详细的讲解了。但是一定要记得安装路径!因为我们要到安装路径里面找到测试软件。比如我安装到了D:\Program Files (x86)里面,安装完成以后就会在此目录下生成一个名为ddr_stress_tester_v2.90的文件夹,此文件夹就是DDR测试软件,进入到此文件夹中,里面的文件如图23.5.2.1所示:
在这里插入图片描述
在这里插入图片描述

图23.5.2.1 ddr_stress_tester安装文件
图23.5.2.1中的DDR_Tester.exe就是我们稍后要使用的DDR测试软件。
2、配置DDR3L,生成初始化脚本
将开发板光盘中的:5、开发工具->5、NXP官方DDR初始化与测试工具->I.MX6UL_DDR3_Script_Aid_V0.02.xlsx文件拷贝到ddr_stress_testr软件安装目录中,完成以后如图23.5.2.2所示:
在这里插入图片描述

图23.5.2.2 拷贝完成以后的测试软件目录
I.MX6UL_DDR3_Script_Aid_V0.02.xlsx就是NXP为I.MX6UL编写的DDR3配置excel表,虽然看名字是为I.MX6UL编写的,但是I.MX6ULL也是可以使用的。
打开I.MX6UL_DDR3_Script_Aid_V0.02.xlsx,打开以后如图23.5.2.3所示:
在这里插入图片描述

图23.5.2.3 配置excel表
图23.5.2.3中最下方有三个选项卡,这三个选项卡的功能如下:
①、Readme选项卡,此选项卡是帮助信息,告诉用户此文件如何使用。
②、Register Configuration选项卡,顾名思义,此选项卡用于完成寄存器配置,也就是配置DDR3,此选项卡是我们重点要讲解的。
③、RealView.inc选项卡,当我们配置好Register Configuration选项卡以后,RealView.inc选项卡里面就保存着寄存器地址和对应的寄存器值。我们需要另外新建一个后缀为.inc的文件来保存RealView.inc中的初始化脚本内容,ddr_stress_testr软件就是要使用此.inc结尾的初始化脚本文件来初始化DDR3。
选中“Register Configuration”选项卡,如图23.5.2.4所示:
在这里插入图片描述

图23.5.2.4 配置界面
图23.5.2.4就是具体的配置界面,主要分为三部分:
①、Device Information
DDR3芯片设备信息设置,此部分需要根据所使用的DDR3芯片来设置,具体的设置项如下:
Manufacturer:DDR3芯片厂商,默认为镁光(Micron),这个没有意义,比如我们用的nanya的DDR3,但是此配置文件也是可以使用的。
Memory part number:DDR3芯片型号,可以不用设置,没有实际意义。
Memory type:DDR3类型,有DDR3-800、DDR3-1066、DDR3-1333和DDR3-1600,在此选项右侧有个下拉箭头,点击下拉箭头即可查看所有的可选选项,如图23.5.2.5所示:
在这里插入图片描述

图23.5.2.5 Memory type可选选项
从图23.5.2.5可以看出,最大只能选择DDR3-1600,没有DDR3-1866选项,因此我们就只能选择DDR3-1600。
DRAM density(Gb):DDR3容量,根据实际情况选择,同样右边有个下拉箭头,打开下拉箭头即可看到所有可选的容量,如图23.5.2.6所示:
在这里插入图片描述

图23.5.2.6 容量选择
从图23.5.2.6可以看出,可选的容量为1、2、4和8Gb,如果使用的512MB的DDR3就应该选择4,如果使用的256MB的DDR3就应该选择2。
DRAM Bus width:DDR3位宽,可选的选项如图23.5.2.7所示:
在这里插入图片描述

图23.5.2.7 DDR3位宽
正点原子ALPHA开发板所有的DDR3都是16位宽,因此选择16。
Number of Banks:DDR3内部BANK数量,对于DDR3来说内部都是8个BANK,因此固定为8。
Number of ROW Addresses:行地址宽度,可选11~16位,这个要具体所使用的DDR3芯片来定,如果是EMMC核心板(DDR3型号为NT5CC256M16EP-EK),那么行地址为15位。如果是NAND核心板(DDR3型号为NT5CC128M16JR-EK),行地址就为14位。
Number COLUMN Addresses:列地址宽度,可选9~12位,EMMC核心板和NAND核心板的DDR3列地址都为10位。
Page Size(K):DDR3页大小,可选1和2,NT5CC256M16EP-EK和NT5CC128M16JR-EK的页大小都为2KB,因此选择2。
Self-Refresh Temperature(SRT):固定为Extended,不需要修改。
tRCD=tRP=CL(ns):DDR3的tRCD-tRP-CL时间参数,要查阅所使用的DDR3芯片手册,NT5CC256M16EP-EK和NT5CC128M16JR-EK都为13.91ns,因此在后面填写13.91。
tRC Min(ns):DDR3的tRC时间参数,NT5CC256M16EP-EK和NT5CC128M16JR-EK都为47.91ns,因此在后面填写47.91。
tRAS Min(ns):DDR3的tRAS时间参数,NT5CC256M16EP-EK和NT5CC128M16JR-EK都为34ns,因此在后面填写34。
②、System Information
此部分设置I.MX6UL/6ULL相关属性,具体的设置项如下:
i.Mx Part:固定为i.MX6UL。
Bus Width:总线宽度,16位宽。
Density per Chip select(Gb):每个片选对应的DDR3容量,可选1~16,根据实际所使用的DDR3芯片来填写,512MB的话就选择4,256MB的话就选择2。
Number of Chip Select used:使用几个片选信号?可选择1或2,正点原子所有的核心板都只使用了一个片选信号,因此选择1。
Total DRAM Density(Gb):整个DDR3的容量,单位为Gb,如果是512MB的话就是4,如果是256MB的话就是2。
DRAM Clock Freq(MHz):DDR3工作频率,设置为400MHz。
DRAM Clock Cycle Time(ns):DDR3工作频率对应的周期,单位为ns,如果工作在400MHz,那么周期就是2.5ns。
Address Mirror(for CS1):地址镜像,仅CS1有效,此处选择关闭,也就是“Disable”,此选项我们不需要修改。
③、SI Configuratin
此部分是信号完整性方面的配置,主要是一些信号线的阻抗设置,这个要咨询硬件工程师,这里我们直接使用NXP的默认设置即可。
关于DDR3的配置我们就讲解到这里,如果是EMMC核心板(DDR3型号为NT5CC256M16EP-EK),那么配置如图23.5.2.8所示:
在这里插入图片描述

图23.5.2.8 EMMC核心板配置。
NAND核心板配置(DDR3型号为NT5CC128M16JR-EK)配置如图23.5.2.9所示:
在这里插入图片描述

图23.5.2.9 NAND核心板配置
后面我就以EMMC核心板为例讲解了,配置完成以后点击RealView.inc选项卡,如图23.5.2.10所示:
在这里插入图片描述

图23.5.2.10 生成的配置脚本。
图23.5.2.10中的RealView.inc就是生成的配置脚本,全部是“寄存器地址=寄存器值”这种形式。RealView.inc不能直接用,我们需要新建一个以.inc结尾的文件,名字自定义,比如我名为“ALIENTEK_512MB”的.inc文件,如图23.5.2.11所示:
在这里插入图片描述

图23.5.2.11 新建.inc文件
用notepad++打开ALIENTEK_512MB.inc文件,然后将图23.5.2.10中RealView.inc里面的所有内容全部拷贝到ALIENTEK_512MB.inc文件中,完成以后如图23.5.2.12所示:
在这里插入图片描述

图23.5.2.12 完成后的ALIENTEK_512MB.inc文件内容
至此,DDR3配置就全部完成,DDR3的配置文件ALIENTEK_512MB.inc已经得到了,接下来就是使用此配置文件对正点原子ALPHA开发板的DDR3进行校准并进行超频测试。
23.5.3 DDR3L校准
首先要用DDR_Tester.exe软件对正点原子ALPAH开发板的DDR3L进行校准,因为不同的PCB其走线不同,必须要进行校准,经过校准一会DDR3L就会工作到最佳状态。
1、将开发板通过USB OTG线连接到电脑上
DDR_Tester软件通过USB OTG线将测试程序下载到开发板中,因此首先需要使用USB OTG线将开发板和电脑连接起来,如图23.5.3.1所示:
在这里插入图片描述

图23.5.3.1 USB OTG连接示意图
USB OTG线连接成功以后还需要如下两步:
①、弹出TF卡,如果插入了TF卡,那么一定要弹出来!!
②、设置拨码开关从USB启动,如图23.5.3.2所示:
在这里插入图片描述

图23.5.3.2 USB启动
2、DDR_Tester软件
双击“DDR_Tester.exe”,打开测试软件,如图23.5.3.3所示:
在这里插入图片描述

图23.5.3.3 NXP DDR Test Tool
点击图23.5.3.3中的“Load init Script”加载前面已经生成的初始化脚本文件ALIENTEK_512MB.inc,注意,不能有中文路径,否则加载可能会失败!完成以后如图23.5.3.4所示:
在这里插入图片描述

图23.5.3.4 .inc文件加载成功后的界面
ALIENTEK_512MB.inc文件加载成功以后还不能直接用,还需要对DDR Test Tool软件进行设置,设置完成以后如图23.5.3.5所示:
在这里插入图片描述

图23.5.3.5 DDR Test Tool配置
一切设置好以后点击图23.5.3.5中右上方大大的“Download”按钮,将测试代码下载到开发板中(具体下载到哪里笔者也不清楚,估计是I.MX6ULL内部的OCRAM),下载完成以后DDR Test Tool下方的信息窗口就会输出一些内容,如图23.5.3.6所示:
在这里插入图片描述

图23.5.3.6 信息输出
图23.5.3.6输出了一些关于板子的信息,比如SOC型号、工作频率、DDR配置信息等等。DDR Test Tool工具有三个测试项:DDR Calibration、DDR Stess Test和32bit Memory Read/Write,我们首先要做校准测试,因为不同的PCB、不同的DDR3L芯片对信号的影响不同,必须要进行校准,然后用新的校准值重新初始化DDR。点击“Calibraton”按钮,如图23.5.3.7所示:
在这里插入图片描述

图23.5.3.7 开始校准
点击图23.5.3.7中的“Calibration”按钮以后就会自动开始校准,最终会得到Write leveling calibtarion、Read DQS Gating Calibration、Read calibration和Write calibration,一共四种校准结果,校准结果如下:
示例代码23.5.3.1 DDR3L校准结果

1  Write leveling calibration
2  MMDC_MPWLDECTRL0 ch0 (0x021b080c) = 0x00000000
3  MMDC_MPWLDECTRL1 ch0 (0x021b0810) = 0x000B000B
4  
5  Read DQS Gating calibration
6  MPDGCTRL0 PHY0 (0x021b083c) = 0x0138013C
7  MPDGCTRL1 PHY0 (0x021b0840) = 0x00000000
8  
9  Read calibration
10 MPRDDLCTL PHY0 (0x021b0848) = 0x40402E34
11 
12 Write calibration

13 MPWRDLCTL PHY0 (0x021b0850) = 0x40403A34
所谓的校准结果其实就是得到了一些寄存器对应的值,比如MMDC_MPWLDECTRL0寄存器地址为0X021B080C,此寄存器是PHY写平衡延时寄存器0,经过校准以后此寄存器的值应该为0X00000000,以此类推。我们需要修改ALIENTEK_512MB.inc文件,找到 MMDC_MPWLDECTRL0、MMDC_MPWLDECTRL1、MPDGCTRL0 PHY0、MPDGCTRL1 PHY0、MPRDDLCTL PHY0和MPWRDLCTL PHY0这6个寄存器,然后将其值改为示例代码23.5.3.1中的校准后的值。注意,在ALIENTEK_512MB.inc中可能找不到MMDC_MPWLDECTRL1(0x021b0810)和MPDGCTRL1 PHY0(0x021b0840)这两个寄存器,找不到就不用修改了。
ALIENTEK_512MB.inc修改完成以后重新加载并下载到开发板中,至此DDR校准完成,校准的目的就是得到示例代码23.5.3.1中这6个寄存器的值!
23.5.4 DDR3L超频测试
校准完成以后就可以进行DDR3超频测试,超频测试的目的就是为了检验DDR3硬件设计合不合理,一般DDR3能够超频到比标准频率高10%15%的话就认为硬件没有问题,因此对于正点原子的ALPHA开发板而言,如果DDR3能够超频到440MHz460MHz那么就认为DDR3硬件工作良好。
DDR Test Tool支持DDR3超频测试,只要指定起始频率和终止频率,那么工具就会自动开始一点点的增加频率,直到达到终止频率或者测试失败。设置如图23.5.4.1所示:
在这里插入图片描述

图23.5.4.1 超频测试配置
图23.5.4.1中设置好起始频率为400MHz,终止频率为600MHz,设置好以后点击“Stress Test”开启超频测试,超频测试时间比较久,大家耐心等待测试结果即可。超频测试完成以后结果如图23.5.4.2所示(因为硬件不同,测试结果可能有些许区别):
在这里插入图片描述

图23.5.4.2 超频测试结果
从图23.5.4.2可以看出,正点原子的ALPAH开发板EMMC核心板DDR3最高可以超频到556MHz,当超频到561MHz的时候就失败了。556MHz超过了460MHz,说明正点原子的ALPHA开发板DDR3硬件是没有任何问题的。
23.5.5 DDR3L驱动总结
ALIENTEK_512MB.inc就是我们最终得到的DDR3L初始化脚本,其中包括了时钟、IO等初始化。I.MX6U的DDR3接口关于IO有一些特殊的寄存器需要初始化,如表23.5.5.1所示:
寄存器地址 寄存器名 寄存器值
0X020E04B4 IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE 0X000C0000
0X020E04AC IOMUXC_SW_PAD_CTL_GRP_DDRPKE 0X00000000
0X020E027C IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 0X00000028
0X020E0250 IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS 0X00000028
0X020E024C IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS 0X00000028
0X020E0490 IOMUXC_SW_PAD_CTL_GRP_ADDDS 0X00000028
0X020E0288 IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET 0X00000028
0X020E0270 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 0X00000000
0X020E0260 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 0X00000028
0X020E0264 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 0X00000028
0X020E04A0 IOMUXC_SW_PAD_CTL_GRP_CTLDS 0X00000028
0X020E0494 IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL 0X00020000
0X020e0280 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 0X00000028
0X020E0284 IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 0X00000028
0X020E04B0 IOMUXC_SW_PAD_CTL_GRP_DDRMODE 0X00020000
0X020e0498 IOMUXC_SW_PAD_CTL_GRP_B0DS 0X00000028
0X020E04A4 IOMUXC_SW_PAD_CTL_GRP_B1DS 0X00000028
0X020E0244 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 0X00000028
0X020E0248 IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 0X00000028
表23.5.5.1 DDR3 IO相关初始化
接下来看一下MMDC外设寄存器初始化,如表23.5.5.2所示:
寄存器地址 寄存器名 寄存器值
0X021B0800 DDR_PHY_P0_MPZQHWCTRL 0XA1390003
0X021B080C MMDC_MPWLDECTRL0 0X00000000
0X021B083C MPDGCTRL0 0X0138013C
0X021B0848 MPRDDLCTL 0X40402E34
0X021B0850 MPWRDLCTL 0X40403A34
0X021B081C MMDC_MPRDDQBY0DL 0X33333333
0X021B0820 MMDC_MPRDDQBY1DL 0X33333333
0X021B082C MMDC_MPWRDQBY0DL 0XF3333333
0X021B0830 MMDC_MPWRDQBY1DL 0XF3333333
0X021B08C0 MMDC_MPDCCR 0X00921012
0X021B08B8 DDR_PHY_P0_MPMUR0 0X00000800
0X021B0004 MMDC0_MDPDC 0X0002002D
0X021B0008 MMDC0_MDOTC 0X1B333030
0X021B000C MMDC0_MDCFG0 0X676B52F3
0X021B0010 MMDC0_MDCFG1 0XB66D0B63
0X021B0014 MMDC0_MDCFG2 0X01FF00DB
0X021b002c MMDC0_MDRWD 0X000026D2
0X021b0030 MMDC0_MDOR 0X006B1023
0X021b0040 MMDC_MDASP 0X0000004F
0X021b0000 MMDC0_MDCTL 0X84180000
0X021b0890 MPPDCMPR2 0X00400a38
0X021b0020 MMDC0_MDREF 0X00007800
0X021b0818 DDR_PHY_P0_MPODTCTRL 0X00000227
0X021b0004 MMDC0_MDPDC 0X0002556D
0X021b0404 MMDC0_MAPSR 0X00011006
表23.5.5.2 MMDC外设寄存器初始化及初始化序列
关于I.MX6U的DDR3就讲解到这里,因为牵扯到的寄存器太多了,因此没有详细的去分析这些寄存器,大家感兴趣的可以对照着参考手册去分析各个寄存器的含义以及配置值。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:22:20  更:2021-08-25 12:24:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 17:45:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计