理解嵌入式开发中的一些硬件相关的概念

做嵌入式系统开发,经常要接触硬件。做嵌入式开发对数字电路和模拟电路要有一定的了解。这样才能深入的研究下去。下面我们简单的介绍嵌入式开发中的一些硬件相关的概念。

电平(Level)

在数字电路中,分为高电平和低电平,分别用1和0表示。一个数字电路的管脚,总是存在一个电平的,要么高要么低,或者说要么1要到0(其实,还有另一种状态,后面会提到)。

总线(Bus)

在嵌入式系统中一定会有一块处理器芯片,此外,还有其它的芯片作为外部设备(后面简称外设),这些芯片与处理器协作实现产品的功能。复杂的产品往往是由 大量的芯片组成的。那么不可避免的是我们需要将所有的外设与处理器进行相连,最为简单的是将所有的外设都采用独立(注意是独立)的信号线连接至处理器,这 样的好处是容易理解,但问题是:不可行。因为处理器芯片需要引出太多的线了,从芯片的生产和产品的生产角度来看都不实际。加之,处理器(在此我们假设处理 器是单核的,而不是多核的)处理事务在微观上是串行的,也就是说在某一时刻如果要对外设进行读写操作,那只可能是对大量外设中的一个进行,即多个外设不可 能在微观上被处理器同时访问。需要注意的是,这里提出了微观这一概念,这是为了区别于宏观。从宏观上来讲,一个处理器中可以有多个任务同时运行,但这些任 务在微观上却是一个一个运行的(后面会用串行来描述这里所说的“一个一个”),多任务的串行运行实现是由操作系统扮演着重要的角色来实现的。回到我们的话 题,即然将每个外设采用独立的信号线连到处理器不可行,且处理器在单一时间内只会对一个外设进行访问,那我们能不能采用共享的信号线将所有的芯片连在一起 呢?这就是总线概念的由来。通俗的说,如果我们周围有十个家庭,为了让这十个家庭每两个之间都能往来,我们并不需要为每两个家庭修一条单独(注意是单独) 的路(如果这样,要修45条路),而是可以修一条大路,然后,每个家都与大路相连。
     
 对于总线,我们往往说总线是处理器的,而其它的外设是挂在总线上的。那有一个问题,我们每一时间只能访问挂在总线上的一个外设,那如何区分这些外设呢?
和我们的路一样,我们需要用地址来区分每一个家庭,在总线上,也是采用地址来进行区分的。这样,总线就根据其功能分为两类了。一类是地址总线,这一总线上
的数据只会是从处理器向外设“流”,是单向的。另一类则是数据总线,用来将数据从处理器传送到外设(从处理器的角度来说是写操作)或者是将数据从外设传送
到处理器(从处理器的角度来说是读操作),显然,数据总线是双向的。也就是说,在我们的嵌入式系统中同时存在地址总线和数据总线将所有需要与处理器进行通
讯的芯片连在一起的。
     
 总线是有宽度的,正如我们的路分为“三车道”或是“四车道”,我们说32位处理器,是指其数据总线宽度是32位,也就是“有32辆车能同时跑”,显然,
宽度越是宽我们的处理器速度就越是快,因为我们从外设芯片存取数据的速度会更快,这就是为什么我们的计算机向64位发展的原因。同样的,地址总线也是有宽
度的,对于32位处理器其最大宽度也就是32位。
     
总线的概念有了,那接下来的一个问题是,即使是每一个外设都有一个地址,那这一地址记在哪里呢?是放在外设芯片上吗?如果这样的话,那就有一个问题,每一
类外设的地址必须是不能重叠的,而当一个产品中需要两块一样的芯片的话,两块芯片的地址就无法区分了,看来这样操作存在问题。还有,如果这样的话每一个外
设也得与(比如,32根)数据总线完全相连,并监听数据线以了解处理器是不是在“叫”自己,这样很是复杂。此外,地址也有可能因为外设种类的增多而用光。
总的来说地址不能存放在外设芯片,那如何让外设知道,此时它是被处理器招换从而需要进行读写访问的呢?答案就是芯片的片选(CS, chip
select)信号,或者又号使能(ENable)信号。

片选(CS 或EN)

片选信号对于外设芯片来讲,就是一个(也是一根)通知信号,告诉芯片“嘿,请开门,我要放些东西进来,或是拿些东西走”,这里的东西只能是数据,不可能
是玉米棒什么的。那有个问题,这个信号源从哪里来呢?显然,只能从处理器来。那是不是也是像总线那样,每一个芯片都共用一根线连在一起呢?如果这样,可能
处理器“一叫开门”所有的芯片都将“门”打开了。如果是处理器写数据,那可能所有的芯片都被写入同样的数据。而取数据时,每个外设芯片都向外“扔”数据,
这一定会造成数据总线冲突,因为有的芯片向总线上“扔”1,有的则“扔”0,这种情况下处理器一定会“发疯”的,因为它不知道应当得到1还是0。
     
即然这样,那显然不能将所有的片选信号连在一起了,只能是各芯片的片选信号独立。前面提到了地址总线,我们是采用一根地址线连一个外设芯片呢?还是采用其
它的方法。如果采用一根地址线连一个外设芯片,那可能最多只能挂接32个芯片了,这显然不行。其实,在现实中,是采用32位的数字来表示一个外设芯片的地
址的,比如1可以表示芯片A,而6534可以表示另外一个芯片B,等等。由此看来,理论上我们可以表示2的32次方(4294967296)个设备,之所
以说理论上,是因为有的设备要占用大量的地址。即然这样,那还有一个问题,如果将32位的地址总线转换成芯片的一根片选信号呢?这需要引入译码(器)的概
念。

译码(器)

译码器将一个数据转换成一根信号线上的信号,比如3/8译码器,可以将一个位宽是3位的数据转换成8根(2的3次方)完全独立的信号线,当向数据侧写入
二进制的011时,对应的是8根线的第3根,当输入二进制的111时,对应的是8根线中的最后一根。有了译码器,处理器的地址线就简化了,只要32根地址
线加上外面的译码器,就可以访问大量的外设芯片了。外部设备的选择问题,我们已经解决了,现在还得回头看一看数据总线。

图1 3/8译码器

在嵌入式系统中,所有芯片的数据总线可以理解成是直接相连的。之所以用了“可以理解”一词,是因为为了提高总线的负载能力,其中会加入总线驱动器。为了理
解,我们看一看我们生活中的自来水,比如,在北京理论上可能所有的水管是连在一起的,但中间可能为了提高水压,存在很多小的水站用来增加供水压力,而不可
能全北京所有的自来水自接来自一个水厂。即然所有的数据总线是连在一起的,那就可能会有问题。当向外部设备写数据时,处理器先向地址总线输送目标外设的地
址,地址译码器将其转换成一根信号的片选信号送到了目标外设,目标外设收到这一信号后,将“门”打开。接下来处理器将要传送到外设的数据往数据总线上一
放,由于只有目标外设芯片打开了“门”,所以数据只会进入到目标外设,而其它的外设什么也不会收到。很好!处理器向外写数据应当没有问题,我们接下来看一
看读。读的话,由于数据是从外设输送到处理器的,尽管我们采用和写一样的方法打开目标外设的“门”,但此时,其它的外设也在数据总线上,它们有可能处于1
也可能处于0,是不是会影响处理器读取目标外设的数据呢?结果当然不会,但我们得引入另一个概念:高阻态。

高阻态

很显然,当处理器从目标外设读数据时,我们希望其它没有被选上的芯片的数据总线不会对目标外设所要传送的数据有影响,那怎么办呢?实际上,当芯片没有被选
中时,其数据总线都处于高阻态。所谓的高阻态,我们可以理解成这一管脚在外设芯片内部是断开的,如此一来,显然不会对处理器从目标外设读取数据造成任何的
影响了。我们说当一个芯片没有被选中或是没有被使能时,其数据总线一定是处于高阻态的。前面用了“门”的开和关来打比方,那“门”是指什么呢?是指外设的
数据总线,片选信号的作用就是控制将外设的数据总线与处理器的数据总线相连或是断开。更多的关于高阻态的讲解可参看前面写的文章《高阻态和三态门》。

驱动

总线上的数据是谁放上去的我们就说谁是那一时刻的驱动者。也就是说,当处理器向外设写数据时,它是在驱动数据总线的,而当处理器从目标外设读取数据时,目
标外设是在驱动数据总线的。对于地址总线,因为只可能从处理器向目标外设写,所以地址总线永远是由处理器驱动的。当一个芯片没有被选中时,我们说它并不驱
动数据总线。

三态门

前面我们说到外设芯片的数据总线在没有被选中时其处于高阻态,当被选中时,其电平可能是高(1)或是低(0)。如此一来,我们说外设的数据总线其芯片管
脚是属于三态门的,即存在高电平、低电平和高阻态,三个状态。更多的关于三态门的讲解可参看前面写的文章《高阻态和三态门》。

电平的有效性

前面我们了解了什么是片选信号,也讲到了三态门,需要指出的是片选信号通常不是三态门,其只存在两个状态,即高电平或是低电平。前面我们也说了,片选信
号是用来“开门”的,而片选信号又有高和低电平,那到底是高电平表示“开门”呢?还是低电平?对于这一问题,我们称如果一个电平对于一个片选信号表示“开
门”那么它就是这一信号的有效电平。比如,对于一个片选信号,如果低电平表示“开门”,那么我们说这个片选信号是低电平有效的。虽然,在这里我们用片选信
号来解释电平的有效性,但是很多信号都存在有效性的问题,比如,后面我们将要谈的读信号和写信号都存在有效性问题。

时序

在前面我们说到当处理器要向外设芯片写数据时,需要先将所需访问的外设的地址放在地址总线上,然后,由译码器将地址总线上的数据转换成片选信号,片选信 号则使能目标外设芯片,接下来处理器写数据到数据总线上,从而完成一个写操作。显然,在处理器将数据写到数据总线之前地址线上的数据必须一直保留一段时 间,否则的话译码器不能长时间的使片选信号有效。当完成了数据的写操作后,处理器就不需要保证地址总线上的地址有效了。我们可以看出,这一系列的操作都有 一定严格的时间顺序的,这称之为时序。时序描述了处理器与外部设备的交互信号 “规程”,大家只有按照这一“规程”来操作,才能保证处理器与外部设备之间能正常的通讯。这好比,我们的道路上的红绿灯,如果我们行人和车辆不按照其指示 来通行的话,就会出现事故。通常,采用时序图来描述芯片之间通讯的信号“规程”。

图2 读时序图

图3 读时序图

从图中我们可以看出ADDRESS是表示地址总线的,DQ是表示数据总线的,CE是片选信号,且是低电平有效,其宽度要保证在进行读操作时总是有效的。学 会看时序图对于做嵌入式系统开发非常有帮助,因为我们不可避免的要与芯片打交道。在时序图中,通常会标识很多的时间需求信息。在写启动代码时需要初始化各 地址空间的片选地址寄存器和读写时序,时序的配置依据就是来自于外设芯片的时间需求,这是芯片手册很重要的一部分内容。当一个地址空间中存在多个外设芯片 时,我们需要考虑到其中最慢的外设芯片的时间需求,否则的话有的芯片就不能正常工作。

读信号

当处理器需要从外设芯片读取信号时,除了需要产生片选信号外,还需要告诉外设芯片这是一个读操作,而不是一个写操作,这是通过读信号来实现的。

写信号

前面讲了读信号,我想对于写信号也就不难理解了,这个信号用于告诉外设芯片,这是一个向外设芯片写数据的操作。

I/O端口

前面提到了外设(芯片)),现在是对外设进行分类的时候了。大体上外设分为两类,一类是存储器外设,而另一类是非存储器外设,后者常被称之为I/O设
备,这里的I/O是Input/Output的简写,即输入、输出。可见,I/O外设是一个非常宽泛的概念。对于存储器外设,其特点是,它所占用的空间是
连续的一片。比如,SDRAM内存就是属于存储器外设,如果其容量是8M字节,那么其占用的地址空间也会是8M的。与存储器外设所不同的是,I/O外设所
点用的地址一般都很少。比如一个I/O外设可能存在多个控制寄存器,这些控制寄存器从处理器来看就是多个I/O端口(地址),向这个地址写数据就是向外设
所对应的寄存器写数据,反之,也可以是读。比如,一个串口芯片可能存在多个寄存器,一个用来查询芯片的状态,一个用来设置芯片的功能,另一个用来读取芯片
从串口线所收到的数据,最后,还有一个用来向芯片写数据以向串口线上发送数据。对于这一串口芯片的寄存器,从处理器的角度来看,都是独立的I/O端口。
     
 I/O端口存在读、写性问题,有的端口是只读的,有的端口是只写的,还有的端口是即可读也可写,其读写性是由外设芯片的寄存器所决定的,在芯片的数据手
册中能找到。需要指出的是,有些存储器外设也存在I/O端口,以对其进行一定的控制。从I/O端口这一名字来看,对于处理器来说,就是对从外面读入数据或
是向外面输出数据的一个接口总称。

中断

中断从硬件的角度来看就是一个能产生高、低电平的一根信号线,但理解它需要从处理器的角度出发。我们说过了,处理器从微观上看,所做的工作是按顺序进行
的,其对程序的处理只能是一条指令一条指令的执行。如果存在需要对外设芯片进行访问,而有可能从处理器发出读、写命令后,由于外设通常比处理器慢很多,所
以外设芯片需要一些时间来准备好所需的数据。在这种情况下,如果处理器一直等外设芯片的返回数据再执行后续的指令的话,将耗费宝贵的时间,这些时间完全可
以用来做其它的工作。别忘了,从宏观上看来处理器常常是多任务的,任务是指操作系统所提供的调度单位。当一个任务因为等待外设芯片的数据而阻塞时,我们可
以切换到另外的任务,从而提高处理效率。这就有一个问题,当处理器去处理另一个任务时,如果外设芯片的数据好了的话,如果告诉处理器呢?对了!就是通过中
断信号。中断信号的高、低电平可以用来表示是否有中断需要处理器注意以处理特定的事件(比如,外设数据准备好了的事件)。
     
 由此看来,中断的引入能大大的提高处理器的运用效率。为了使用处理器上的中断,一开始我们需要初始化好处理器的中断控制器,比如安装好所需的中断服务程
序或称之为ISR(Interrupt Service Routine),然后,打开中断屏蔽位。中断服务程序中需要做如下的操作:

  1. 从外设读入或向外设写数据。读还是写通常需要读取外设的中断状态寄存器来决定。

  2. 除外设的中断信号。我们知道,中断信号是由外设芯片驱动的,为了告诉外设芯片,处理器已经处理完了所需做的工作,那么处理器需要通过一定的方式通知外设芯
    片。这种方式就是向外设芯片的寄存器中的某一位写入一个数据,比如,可能是写入1表示清中断,也可能是写入0表示清中断,这通常在外设的数据手册中能查
    到。当外设收到了处理器的清中断请求后,其就会驱动中断线使其无效。比如,一个外设的中断线是当其为低电平表示有中断,将其从低电平变为高电平就是驱动为
    无效。
  3. 清除处理器的中断信号标识。处理器中往往也会保存外部中断信号是否发生过,当我们处理完了外设芯片的中断时,我们也需要清除处理器上的标识,从而为下一次中断做准备。需要注意的是,清外设的中断必须发生在请处理器中断标识之前!

中断还存在一个触发方式问题。有两种触发方式
,一种是电平触发,另一种是沿触发。电平触发是指电平的高低表示外设是否有中断,而沿触发则是能过中断线上的电平的升或降来表示的,显然,存在两种沿触发
方式。一种是中断线从低电平变为高电平,我们称之为上升沿触发,另一处是中断线从高电平转换为低电平,我们称之为下降沿触发。总的来说中断的触发方式有电
平触发、上升沿触发和下降沿触发。电平触发方式中处理中中断设置很重要的一个步骤。

万用表

万用表通常是用来查看电平的高低、电阻的大小等的,是常用且必不可少的工具之一。在嵌入式系统开发中,我们常用的是数字万用表。

示波器

在嵌入式系统开发中,我们不可避免的要与外设芯片打交道。调试驱动程序时,除了需要完全看明白芯片的数据手册,且在软件高度的过程中,还需要看我们所期望
的信号电平是否发生在芯片上。比如,我们在写驱动程序时,需要通过写I/O端口来对外设芯片进行操作,当写相应的I/O端口时,我们知道所对应芯片的片选
信号应当有效,有时,我们需要验证是否按预期发生了,这就需要用到示波器。一般的示波器是能同时观测两个信号线的信号状态的。示波器都提供一定的功能,比
如设置信号扑捉的方式等等。示波器很重要的一个参数据是其采集频率,根据Nyquist采集定理,如果我们想用示波器查看频率是100M赫兹的信号,那么
其采样频率必须至少是其两倍,即200M赫兹。有人可能会问:为什么不用万用表来看呢?因为万用表的采集频率很底,无法采集到很快的信号变化。

逻辑分析仪

简单的说逻辑分析器就是具有很多信号通道的示波器。通过逻辑分析仪,我们可以看到地址总线和数据总线上的数据。逻辑分析仪都提供一定的编程能力,用于编程什么时候开始对总线上的数据进行采集。

时间: 2024-08-04 14:12:37

理解嵌入式开发中的一些硬件相关的概念的相关文章

【详解】嵌入式开发中固件的烧录方式

版本:v1.2 Crifan Li 摘要 本文主要介绍了嵌入式开发过程中,将固件从PC端下载到开发板中的各种方式,主要包括NFS挂载,Nand Flash和Nor Flash,USB,RS232,网卡NIC等方式. 本文提供多种格式供: 在线阅读 HTML HTMLs PDF CHM TXT RTF WEBHELP 下载(7zip压缩包) HTML HTMLs PDF CHM TXT RTF WEBHELP HTML版本的在线地址为: http://www.crifan.com/files/do

嵌入式开发中常见3个的C语言技巧

Hey,大家好!我是CrazyCatJack.今天我来说几个在嵌入式开发中常用的C语言技巧吧.也许你曾经用过,也许你只是见到过但是没有深入理解.那么今天好好补充下吧^_^ 1.指向函数的指针 指针不光能指向变量.字符串.数组,还能够指向函数.在C语言中允许将函数的入口地址赋值给指针.这样就可以通过指针来访问函数.还可以把函数指针当成参数来传递.函数指针可以简化代码,减少修改代码时的工作量.通过接下来的讲解大家会体会到这一点的. /*函数指针简单讲解 *通过指向函数的指 *针调用比较两个数 *大小

全面理解iOS开发中的Scroll View

转自:http://mobile.51cto.com/hot-430409.htm 可能你很难相信,UIScrollView和一个标准的UIView差异并不大,scroll view确实会多一些方法,但这些方法只是UIView一些属性的表面而已.因此,要想弄懂UIScrollView是怎么工作之前,你需要了解 UIView,特别是视图渲染过程的两步. 光栅化和组合 渲染过程的第一部分是众所周知的光栅化,光栅化简单的说就是产生一组绘图指令并且生成一张图片.比如绘制一个圆角矩形.带图片.标题居中的U

在嵌入式开发中应该这样理解嵌入式C编程

一.新手常常问的一个问题:C语言和嵌入式C编程有什么区别?而嵌入式工程师一般都会告诉你,其区别在于嵌入式的C语言是跑在嵌入式的开发板上的,CPU和电脑不一样,所以编译器也是不一样的,生成的可执行程序也是不一样的.不同于一般形式的软件编程,基于特定的硬件平台嵌入式系统编程的,势必要求其编程语言具备较强的硬件直接操作能力.毫无疑问,汇编语言是具备这种特点的.然而,由于该语言编写开发过程的复杂性,通常不选择它用于嵌入式系统开发,而C语言是一种"低层次"的语言,已经成为嵌入式系统开发的最佳选择

深入理解 iOS 开发中的锁

来源:伯乐在线 - 夏天然后 链接:http://ios.jobbole.com/89474/ 点击 → 申请加入伯乐在线专栏作者 摘要 本文的目的不是介绍 iOS 中各种锁如何使用,一方面笔者没有大量的实战经验,另一方面这样的文章相当多,比如 iOS中保证线程安全的几种方式与性能对比.iOS 常见知识点(三):Lock.本文也不会详细介绍锁的具体实现原理,这会涉及到太多相关知识,笔者不敢误人子弟. 本文要做的就是简单的分析 iOS 开发中常见的几种锁如何实现,以及优缺点是什么,为什么会有性能上

深入理解iOS开发中的BitCode功能

前言 做iOS开发的朋友们都知道,目前最新的Xcode7,新建项目默认就打开了bitcode设置.而且大部分开发者都被这个突如其来的bitcode功能给坑过导致项目编译失败,而这些因为bitcode而编译失败的的项目都有一个共同点,就是链接了第三方二进制的库或者框架,而这些框架或者库恰好没有包含bitcode的东西(暂且称为东西),从而导致项目编译不成功.所以每当遇到这个情况时候大部分人都是直接设置Xcode关闭bitcode功能,全部不生成bitcode.也不去深究这一开关背后隐藏的原理.中枪

开发中遇到的数据库相关问题

最近对于数据库的增删改查做的多了突然发现个问题就是:数据库表结构如果设计的不好, 那么到开发中会产生很多问题.(本文还未总结完,语言些许模糊,如有异议,欢迎指正) 问题如下:(1)1个表中表结构不全问题:冗余,该有的没有.不该有的也有:当然了,这不能完全算是设计问题,因为往往需求在不停的变化不停的发现问题的,可是到了需求分析较成熟阶段这就不应该了,如果出现,那只能说明你设计的不严谨或你的水平有限.这里不聊需求分析了,因为其内容不是一两句话就能说完的.(2)2个及以上表关联时,表与表之间的耦合性高

iOS-Runtime在开发中的使用及相关面试题

OC语言中最为强大的莫过于OC的运行时机制-Runtime,但因其比较接近底层,一旦使用Runtime出现bug,将很难调试,所以Runtime在开发中能不用就不用.下面我将介绍一些Runtime在开发中的使用,已经面试可能遇见的面试题. 1.OC语法和Runtime语法的区别 OC语法和Runtime语法的区别,换而言之就是OC中我们写的语句,最终被转换成Runtime中什么样语句.由于Xcode6之后,苹果不建议使用Runtime,也就是现在在编译的时候,runtime的函数不会提示,需要去

嵌入式开发中对(*(volatile unsigned long *)) 的理解

一.说明 (*(volatile unsigned long *)) 这个语句对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的.如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的"端口"的概念.如果是内存映射,那就方便多了. 二.举例讲解 以 #define IOPIN (*((volatile unsigned long *)0xE0028000))为例: 作为一个宏定义语句,define是定义一个变