- 本课程为精品课,您可以登录eeworld继续观看:
- 讲座视频 - GPIO 编程
- 登录
- 课程目录
- 相关资源
- 课程笔记
大家好,我是 Jon Valvano。
在本视频中,我们将讨论
通用输入输出接口的编程。
我们在前一个视频中看到了“连接”的概念。
换句话说,如果我在这里有一个系统,
然后我将它连接到那里的另一个系统,
那么当一个数字逻辑连接到另一个
数字逻辑时,我必须关心电压和电流。
那么,在前一个视频中,我们
讨论了该硬件互连,
硬件接口。
那么,在该模块中,
我们将讨论它的软件方面。
我如何编写这些系统上存在的软件,
以便我可以执行输入输出?
与该模块关联的
实验中的最终目标是光传感器。
在光传感器接口中,您将
看到硬件和软件。
换句话说,我们将看到与 8 个传感器
关联的电压和电流。
然后,这将为我提供 1 和 0 输入,
具体取决于它是否看到了线。
然后,第二点将是中心集成,
其中您获取这 8 个数字数
并将其合并到单个数字中,
该数字可告诉您相对于线的位置。
希望您喜欢本次实验。
该实验应该很有趣。
那么,让我们来讨论软件是怎样工作的。
对于通用输入/输出,您有两种可能的选择,
即输入和输出。
这不是很复杂。
输入意味着来自世界的
信号将进入微控制器。
我们在前一个视频中看到,如果我有一个
输入引脚并且该引脚上的电压小于 VIL,那么
该电路会将其视为低电平。
它是输入。
如果该电压大于 VIH,嗯,
那么该电路会将其视为高电平。
因此,当我们在软件中看到它时,
它将在该寄存器中为 0,或者在该寄存器中
为 1。
为了将引脚设置为输入,
我们要将其方向寄存器设置为 0。
当我们将方向寄存器设置为 0 时,它将
断开所有关联的输出物理硬件,从而
使该引脚成为输入,因为它不是输出,
它是输入。
因此,当我想进行输入时,我要将
寄存器,一个称为端口 1 的
内存映射 I/O位置中的数据
读取到该输入寄存器中,因为您应该记得,I/O 设备
划分到多个引脚中,然后
大约 8 个引脚组合在一起,形成一个端口。
当我说 P1 时,我指的是端口 1。
在这里,当我看到 P1.1 时,我将讨论的是端口 1 的
引脚 1。
初始化该端口需要执行两个步骤。
换句话说,让我们使它成为一个 GPIO。
我们通过向选定的寄存器进行写入来实现它。
我们实际上向其写入 0。
我们所做的第二件事是,我们对方向寄存器进行写入 --
0 意味着输入。
那么,正如我说过的,像大多数端口一样,
端口 1 的宽度为 8 位。
因此您可以将该寄存器,P1 视为输入,
它具有 8 位的宽度。
7, 6, 5, 4, 3, 2, 1, 0.
我感兴趣的特定位是位 1。
但还有一个选择寄存器。
选择寄存器、选择 1 寄存器和
方向寄存器有一个 P1。
因此每项操作有 4 个寄存器。
此外,还会有另一个 8 位寄存器。
具体而言,为了将 P1 设置为输入,
我需要在两个选择寄存器的位 1 位置中
设置 0,并且我需要在方向寄存器,
DIR 寄存器的位1 位置中设置 0。
我将使用该 C代码来实现它。
我将 -- 该 C 代码的作用是访问这 3 个
寄存器的位1 并清除位 1。
现在,您会注意到一件奇怪的事情 --
我是通过一种非常有趣的方式来实现它的。
再说一次,它是读取-修改-写入。
那么,让我们来看看这里的
方向寄存器。
该方向寄存器中将具有 7 个位 --
具有 8 个位。
1, 2, 3, 4, 5.
再说一次,我最感兴趣的是这个位,位 1。
7,6,等等等,2,1,0。
因此,我要做的是,我将为其添加一个
用于清除位1 的掩码,
它是 1111,1101。
当我向它添加该 FD 后,这将
导致位 1 变为 0。
这正是我需要的结果。
但是,请注意它对其他 7 个位的影响。
它完全没有更改这些位。
因此,如果我的实验伙伴要使用位 7,
我未更改他或她的方向寄存器。
我没有动它。
那么,每当您在编写 I/O
代码时仅更改您必须更改的位,
而不更改不属于您
或您不必更改的位,
我们就将该类编程定义为友好的。
这样您就可以对某个寄存器中的
几个位进行操作,而您的实验伙伴对其他位进行操作,
然后你们的两个软件可以合并在一起,
并且不会以不利的方式相互影响。
那么,我们将反复不断地看到该情况。
那么,使用输入引脚的第一步是对其进行初始化。
那么,这里的代码恰好在开头执行一次。
这会将端口 1 位1 建立为输入引脚。
但是,然后我希望实际上反复不断地执行输入。
我们将看到,由于该寄存器中有 8 个位,
每个引脚 1 个,7、6、5、4、3、2、1、0 -- 再说一次,
我只对位 1 感兴趣 --
读取寄存器中特定的一组
引脚的过程包含两个步骤。
我将首先读取全部 8 个位,
然后我将屏蔽 --
2、3、4、5、6、7 --
或者对其执行与运算,从而使结果
仅是位 1 的函数。
您可以在这里明显地看到该情况。
那么,第一步是读取全部 8 个位。
那么,我将获得该值,然后我将对它执行与运算,
然后我将在这里获得一个数字,
它将是 0000 --如果引脚
处于低电平,那么我将获得该值,
或者如果引脚处于高电平,那么我将获得该数字。
换句话说,我将获得 0 或 2,
具体取决于端口1 位 1 的状态。
现在,您可以通过包含两个步骤的过程来显式实现它,
即读取和与运算。
再说一次,这将返回 0 或 1。
或者,如果您愿意,可以将这合并到
一行 C 代码中,其中它首先将
该值临时读取到一个
寄存器中,然后执行掩码运算,
即选择,以获取
我感兴趣的位,然后返回该 0 或 2。
现在,如果您的编译器功能良好,
那么这部分 C 代码和那部分 C 代码
实际上将生成完全相同的机器码,因此
使用一种方法或另一种方法
没有任何速度优势。
因此,您可以选择这两种
方法中您感觉最易于了解实际
发生的情况的一种。
那么,这是输入。
那么,再说一次,输入会将数据引入到处理器中。
现在,要进行输出,我必须做相同的两类事情。
我要将同一程序恰好执行一次,
这会将引脚建立为输出,
然后,我将反复不断地根据需要
进行输出。
那么,我要执行的示例是,我有 P1,即端口 1,
现在位 0 将是我的微控制器的一个输出。
因此,我需要能够将其设置为高电平或低电平。
再说一次,我们曾在前面的一个
讲座中看到,如果这需要是高电平,
那么这里的电压将大于 VOH。
因此,如果数字 1出现在这里,即
布尔高电平,那么该电压将上升到接近 3.3 伏。
如果您需要使其成为低电平,那么
这里的软件将使其成为低电平,
但硬件将在该点建立电压,小于 VOL。
然后,再说一次,只要该输入或输出设备上的
电流小于 6 毫安,那么一切就没有问题。
您应该记得有这个选择寄存器,
0 意味着常规。
那么,再说一次,我们将使该引脚成为常规引脚。
这恰好要清除位 0。
我们在前一张幻灯片中看到,输入引脚方向寄存器为 0
意味着输入。
但我们需要输出,因此我们将设置该位。
那么,再说一次,这是对方向寄存器
进行读取-修改-写入,这将设置位 0,从而
导致端口 1位 0 成为输出。
这全部三项操作都访问一个 8 位寄存器,但仅
修改位 0。
换句话说,它们仅修改
需要修改的位,而不更改其他
7 个位,它们不是这里的规范的一部分。
我们要将这称为友好的。
然后,您可以在这里看到
初始化,几张幻灯片之前的
初始化可以在完全不相互影响的情况下
分别进行。
那么,这个将访问位 0。
另一个访问位 1。
任何一个都不会破坏另一个人的初始化。
那么,这是初始化。
再说一次,我们恰好可以将其执行一次。
我们要做的下一件事实际上是进行输出。
正如我说过的,您将进行写入,如果您对端口 1 进行写入,
位--
哦,就像那里的那个。
如果您对端口 1进行写入,对于
作为输出的引脚,这将设置或清除位。
现在,它恰好是输入引脚,因此不会执行任何操作。
但对于输出引脚,它将变为高电平或低电平。
但我们希望通过友好的方式加以
实现,因为在本例中,
我们只能访问或需要修改
端口 1 位 0。
那么,我们将通过一个包含四个步骤的过程来实现它。
我们将首先读取全部 8 个位。
换句话说,我将读取
我的实验伙伴在他或她的寄存器中剩余的位。
我将屏蔽我将最终更改的位。
我将设置或清除我想更改的位。
在本例中只有 1 个位。
然后我要写回整个内容,从而
再次修改整个 8 位端口,但再说一次,
仅更改我拥有的位 --在本例中,仅更改位 0。
因此,我们将在这里看到该步骤。
那么,在这里,我要将全部8 个位读到一个局部变量中。
我将屏蔽、清除我要最终更改的位,
然后我要将原来的位,
即我的实验伙伴留下的其他 7 个
位与我希望修改的这个新位 -- 它来自
我的函数 --
进行合并,从而使这里的运算
现在包含我希望更改的 1 个位和
我不希望更改的其他 7 个位。
因此,当我再次将它写回时,
我将仅更改这 1 个位。
现在,我要提醒您,这里的代码行不会
更改输出。
您可以看到,old是一个局部变量。
那么,当我清除和设置某个变量中的位时,
不会对外部世界产生任何影响。
仅当我将该合并的内容写回到端口 1 时,
才会输出实际的位变为高电平或低电平的寄存器,
正如我所指定的。
再说一次,该包含四个步骤的序列是一种用于实现友好
代码的方法。
现在,您可以通过该方法显式写出
这四个步骤,您也可以通过 1 行 C
代码来写出它们,其中它在这里读取值,它清除
我将最终更改的位,
我更改我想更改的位,然后我将其写回。
那么,事实上,这里显式提供了全部四个步骤,
但它在我的 C 代码行中。
再说一次,如果您的编译器功能良好,
这个函数和那个函数将生成完全
相同的机器码。
换话句话说,它们将以相同的速率
和相同的速度执行。
那么,我们选择对您更有意义的一个。
再说一次,对于某个输出引脚,我们对其进行初始化,
然后每当我想更改它时,我会
执行这个函数,这将设置 LED。
或者,我会执行这个函数,这会
清除 LED。
那么,再说一次,我可以在更高的
级别打开和关闭与端口1 位 0 相关联的 LED。
让我们来执行一个示例。
这个恰好是负逻辑,因为
这里有一个灯泡。
那么,这是一个常规120 伏交流灯泡。
那么,这是电源线。
这是灯泡。
那么,我有某种电器
设备,我要使用我的微控制器来控制它。
我将使用一种称为固态继电器的设备,
它在输入端用作一个可选接口。
那么,它的工作方式是,如果这是
高电平,您知道,如果是3.2 伏,那么所发生的是,
该 LED 现在是暗的,该开关断开,您将
在它周围放置一个框,然后
这里的电器将关闭,因为没有电流,因为
开关是断开的。
但是,如果我发送一个低电平,0.1 伏 --
我将在这里放一个圆圈 --
那么光线将进入这里的 LED。
这将使开关闭合,因此现在电流将流动,
该电器将打开。
电灯打开,电机旋转,
无论我们要做什么,在这一点上,
该微控制器都可以影响它的世界。
这称为固态继电器。
它没有那么复杂。
但是,如果您看看与它相关联的软件,
它看起来就像另一个 LED。
在本例中,我恰好使用了 20 毫安
输出引脚之一。
MSP432 上有 4 个可以生成 20 毫安的引脚。
我将通过友好的方式清除该位,
以便它成为一个常规位,而不是交替位。
我将使它成为一个输出。
很显然,它是输出。
信息将沿着这个方向传递。
它是一个输出引脚。
但我可以添加另一个步骤,将该引脚的驱动
强度设置为高,以便该端口现在可以拉取
或同步高达 20 毫安的电流。
那么,这几乎可以驱动我要连接的
任何固态继电器。
那么,当我想打开灯泡时 --
再说一次,要友好一些 --
我将使用读取-修改-写入来清除位 3,因为它现在是
负逻辑,您还记得吧?
0 使其变为低电平,但灯泡会亮起。
这就是我将其称为负逻辑的原因。
然后,如果我想将灯关闭,那么
我就将端口引脚设置为 1,从而使电压变为高电平,
LED 将熄灭,电器将关闭。
那么,再说一次,该软件具有两个组件。
您应该注意到抽象。
我们已经完全抽象出了我们实际上绑定到端口
2 位 3 的性质。
我们已经抽象出了这样一个事实,即它是负逻辑
并且它的驱动强度为 20 毫安。
那么,从另一个观点而言,我们
具有一个简单的功能,如打开灯
或关闭灯。
它就是这么简单。
这是您可以在实验室中实现的功能。
当您开始进行实验时,您将看到它的细节。
但您将具有输入和输出。
那么,所有这些电阻器和电容器
都内置到实际传感器中。
那么,除了将 3.3,将该引脚通过导线连接到那里,
将那个引脚连接到那里,以及将这个引脚连接到
那里,这些有 8 个。
那么 8,9,10,11 --我们现在有 11 个
引脚,我们要连接它们,从而使该线传感器正常工作。
我向已经您展示了这些传感器之一。
但我现在想讨论的是 GPIO。
关于 GPIO,您知道些什么?
引脚可以是输入或输出。
那么我们要使端口5 位 3 成为输出。
您知道如何实现它 --方向寄存器,选择
寄存器等,清除选择寄存器,
将方向寄存器设置为高电平。
您将使端口 7 位0 成为高电平。
我们再次将其方向寄存器,
将其选择寄存器设置为 0,然后向
数据寄存器或输出寄存器输出 1。
我们将等待10 微秒 --
它是一段很短的时间 --
以 48 兆赫兹的频率运行它 --
这是 480 个总线周期,因此它是一段很短的时间。
然后我们将做一件奇怪的事情。
这个用作输出的引脚
现在将成为输入。
这些有 8 个,抱歉 --
这些有 8 个,这些有 1 个。
那么,这是 P7.7,P7.6。
这些有一组。
那么,这些有 8 个,这些有 1 个。
是的,有 1 个灯,8 个传感器。
是的,好了。
我们将切换该引脚,使其成为一个输入。
这个引脚,正如您看到的,将保持 10 微秒。
该引脚是一个输出,就在这里。
该引脚是一个输出。
然后,我们将做的是,将其切换回输入。
请注意,这不是按比例绘制的,因为这里的距离
是 10 微秒,而那个距离是 1 毫秒。
因此它不是按比例绘制的。
我们将等待 1 毫秒。
请注意,这是很多总线周期。
这是 48,000 个总线周期。
然后,我们将读取该引脚。
根据您在该传感器下方看到的是白色
还是黑色 --
如果您看到白色,它会更快地放电。
然后,当我读取时,我将获得 0,
相反,如果我具有黑色,那么当我读取它时,
我将看到 1。
因此,如果我在 1 毫秒时读取它,那么这将返回 0,
而那将返回 1。
那么,通过这种方法,您将能够
在您的机器人的底部询问您的
机器人是否位于线上。
为了节能,在该 1 毫秒之后,在我读取它之后,我们
要将该引脚设置为低电平。
这将关闭该灯,从而可以节能。
因此,我们将仅驱动该 LED 1 毫秒。
事实上,如果我每 10 毫秒驱动
该传感器一次,那么我们要将它关闭 9 毫秒,
然后我们将重新执行该操作,反复不但地执行。
因此,我们在这里进行该实验的目的 -- 很显然,
您将使用线传感器
使机器人感应线,但正是通过该传感器,
您可以实际看到输入引脚、输出引脚、
等待时间。
那么,这是一个您需要连接的很有趣的传感器。
具体而言,您可以通过它
了解 VIH 的概念,VIH 是一个电压,当高于该电压时,它可在 VIL 中
感应到高电平,VIL 也是一个电压,当低于该电压时,
会将该引脚感应为低电平。
对于该传感器,您必须了解
该特性。
总之,我们将实现 GPIO。
事实上,它们无处不在。
在本节课中,我们将在各种情形下
看到 GPIO。
本实验将使用线传感器,但
我们的碰撞传感器将是 GPIO。
一个输出引脚将设置我们的电机方向 -- 我们
是要前进还是后退?
如果您在实验 11 中实现液晶显示器,
您将看到会采用 GPIO。
您的转速计输入引脚将是 GPIO。
如果我们有一个超声波传感器,它将具有 GPIO。
蓝牙引脚具有 GPIO。
Wi-Fi 模块具有 GPIO。
因此,它实际上在本课程中无处不在。
我们将在本实验中实现一个非常简单的此类引脚。
希望您喜欢本次实验。
它比较有趣。
课程介绍
共计4课时,51分28秒
猜你喜欢
换一换
推荐帖子
- 基于Proteus的MSP430单片机仿真实例19-D/A转换之正弦波发生器
- 此内容由EEWORLD论坛网友tiankai001原创,如需转载或用于商业用途需征得作者同意并注明出处 一、任务要求利用MSP30F247单片机作为控制器,实现正弦波信号输出,最大值正负5V,频率50Hz。。二、硬件电路硬件电路如下图所示。输出最大值正负5V正弦信号,运放电路采用两级设计,第二级为加法电路,可实现双极性输出。三、程序设计//main.c#include "msp4...
- tiankai001 微控制器 MCU
- 输出电压纹波来源和抑制
- 作者: Yuan Tan 医疗设备、测试测量仪器等很多应用对电源的纹波和噪声极其敏感。 理解输出电压纹波和噪声的产生机制以及测量技术是优化改进电路性能的基础。 第一部分:输出电压纹波 以Buck电路为例,由于寄生参数的影响,实际Buck电路的输出电压并非是稳定干净的直流电压,而是在直流电压上叠加了输出电压纹波和噪声,如图1所示。 图1. Buck 输出电压纹波和噪声...
- qwqwqw2088 模拟与混合信号
- 【Launchpad 心得】我与430的故事
- 【Launchpad 心得】我与430的故事 我不敢在这里班门弄斧讲些专业性的知识,我只说一下我和430的故事 我还是一个在校学生,一次偶然的机会我认识了EEWORLD,那个时候还在还在玩51单片机,我知道我自己的基础不好,我整天的逛论坛,后来自己进了我们学校的重点实验室,跟着老师做些东西,单片机也很快上手了,再也感觉不到有那么难了。 今年的5月份正在准备学习新的单片机,那时候一直在考虑是学...
- 海盗郭兆广 微控制器 MCU
- 请教pmsm的FOC中转角计算的一些问题
- 这是MATLAB官方demo里基于模型设计的例程,用QEP和QEP_index来计算出了position。 实在看不懂这个计算过程:'(:'( 有没有大神帮忙解释一下,跪谢!! ...
- 后小弦 微控制器 MCU