上节讲了用MCU构成的数字系统的MCU选用及资源利用。关于MCU的编程就不再赘述,就跟不同的人每天要做的事情不同一样,千差万别,靠自己去按照逻辑流程去写就是。
MCU作为控制器,主要的作用是“控制”,而控制的依据,也就是来源,就是信息的输入,没有输入也就不知道该控制啥、如何控制。就如人,没有外界的任何刺激,无缘无故地做动作是不可能的。因此“信息的输入”是因,“控制”的动作是果。
MCU的CPU(中央处理单元,类我们的大脑)跟外界打交道是通过各种“外设接口”来实现的(类我们的神经系统)。下面的这张图简单示意了CPU同外设接口的几种常见方式,无论你用哪款通用的MCU,无外乎这些(一些高端专用的MCU还支持CAN、MIPI、以太网等)。
所谓外设接口,在器件上就表现为Pin(管脚),现在的趋势是:
并行总线越来越少用,占用管脚多、封装大、如果用并行总线进行器件和器件连接造成双倍的管脚数量、板卡面积的浪费以及设计复杂度,如果你的PCB设计能力不够的话,信号传输速率高了会出现性能问题,除非迫不得已使用DDR之类的器件,一般的场合用SPI、SDIO这种也能满足要求了;
同步串行的SPI和I2C大行其道,SPI速度高(一般时钟可以到50MHz),驱动个320*240的LCD甚至做数据采集足够了;I2C连接简单,两根线上可以挂一串外设,尤其是在物联网领域传感器基本都是用I2C连接的(也有SPI兼有的),因为其需要的数据率一般不会不高;SPI和I2C的区别我专门写过文章做了介绍,点击上面的链接即可;
管脚复用,如论你用STM32还是NXP的LPC,28个管脚的MCU支持的总线可多了 - SPI、I2C、UART等都有,甚至还不只一组,如何实现的?就是通过内部的开关矩阵来灵活配置的,设计硬件的时候你要认真阅读数据手册,明确哪些信号是固定的,哪些信号是灵活配置的,以及可以被配置的功能;
ADC一般也被集成进来,因为很多场合都需要检测外部的模拟信号,弄一个12bit、1-2Msps的串行ADC(多个输入切换共用内部的一个ADC转换器)在器件内部,跟外设的接口基本就齐全了。如果你需要更高速的ADC来采集外面的数据,那就要通过并行总线或者通过外部的FPGA进行一下处理。
MCU的输入/输出管脚一般都被称为GPIO - General Purpose Input/Output,顾名思义,也就是这些管脚可以灵活地被用于输入或者输出管脚,作为输入管脚,它可以感知外面的信号的变化,如果是开关信号,则可以感知是高电平1(一般为70%Vcc~Vcc之间)还是低电平0(一般为GND ~0.3Vcc之间),如果是模拟信号,则可以通过内置的ADC或比较器来测量外部信号的电压;作为输出管脚,它可以输出1 - 高电平、0 - 低电平来控制外部的开关、指示LED等。
不要小瞧独立做战的一根GPIO,它能入、能出,能感知外部的波形变化,更能通过其电平的变化传输信息、控制外设,比如“PWM”。这方面的应用我专门介绍过。
所有的电子产品系统最基础的两个功能,如果你做电赛的话几乎所有的自控题目中都会要实现的:
输入控制 - 一般为用一个按键(push button)通过一根I/O来连接MCU,多个控制输入可以用多根I/O线,当然还可以是拨码开关(Switch)或传感器的输出。
显示状态或信息 - LED(亮、灭或按一定模式变化)、数码管(多个LED组成的,显示数值)、OLED(文字、图案、波形)、LCD(文字、图案、波形)。
看起来很简单,但我建议同学们一定要苦练这一部分,这是基本功,不仅会用,而且要知道如何用好,如何在不同的平台上用好,比如你在8051上会了,可以在STM32上也很容易写出来,即便不调用系统自带的库函数,自己去写也能写出来。你在MCU上能用,在FPGA上也能用Verilog写出来,通过对比二者的实现方式的不同来体会一下。
像SPI、I2C、UART这种常用的总线,MCU一般都会有现成的硬件功能,通过调用它们的库就可以轻松使用,你可以尝试这根据这些总线的时序用GPIO来模拟实现一下,理解一下这些总线的构成、不同、优缺点、局限性等。尤其是通过FPGA来实现一下,如果能全部写出来会感觉非常的酸爽。
还要学会灵活地应用这些管脚,根据具体的需要适当地变通,下面我们看一个案例 - 按键的输入:
常规的方法如下图:一个按键对应于一个管脚。
4个输入按键需要4根I/O
再多几个按键输入呢?比如下面的这个4*4键盘:
用最直接的方式需要16根I/O,用矩阵扫描的方式也要用8根I/O才能搞定
再看下面的这两个产品:
你会发现它们都只用了一根信号管脚(另外两个信号是Vcc和GND),支持16/8个按键的输入!一下子节省了好多管脚资源,惊不惊喜?
这种方式的实现就是利用了MCU内部自带的ADC,数字信号只有0、1两种状态,而ADC则可以通过量化的位数来区分外部的2的n次方种不同的电压区间,比如8位的ADC可以区分256个不同的电压区间,用来区分16个按键组合出来的不同电压区间小菜一碟。
下面这个图就是用现成的8腿16键矩阵键盘构成的电路,只要一根ADC管脚就可以了,后面的C1实现了消抖的功能,都不需要软件进行按键的消抖处理了。
如果你手头的按键不是这种4*4的矩阵键盘,而是8个分立的push button,就可以采用下面的电路方式,当然更多的按键按照同理也可以轻松实现:
用8位的ADC量化后每个按键对应的数值区间,有些非线性,给程序带来了点麻烦。
可以修正一下电阻的值,让其更线性,按键增加到12个:
把计算出来的电阻值调整为能够方便买到的标准值,线性度依然很好:
这种灵活的变通解决了处理器上管脚较少的问题,当然也是一种比较好的训练,可以顺便体会一下ADC的工作原理,同时有一定的软件编程工作量,属于软硬配合实现一定的功能,很好,建议大家尝试一下,下面附赠两个代码示例,一个是Copy下面的连接到浏览器:
http://www.nerdkits.com/forum/thread/1956/
另一个是点击左下角的“阅读原文”,跳转到的网址就是今天文章中引用的是电路。
正如文章中所说,这种灵活变通的方式毕竟是模拟方式的,把只有0、1的泾渭分明的世界变成了多级灰度,自然抵抗噪声的能力就会降低,因此在高可靠性的应用场景最好不用。
但,这对于理解好电子系统的“神经系统”是很有帮助的。
硬禾小帮手 - 硬件工程师的设计助手
硬禾学堂 - 硬件工程师的在线学习平台