当前课程知识点:ARM微控制器与嵌入式系统 >  第五章 ARM微控制器的各种外设 >  5.7.3 ARM微控制器外设:I2C寄存器与编程 >  5.7.3 ARM微控制器外设:I2C寄存器与编程

返回《ARM微控制器与嵌入式系统》慕课在线视频课程列表

5.7.3 ARM微控制器外设:I2C寄存器与编程在线视频

5.7.3 ARM微控制器外设:I2C寄存器与编程

下一节:5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器

返回《ARM微控制器与嵌入式系统》慕课在线视频列表

5.7.3 ARM微控制器外设:I2C寄存器与编程课程教案、知识点、字幕

各位同学大家好

我是清华大学工程物理系的曾鸣老师

我们来继续我们

ARM微控制器与嵌入式系统的MOOC之旅

我们在这几个单元里呢

一直在学习I2C这样一种同步串行通讯

这是一种比较麻烦的通讯协议

也是我们这门课里应该来讲

学的最麻烦 最复杂的一类通讯

我们花了两个单元的时间来讲它的原理

它的思想

它的电气特性

它的数据帧

那么总体上来讲

回过头来看 会发现

它里头有UART异步串行通讯的影子

也有SPI同步串行通讯的影子

但是我们学了它们好像上了一个台阶

有了数据帧的概念

有了像这样几个积木组成的这样一个

时序的这个单元的概念

那么展开了讲日后大家

如果把这个I2C学习好了

日后大家去看USB

或者以太网通讯

特别是USB

你去看它里头那个数据帧的结构的时候

你会发现

哇 理解起来好像很容易

那么它们技术发展就是这么一脉相承的

所以这也是为什么

USB叫Universal Serial Bus

跟我们这样一个I2C的名字

都是一脉相承的这样一种关系

所以呢

我们学通讯到这里就告一个段落了

但是我们这门课的本质

我们这门课一直给大家讲的一个精神

是我们学的东西

要带着兴趣我们把它给玩起来

所以在这个单元里

我来给大家讲如何把I2C编程玩起来

玩一个比较好玩的功能

那么在我们所拿到的这样一个开发板里

我们的I2C接口

接了一个非常有意思的芯片电路

就是数字加速度传感器

那么数字加速度传感器

说起来好像还比较学术

Accelerometer是什么东西

感受加速度

那我给大家换一个说法就是运动传感器

也就是我们现在手机上大家用的摇一摇啊

翻个面啊

倾斜角度啊

这样一类的物理传感器

我们用了它的一个I2C接口的sensor

传感器芯片

也就是Freescale的MMA这个8551这样一个芯片

那么这个芯片它接在我们这个板子上

用了其中一个I2C的接口

那么看看这张电路图

大家读一读图就会发现

芯片抽象成了这样一个黄色小方块

接的两个除了共地之外

接的两个时序引脚

从PORT上来讲就是PTE

PORTE的24和25这两个引脚

它们的第5号复用功能

分别是I2C的SCL时钟和I2C的SDA数据

那么我们怎么编程把它给用起来呢

这就涉及到了I2C的通讯协议

包括我们刚才讲的拔高内容里头的

这样一个芯片内部是有若干个寄存器的

我们需要对它内部地址进行读和写操作

来如何编程实现

那么所有同学都会说分三个步骤对吧

第一个步骤配置好时钟打开

第二个步骤把引脚配置给I2C模块用

第三个步骤学习一下I2C的寄存器

把曾老师刚才讲的那些理论

那些时序怎么转换成语言

转换成封装的函数给实现出来对吧

那么第一个步骤非常简单

前两个步骤我都讲快一点

如何把时钟打开

还是System integration Module里头

有两个寄存器我们要涉及

一个是在SIM的SCGC4这个寄存器里头

我们可以找到I2C0和I2C1我们这个芯片里

有两个I2C模块

它们分别都可以用一个比特

控制时钟的开关

那么第二个就是不要忘记了

我们现在用的这个引脚是PORTE的引脚

我们要记得把PORTE的时钟也打开

具体的语句我就不给大家展开讲

那么打开时钟之后背后一定要有个概念

就是我们这个芯片每一个模块

都在一个共同的时钟Tree的驱动下

一个Clock 一个Clock像心跳一样的工作

那么如果我们看我们芯片手册的

第三章关于Clock的distribution

时钟树的解释

专门会有一个部分提到I2C0和I2C1

我们这个芯片里头这两个I2C模块

使用的参考时钟源都是Bus Clock

所以在上电默认没有启动锁相环的时候

我们的锁频环的这个片内晶振产生的

这个时钟是20.97兆

Bus Clock是它的一半

所以我们分频的基础频率

就是20.97兆除以2

这个大家要弄清楚

那么如果大家用的是别家的

别的厂商的ARM芯片

你们也去看对应的这样一种芯片手册

一定能找到你所使用I2C模块的时钟源

这一点大家不要忘

为什么呢

因为一到通讯肯定有速度

肯定有波特率

后面的寄存器设置会用到它

所以这个单元加起来就这么两句话

打开时钟非常简单 对吧

那么第二个步骤呢

就是把我们的引脚配置为给I2C使用

这个大家做了很多次

这次格外简单

为什么呢

因为I2C除了地线

它就只有两根数据线

所以我们就是两句话

PORTE的PCR24

和PORTE的PCR25

指定为对应的第5号功能

就是给I2C用

那么这件事就做完了

那么最后一个步骤相对麻烦一点

也是我们这个单元里学习的难点或者重点

就是I2C的寄存器的编程

那么I2C在我们用的KL25这款芯片里头

有两个模块 I2C0、I2C1

所以是同样的电路

同样的寄存器一式两份

每一个模块对应有12个寄存器

在400的这个地址段

可以帮助我们来对I2C进行配置

我们对寄存器的使用

可以完成对于电路

这样一个框图功能内的功能的设置

包括对于这些数据的按照时序如何出去

如何按照刚才我们所讲的时序收进来

框图我就不展开讲了

那么这有12个寄存器里头

在这门课单元

读一个加速度传感器大家放心

我们只用深入掌握其中四个寄存器使用

就能把一个I2C模块给初步的用起来

但是更多寄存器我鼓励大家

自己去看芯片手册对吧

那么这四个寄存器分别就是

I2C_F Frequency也就是baudrate

我们这个速度的频率的设置寄存器

还有I2C的这个C1控制的Control Register

还有I2C的S

Status Register和I2C的D

大家会发现我们用过的

每一个通讯模块的寄存器基本上都是这几个

所以编程的思想和步骤很接近

在I2C里头唯一的一个区别是什么呢

就是在上个单元我们讲的

它有一个数据帧的结构

里头涉及到主机与从设备当中彼此的交互

所以它在编程实践上会稍微有一点不一样

我们先来看这个Frequency第一个寄存器

设置我们I2C通讯模块的时钟频率

那么同样它就是跟我们以前

设波特率那寄存器一样

把一个八比特寄存器分成了两段

这两段各是一个值

所以呢

我们的基础频率20.97兆的

那个一半除以这两个值的乘积

就是我们I2C模块的

最终一个比特位宽的那个时钟频率

那么这个时钟频率大家做过

上一个单元里头

对于屏幕那个OLED点阵屏的控制以后

就会有概念

我的频率必须跟我通讯的对象设备协商好

是它能接受的

那我们现在要跟这么一个加速度传感器

这样一个运动传感器通讯

我们是不是应该去看一看它的芯片手册呢

所以详细的芯片手册下一节课

我带着大家看

现在大家跟着我一起去看

这个芯片手册的时候

直接翻到这个第八页里

你会发现有一张这个电气特性表

里头有一个它的I2C这个接口的通讯频率

和Maximum最大值 是多少啊

是400K赫兹

所以我们选一组分频因子

使我们I2C模块

工作在比这个低的频率

就可以确保跟这个芯片正确的通讯了

所以比如说我们现在红框里

在这个芯片手册的表里

选了一组值来设置我们这个ARM芯片

让它是20.97兆再除以1乘以80

得到一个100多K的通讯速率

这样我们就可以以一个比较稳妥的速度

跟加速度传感器进行通讯

当然它离这个芯片能够承受的最高速率

还差那么一点点

有兴趣的同学

你可以把速度再改高一点看一看

那么这就是对于这个频率寄存器的控制

那么我们涉及到的第二个寄存器呢

就是C1控制寄存器

控制寄存器里头有非常多的比特

我们可能会用到

包括我标为绿色的这几个比特

它们有的比如说最高位控制I2C

这个模块的Enable和Disable

比如第五个比特控制这个I2C模块

是工作在Master模式还是Slave模式

然后第四个比特控制这个I2C模块

是控制在发送状态还是接收状态

那么学过前面的电气特性

大家应该深刻理解的是

所谓的工作在发送状态

就是由主机来控制数据线

负责数据线的是否往下拽产生零电平

而所谓控制在接收状态

是指主机松开对于数据线的控制

而交由设备来控制

也就是我们刚才通讯里白色的部分

而主机这个时候是读取数据线上的值

然后第二个比特

Restart这个比特呢

指可以做写操作

每写一次产生一个

我们刚才说到的重启信号

也就是重复发送一个起始信号

那么I2C的特殊性

就如我这段代码所示

实际上呢

我们通过一系列的宏

把这样对于寄存器

这些比特的操作进行了封装

来实现我们I2C通讯协议里头

刚才说的在上一个单元里所讲的

起始位 停止位

重复起始位

发送ACK 发送NACK

以及进入接收模式

把控制权交给从设备等等

这样一系列的操作

所以也就是说I2C的通讯

我们不再简单的是对寄存器

完成一次配置就不管了

而是得封装成这些宏

再对这些寄存器的操作

或者以这种宏的形式完成我们刚才

时序图里所讲的那样一个通讯协议

那么I2C的第三个寄存器是数据寄存器

也就是I2C_D

数据寄存器在UART

在SPI里头我们都学过

它是一个寄存器

同时对应读和写两种不同操作

这个概念大家已经有了

那么在I2C的数据寄存器

I2C_D里头

它也有它的特殊性

那么讲了一大段英文

Transmit model和Receive Model分别怎么样

我们把它简述从芯片手册上

翻译成中文是这么几个意思

对于这个寄存器的写操作

会发起一笔新的I2C通讯

也就是主机开始向外

一个比特一个比特的发出通讯

也就是产生这个数据出去

那么对于I2C_D的这个数据寄存器的读

总是读到的是I2C上一次已经接收到的字节

而这个读操作本身会启动一次新的读取操作

那么这句话什么意思呢

就意味着我们待会编写读写函数

对I2C进行编程的时候

我们每一次写操作把数据写进去

就发起了一个字节的写

在I2C的时序里

读操作我们应该先做一次Dummy读取

也就是空读取

来把上一次存在里头的数据读出来不要

同时通知这个模块产生一次新的读取时序

接下来下一次读取

才会读到我们

在未来这八个比特时钟周期里

真正读到我们要接收的值

这是这句话背后的含义

第三件事呢

是由于我们I2C的通讯协议刚才已经讲了

它是有规范 有约束的

所以每一笔通讯

每一笔独立的通讯

在起始位

我们刚才说对这个

控制寄存器的比特进行读写

产生起始位之后

我们第一次操作一定是通过

对于I2C_D的这个寄存器的写操作

写入一个从机的地址

加上一个比特读写方向

然后这一个比特写完了以后

我们之后做的读取

或者是写入

就是对这个数据寄存器操作

必须与我们写的这第一个字节的方向一致

也就是我们写的这第一个字节

七个比特地址后面

跟的是读 还是跟的是写

我们后面对数据寄存器的操作

必须跟它相应的是读或者是写

如果两者不匹配

这个模块就无法正确的返回数据

无法正确的工作

I2C的通讯就不会成功

因为我们的程序编错了

所以就这么三个要点

写 发起写的时序

读 应该先预读一次

然后等待数据收到了

再第二次读

才会读到真正的数据

然后读第一次写入的字节

决定了我们的设备地址和读写方向

之后对寄存器的读写

必须与第一个字节的

读写标志位方向一致

符合I2C的通讯协议

这是几个要点

那么我们回过头来看看

刚才讲到的数据帧

也就是所说的这个意思

第一个字节是地址加读写

后面的读和写的方向

必须与第一个字节一致才符合协议

最后是I2C的Status这个状态寄存器

状态寄存器里有很多标志位

实际上在我们这个编程里

真正用到的是比特1

也就是I2CIF中断标志位

跟我们做SPI通讯的时候一样

这个中断标志位

其实在启用了中断的时候

可以作为中断的标志位

但是在我们做查询模式的时候

它也是我们每一次I2C的通讯

完成一个字节的时候的一个标志位

所以我们真正的通讯流程是

每当发送或者接受一个字节后

这个标志位都会置1

那么在进行I2C通讯时

我们每一次读写I2C_D这个寄存器以后

都应该查询一下这个标志位

然后再来进行下一次操作

而对这个标志位做写1

注意大家这个寄存器的图里写的

W1C Write once to clear

写1会清楚这个标志位

在查询模式里我们需要通过

清除标志位便于下一次查询

在中断模式里我们需要在中断函数里

去清这个标志位

所以这样一件事情

我们也定义成了这样一句宏语句

叫做I2CWait

也就是每一次的

无论读或者写的字节操作完了以后

我们会反复查询这一位

直到它发生改变

并且再把它清除再做下一次操作

这样完成

保证我们的时序

是等待I2C内八个比特Clock的时序

一个字节一个字节的完成通讯

那么我们回过头来

再看我们对于函数的封装

我们会发现在前面的经验上

我们首先I2C模块会封装出一个Init函数

就是这么三段关于时钟的打开

引脚的配置以及I2C的一些初始配置

那么对于读写我们现在控制的

是一个MMA8510这样一个加速度传感器

它内部是有内部地址的

我们在下一个单元会给大家再详细讲

所以封装成它的写函数和读函数

我用这个伪代码给大家写出来

大家自己去写

是不是对于写操作

我们就变成了I2C的三个步骤操作

起始位刚才有宏定义 对吧

然后写一个字节

这个字节必须是这个芯片的子地址

加上一个写的标志位

然后查一下ACK

芯片是否回应

再写入一个寄存器

写入一个铺位号

写入一个子地址

然后查一下芯片有没有ACK

再写入我要给这个寄存器写入的值

再查一下芯片的ACK

再Stop停止位

完成一次完整的操作

那么读操作比刚才要麻烦一点

因为这是一个有子地址的I2C设备

所以就跟我们前面在上个单元讲的

高阶的内容一样

那么我们完成一次读操作要分为两段

首先是一次写操作

写入芯片的地址和一个写的标志位

紧接着呢写入一个字节

这个字节是我们要写的那个子地址

也就是芯片内部寄存器的地址

哪个铺位我要进行读

然后这个操作完成了以后

芯片已经知道主机

要从我这儿读取设备

而且主机是要从我这儿

哪个寄存器读取设备

芯片准备好了对吧

这个时候主机发起一次Restart

然后再做一次新的通讯

这个新的通讯首先是一个读操作

向芯片写入一个芯片的地址

跟一个读的比特位

因为这个比特位是读

接下来的操作就是读取了

由芯片乖乖的把刚才设定那个

寄存器的值的内容

向主机返回一个字节的内容

然后主机给ACK通讯完成

这样两笔通讯中间有一个Restart

完成一次完整的对于这个芯片内

某个寄存器的读取

所以这两个函数的封装

我们用伪代码给大家写清楚它的步骤

它的起始 它的写字节

它的ACK 它的Restart

它的读字节 它的停止位

大家尝试用刚才那些代码 那些宏

可以自己把它写出来

那么如果你能写出这两个函数

也就完成了对于I2C里头

相对麻烦的

有内部地址结构的读写函数的封装

它可以用于这个加速度传感器

也可以用于别的I2C设备

你就真正掌握它了

下一个单元我来讲如何把这个I2C芯片

真正的有效值给读出来

和它的原理

ARM微控制器与嵌入式系统课程列表:

第一章 概览

-1.1 课程概览

--1.1 课程概览

-1.2 如何学好嵌入式系统

--1.2 如何学好嵌入式系统

第二章 绪论

-2.1 计算机的基本概念、发展历史

--2.1 计算机的基本概念、发展历史

-2.2 从晶体管到CPU

--2.2 从晶体管到CPU

-2.3 概念CPU、微控制器MCU和嵌入式系统

--2.3 概念CPU、微控制器MCU和嵌入式系统

-2.4 八卦计算机史

--2.4 八卦计算机史与创新

-2.5 不同领域、不同系列的嵌入式系统

--2.5 不同领域、不同系列的嵌入式系统

-2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU【习题】

--2.6 ARM历史与MKL25Z128 MCU【讨论】

第三章 MCU基础

-3.1 CPU的基本结构和运行机制

--3.1 CPU的基本结构和运行机制

-3.2.1 堆栈的概念

--3.2.1 堆栈的概念

--3.2.1 堆栈的概念【习题】

-3.2.2 堆栈的概念-头脑体操

--3.2.2 头脑体操

-3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构【习题】

-3.3.2 ARM的体系结构-头脑体操

--3.3.2 ARM的体系结构-头脑体操

-3.4.1 中断的概念和机制

--3.4.1 中断的概念和机制

-3.4.2 中断子程的概念和编程

--3.4.2 中断子程的概念和编程

-3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线【习题】

-3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制【习题】

第四章 ARM微控制器的开发

-4.1 第一种外设:IO

--4.1 第一种外设:IO

-4.2 IO外设的编程实操-点亮LED

--4.2 IO外设的编程实操-点亮LED

-4.3 IO外设的进阶知识

--4.3 IO外设的进阶知识

-4.4 嵌入式开发的基本概念与工具链

--4.4 嵌入式开发的基本概念与工具链

-4.5 嵌入式开发的进阶知识

--4.5 嵌入式开发的进阶知识

-4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)【习题】

-4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)【习题】

-E0.1 实验零 开发板的初步认识与工具链的安装

--E0.1 实验零 开发板的初步认识与工具链的安装

-E0.2 实验零 体验一个例程的编译与下载

--E0.2 实验零 体验一个例程的编译与下载

-E0.3 实验零 编写第一个程序:点亮核心板LED

--E0.3 实验零 编写第一个程序:点亮核心板LED

-E1 实验一 点灯秘籍

--E1 实验一 点灯秘籍

第五章 ARM微控制器的各种外设

-5.1 ARM微控制器外设学习概述

--5.1 ARM微控制器外设学习概述

-5.2.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编程实操

--E2 实验二 UART编程实操

-5.3.1 ARM微控制器外设:IO的中断编程(上)

--5.3.1 ARM微控制器外设:IO的中断编程(上)

-5.3.2 ARM微控制器外设:IO的中断编程(下)

--5.3.2 ARM微控制器外设:IO的中断编程(下)

-5.4.1 ARM微控制器外设:定时器的原理

--5.4.1 ARM微控制器外设:定时器的原理

-5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程【习题】

-E3 实验三 定时器中断编程实操

--E3 实验三 定时器中断编程实操

-5.5.1 ARM微控制器外设:PWM的原理

--5.5.1 ARM微控制器外设:PWM的原理

-5.5.2 ARM微控制器外设:PWM寄存器与编程

--5.5.2 ARM微控制器外设:PWM寄存器与编程

-5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

--5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

-E4 实验四 数码管显示编程实操

--E4 实验四 数码管显示编程实操

-5.6.1 ARM微控制器外设:SPI通讯简介

-- 5.6.1 ARM微控制器外设:SPI通讯简介

--5.6.1 ARM微控制器外设:SPI通讯简介【习题】

-5.6.2 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.1 ARM微控制器外设:I2C通讯简介

-5.7.2 ARM微控制器外设:I2C的通讯协议

--5.7.2 ARM微控制器外设:I2C的通讯协议

-5.7.3 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.1 ARM微控制器外设:ADC简介

-5.8.2 ARM微控制器外设:ADC基础

--5.8.2 ARM微控制器外设:ADC基础

-5.8.3 ARM微控制器外设:ADC寄存器与编程

--5.8.3 ARM微控制器外设:ADC寄存器与编程

-E5 实验五 ADC编程实操

--E5 实验五 ADC编程实操

-E6 挑战实验

--E6 挑战实验

第六章 嵌入式系统设计

-6.1 嵌入式系统的接口与设计

--6.1 嵌入式系统的接口与设计

-6.2 嵌入式系统的实例

--6.2 嵌入式系统的实例

5.7.3 ARM微控制器外设:I2C寄存器与编程笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。