当前课程知识点:智能车制作:嵌入式系统 >  第四章 MCU外设与开发 >  4.3 IO外设的进阶知识 >  Video

返回《智能车制作:嵌入式系统》慕课在线视频课程列表

Video在线视频

Video

下一节:Video

返回《智能车制作:嵌入式系统》慕课在线视频列表

Video课程教案、知识点、字幕

各位同学大家好

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

欢迎大家回到我们ARM微控制器与

嵌入式系统的慕课课堂

我们在第四个章节里

前面两个小段已经分别学习了

IO模块的基本概念原理方法

以及在我们KL25这样一个具体型号里

它所涉及到的寄存器

如何通过一个简单 三个步骤的编程

把八个灯给点亮

了解了编程的模型和方法

那么这个小节呢

我们会在这个基础上

再对于IO的日常使用

进行一些更进一步的探讨和学习

我们学习了如何通过简单三个步骤

若干句简单的C语言语句编程

来把这八个灯给点亮

那大家会觉得 哇 小菜一碟

接下来我们还要再看一下

IO在使用当中不是那么小菜一碟

或者稍微比看上去

要复杂一点的一些注意事项

比如说最最简单的在点灯这件事儿上

我这两张抽象的图

省掉了当中的限流电阻

但大家最直观的一个感受是

我们LED发光二极管的接法是一正一反

大家都会觉得从引脚连接一个

LED的阳极直接接地

这样一种正向的连接

是比较符合很多初学者的感觉的

我用一个引脚来驱动一个LED

给高电压 灯就亮了

给低电压 灯就灭了

为什么老师给的例子里头

要把LED倒过来接

从电源接阳极

再通过限流电阻到我们的IO

让IO输出高电平的时候灯灭

IO输出低电平的时候灯亮呢

这是一个问题

其实在我们数字电路漫长的发展历程里

很多数字器件和它的引脚

拉和灌电流的能力是不一样的

也就是对外输出电流

对内灌入电流的能力是不一样的

很多时候

灌电流的能力要大于拉电流的能力

也就是说更善于向内输入电流

而在我们所使用的这样一个微控制器

我们刚才看了它的手册

不知道大家还记不记得

它对内对外输出电流

也就正向和反向电流的局限

都是25个毫安也就是这样的微控制器

在他的IO引脚上专门做了强化

增加了电流的驱动能力

所以25个毫安点亮一个LED

无论正或者反都是绰绰有余的

有的同学会说

我不知道点亮一个LED要多少电流呢

这就是我们在电子学上一个长期的积累

我们一般在这样的弱电电路里头

我们的VCC

比如我们系统是3.3伏

那么我们的限流电阻一般在百欧到K欧量级

所以我们这个二极管的

流过的电流一般就在毫安量级

电流大一点二极管就亮一点

电流小一点二极管就弱一点

但是呢我们的电流不能超过这个

发光二极管的额定功率或者额定电流值

那么是不是在我们这样一个

微控制器上这电流就随便接了呢

不是

记不记得看芯片手册的时候我给大家提示

注意过另外一件事儿

就是我们这个芯片的VCC 3.3伏引脚供电

有个最大的供电电流值是120个毫安

也就说如果我们采用第一种接法

由引脚来直接驱动发光二极管

所有的电流都需要通过

我们芯片的电源芯片

来统一的由芯片内部获得

所以这些电流都会叠加到

我们的电源引脚所获取的电流上

而那是有120毫安的总限值的

所以基于这些考虑

考虑到芯片的发热

我们会更多地使用

反着的这样的连接方法

这是在我们设计包括智能车 机器人的

很多类似电路当中

同学们往往会忽略的

所以说数字电路和嵌入式系统

一定不要仅仅站在编程的角度去理解

一定要抠它的电路的本质和原理

第二个方面呢 是我们在用IO

获取一个外部量的时候

比如说一个按键有没有按下

一个量是零还是一

我们往往会把它觉得很理想

得到零就是零 得到一就是一

而在现实生活当中往往不是这样

从比较慢的尺度来看

两类现象我们都可以体验过

一个呢是我们的手机一响

经常会旁边的喇叭发出干扰

哗哗声 对不对

那么我们的电子学器件

往往是生活在一个复杂的电磁环境里的

我们引脚上的电信号

经常会受到周围电磁波的干扰

产生短暂的这种干扰信号 零或者一的跳变

这些跳变如果被我们的IO引脚错误的拾取

那么会引起我们对一些控制信号的误判

其次呢在我们一个简单的按键

这样一个操作

人对机器的输入的时候

有很多同学做了一个简单的按键的程序

最后跟我说老师这个电路不好

这个按键不灵

为什么呢

因为按下去以后程序没有让

他期望的一按发生作用

这个时候我们会发现

因为我们的按键是一个机械元件

它是由一个弹簧金属片的按下

和弹起来发挥作用的

而这样的机械金属片

它往往无法做到干净利落的由一变零

由导通变断开

而是会产生若干次机械的振动

这些振动会形成时间持续较短

但是对于计算机的视角

注意计算机的视角

一个时钟周期在纳秒微秒尺度看来

是持续了一个足够长时间的若干次跳变

那么这样若干次跳变

如果我们的程序写的不合适

每一次跳变都会被识别为一次按键

所以大家会发现

按键时灵时不灵

为什么呢

如果跳变了奇数次

你的程序正好发挥了作用

如果跳变了偶数次

你的程序比如点个灯

它就可能体现为 什么都没做

因为偶数次归零了

那么像这样一些我们

称为glitch 称为干扰的这样一些东西

是我们在IO使用当中要注意的

还有一类注意的事项呢

就是我们如何去掉这样一种干扰

我们往往会采用硬件和软件的方法

硬件去掉这样的跳转

我们最容易想到的是什么

是加入一个RC电路

使它的电压无法迅速的快速的

发生零到一的多次变化而只能渐变

那么我们往往会在我们的按键电路

不像我们上节课所看到那么简单

只是一个电阻加个按键

而是像图中这样加上一些RC

加上一些单稳触发

来实现硬件的去抖

那么软件的去抖呢

我们往往会考虑真正产生

这个信号的物理机制是什么

比如说我们按健是一个人的输入

大家想想人的反应在什么尺度上

如果没有概念的同学可以想想膝跳反射

敲下你的膝盖你什么时候会产生反应

对于一个人

他可能在百毫秒尺度

而对于一个树懒

它可能在分钟尺度

我们的输入决定了

我们的物理量的大小

那么一个人输入无论如何多快

在十毫秒尺度不可能发生若干次

所以我们可以在检测到了

一个跳变的信号的时候间隔

五毫秒 十毫秒再检查一次

这个值是否仍然存在

因为人按下键在十毫秒之内肯定来不及松开

通过这样的方法

我们可以过滤掉一定

时间长度以内的干扰信号

这是一种软件的方法

日后我们如果学习了信号与系统的概念

我们会发现

我实际上是做了一个时域

或者频域上的滤波

等效于RC电路在硬件上所做的事情

这就是数字电路和嵌入式开发里头的本质

那么站在一个更快的角度

我们往往会想要用IO

或者用IO引脚衍生出来的时钟模块

这些功能来对一个周期跳变的

信号进行计数或者检测

这个时候我们会说

如果这个输入信号的频率过高的时候

使用IO不一定是个好方法

或者换一句话说

用IO做这样的事情的时候

我们一定要考虑

这个频率和周期是多少

我们有同学说做智能车

做智能车的时候

我们用一个霍尔元件去检测轮子的转速

轮子每转过一下会产生一个脉冲

说这个速度测的不准

数到的脉冲数远低于轮子真实转过的圈数

为什么呢

检查会发现 哦

因为这个轮子

通过霍尔元件产生的脉冲太窄了

那么这就回到我们最最本初的一个概念

就是在嵌入式系统里头

我们每个模块都是一个数字系统

它是在一个时钟驱动下的

所以我们引脚上的电压

只能在一定的时钟频率下

被刷新到我们的寄存器

那么这样一个最小的时钟周期

最快的这样一个频率

就是我们这样一个IO模块

工作在一个特定频率的

微控制器里头的极限

所以当我们产生的输入信号

至少要大于这么一个时钟周期的时候

才能体现在我们的寄存器里

而在我们寄存器里这个值

所体现出来的最小时间间隔

也至少是一个周期

换言之这个值变成一或者变成零

在寄存器里至少维持一个周期的时间

那么其次呢

如果这个信号真实存在的时间

比我们的最小时钟周期还要短

就跟这个图当中所示

它就压根不会体现在

我们这个寄存器上

我们就会漏记

如果我们使用IO

我们在寄存器里

看不到这样一次值的跳变

如果我们使用这个微控制器的计数

或者脉冲计数这样的模块

我们会发现数出来的数就比它短

这也是我们需要考虑的

那么这样一个时钟周期的极限值

在哪可以找到呢

在我们所使用的任何一款芯片

它的电气特性指标的

这个参数表里一定会给

然后除掉这些

我们的IO模块

不仅仅可以通过寄存器被动的去读取

我们在前面学习中断的原理的时候

我们会说很多的编程会工作在

轮询的模式和中断的模式

我们反复读寄存器

看寄存器所体现出来的这个

IO的值有没有发生跳变

这叫做轮询

那么实际上我们的IO

也可以工作在中断方式

每当IO上的状态值发生了变化

产生一个中断主动的通知CPU

来查询这种中断

调用程序做相应的处理

这样的话

就工作在了中断方式

对于数字IO

它可以工作在若干种

中断源产生的中断方式

我们可以在这个IO引脚

每当产生上升沿

也就是电压由零变一的时候产生中断

也可以让这个IO引脚

在下降沿由一变零的时候

或者是Both Edge 上升沿和下降沿都发生中断

或者是用电平触发

当它为高电平或者

为低电平的时候产生中断

那么这些东西在哪里设置呢

首先我们一方面要对照我们的芯片手册

找到它的中断源 中断号

以及对应的中断编程的注意事项

其次呢

就在我们刚才所讲的

每一个引脚对应的PORTx

比如说PORTD PORTA_PCRn

比如说PCR0 PCR1 PCR3

这样一个每个引脚对应的

这个寄存器里可以配置

在哪呢

在上面的16到20这四个比特

可以进行我们中断源的配置

使用DMA或者使用不同类型的

上升沿下降沿触发的中断

那么对它进行配置加上我们之前讲过的

中断的向量表中断函数的若干的设置

我们可以对任意一个引脚

工作在中断模式

当外部的信号发生变化的时候

自动调用一个函数来完成编程(功能)

那么在我们所使用的Kinetis (Cortex M0)这样一个

MCU里头

这样一个微控制器里头

具体到KL25这个型号上

所有PORTA和PORTD的引脚

都是具有中断的能力的

那么More and Better我们再来讲讲更多的

我们刚才在编程里头有很多高阶的

有兴趣同学会认真的揣摩老师给的程序

会给我挑刺

说老师你说我们一个方向寄存器

和一个赋值寄存器

管了32个比特

对应32个引脚

对它统一进行赋值是不好的

所以你告诉我们在初始化的时候

方向寄存器用或 赋值寄存器

也就是PDOR寄存器用与

分别想办法让它的最低八位

只变成一

和只有最低八位变成零

来实现只对最低的八个比特赋值

前24个比特不变

但是到了循环体里

你这句话写的并不够漂亮啊

你是直接把这个寄存器

整体读出来32个比特取反赋回去

那除了这八个灯每次一起亮或者灭

那前24个引脚的值不又是变了吗

对 所以呢

如果我们在编程的角度

要做只改变后八位的值的话

我们需要把这个for循环写得更加的复杂

是不要写if和else的判断语句来把它做的更完善

这是聪明的同学或者细心的同学

注意到的非常好的一个事

那么我现在要讲的是在微控制器设计的时候

也给我们留出了这样的寄存器

让我非常简单地用单指令

能够完成这样的操作

那是哪几个寄存器呢

就是在一开始

我所讲的标灰的这三个寄存器

作为高阶的使用

它们分别是这个PORT的翻转寄存器

SET赋值寄存器

和Clear清零寄存器

那么这三个寄存器非常的简单

我几乎用一句话就能讲完

比如PSOR寄存器 GPIOx的Port Set Output Register

它就有32个比特

对它进行读操作是忽略的

对它进行写操作

任何时候对它写一

就会使它对应的引脚变成一

而对它写零 是对应的引脚的值不发生改变

注意这是不一样的

写一变成一 写零不发生改变

所以我们希望最低八个引脚变一的时候

是不是我们对它进行

最低八个引脚写一

前面二十四个引脚写零

前面二十四个引脚的值就没有变

与之呼应的PCOR寄存器Port Clear Output Register

是对应的比特写一

那么对应的引脚就会清零

注意写一清零

而对应的比特写零的时候

对应的引脚的值不发生改变

换言之你希望把哪个引脚上的

电压变成零电压

你对应的比特

赋一就可以了

那么对于我们刚才的翻转

这好像还不够方便

没关系 还有第三个寄存器

叫PTOR寄存器Port Toggle Output Register

它的定义是32个比特里头

对应的比特写一

使这个比特所对应的引脚上的电压值

在原来的值基础上进行一次翻转

由一变零 由零变一

而你希望不改变的引脚

它对应的比特写零就可以了

有了这个寄存器

刚才我们所说的那个编程非常简单

只用给这个寄存器赋上一个

多少0x0000 00FF的值

前24个比特是零

最后八个比特是一

那么就能在每一次的循环里头

只让最后八个引脚进行翻转

一个语句漂漂亮亮地完成了这件事儿

编程的时候会非常的舒服

那么有一些有洁癖或者有瑕疵的同学

很多程序员都有洁癖 对不对

会说老师那我觉得还有个很别扭的事情

我用了八个引脚

刚才的这个PORTx_PCRn这个寄存器的语句

我就得写八遍 每一次 每一句

都要定义这个引脚的值

当哪个功能用

当一号功能用 能不能简单一点

答案是也是可以的

在我们对应的这个模块

我们芯片手册的177页里头

除了PORTx_PCRn这个寄存器

还有PORTx_GPCLR

和PORTx_GPCHR这两个寄存器

它们各能管十六个引脚的集中配置

对于它们的功能

我在这里就不展开讲了

有兴趣同学可以到指定的页面

看这个芯片的英文说明

锻炼阅读英文的能力

学会如何用一句话完成八个引脚的功能配置

那么IO模块的高阶讲解呢

到这基本上就结束了

所以呢 我们学习了IO的使用

也能完成花样的点灯

那么在后面的环节

我会花几个小节 以它为例来讲

微控制器开发的开发工具

和一般性的开发方法

更重要的是深入理解

我刚才给大家讲的

那些看上去很简单的c语言

赋值语句背后的含义是什么

最后呢

我们会动手实践

来把按键的功能 引脚的功能

组合使用起来

玩一些好玩的程序

那么在后面几节课

我会给大家讲解

今天的课就到此结束

智能车制作:嵌入式系统课程列表:

第一章 概览

-1.1 课程概览

--Video

-1.2 进入嵌入式系统的世界

--Video

-1.3 如何学好嵌入式系统

--Video

第二章 绪论

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

--Video

-2.2 从晶体管到CPU

--Video

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

--Video

-2.4 八卦计算机史

--Video

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

--Video

-2.6 ARM历史与MKL25Z128 MCU

--Video

第三章 MCU基础

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

--Video

-3.2.1 堆栈的概念

--Video

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

--Video

-3.3.1 ARM的体系结构

--Video

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

--Video

-3.4 中断的概念和机制

--Video

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

--Video

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

--Video

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

--Video

第四章 MCU外设与开发

-4.1 第一种外设:IO

--Video

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

--Video

-4.3 IO外设的进阶知识

--Video

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

--Video

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

--Video

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

--Video

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

--Video

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

--Video

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

--Video

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

--Video

-E1 实验一 点灯秘籍

--Video

第五章 MCU与嵌入式系统设计

-5 智能车视角的嵌入式设计

--Video

Video笔记与讨论

也许你还感兴趣的课程:

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