当前课程知识点:ARM微控制器与嵌入式系统 > 第五章 ARM微控制器的各种外设 > 5.2.6 ARM微控制器外设:UART的寄存器编程(下) > 5.2.6 ARM微控制器外设:UART的寄存器编程(下)
各位同学大家好
我是清华大学工程物理系的曾鸣老师
接着来给大家讲一讲我们
ARM微控制器与嵌入式系统里头外设UART的编程
那么在上一个单元呢
我们讲了第一个和第二个编程的步骤
也就是如何把这个UART模块
乃至它所用到的PORT的时钟打开
以及如何把PORT里头这个物理引脚
指定为给UART这个功能来使用
那这个单元
也就是我们编程的真正的第三个步骤
也是我们学习UART编程的干货
一个ARM微控制器里的UART模块
它究竟有哪些寄存器来控制它工作
我们如何编程
能够让它按照我们约定的协议波特率
去进行通讯
如何把这个通讯真正做起来
那么这是这个单元要给大家讲的
那么我们前面学过IO模块以后会有一个概念
比如说IO
我们可能会有GPIOA、GPIOB若干组
每一组都会有一套一模一样的寄存器
来控制它所管的那一系列引脚的
输入还是输出的方向啊 值啊 这些东西
那么UART也一样
在上一个单元里
我已经提到我们ARM的KL25这个型号的
微控制器里头
有三个UART
分别是UART0、UART1、UART2
每一个UART都可以独立工作
跟不同的设备以不同的速度和帧格式
完成它自己的通讯
所以对它的控制
我们同样每一个UART都有一套寄存器
就像右边所示
那么它们分别是UART0、UART1、UART2
三套各来一遍完成对应一个UART的编程和开发
那么对于UART0、UART1、UART2
绝大多数这些寄存器的值是一模一样的
所以我们以通用的方式来进行讲解
那么这些寄存器看着很多
一大列比IO还要多
大家有点怕
那么我负责任的告诉大家
我们要把一个UART用最基本最简单的方式
编程开发起来
大家只需要使用到其中5到6个寄存器
每个寄存器
只需要使用到其中1到2个比特的值的设定
就可以完成这样一个功能
我来给大家一点点讲
那么这一系列寄存器
大家扫一下会发现它大概可以分成4类
最上面的BDH和BDL呢
是用来设置这个通讯的波特率
也就是速率
每个比特多宽的
然后UARTx_D是个Data Register
是用来读写我们串行通讯的数据的
接下来有一组UART的C1到C4
我们称为Control Register
是负责配置这个UART模块怎么工作的
最后两个S1和S2我们称为Status Register
是获得这个模块当前工作的状态的
所以以后我们学的一系列外设
在这个章节里都会给大家讲
其他的外设寄存器都会跟这类似
有数据的寄存器 有控制寄存器
有状态寄存器
我们对它的功能在不同的模块里
可能芯片设计的时候
有不同的定义
但我们对它加以掌握
就能这些模块越来越简单的用起来
我们先看UART
那么如我所说
在整个庞大的这个寄存器的映射地址空间里
UART的这一套寄存器
一共根据UART0、UART1、UART2
有三套各占一个地址段往下重复
所以每个UART0、UART1、UART2
对应的寄存器地址是有差异的
那么我们对这个地址映射的寄存器
有了理解以后
我们会知道在开发端
因为我反复给大家讲它像存储器
但不是存储器
因为你给它写了0或者1的值
它能存住
但最终是反过来指导一个电路的工作
那么UART的电路是什么呢
本门课程学习的不是芯片的设计
我们不会去讲里头每个模块的设计
但是我们可以定性的对它加以了解
从而更深的理解我们寄存器究竟怎么工作
那么比如说一个典型的UART的发送模块
我们看一张抽象图
就是像这一张图所示
这张图看着密密麻麻非常复杂
我们来对它的从顶层从块上做做划分
让大家理解
首先我们会有一个系统的这个发送时钟
那么这个发送时钟我加了一个标注
说他是发送时钟除以16
为什么呢
因为我们以一个波特率来工作的时候
我们在接收的时候
要用它16倍的速度去看收到数据
所以换言之就是发送的时候
我们会用十六分之一的速度
来一个比特一个比特的发送我们的数据
接着呢我们会有一系列的寄存器
最大一个寄存器是一个data register
我们是跟总线连在一起
换言之我们通过总线的地址
向这个寄存器里写入我们要发送的
比如是一个字节的值
那么这个值是从软件获得的值
而这个值
会被拷贝到我们的一个移位寄存器里
在电路的驱使下
按照我们约定好的波特率和时序
一个比特一个比特的从它的右端发送出去
而右端连的就是具体的物理的引脚
比如3.3伏代表逻辑1
0伏代表逻辑0送出去
那么在这个底下我们还会有一个小小的电路
也就是产生我们所说的奇偶校验位
如果我们决定使用奇偶校验
需要有一部分电路
根据这个移位寄存器存的值
算一算有多少个1
要不要加个1或者加个0
或者什么都不加
不用奇偶校验
然后再往下呢
我们会发现会有一系列的控制逻辑
来保证刚才说的这些东西能够有序的运行
然后这些控制逻辑会有一个副产品
就是我们会有一系列的中断产生
我们串行通讯跟IO一样
也是可以工作在中断方式下的
比如每当收到一个字节
或者每当一个数据发送完
我们可以用本门课程待会所讲的
轮询的方式来控制它工作
但是我们更可以通过设置中断
让中断通知CPU来自动处理
这个作为高阶的内容
有兴趣同学可以自己阅读芯片手册进行学习
但是完整的这样一个从时钟
到数据到奇偶校验
到控制逻辑到中断
是我们一个发送模块的内部电路的框图结构
那么我们需要理解的是
我们刚才提到的所有寄存器
是通过它的值来控制这些电路
进行正确的有序的工作
那么我们的数据就像这张箭头所示
从总线写给数据寄存器
再到移位寄存器一个比特一个比特的送出去
那么不再详细展开讲是我们接收
接收会以一个原始的时钟
也就是发送时钟的16倍
来看待我们从引脚收到的数据
那么通过一些附加的电路
我们可以检查它奇偶校验的正确
然后以及产生一些接收的中断
但是最终的目的是把接受到的数据
拷贝到数据寄存器
由总线把它读走
从而给程序其他的部分加以使用
那么我们同样一系列寄存器
会控制这些东西的有序运行
那么回过头来我们来看看寄存器的视角
那么刚才讲了一系列寄存器
从波特率 数据 控制寄存器 状态寄存器
这四大类我们先讲数据寄存器
数据寄存器非常地简单
他是映射在地址上的一个8比特位宽的寄存器
也就一个字节
虽然我们计算机是32位的
但是我们对任意地址
做8比特一字节的读写
所以这个字节计算器
就只有8个比特一个字节
那么这个寄存器就叫UARTx
比如UART0/1/2_D data register
那么它的说明非常的简单
就是我们对它写的数据是将要发送出去的
我们如果收到了数据我们可以从它读回来
我不知道对于这句话
大家理解到了背后的意思没有
这个背后的意思是一个小小的难点
那么大家在理解时候经常会卡在这儿
一般情况下
我们会说寄存器和存储器是有差异的
大家不会往细了想
这个地方是一个非常好的例子
如果一个存储器对应一个地址
我们写入一个字节
我们待会读
读到的肯定是它
如果我们中间有中断发生把它的值改了
那也是改过以后的值对吧
我们反复提寄存器
是一个存储着数据的电路
它的值可能会在程序的流程之外
被电路所改变
它的运行方式也不能完全等同于存储器
那么这个UART通讯的数据寄存器
包括以后我们要学习的
其他的通讯的数据寄存器
都有这样一个类似的特点
这个寄存器它的读和写
意味着完全不一样的操作
我们对它进行写操作的时候
写进去的数据是用来拷贝给移位寄存器
Shift register到发送引脚
逐一发送的
而我们对它进行读操作
注意 不是读
我们刚才真正所写的那个值
而是读我们的接收引脚从电路上收到的数据
拷贝回来的备份
那么你可以把它理解为
它是一个地址映射的寄存器
读和写两个操作分流到了不同的数据方向上
写 写到了引脚上
读 读的是接收引脚收到的数据
所以如果我们对这样一个寄存器
同时进行写个值 再读个值
他不等同于存储器的写个值
把它的原值读回来
如果是存储器可能我们的编译器
就把这两句话给优化掉了
因为等于什么都没做
但是对于UART的数据寄存器
UARTx_D这个寄存器
我们很有可能在这样一个操作里
做的是从串口发送一个字节
再读一个字节
别人给你的反馈对不对
所以大家一定要深度理解
这是一个数据寄存器复用为了
发送 写和读取 接收这两个不同的功能
这是数据寄存器
第二类寄存器我要讲的呢
是跟我们刚才讲的这张时钟图息息相关的
波特率的设置
我们都说我们UART1、UART2
包括按我给的例程UART0
我们配置为以Bus Clock 10.485兆
作为我们的参考时钟
那么这样一个时钟
如何得到我们想要的波特率呢
这个问题或者反过来说
我们怎么对寄存器编程
把它设置成任意一个波特率的值呢
那么我们会用到UARTx_BDL和UARTx_BDH
这两个寄存器
那么BDL和BDH分别是
Baud rate high register和Baud rate Low register缩写
它是高低两个各8比特一字节的寄存器
那么我们BDH寄存器的后面五个比特
加上BDL寄存器的这8个比特
一共可以组成一个13比特的二进制数
它的值就从0到8191是可以设置的
那么我们要的波特率的值
或者是我们对这个寄存器进行了配置以后
得到波特率的值
就是我们这个UART模块所使用的时钟源
源时钟除以这个13比特的值
再除以16得到就是我们的波特率
我不知道大家明白这个公式背后的事没有
我再说一遍
我们这个UART的模块所使用的源时钟
除以这两个寄存器联合设置的
13比特的二进制数的值
再除以16就是我们得到的波特率
所以我们的UART模块刚才说到
使用的源时钟是10.485兆
那么我们给这两个寄存器设置了一个值
所以这个10.485兆除以这个数
再除以16
是我们这个设置给串行通讯的波特率
所以大家要做一个通讯的时候
比如说我要跟一个计算机连
我就会约定好计算机那边
和微控制器这边都用哪一个波特率来通讯
那边用这个波特率收
这边用这个波特率发
这就是异步串行通讯
如果我要用一个现成的GPS模块
我得看芯片手册
这个GPS模块它的波特率是多少
我用跟它对应的波特率去读它和写它对吧
所以这是第一个问题
我们从一个已有频率分到一个要的频率
第二个问题呢
为什么要除以这个寄存器值
再除以16呢
这又是我们上一个单元
所讲过的过采样的概念
我们需要设定一个波特率的值
让这个波特率的值是实际数据的比特宽
但是我们还要一个比它快16倍的频率
是可达到的来进行接收的时候的16倍的采样
所以是频率除以值除以16
那么第三个问题是我们如何知道
我们该如何编程
对这些寄存器配置得到值呢
那非常简单
因为波特率等于时钟除以它
所以换言之
我们要想知道寄存器设成哪个值
就应该用我们的10.485兆的时钟
除以16除以我们要的波特率
得到那个商就是我们的寄存器该设的值对不对
非常简单
所以我们想一想
如果我们的总线频率是10.485兆
我们的波特率最大能设多少
最小能设多少
这是第一个问题大家想一想对吧
这13比特能取多少值
第二个问题呢
是如果我们要9600的波特率
我们这个寄存器值应该设成多少
拿10.485兆除以16再除以我们要的波特率 对吧
然后最后一个问题呢
是如果我们设了9600波特率
算出来这个商这个值
大家带到这个公式里反着算
除出来的值刚好是9600吗
然后我负责任告诉大家
一定不是的
而且这个误差还不小
可能差几十 可能差上百
那有关系吗
那又回到上个单元我给大家讲的
异步串行通讯
双方的时钟不一定要严格的一模一样
因为有UART这样一个数据帧的结构
那这个时钟误差多少以内
是可以接受的呢
比如说我接收到计算机是刚好9600
我算一下这个值
比9600大多少小多少可以接受呢
在上个单元里讨论的时候给大家讲了
正负5%通讯都不会出错对吧
所以大家可以有兴趣可以算一算
到实际开发的时候编编程就知道了
那么最后提示一件事从芯片设计的角度
UARTx的BDH和BDL这两个寄存器
必须连续编程访问赋值
也就换言之你必须BDH这个寄存器等于多少
紧接着跟一句BDL这个寄存器等于多少
你单对其中一个编程
芯片会把这句话忽略掉
认为没有正确的赋值
因为你设波特率肯定两个寄存器一起设
所以大家要注意这件事
所以如果我们把对波特率的设置进行编程
就是下面这两句话
UART1的BDH等于多少
UART1的BDL等于多少
就完成了波特率的设置
而设置的这个值
比如我们现在设的0x0044
大家换算一下它对应的是
阿拉伯数字十进制的68
就是我们根据10485这样一个赫兹数
要9600的波特率做除法除出来的
我们写了这两句话
那有的同学会说
老师我这个程序如果
有的时候用9600的波特率
有时候用4800的波特率
老是变 每次都拿计算器点
有没有简单的方法呢
有啊 我们写的就是程序啊
所以大家可以用上面这一段
看上去更复杂的代码
我们在编程的时候慢慢会有这样的概念
我们总是通过代码的复杂度
换来人理解的简单
或者用代码的简单要牺牲人去做计算
所以用上面这段代码
我们只需要把上面的变量定义
或者是宏定义改成我们的要的波特率
比如9600改成4800
下面他就用乘除法
自己来算出寄存器的值应该是多少
这些技巧大家可以自由的去编程和进行开发
好 讲完了数据寄存器那一点点
有点绕的小难点
讲完了波特率剩下的比较简单了
两类的寄存器
一个是UART的控制寄存器C1C2
一类是UART的status的寄存器S1
那么完成这些寄存器
我们就能真正把一个UART模块给用起来
那么第一个寄存器呢是UART的C1
control register 1
也就是控制寄存器1号
那么它有若干个比特
上面的比特都是控制着
UART模块的工作模式的在本门课的范畴里
我们不去深究
主要看它最后两个比特
这两个比特一个是PE
一个是PT
那么这两个寄存器控制的单元
其实就是我们是否在这个UART模块里
使用奇偶校验
以及是使用奇校验还是使用偶校验
那么这两个比特上电默认值都是0
它的含义是什么呢
就是不使用奇偶校验
那么在本门课范畴里
为了简化我们的理解和通讯
我们计算机通讯
我们可以约定双方都不用奇偶校验
也就是8个比特发完就是停止位
所以这个寄存器我们给它赋0就可以了
或者我们更简单我们编程的时候
这个寄存器我们不动它
不对它进行编程
用它的默认值就可以了
那么第二个控制寄存器
UARTx的C2寄存器
那么这个寄存器
前面有若干比特
是涉及到使不使用UART的中断
以及中断的子开关
那么学过中断的同学可以回忆这个部分
但是我在这个单元里我们不讲
我们用到是我标为绿色这两个比特
分别是比特2和比特3
一个叫TE一个叫RE
很简单一个是TXD的Enable
或者transmitter的Enable
一个是RE的Enable
也就是receiver的Enable
换言之这两个比特默认是0
置1 就打开了对应这个UART模块的
发送器和接收器
就刚才我给大家展示那个电路
让他开始干活
那我们要通讯我们当然要把它打开了
所以一定不可以少的一句话是
比如说UART1的C2寄存器
要或上这两个比特
这两个比特其实大家一看是比特3和比特2
那就是或上0x80再或上0x40
这两个比特置1
我们的UART模块的开关就打开了
然后状态寄存器只涉及到了一个
也就是UART的S1第一个状态寄存器
这个状态寄存器也有很多个比特
后面低位这个几个比特
是状态中断发生的标志位
后面几个比特是中断发生的标志位就是flag
所以当我们中断打开这个地方置位的时候
会自动通知CPU发生中断
我们也可以通过检查这些位
知道是哪个中断发生了
那么我们这个单元不讲中断
这个部分就忽略
我们只看我标为绿色的这两个比特
它直接影响到了
我们如何写出第一个收发函数
比如说第一个比特最高位比特7
它的名称是TDRF比特
那么它的含义是TXD的Data Buffer Empty Flag
翻译成中文
就是发送器的数据缓存空了的标志位
什么叫发送的数据缓存空了
意思就是之前放在那儿
要发送的数据已经发送完了
进一步的意思就是说
此时你可以发送下一个字节
所以我们如果要做一个发送函数
大家想一想
我们是直接给UART_D的数据寄存器
写个值就行了吗
这个时候会出现一种潜在的风险
就是前一个字节
一个比特一个比特的frame数据帧
还没有发送完
结果你拿了一个新的值来覆盖它
所以正确的写法
比如说我们自己写一个UART串行通讯的
数据发送函数
我给大家一个例子应该写成这个样子
是比较规范的一种写法
比如说我们不要返回值void
那么这个函数的名称
我们自己起比如叫UART1的Putchar函数
发送一个字节
那么它应该有一个参数是unsigned char data
也就是我给他一个字节的数据
那么这个字节的数据要想发送出去
我们要分两句话写
第一句话就是我这里写的while函数
第二句话大家非常容易想到
是UART1_D寄存器等于我给这个函数的data值
把这个字节写给数据寄存器对吧
那么在波特率配置好的情况下
它就自动的一个比特一个比特
把这样一个UART数据帧从引脚发送出去了
这个While语句大家看看写的是什么
首先注意语法
他是While一个括号后面跟了个分号
我们While语句正常情况下后面不跟分号的
所以这个分号不是这个句子的结尾
而是While这个语句的执行条件
执行一个空语句
那么也就说在While里头条件满足的情况下
它就一直在那儿循环执行这个空语句
那它检查的事情是什么呢
你会发现检查的事情
是拿我们的UART的S1寄存器
跟它的最高位也就是TDRF这一位
一直通过与运算来检查它有没有变1
如果它没有变1是不是意味着
发送寄存器没有空啊
因为发送寄存器没有空
这前面感叹号是取反 对吧
因为发送寄存器没有空
就意味着前面有数据没有发送完
就在While这儿一直循环等
等到发送寄存器这个比特置1
发送寄存器为空
才执行下一句话
发送一个新的字节
所以我们这个函数写完了的含义是
请检查发送的寄存器
有没有发送完上一个比特
上一个字节
如果上一个字节成功发送完了
请给它一个新的字节
发送出去
如果没有发送完
我就会在这儿一直等
这种方式称为阻塞式的数据通讯
阻塞在这儿等它能够发送
那么与之相关的另外一个比特
我可以讲快一点
讲简单一点
就是这个比特5
也就是从上面说第三个比特
它的名字叫RXD Data Buffer Full flag
也就是数据接收的缓存寄存器满的标志位
什么叫数据接收的寄存器满
那就说明收到了一个字节等着你读
这个时候我们就很好理解了
如果我们要写一个函数
来完成通过UART的数据接收怎么写呢
这个时候我们会发现
我们写一个类似的函数
就像这样叫UART1_Getchar
获得一个字节的数
这个时候参数我可以写成是void
但是我得有一个返回值
因为我调用这个函数就从外面的接口
读到一个字节
得是函数的返回值
所以函数的返回类型是unsigned char
那么这个语句同样是两句话
后面一句话很好理解
return UART的data寄存器
把data寄存器值读出来
从函数返回回去
我们读到了数据寄存器
但是我能随时读吗
是不能的
必须确实收到了一个字节
然后这个模块在寄存器里告诉我
有一个字节在那儿我才读
否则我可能读到的是空的值没有意义的值
也可能读到是上一次通讯遗留在那里的值
所以仍然是用一个While语句
来反复检查这一位是否置位
如果没有收到数据
它也在这儿一直等 也是阻塞式的
那么聪明的同学可能会想
能不能编成非阻塞的呢
能不能让它不要一直等呢
能不能用中断
来让它收到数的时候告诉CPU呢
这些问题
都是很好的
有兴趣的同学可以自己去试一试
那么这个单元讲完了以后
我们就获得了编程的第三个步骤里头
最重要的两个函数
如何通过UART发一个字节的数出去
或者接收一个字节的数
C语言学的好的同学应该概念清楚
发一个字节的数或者接收一个字节的数
也可以是发送和接收一个ASCII的字符
字符就是数对吧
那么这个单元的思考题就是
基于我刚才所讲的这么一堆寄存器
大家有了发送和接收的函数
能不能自己写一个UART1的初始化函数
把它初始到我们要的
比如9600 8N1的数据格式上
我提示大家要想一想要做哪几件事
这个初始函数
或者包括我们刚才说的
步骤一 步骤二的打开时钟配置时钟
配置引脚的功能那些东西
如果不包括把它放在前面单独调用函数
那它是不是也应该包括刚才提到设置波特率
打开发送和接收对不对
设置奇偶校验要不要
完成这几件事是不是完成初始化了
好像也不难
四五句话就可以实现
那么大家试一试吧
到了做实验的时候
我再来带着大家进行实际的编程
-1.1 课程概览
--1.1 课程概览
-1.2 如何学好嵌入式系统
-2.1 计算机的基本概念、发展历史
-2.2 从晶体管到CPU
-2.3 概念CPU、微控制器MCU和嵌入式系统
-2.4 八卦计算机史
-2.5 不同领域、不同系列的嵌入式系统
-2.6 ARM历史与MKL25Z128 MCU
--2.6 ARM历史与MKL25Z128 MCU【习题】
-3.1 CPU的基本结构和运行机制
-3.2.1 堆栈的概念
--3.2.1 堆栈的概念【习题】
-3.2.2 堆栈的概念-头脑体操
-3.3.1 ARM的体系结构
--3.3.1 ARM的体系结构【习题】
-3.3.2 ARM的体系结构-头脑体操
-3.4.1 中断的概念和机制
-3.4.2 中断子程的概念和编程
-3.5 复位、时钟、存储器和总线
--3.5 复位、时钟、存储器和总线【习题】
-3.6 小结:MCU的总体结构和程序运行机制
--3.6 小结:MCU的总体结构和程序运行机制【习题】
-4.1 第一种外设:IO
-4.2 IO外设的编程实操-点亮LED
-4.3 IO外设的进阶知识
-4.4 嵌入式开发的基本概念与工具链
-4.5 嵌入式开发的进阶知识
-4.6 嵌入式开发中的C语言(上)
--4.6 嵌入式开发中的C语言(上)【习题】
-4.7 嵌入式开发中的C语言(下)
--4.7 嵌入式开发中的C语言(下)【习题】
-E0.1 实验零 开发板的初步认识与工具链的安装
-E0.2 实验零 体验一个例程的编译与下载
-E0.3 实验零 编写第一个程序:点亮核心板LED
-E1 实验一 点灯秘籍
-5.1 ARM微控制器外设学习概述
-5.2.1 ARM微控制器外设:通讯
-5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)
--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)
--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)【习题】
-5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)
--5.2.3 ARM微控制器的外设:异步串行通讯UART的原理(下)
--5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)【习题】
-5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口
--5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口
-5.2.5 ARM微控制器外设:UART的寄存器编程(上)
--5.2.5 ARM微控制器外设:UART的寄存器编程(上)
-5.2.6 ARM微控制器外设:UART的寄存器编程(下)
--5.2.6 ARM微控制器外设:UART的寄存器编程(下)
--5.2.6 ARM微控制器外设:UART的寄存器编程(下)【习题】
-E2 实验二 UART编程实操
-5.3.1 ARM微控制器外设:IO的中断编程(上)
-5.3.2 ARM微控制器外设:IO的中断编程(下)
-5.4.1 ARM微控制器外设:定时器的原理
-5.4.2 ARM微控制器外设:定时器的编程
--5.4.2 ARM微控制器外设:定时器的编程【习题】
-E3 实验三 定时器中断编程实操
-5.5.1 ARM微控制器外设:PWM的原理
-5.5.2 ARM微控制器外设:PWM寄存器与编程
-5.5.3 ARM微控制器外设:PWM编程实例—电子音乐
--5.5.3 ARM微控制器外设:PWM编程实例—电子音乐
-E4 实验四 数码管显示编程实操
-5.6.1 ARM微控制器外设:SPI通讯简介
--5.6.1 ARM微控制器外设:SPI通讯简介【习题】
-5.6.2 ARM微控制器外设:SPI寄存器与编程
-5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动
--5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动
-5.7.1 ARM微控制器外设:I2C通讯简介
-5.7.2 ARM微控制器外设:I2C的通讯协议
-5.7.3 ARM微控制器外设:I2C寄存器与编程
--5.7.3 ARM微控制器外设:I2C寄存器与编程【习题】
-5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器
--5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器
-5.8.1 ARM微控制器外设:ADC简介
-5.8.2 ARM微控制器外设:ADC基础
-5.8.3 ARM微控制器外设:ADC寄存器与编程
-E5 实验五 ADC编程实操
-E6 挑战实验
--E6 挑战实验
-6.1 嵌入式系统的接口与设计
-6.2 嵌入式系统的实例