当前课程知识点:智能车制作:嵌入式系统 > 第四章 MCU外设与开发 > E1 实验一 点灯秘籍 > Video
各位同学大家好
我是清华大学工程物理系的曾鸣老师
欢迎大家继续回到我们
ARM微控制器与嵌入式系统的课堂
那么我们开始进行我们真真正正的第一次实验
在这次实验里呢
我们接着上次第零次实验那些小小的体会
真真正正把我们学的第一类外设IO给用起来
来点灯 来各种点灯 来花式点灯
那么作为实验的一个良好习惯
我们一般首先先回顾一下
这次实验所涉及到的知识内容
从我们这门课的范畴来讲
这节课用的是第一类最简单的外设
就是我们在第四章第一节学的IO这一类外设
那我们所用到所有的寄存器的知识
和编程所用的内容呢除了在这门课里
我希望大家学会看我们的芯片手册
那么本次实验的内容
都在我们MKL25Z128的Reference Manual
这个芯片手册的第11章、第12章
和第41章这三个章节
分别讲了物理的引脚以及这些引脚怎么配置成IO
以及IO的寄存器他们的含义
都可以在这三个章节找到
那么我们来看看我们的实验任务
其实在第零次实验里我们做了一个非常小的任务
有一个灯在核心子板
也就是在我们开发板的背面
接在了一个引脚
叫这个LEDTEST也就是PTB0
PORTB的第0个引脚上
我们通过写一个小程序
曾老师给了大家一段delay的函数
我们尝试着去写这个main函数写几段代码
配置这个引脚当IO用
配置这个当IO用了以后是输出
配置了它的初值
当然前面其实把它时钟打开
最后在delay函数下定时翻转
最后我们看到了这个引脚上电压忽高忽低
看到这个灯亮和灭
我不知道大家还有没有印象
那么写出来的程序就是像这个样子的
我希望大家不是照着它copy或者敲进去
而是一句话一句话对照我们课件理解他的含义
那么在真真正正的实验一里头
我们要把我们这块开发板正面下方
那4个绚丽多彩的LED
教大家一点一点的把它给点亮和玩起来
我们看看这个LED灯的电路
大家一看会觉得很晕很复杂
但实际上你静下心来看你会发现并不是那么复杂
在电路图里所有这个英文的这个字符串
这个net名是等价于引线的
它接到我们一个又一个的单片机IO引脚上
所以我们会发现左侧接了三个独立的IO引脚
PORTB两个引脚
PTC9一个引脚
右侧接了四个独立的IO引脚
PTC12、13一直下来
一共是四个PORTC的引脚
那么这些引脚往里头走
中间区域大家很明显会看到有四个块
每个块画了红绿蓝三个颜色的LED
对 在我们这个板子上
大家看到有四个灯
其实这四个灯比较高级
每个灯里都是红绿蓝三色
它们可以分别点亮
也可以一起点亮
所以分别可以形成红绿蓝、红加蓝、绿加蓝
红加绿不同的组合颜色达到七彩的效果对吧
那么一共实际上看着是四个
实际上是有三四一十二个LED要被控制
而我们实际上从控制上来讲
会发现他们每个都串联了一个电阻
而这张图的右边
一组一组的三色LED
他们的阳极是在一起
通过了一个起着开关作用的
场效应管被一个IO所控制
所以右边每一个IO
控制一个独立LED的模组的阳极是否有电
然后每一种颜色到了左边
所有的红色 所有的绿色
所有的蓝色被串接在了一起
接到了左边一个独立的MOS管、场效应管
然后有一个IO来控制
所以大家会发现这是节约了IO
这个电路图并没有想象中复杂
四个IO控制这四个模块的阳极是否有电
左边三个IO控制这每个模块里头的红色
绿色、蓝色是否在阴极导通
也就是它们的组合形成一个回路的时候
对应的那一个灯就可以点亮
所以3乘以4可以刚好控制12个LED是否发光
就这么个简单的道理
那么在右侧的IO
因为MOS管的型号
它是以低电平控制表示导通也就逻辑0
而在左侧这三个IO是高电平表示表示导通
也就是逻辑1表示这个开关导通
能够点亮
所以我们在左侧设1
右侧设0的时候就会有一个回路
导通是一个灯点亮
那么我们来看看我们的任务
第一个任务
把我们板子上 头两个LED像这样闪烁起来
大家注意颜色是红色的
也就说我们希望
让头两个LED的红色灯同亮同灭的闪烁
那么我们读一读我们上一页
或者刚才看到的电路图会发现
头两个模组分别他们的阳极是由PTC12
和PTC13来确定的
而他们的红色串联到一起
是由左下角的PTC9来控制
所有的红色灯的阴极是否导通
所以这三个引脚配合
就能控制头两个灯的里头的红色是亮还是灭
所以这个提示已经很清楚了
所以我们跟刚才那个实验零里头小任务类比
是不是我们就要编程把PTC9、PTC12
和PTC13这三个引脚
PORTC的时钟打开
引脚当成IO用
IO设成输出模式
然后根据亮和灭的需求
让他们分别输出0或者1
并且在delay函数的下面循环起来
我们来写这个程序
涉及到的寄存器就是GPIOC_PDDR方向寄存器
和GPIOC的PDOR数值寄存器
所以我给大家一个代码的框架
还是给了大家一个delay函数
每次耽误大概半秒钟
main函数该怎么写呢
是不是就是刚才我说的那几个步骤
所以我建议大家看到这里的时候暂停一下
然后自己在程序里
在CodeWarrior里头在那个main函数里头
把代码写出来
去调试 去编译 去尝试
任何的知识和调试的知识自己通过编写写出来的
自己通过debug找出来错误提升的经验
比老师给你的要好100倍
那么涉及到MOOC课的形式呢
在下一页我会给出这样一个程序的例程
有困难的同学或者已经做完同学
可以跟他加以对照 接着往下看
那么我们最终给出的代码
能是这个样子的
我们打开时钟 指定为IO用
给他们分别赋上初值
这几个寄存器的初值用与或关系
为什么是刚好赋成我们要的值
希望大家认真读懂和电路图对应哪个比特置0了
哪个比特置1了
然后在这里我就不展开讲
然后我们在底下的for循环里头
有个delay 有个整个GPIOC的翻转
也就所有的开关是你高我低
导通状态
那一翻转就两边都关了
再一翻转两边都开了
是不是实现这两个灯同亮或者同灭呢
那么我们将我们写好的程序烧写到这个板子当中
点一下运行
就能看到两个小灯开始了同时的亮和灭的闪烁
好我多问一个问题
也是后面几个实验大家会遇到的问题呢
就这个代码是否完美
还可以怎么修改 我给点提示
就是可能在for循环里头
那几句话写的还不够漂亮还不够严谨
那么有兴趣同学或者有能力同学可以再想一想
那么实验2 实验2的任务稍微变了变
还是这两个灯
我们的任务变成了要让这两个灯交替亮灭
你亮我灭 你灭我亮
这个任务好像有点不一样了
我们回忆一下刚才那个电路图
控制红色的是左下角的阴极对吧
然后控制阳极的每一个模组有PTC12
和PTC13两个引脚分别控制
那么因为在任意时刻都至少有一个红灯亮
所以这个时候那个PTC9共同的那个
红色的阴极的那个引脚就得一直保证开关是导通的
就不能变了
而这两个灯谁亮谁灭
主要靠这两个模组各自阳极的那个IO
谁高电平谁低电平来切换
是不是这么一个思想
所以我教大家的一件事情是你要把你要做的功能
慢慢的抽象成对引脚
对电路时序的操作 再锻炼一种能力
把这种引脚和电路的操作
再抽象成程序的语言把它写出来
这就是开发的过程
那么我们有了这么一个思想
我们再来想想在刚才的程序上
我们怎么来对照这个电路图修改我们的程序
让左下角一直导通
让右上角让两个模组分别有电没电
导通不导通
那么我们程序
我给大家一个例程对吧
说我们同样还是时钟打开指定为引脚用
然后IO配置方向和初值
然后我给了一个全局变量
或者叫局部变量叫bLED
它只有两个值
0或者1 或者0或者非0
在for循环里逐次翻转
那么当bLED为1的时候
你亮我灭给PORTC赋个值
当bLED为0的时候
我灭你亮给PORTC再赋一个值
这样子在delay的驱动下来回循环
是不是实现了这两个灯
亮灭亮灭之间来回变换啊
这是一种写法吧
那我想问大家的是
除了这个之外还有别的写法吗
或者在想法上跟他有点不一样
或者说比他更简单一点
大家想一想
那么有的同学可能会自己开始尝试
开始编程 这就是编程的魅力
同样的问题每个人的实现是不一样的
那么有的同学如果我不给他例程
他上来写可能会写成这样
说老师我很简单啊
你这两个灯一个亮一个灭
我更简单的写法是
给他们的赋的初值就是一亮一灭的
我之后每一次
只要在for循环里头delay然后给PORTC翻转一下
你亮的变成我灭 我灭的变成你亮
我只用给初值两个不一样不就OK了吗
这是一个非常好的想法
但是大家注意的是不要忘了
在这个for循环这个翻转后面要加这么一句话
GPIOC的PDOR寄存器
跟1左移9位或了一下
为什么呢?因为电路图里
PTC9管的是我们两个LED
共同的阴极的这个电源的导通
我们不管阳极这边怎么翻转
一定记得PTC9得是导通的
所以不能因为整个寄存器的翻转
把他的值给改变了
那么也因为这句话
大家就知道对整个寄存器的值做翻转
好像是有点问题的
那我再拔高问一问
这个实验2怎么写这个代码会更漂亮呢
有基础的同学就可以回忆起
我曾经讲过有三个灰色的不常用的寄存器
他们分别是写1不起别的作用
只是设置值 只是清除值和只是翻转值
特别是最后这一个
GPIOC的PTOR寄存器
你对他写值指使对应的比特发生翻转
如果把这个寄存器当时学习掌握的同学
我们可以把我们代码改的更加漂亮就像这样
只对我们想要操作的一两个引脚产生翻转
而不影响别的IO
这样也不用再写额外的语句
去保证左下角的开关一直是开着的
所以小小一个翻转点灯
我们也可以有不同的写法
不同的寄存器
所以每个人写出来的程序
应该带有鲜明的自己的思想和特点
同样对于实验任务二呢
我们把写好的代码下载到我们的微控制器里头
那么我们点击运行
也可以看到他的相应的效果
这个时候我们会发现
第一个灯和第二个灯在进行交替的闪烁
这里要给大家提示的呢
是我们开发工具所使用的调试器
一次只能支持一个程序的调试和下载
所以大家每一个程序调试完
一定要记得点一下红色的方块
停止当前的调试
特别是当你有多个工程文件
在一个work space里调试的时候
否则第二个调试的程序
可能会发现无法下载并且报错
这个呢没有关系
最简单的一种方法就是
你退出CodeWarrior重新进来一次
这样它会终止前一次下载
那么新的下载就可以成功进行了
然后我们再来看看任务三和任务四
我就不讲这么详细了
那么任务三很简单
我们板子上有很多按键
能不能让两个灯
跟我们板子上的头两个按键的关系是一一对应的
比如说按下去这个灯就亮了
撒手这个灯就灭
让两个灯跟两个按键关联起来
那么任务四更简单了
就是能不能让两个灯
跟着板子上随意这八个按键
任意当中一个来发生关联
其实这两个任务是非常类似 等价的
你做成一个 另外一个你就会做了
那么IO引脚接的按键在我们的板子上的电路图
如果大家打开电路图发现是这样的
一个引脚后面接着一个具体的IO是直接连起来的
那么我们通过引脚的按下和放开
希望在IO上
能够用输入方式读到0或者1
从而就知道这个键有没有被按下
那么这样一种直观的想法
我们得回忆起按键的一个连接电路
在我们的单片机这个虚线的框里头
一个引脚伸出来外面接了个按键
要想正确的得到的输入信号
一定不要忘了里头得应该有一个什么
上拉电阻
有这个上拉电阻接着3.3伏
才能保证当键没有按的时候引脚悬空
IO读到的是逻辑1
当键按下去的时候跟地短路
引脚读到的是逻辑0
我们可以通过输入的IO得到按键的状态
所以我们对于这样一个引脚的配置
多了一点新的内容
这是在课上讲实验的时候没有讲的
我们要把这个引脚在配置给当IO用的时候
一定注意把PORT
比如说PORTx_PCRn这个寄存器里头
右下角比特1
我用红字标的这个比特
Pull Up上拉电阻置成1启用
也就是对应的引脚待会要配成输入
同时一定要有上拉电阻
才能读一个外接按键的IO值
那么在这个原理下面
我们再来写我们的代码
大家想一想该怎么写
如果大家有基础同学我希望还是一样暂停在这里
自己把代码写出来
那么我们会想一想我们的程序
大家先脑补整个流程
我们需要把对应的所有用到PORT的时钟打开
把对应的所有当中的引脚配置给IO用
而不是给别的功能用
然后给对应的引脚配置好他们的方向
按键是输入 点灯是输出
然后点灯的引脚要配置好他们的初值
包括他们对应的开关关系
然后在for循环里头
不停的去读取按键的输入引脚的值
把这个值成功的用If else
或者用别的语句赋值影响我们的输出引脚
换言之IO输入一个零
我们的点灯是不是就输出一个零让它亮
IO输入一个1我们点灯就输出一个1让它灭
把这样一个思想用C语言的代码写出来
那可能就是像这样一个程序
那么这个程序里头我们考虑了这些事
并且用if else
以及与或关系来检查一个PORT里
某一个引脚的值输入是0还是1
换言之就检查了这些按键的值是0还是1
好 跟前面两个任务一样的
那么我们把第三个任务的程序
下载到我们开发板里头
那么我们看看效果会发现
在默认情况下
四个灯都是灭着的
如果我们分别按键1和按键2
就会明显看到随着按键1和2的按键功能
这几个灯在对应的闪烁
而其他的按键并不会影响灯的状态
那么实验3的任务也就完成了
那么最后第五个任务呢
用一个按键 根据这个按键按一下的情况
它按一下就把两个灯的闪烁模式切换一下
比如说我一上电两个灯是同亮同灭的
我如果键按了一下
这两个灯就变成你亮我灭 交替闪烁
我再按一下又换回来变成同亮同灭
那么这样一个任务来了 以后大家会想到是什么呢
会发现刚才讲到的东西全都能用上了
按键我会做了 灯怎么闪烁我也会做了
同亮同灭我也会做 交替闪烁我也会做
然后我要用一个按键的值
在循环体里头去查它有没有被按下
以及如何控制这两个灯
切换闪烁的模式
然后这当中背后有一个关系是什么呢
是我不再是键按下灯就亮 撒手灯就灭
而是我键按一下
灯的闪烁模式持续的维持一段的发生改变
我需要有一个什么
有一个变量把键曾经按下这件事给记下来对不对
所以我们需要有一个全局变量
比如说在我这儿我给出来叫bMode
定义一个unsigned char类型的变量
每当键按过一次以后
这个变量的值比如说布尔变量
就翻转一下为零或者为一
来记载键有被按过
同时根据这个变量值决定两个灯以什么模式闪烁
所以如果大家好好想一想
就会想象出来这个程序代码该怎么写
仍然是时钟打开配置给IO用
配置好IO的初值和方向
到了for循环里头很关键
我们要通过一些定时的检查按键有没有按下
来改变bMode这个变量的值
同时在循环体里头
根据bMode的值
决定下一次两个灯要怎么闪烁
是同亮同灭还是切换成一亮一灭对不对
那么最简单的切换方法
是我们给两个灯分别赋一个同亮的值
或者是一亮一灭的值
而在之后的循环体每次只是让他们进行翻转
是不是这个程序写起来就会特别simple
那么大家想一想这件事以后
尝试着把它写出来
如果你写出来以后跟老师给的这个代码比一比
看看是不是想法上有差异
或者比老师想的还要好
那么如果跟老师的想法有差异
或者比我想的还要好
那我觉得就很棒
那么我多问一个问题
即使你写的非常好
代码如果像我给的例程这么写他会有什么问题
如果你从代码看不出来有什么问题
你把它烧到板子里按按键试一试
你看看有什么问题
进而你去想一想该怎么解决
那么我给点提示呢
这就是一个按键抖动和防抖的问题
那么第一次实验的内容就到这儿了
我最后给大家布置一个思考题
就是大家能不能给这个板子上下面这一排四个
每个有三种颜色可以组合
七彩颜色可以出现的灯
做出一个呼吸灯的效果
什么叫呼吸灯
就是这个灯单一颜色的时候
由亮慢慢的变灭 再慢慢的变亮
或者这个灯从颜色当中从一种颜色变成七种颜色
再慢慢的变回来
那么我给的提示是大家可以试一试
把这个灯的闪烁间隔改短 越改越短
改到最后你会发现
灯好像是常亮的那是视觉暂留
那么我再用两个delay
让这个灯在眼睛看不出来闪烁的时候
亮的时间和灭的时间的比例发生变化
你会看到什么
会发现他的亮度在发生变化
而如果他们的亮的时间和灭的时间的比例
再变成一个变量
随着时间的推移 缓慢地发生变化呢
你是不是就能看到
这个灯在像呼吸灯一样由亮变灭 由灭变亮
而如果三种颜色搭配
此起彼伏地由亮变灭呢
你是否会看到这三种灯会组成绚烂多彩的颜色
所以一个点灯到了最后一个任务
就是由大家自由来发挥
能不能写出一个七彩呼吸灯
那这就是第一次实验的内容
-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
-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
-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
-5 智能车视角的嵌入式设计
--Video