精华内容
下载资源
问答
  • 部分内容来自于 电子发烧友 内部总线、系统总线和外部总线汇总 部分内容来自于 知乎 前端总线,系统总线,内部总线,外部总线 本文在两篇文章的基础上进行了二次加工,对两篇文章的精华内容进行了提炼,删掉了对...

    文章
    部分内容来自于 电子发烧友 内部总线、系统总线和外部总线汇总
    部分内容来自于 知乎 前端总线,系统总线,内部总线,外部总线

    本文是在两篇文章的基础上进行了二次加工,对两篇文章的精华内容进行了提炼,删掉了对理解主题不重要的,或已经过时的内容。并且为了更好的理解,自己又加了一些文字和图片。

    说在前面的话

    对于这样的概念不需要太过于纠结,看完以后心中有个大体的把握即可,因为概念性的东西没有标准答案,而且国内外各种资料相互“打架”,众说纷纭,造成现在这样一种概念混乱的局面。重要的是知道了这些概念之后,在以后的实际解决问题中,头脑能比较清楚就行。


    好了,正文开始

    什么是前端总线,内部总线、系统总线和外部总线?

    首先把这个问题仅限于x86平台。其他cpu架构不见得是这么分。并且仅限于2000-2009年范围。这些概念也许只有DIYer圈知道。近几年intel的动作频频,把南北桥都要合并了。这个问题,再过几年也许就没意义了。
    ++++++++++++++++++++++++++我是时间线++++++++++++++++++++++++++++++++++++
    2009年,英特尔和AMD已采用单芯片组技术,取代原有的南桥/北桥方案。Intel平台北桥被内置到CPU中。还有一些处理器,比如Intel超低压CPU、Intel Xeon D等Intel CPU已经内置南桥。


    什么是总线

    总线(Bus)是供多个部件分时共享的公共信息传送线路,一个系统的总线结构决定了该计算机系统的数据通路及系统结构。如今,几乎所有的计算机系统中都采用了总线结构。

    在微型计算机中,总线以及所连接的部件都安放在主板(Main Board)上。计算机在运
    行中对于系统内的部件和外部设备的控制都通过主板实现,主板的组成与布局也影响着系
    统的运行速度、稳定性和可扩展性。

    从另一个角度来看,如果说主板(Mother Board)是一座城市,那么总线就像是城市里的公共汽车(bus),能按照固定行车路线,传输来回不停运作的比特(bit)。这些线路在同一时间内都仅能负责传输一个比特。因此,必须同时采用多条线路才能发送更多数据,而总线可同时传输的数据数就称为宽度(width),以比特为单位,总线宽度愈大,传输性能就愈佳。

    总结:个人感觉总线就是为了主板上各种东西的通信,建立的一些逻辑电路。


    总线的分类

    总线应用很广,形态多样,从不同的角度可以有不同的分类方法。下面列举几种。

    1.按照总线传递的信号性质分类

    按照总线传递的信号性质,可将其分为 3 种。
    (1)地址总线(Address Bus,AB),用来传递地址信息。
    (2)数据总线(Data Bus,DB),用来传递数据信息。
    (3)控制总线(Control Bus,CB),用来传递各种控制信号。

    2.按照总线所处的位置分类

    按照总线所处的位置分为机内总线和机外总线。

    机内总线分为片内总线片外总线片内总线CPU 芯片内部用于在寄存器、ALU 以及控制部件之间传输信号的总线;片外总线CPU 芯片之外,用于连接 CPU、内存以及 I/O设备的总线。

    机外总线与外围设备接口的总线,实际上是一种外设的接口标准。目前在微型计算机上流行的接口标准有 IDE、SCSI、USB 和 IEEE 1394 等。

    3. 按照总线在系统中连接的主要部件分类

    按照总线在系统中连接的主要部件,可以将总线分为 5 种。
    (1)存储总线:连接存储器。
    (2)DMA 总线:连接 DMA 控制器。
    (3)系统总线:连接 I/O 通道总线和各扩展槽。
    (4)I/O(设备)总线:连接外部设备控制芯片。
    (5)局部总线:通常是一种实现高速数据传送的高性能总线,用来在高度集成的外设控制器器件,扩展板和处理器/存储器系统之间提供一种内部连接机制。

    4. 按照总线传输的数据单位分类

    按照总线传输的数据单位分为串行总线和并行总线。图 3.2 为两者示意图。
    在这里插入图片描述
    (1)串行总线按位进行传输,每次传输一个位的数据。
    (2)并行数据每次传输多位,通常有 8b、16b、32b 和 64b 等几种。所以,并行传输除了控制信号、电源等之外,要传输多少位数据,就需要多少根数据线。

    5. 按照发送端与接收端有无共同的时钟分类

    按照发送端与接收端有无共同的时钟,总线可以分为同步总线异步总线等类型。

    6. 按照系统中使用的总线数量分类

    大多数总线都是以相同方式构成的,其不同之处仅在于总线中数据线和地址线的数目,以及控制线的多少及功能。按照系统中使用的总线的条数可以分为单总线结构、双总线结构和多总线结构。

    单总线结构

    单总线结构使用一组单一的系统总线来连接 CPU、主存和 I/O 设备。在这类系统中,同一类信息在不同部件间传递时,通过同一组总线,或者说,所有的模块都挂在同一组总线上
    在这里插入图片描述
    这种总线结构连接灵活、易于扩充。单总线结构容易扩展成多 CPU 系统,这只要在总线上挂接多个 CPU 即可。因所有信息都在一组系统总线上传送,故信息传输的吞吐量受到限制。
    在这里插入图片描述

    双总线结构

    双总线结构保持了单总线结构简单、易于扩充的优点,又在 CPU 和主存之间有一组专门高速总线,使 CPU 可与主存迅速交换信息,而主存不必经过 CPU 仍可通过总线与外设之间实现 DMA 操作。这样,缓解了对系统总线和 CPU 的压力,提高了系统的效率。
    在这里插入图片描述
    由于各种设备对于总线的要求不同,在设备不断增加的形势下,总线趋向于分级的总线结构。

    三级总线结构。

    在双总线的基础上增加了I/0总线,这条线就是所有外设与“通道“通信的一条线。”通道“乍一听好像很抽象,其实就是南桥芯片。各芯片组厂商的南桥名称都有所不同,例如英特尔称之为I/O路径控制器(ICH)或平台路径控制器(PCH)。
    在这里插入图片描述
    上图中的”通道“就是下图的局部I/O控制器,I/O总线就是下面的扩展总线。
    在这里插入图片描述
    这种三级总线结构一般用于 I/O 设备性能相差不大的情况。在高速的视频设备、网络、硬盘等大量涌现的情况下,将它们与低速设备(如打印机、低速串口设备)接在同一条总线上,非常影响系统的效率。进一步的改进是为这些高速设备设立一条单独的高速总线,形成如图 3.4 所示的由系统总线、局部总线、高速总线和扩展总线组成的四级总线结构
    在这里插入图片描述

    上面已经对总线进行比较全面的分类,不过仅仅只是分了类,缺乏一些详细的内容,下面的部分就来补充一下,帮助理解的更全面。

    补充

    1、总线按功能和规范可分为五大类型:数据总线地址总线控制总线扩展总线局部总线

    地址总线:是专门用来传送地址的,由于地址只能从CPU传向外部存储器或I/O端口,所以地址总线总是单向的,这与数据总线不同,地址总线的位数决定了CPU可直接寻址的内存空间大小

    控制总线:用来传送控制信号时序信号。控制信号中,有的是微处理器送往存储器和I/O接口电路的;也有是其它部件反馈给CPU的,比如:中断申请信号、复位信号、总线请求信号、设备就绪信号等。

    • 一般规定送入 CPU 的信号称为输入信号(IN),从 CPU 发出的信号称为输出信号(OUT)。例如,地址总线是输出线,数据总线是双向传送,控制总线一般是单向的,有输出的也有输入的,如下图
      在这里插入图片描述

    数据总线地址总线控制总线也统称为系统总线,即通常意义上所说的总线。常见的系统总线看下面的图
    在这里插入图片描述
    上述这些标准中有些已经被淘汰,有些正在被应用,有些即将被应用

    2、按照传输数据的方式划分,可以分为串行总线并行总线。串行总线中,二进制数据逐位通过一根数据线发送到目的器件;并行总线的数据线通常超过2根。常见的串行总线有SPI、I2C、USB及RS232等。

    3、按照时钟信号是否独立,可以分为同步总线异步总线。同步总线的时钟信号独立于数据,而异步总线的时钟信号是从数据中提取出来的。SPI、I2C是同步串行总线,RS232采用异步串行总线。

    4、微机中总线一般有内部总线系统总线外部总线内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连;而系统总线是微机中各插件板与系统板之间的总线,用于插件板一级的互连;外部总线则是微机和外部设备之间的总线,微机作为一种设备,通过该总线和其他设备进行信息与数据交换,它用于设备一级的互连。
    在这里插入图片描述


    内部总线

    内部总线原是指南桥芯片与北桥芯片之间的连线。下图南北桥中间的Internal Bus就是内部总线
    在这里插入图片描述
    在早期的主板上,对于Intel来说,这条内部总线有专门的名字,叫DMI(Direct Media Interface,直接媒体接口)。

    现在英特尔和AMD已采用单芯片组技术,取代原有的南桥/北桥方案。所以现在的内部总线不再是原来的意思了。

    外部总线上,还有一些零碎的低速小芯片。这个一般用户接触不到,是给制造商的开发人员用的。例如网卡需要一片eeprom来存唯一的MAC地址。很多pci卡上都能找到这些小flash。某些pci卡还有温度传感器。网卡的MAC和PHY之间也要有总线来读取链接速度、是否link等信息。控制这些小芯片使用诸如I2C SPI总线,即所谓的内部总线。

    科普时间

    I2C总线:I2C(Inter-IC)总线是同步通信的一种特殊形式,在主从通信中,可以有多个I2C总线器件同时接到I2C总线上,通过地址来识别通信对象。

    SPI总线:SPI(Serial Peripheral Interface:串行外设接口)。SPI接口主要应用在EEPROMFLASH,实时时钟之间。


    前端总线

    前端总线(FSB,Front Side Bus)是指中央处理器数据总线的专门术语,此总线负责中央处理器和北桥芯片间的数据传递。现在的x86处理器内置了存储器控制器,FSB已被Intel QPI和AMD HyperTransport取代,QPI和HyperTransport在下面有科普。

    某些带有L2和L3缓存(Cache)的CPU,通过后端总线(Back Side Bus,下面会介绍后端总线)实现这些缓存和中央处理器的连接,而此总线的数据传输速率总是高于前端总线。

    通俗的说,前端总线(FSB)就是CPU和北桥、内存的连接总线了。北桥是PCI/PCIe 总线的发源地。但是由于技术的进步,FSB已经被取代,AMD很早就开始采用自己的HyperTransport(后续版本更改为HyperTransport Link简称HT link)代替了FSB来提高cpu与内存等芯片的数据传输速度,而intel亦采用QuickPathInterconnect(QPI)技术。但是总体上讲,这两种技术都是FSB的进化。

    科普时间

    QPI

    快速通道互联(英语:Intel QuickPath Interconnect,缩写:QPI),是一种由英特尔开发并使用的点对点处理器互连架构,用来实现CPU之间的互联。英特尔在2008年开始用QPI取代以往用于至强(Xeon)、安腾处理器的前端总线(FSB)。

    HyperTransport

    HyperTransport总线技术,简称“HT总线”,是AMD开发的一种处理器的互连技术。

    前方高能 HT and HTT

    卖场中常有“HT总线”与日后英特尔“HT技术”的混淆,然而这两个是截然不同的技术。HT一般指HyperTransport,或简称HT总线,一般情况下HyperTransport联合会都是使用全称“HyperTransport”以免造成歧义。而应用于奔腾4处理器、英特尔Nehalem微架构及其后续微架构之处理器的“HT技术”,英特尔的官方简称是HTT,Hyper-Threading Technology 或简称HT Technology(HT技术)。


    后端总线

    后端总线(BSB,Back Side Bus):带有L2和L3缓存(Cache)的计算机中,负责中央处理器和外部缓存(经常为第二级缓存)之间的数据传递的数据通道。后端总线传输速率总是高于前端总线。用于处理缓存数据的后端总线实际上是以CPU时钟速度运行。在在90年代中期,后端总线曾是保持数据移动的重要路径。Intel公司的Pentium II和Pentium Pro都使用所谓的芯片外缓存(Cache),与保存在传统内存中的数据相比,这类缓存将经常使用的数据靠近(在访问数据所需的距离和时间上)主处理单元保存。连线将CPU连接到第二级(L2)缓存并以CPU时钟速度在CPU与L2缓存之间交换数据。
    在这里插入图片描述


    系统总线

    特指 PCI/PCIe 总线。这是Intel主导发展的总线标准。

    什么?还有EISA、VESA总线?请把他们遗忘在20世纪吧。胜者为王。

    人的大脑和其他的器官、四肢,大部分靠脊髓相连。PCI/PCIe 总线 ,就相当于x86架构机器的脊髓。其他内部总线、外部总线,都是挂在系统总线上的。USB、SATA、1394,统统是 PCI/PCIe 总线的下级。主要因为PCI/PCIe 总线带宽高;拥有硬件探测能力;改进的标准能热插拔。顺带提一下,因为PCI/PCIe 总线的硬件探测能力,加上微软定义的几套PC制造标准,我们才能一张xp盘装无数的x86机器。

    科普时间

    PCI总线:PCI(Peripheral Component Interconnect)外设元件互连标准。PCI总线是当前最流行的总线之一,它是由Intel公司推出的一种系统总线。它定义了32位数据总线,且可扩展为64位。PCI总线主板插槽的体积比原ISA总线插槽还小,其功能比VESA、ISA有极大的改善,支持突发读写操作,最大传输速率可达132MB/s,可同时支持多组外围设备。PCI总线不能兼容现有的ISA、EISA、MCA总线,但它不受制于处理器,是基于奔腾等新一代微处理器而发展的总线。
    在这里插入图片描述
    在这里插入图片描述


    外部总线

    诸如USB,SATA,IDE,1394,串口,以太网,这些暴露给普通用户插的,就是外部总线。前面提到过,他们都是PCI/PCIe 总线 的下级。例如在PCI/PCIe 总线上,USB控制器是pci设备。在USB总线上,USB控制器又是头头,U盘是设备。 U盘里的数据想去cpu,得经由 usb总线 -->pci总线–>前端总线–>CPU

    科普一下USB
    USB总线:通用串行总线USB是由Intel、Compaq、Digital、IBM、Microsoft、NEC、NorthernTelecom等7家世界著名的计算机和通信公司共同推出的一种新型接口标准。它基于通用连接技术,实现外设的简单快速连接,达到方便用户、降低成本、扩展PC连接外设范围的目的。它可以为外设提供电源,而不像普通的使用串、并口的设备需要单独的供电系统。
    在这里插入图片描述

    总结:

    PC上一般有五种总线:

    • 数据总线(Data Bus):在CPU与RAM之间来回传送需要处理或是需要储存的数据。
    • 地址总线(Address Bus):用来指定在RAM(Random Access Memory)之中储存的数据的地址。
    • 控制总线(Control Bus):将微处理器控制单元(Control Unit)的信号,传送到周边设备,一般常见的为USB Bus和1394 Bus
    • 扩展总线(Expansion Bus):可连接扩展槽和电脑。
    • 局部总线(Local Bus):取代更高速数据传输的扩展总线。

    PS

    做底层开发的,其实根本不关心内部总线、外部总线、系统总线这些叫法,因为这些叫法都不标准,充满歧义。真正干活时,总是明确地指出总线的具体名称:USB、PCIE、I2C、SPI。

    展开全文
  • 文章目录1 总线的概念与分类1.1总线的定义1.2 总线的特点1.3 总线的特性1.4 总线的分类1.4.1 串行总线与并行总线1.4.2 按总线功能分类1.5 系统总线的结构1.6 总线概念与分类小结2 总线的性能指标2.1 性能指标分析2.2...


    总线框架:
    在这里插入图片描述

    1 总线的概念与分类

    1.1总线的定义

    总线是一组能为多个部件分时共享的公共信息传送线路。

    在这里插入图片描述

    为什么要用总线?

    早期计算机外部设备少时大多采用分散连接方式,不易实现随时增减外部设备。
    为了更好地解决I/O设备和主机之间连接的灵活性问题,计算机的结构从分散连接发展为总线连接。

    1.2 总线的特点

    • 共享是指总线上可以挂接多个部件,各个部件之间互相交换的信息都可以通过这组线路分时共享。
    • 分时是指同一时刻只允许有一个部件向总线发送信息,如果系统中有多个部件,则它们只能分时地向总线发送信息。

    1.3 总线的特性

    1. 机械特性:尺寸、形状、管脚数、排列顺序
    2. 电气特性:传输方向和有效的电平范围
    3. 功能特性:每根传输线的功能(地址、数据、控制)
    4. 时间特性:信号的时序关系

    1.4 总线的分类

    在这里插入图片描述

    1.4.1 串行总线与并行总线

    在这里插入图片描述

    • 设备A一位一位的发,经过总线,设备B一位一位的接收
    • 优点:只需要一条传输线,成本低廉,广泛应用于长距离传输;应用于计算机内部时,可以节省布线空间。
    • 缺点:在数据发送和接收的时候要进行拆卸和装配,要考虑串行-并行转换的问题。

    在这里插入图片描述

    • 数据同时放到总线,同时向B传输,B同时接收
    • 优点:总线的逻辑时序比较简单,电路实现起来比较容易。
    • 缺点:信号线数量多,占用更多的布线空间;远距离依输成本高昂;由于工作频率较高时,并行的信号线之间会产生严重干扰,对每条线等长的要求也越高,所以无法持续提升工作频率。
    1.4.2 按总线功能分类
    1. 片内总线
    • 片内总线是芯片内部的总线。
    • 它是CPU芯片内部寄存器与寄存器之间、寄存器与ALU之间的公共连接线。
    1. 系统总线
      系统总线是计算机系统内各功能部件(CPU、主存、l/O接口)之间相互连接的总线。
      按系统总线传输信息内容的不同,又可分为3类:数据总线、地址总线和控制总线
      在这里插入图片描述
    1. 数据总线用来传输各功能部件之间的数据信息,它是双向传输总线,其位数与机器字长、存储字长有关。

    数据通路表示的是数据流经的路径
    数据总线是承载的媒介

    1. 地址总线用来指出数据总线上的源数据或目的数据所在的主存单元或I/O端口的地址,它是单向传输总线,地址总线的位数与主存地址空间的大小有关
    2. 控制总线传输的是控制信息,包括CPU送出的控制命令和主存(或外设)返回CPU的反馈信
    1. 通信总线

    通信总线是用于计算机系统之间或计算机系统与其他系统(如远程通信设备、测试设备)之间信息传送的总线,通信总线也称为外部总线。

    1.5 系统总线的结构

    1. 单总线结构
      在这里插入图片描述
    • 结构:CPU、主存、I/O设备(通过I/O接口)都连接在一组总线上,允许I/O设备之间、I/O设备和CPU之间或I/O设备与主存之间直接交换信息。

    :单总线并不是指只有一根信号线,系统总线按传送信息的不同可以细分为地址总线、数据总线和控制总线。

    • 优点:结构简单,成本低,易于接入新的设备。
    • 缺点:带宽低、负载重,多个部件只能争用唯一的总线,且不支持并发传送操作。
    1. 双总线结构
      在这里插入图片描述
    • 主存总线:支持突发(猝发)传送:送出一个地址,收到多个地址连续的数据。
    • 通道是具有特殊功能的处理器,能对I/O设备进行统一管理。通道程序放在主存中。
    • 结构:双总线结构有两条总线,一条是主存总线 ,用于CPU、主存和通道之间进行数据传送;另一条是I/O总线 ,用于多个外部设备与通道之间进行数据传送。
    • 优点:将较低速的I/O设备从单总线上分离出来,实现存储器总线和I/O总线分离。
    • 缺点:需要增加通道等硬件设备。
    1. 三总线结构
      在这里插入图片描述
    • 结构:三总线结构是在计算机系统各部件之间采用3条各自独立的总线来构成信息通路,这3条总线分别为主存总线I/O总线 和直接内存访问DMA总线
    • 优点:提高了I/O设备的性能,使其更快地响应命令,提高系统吞吐量。
    • 缺点:系统工作效率较低。
    1. 四总线结构简介
      在这里插入图片描述
    • 1.桥接器:用于连接不同的总线,具有数据缓冲、转换和控制功能。
    • 2.靠近CPU的总线速度较快。
    • 3.每级总线的设计遵循总线标准。

    1.6 总线概念与分类小结

    在这里插入图片描述

    2 总线的性能指标

    总线的性能指标

    (1)总线的传输周期(总线周期)
    (2)总线时钟周期
    (3)总线的工作频率
    (4)总线的时钟频率
    (5)总线宽度
    (6)总线带宽
    (7)总线复用
    (8)信号线数

    2.1 性能指标分析

    1. 总线的传输周期(总线周期)

    总线的工作通过时钟控制
    在这里插入图片描述
    一次总线操作所需的时间(包括申请阶段、寻址阶段、传输阶段和结束阶段对应T1~T4),通常由若干个总线时钟周期构成。

    1. 总线时钟周期

    即机器的时钟周期。计算机有一个统一的时钟,以控制整个计算机的各个部件,总线也要受此时钟的控制。

    1. 总线的工作频率

    总线上各种操作的频率,为总线周期的倒数。
    若总线周期=N个时钟周期,则总线的工作频率=时钟频率/N
    实际上指一秒内传送几次数据。

    1. 总线的时钟频率

    即机器的时钟频率,为时钟周期的倒数。若时钟周期为T,则时钟频率为1/T
    实际上指一秒内有多少个时钟周期。

    1. 总线宽度

    又称为总线位宽,它是总线上同时能够传输的数据位数,通常是指数据总线的根数,如32根称为32位(bit)总线。

    1. 总线带宽

    可理解为总线的数据传输率,即单位时间内总线上可传输数据的位数,通常用每秒钟传送信息的字节数来衡量,单位可用字节/秒(B/s)表示。

    总线带宽=总线工作频率×总线宽度(bit/s)=总线工作频率×(总线宽度/8)(B/s)
    在这里插入图片描述
    注:总线带宽是指总线本身所能达到的最高传输速率。
    在计算实际的有效数据传输率时,要用实际传输的数据量除以耗时。

    例题:某同步总线采用数据线和地址线复用方式,其中地址/数据线有32根,总线时钟频率为66MHz,每个时钟周期传送两次数据(上升沿和下降沿各传送一次数据)。

    1. 该总线的最大数据传输率(总线带宽)是多少?
    2. 若该总线支持突发(猝发)传输方式,传输一个地址占用一个时钟周期,则一次“主存写”总线事务传输128位数据所需要的时间至少是多少?

    解答

    1. 每个时钟周期传送两次数据→总线工作频率是时钟频率的两倍
      总线工作频率=2×66MHz=132MHz
      总线宽度=32bit=4B
      总线带宽=总线工作频率×总线宽度=132×4MB/s=528MB/s
    2. 突发(猝发)传输方式:一次总线事务中,主设备只需给出一个首地址,从设备就能从首地址开始的若干连续单元读出或写入多个数据。
      发送首地址占用1个时钟周期,128位数据需传输4次,占用2个时钟周期
      一个时钟周期=1/66MHz=15ns
      总耗时=(1+2)×15ns=45ns

    由总线带宽=总线工作频率×总线宽度(bit/s)可知:

    1. 工作频率相同时,串行总线传输速度比并行总线慢。
    2. 并行总线的工作频率无法持续提高,而串行总线可以通过不断提高工作频率来提高传输速度,最终超过并行总线。
    1. 总线复用

    总线复用是指一种信号线在不同的时间传输不同的息。
    可以使用较少的线传输更多的信息,从而节省了空间和成本。

    在这里插入图片描述
    AD0 ~AD15 数据线和地址线复用,不同时刻传递不同类型数据

    1. 信号线数

    地址总线、数据总线和控制总线3种总线数的总和称为信号线数。

    2.2 总线性能指标小结

    1. 总线的传输周期(总线周期)

    一次总线操作所需的时间(包括申请阶段、寻址阶段、传输阶段和结束阶段),通常由若干个总线时钟周期构成。

    1. 总线时钟周期

    即机器的时钟周期。计算机有一个统一的时钟,以控制整个计算机的各个部件,总线也要受此时钟的控制。

    1. 总线的工作频率

    总线上各种操作的频率,为总线周期的倒数。实际上指一秒内传送几次数据。

    1. 总线的时钟频率

    即机器的时钟频率,为时钟周期的倒数。实际上指一秒内有多少个时钟周期。

    1. 总线宽度

    又称为总线位宽,它是总线上同时能够传输的数据位数,通常是指数据总线的根数,如32根称为32位(bit)总线。

    1. 总线带宽

    可理解为总线的数据传输率,即单位时间内总线上可传输数据的位数,通常用每秒钟传送信息的字节数来衡量,单位可用字节/秒(B/s)表示。
    总线带宽=总线工作频率×总线宽度(bit/s)=总线工作频率×(总线宽度/8)(B/s)

    1. 总线复用

    总线复用是指一种信号线在不同的时间传输不同的信息。可以使用较少的线传输更多的信息,从而节省了空间和成本。

    1. 信号线数

    地址总线、数据总线和控制总线3种总线数的总和称为信号线数。

    3 总线仲裁

    3.1 总线仲裁的基本概念

    同一时刻只能有一个设备控制总线传输操作,可以有一个或多个设备从总线接收数据。
    在这里插入图片描述
    将总线上所连接的各类设备按其对总线有无控制功能分为:

    • 主设备:获得总线控制权的设备。
    • 从设备:被主设备访问的设备,只能响应从主设备发来的各种总线命令。

    为什么要仲裁?

    总线作为一种共享设备,不可避免地会出现同一时刻有多个主设备竞争总线控制权的问题。

    总线仲裁的定义:

    多个主设备同时竞争主线控制权时,以某种方式选择一个主设备优先获得总线控制权称为总线仲裁。

    总线仲裁分类:

    • 集中仲裁方式:链式查询方式、计数器定时查询方式、独立请求方式
    • 分布仲裁方式:自举分布、冲突检测、并行竞争

    3.2 集中仲裁方式

    工作流程:

    1. 主设备发出请求信号;
    2. 若多个主设备同时要使用总线,则由总线控制器的判优、仲裁逻辑按一定的优先等级顺序确定哪个主设备能使用总线;
    3. 获得总线使用权的主设备开始传送数据。
    3.2.1 链式查询方式

    在这里插入图片描述
    在这里插入图片描述
    设备1和设备n同时申请总线,先把总线分配给设备1,待设备1完成后再分配给设备n

    “总线忙”信号的建立者是获得总线控制权的设备

    优先级

    离总线控制器越近的部件,其优先级越高;
    离总线控制器越远的部件,其优先级越低。

    优点

    链式查询方式优先级固定。
    只需很少几根控制线就能按一定优先次序实现总线控制,结构简单,扩充容易。

    缺点

    对硬件电路的故障敏感,并且优先级不能改变。
    当优先级高的部件频繁请求使用总线时,会使优先级较低的部件长期不能使用总线。

    3.2.2 计数器查询方式

    在这里插入图片描述
    结构特点:用一个计数器控制总线使用权,相对链式查询方式多了一组设备地址线,少了一根总线响应线BG;它仍共用一根总线请求线BR

    工作方式

    • 当总线控制器收到总线请求信号,判断总线空闲时,计数器开始计数,计数值通过设备地址线发向各个部件。
    • 当地址线上的计数值与请求使用总线设备的地址一致时,该设备获得总线控制权。同时,中止计数器的计数及查询。

    优点

    1. 计数初始值可以改变优先次序

    计数每次从“0”开始,设备的优先级就按顺序排列,固定不变;
    计数从上一次的终点开始,此时设备使用总线的优先级相等;
    计数器的初值还可以由程序设置

    1. 对电路的故障没有链式敏感

    缺点

    1. 增加了控制线数

    若设备有n个,则需 log2n+2条控制线

    1. 控制相对比链式查询相对复杂
    3.2.3 独立请求方式

    结构特点:每一个设备均有一对总线请求线BRi和总线允许线BGi在这里插入图片描述
    当总线控制器按一定的优先次序决定批准某个部件的请求时,则给该部件发送总线响应信号。

    优点:

    1. 响应速度快,总线允许信号BG直接从控制器发送到有关设备,不必在设备间传递或者查询。
    2. 对优先次序的控制相当灵活。

    缺点:

    1. 控制线数量多

    若设备有n个,则需要2n+1条控制线。其中+1为BS线,其用处为,用于设备向总线控制部件反馈已经使用完毕总线。

    1. 总线的控制逻辑更加复杂。

    3.3 集中仲裁方式小结

    在这里插入图片描述
    “总线忙”信号的建立者是获得总线控制权的设备,不是总线控制器!

    3.4 分布式仲裁

    特点:不需要中央仲裁器,每个潜在的主模块都有自己的仲裁器和仲裁号,多个仲裁器竞争使用总线。

    (1)当设备有总线请求时,它们就把各自唯一的仲裁号发送到共享的仲裁总线上;
    (2)每个仲裁器将从仲裁总线上得到的仲裁号与自己的仲裁号进行比较;
    (3)如果仲裁总线上的号优先级高,则它的总线请求不予响应,并撤销它的仲裁号;
    (4)最后,获胜者的仲裁号保留在仲裁总线上。

    4 总线操作和定时

    4.1 总线传输的四个阶段

    总线周期的四个阶段

    1. 申请分配阶段:由需要使用总线的主模块(或主设备)提出申请,经总线仲裁机构决定将下一传输周期的总线使用权授予某一申请者。也可将此阶段细分为传输请求总线仲裁两个阶段。
    2. 寻址阶段:获得使用权的主模块通过总线发出本次要访问的从模块的地址及有关命令,启动参与本次传输的从模块。
    3. 传输阶段:主模块和从模块进行数据交换,可单向或双向进行数据传送。
    4. 结束阶段:主模块的有关信息均从系统总线上撤除,让出总线使用权。

    总线定时是指总线在双方交换数据的过程中需要时间上配合关系的控制,这种控制称为总线定时,它的实质是一种协议或规则

    1. 同步通信(同步定时方式)由统一时钟控制数据传送
    2. 异步通信(异步定时方式) 采用应答方式,没有公共时钟标准
    3. 半同步通信 同步、异步结合
    4. 分离式通信 充分挖掘系统总线每瞬间的潜力

    4.2 同步定时方式

    系统采用一个统一的时钟信号来协调发送和接收双方的传送定时关系。
    在这里插入图片描述
    一个读命令执行过程:

    在这里插入图片描述

    1. CPU在T1时刻的上升沿给出地址信息
    2. 在T2的上升沿给出读命令(低电平有效),与地址信息相符合的输入设备按命令进行一系列的内部操作,且必须在T3的上升沿来之前将CPU所需的数据送到数据总线上。
    3. CPU在T3时钟周期内,将数据线上的信息传送到其内部寄存器中。
    4. CPU在T4的上升沿撤销读命令,输入设备不再向数据总线上传送数据,撤销它对数据总线的驱动。
    • 同步定时方式是指系统采用一个统一的时钟信号来协调发送和接收双方的传送定时关系。
    • 时钟产生相等的时间间隔,每个间隔构成一个总线周期。
    • 在一个总线周期中,发送方和接收方可进行一次数据传送。
    • 因为采用统一的时钟,每个部件或设备发送或接收信息都在固定的总线传送周期中,一个总线的传送周期结束,下一个总线传送周期开始。

    优点:传送速度快,具有较高的传输速率;总线控制逻辑简单。
    缺点:主从设备属于强制性同步;不能及时进行数据通信的有效性检验,可靠性较差。

    同步通信适用于总线长度较短及总线所接部件的存取时间比较接近的系统。

    4.3 异步定时方式

    • 在异步定时方式中,没有统一的时钟,也没有固定的时间间隔,完全依靠传送双方相互制约的“握手”信号来实现定时控制。
    • 主设备提出交换信息的“请求”信号,经接口传送到从设备;
    • 从设备接到主设备的请求后,通过接口向主设备发出“回答”信号。

    根据“请求”和“回答”信号的撤销是否互锁,分为以下3种类型。

    (1)不互锁方式
    (2)半互锁方式
    (3)全互锁方式

    1. 不互锁方式
    • 主设备发出“请求”信号后,不必等到接到从设备的“回答”信号,而是经过一段时间,便撤销“请求”信号。
    • 而从设备在接到“请求”信号后,发出“回答”信号,并经过一段时间,自动撤销“回答”信号。双方不存在互锁关系。
      在这里插入图片描述
    1. 半互锁方式
    • 主设备发出“请求”信号后,必须待接到从设备的“回答”信号后,才撤销“请求”信号,有互锁的关系。
    • 而从设备在接到“请求”信号后,发出“回答”信号,但不必等待获知主设备的“请求”信号已经撤销,而是隔一段时间后自动撤销“回答”信号,不存在互锁关系。
      在这里插入图片描述
    1. 全互锁方式
    • 主设备发出“请求”信号后,必须待从设备“回答”后,才撤销“请求”信号;
    • 从设备发出“回答”信号,必须待获知主设备“请求”信号已撤销后,再撤销其“回答”信号。双方存在互锁关系。
      在这里插入图片描述

    不互锁方式速度最快可靠性最差;全互锁方式最可靠速度最慢

    优点:总线周期长度可变,能保证两个工作速度相差很大的部件或设备之间可靠地进行信息交换,自动适应时间的配合。
    缺点:比同步控制方式稍复杂一些,速度比同步定时方式慢。

    异步定时方式-数据传输率例题:

    在异步串行传输方式下,起始位为1位,数据位为7位,偶校验位为1位,停止位为1位,如果波特率为1200bit/s,求这时的有效数据传输率为多少?

    补充:

    波特率:单位时间内传送的二进制数据的位数,单位用bps(位/秒)表示,记作波特
    比特率:单位时间内传送二进制有效数据的位数,单位用bps表示,bps即bit/s
    在这里插入图片描述
    有效数据传输率即比特率

    解答:每传送(1+1+7+1)=10个二进制位,就传送了7个有效数据位
    故有效数据传输率为1200×7/(1+7+1+1)=840bit/s

    4.4 半同步通信

    同步

    发送方用系统时钟前沿发信号
    接收方用系统时钟后沿判断、识别

    异步

    允许不同速度的模块和谐工作

    半同步通信:同步通信和异步通信的结合
    在这里插入图片描述

    4.5 分离式通信

    上述三种通信的共同点:

    一个总线传输周期(以输入数据为例):

    分离式通信的一个总线传输周期

    • 子周期1:主模块申请占用总线,使用完后放弃总线的使用权
    • 子周期2:从模块申请占用总线,将各种信息送至总线上

    特点:

    1. 各模块均有权申请占用总线
    2. 采用同步方式通信,不等对方回答
    3. 各模块准备数据时,不占用总线
    4. 总线利用率提高

    5 总线标准

    5.1 总线标准的基本概念

    • 总线标准是国际上公布或推荐的互连各个模块的标准,它是把各种不同的模块组成计算机系统时必须遵守的规范。
    • 按总线标准设计的接口可视为通用接口,在接口的两端,任何一方只需根据总线标准的要求完成自身方面的功能要求,而无须了解对方接口的要求。
    • 系统总线标准:ISA、EISA、VESA、PCI、PCI-Express等。
    • 设备总线标准:IDE、AGP、RS-232C、USB、SATA、SCSI、PCMCIA等。
    • 局部总线标准:在ISA总线和CPU总线之间增加的一级总线或管理层,如PCI、PCI-E、VESA、AGP等,可以节省系统的总带宽。
    • 即插即用(Plug-and-Play)的作用是自动配置(低层)计算机中的板卡和其他设备,然后告诉对应的设备都做了什么。把物理设备和软件(设备驱动程序)相配合,并操作设备,在每个设备和它的驱动程序之间建立通信信道。
    • 热插拔(hot-pluggingHot Swap)即带电插拔,热插拔功能就是允许用户在不关闭系统,不切断电源的情况下取出和更换损坏的硬盘、电源或板卡等部件,从而提高了系统对灾难的及时恢复能力、扩展性和灵活性等,例如一些面向高端应用的磁盘镜像系统都可以提供磁盘的热插拔功能。

    5.2 总线标准

    在这里插入图片描述

    5.2.1 系统总线标准

    在这里插入图片描述

    最早的PC总线是IBM公司1981年在PC/XT电脑采用的系统总线,它基于8bit的8088处理器,被称为PC总线或者PC/XT总线。

    1984年,IBM推出基于16-bit Intel80286处理器的PC/AT电脑,系统总线也相应地扩展为16bit,并被称呼为PC/AT总线。而为了开发与IBMPC兼容的外围设备,行业内便逐渐确立了以IBMPC总线规范为基础的ISA(工业标准架构:Industry Standard Architecture)总线。

    ISA总线最大传输速率仅为8MB/s,数据传送需要CPU或DMA接口来管理,传输速率过低、CPU占用率高、占用硬件中断资源等,很快使ISA总线在飞速发展的计算机技术中成为瓶颈。不支持总线仲裁

    因此在1988年,康柏、惠普等9个厂商协同把ISA扩展到32-bit,这就是著名的EISA(Extended ISA,扩展ISA)总线。EISA总线的工作频率仍旧仅有8MHz,并且与8/16bit的ISA总线完全兼容,带宽提高了一倍,达到了32MB/s。从CPU中分离出了总线控制权,支持多个总线主控器和突发传送。可惜的是,EISA仍旧由于速度有限,并且成本过高,在还没成为标准总线之前,在20世纪90年代初的时候,就给PCI总线给取代了。

    5.2.2 局部总线标准

    在这里插入图片描述

    由于ISA/EISA总线速度缓慢,造成硬盘、显示卡还有其它的外围设备只能通过慢速并且狭窄的瓶颈来发送和接受数据,使得整机的性能受到严重的影响。为了解决这个问题,1992年Intel在发布486处理器的时候,也同时提出了32-bit的PCI(周边组件互连)总线。

    最早提出的PCI总线工作在33MHz频率之下,传输带宽达到了133MB/s(33MHzX32bit/8),比ISA总线有了极大的改善,基本上满足了当时处理器的发展需要。
    目前计算机上广泛采用的是这种32-bit、33MHz的PCI总线,可扩展到64bit。

    特点:

    1. 高性能:不依附于某个具体的处理器,支持突发传送。
    2. 良好的兼容性。
    3. 支持即插即用。
    4. 支持多主设备。
    5. 具有与处理器和存储器子系统完全并行操作的能力。
    6. 提供数据和地址奇偶校验的能力。
    7. 可扩充性好,可采用多层结构提高驱动能力。
    8. 采用多路复用技术,减少了总线引脚个数。
    5.2.3 设备总线标准

    在这里插入图片描述

    • USB是在1994年底由英特尔等多家公司联合在1996年推出后,已成功替代串口和并口,已成为当今电脑与大量智能设备的必配接口。USB属于设备总线,是设备和设备控制器之间的接口
    • USB所有新版本都向下兼容,可以连接鼠标、键盘、打印机、扫描仪、摄像头、充电器、闪存盘、MP3机、手机、数码相机、移动硬盘、外置光软驱、USB网卡、ADSL Modem、Cable Modem等几乎所有的外部设备。

    特点:

    1. 可以热插拔、即插即用。
    2. 具有很强的连接能力和很好的可扩充性。采用菊花链形式将众多外设连接起来,可使用USB集线器链式连接127个外设。
    3. 标准统一。以前大家常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫描仪,可是有了USB之后,这些应用外设统统可以用同样的标准与个人电脑连接,这时就有了USB硬盘、USB鼠标、USB打印机等等。
    4. 高速传输。
    5. 连接电缆轻巧,可为低压(5V)外设供电。

    计算机内部总线连接情况如下:

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 好久好久没有写博客了~唉~...用的是标准总线结构,锁存器用的74L373,RAM用的6264,液晶1602,使能用74LS00来选择。最后用7407作为了 驱动。 本来他们公司给的代码说的C51,实际上核心的确C,不过LCD

     好久好久没有写博客了~唉~最近弄得东西都是实物没什么研究可写,全部就是调试啊调试啊~还是写一点东西吧。

    最近做了一个基于51外部扩展RAM的小计算器。

     

     这是仿真SAMPLE的图

    用的是标准的总线结构,锁存器用的74L373,RAM用的是6264,液晶是1602,使能用74LS00来选择。最后用7407作为了

    驱动。

    本来他们公司给的代码说的是C51,实际上核心的确是C,不过LCD和键盘用的都是汇编。由于正在略微研究下外部扩展就拿来做出来顺便把代码都改成C的。LCD的驱动完全是总线结构,根据硬件连接来写代码。下面把LCD的代码汇编和C都放上来

    我把前面汇编的注释掉了~

    1.          /****************************************************************************** 
    2. ************                LABCENTER ELECTRONICS                   ************                               
    3. ************             Proteus VSM Sample Design Code             ************             
    4. ************            Integer Calculator ( 2K Code Limit)         ************ 
    5. ********************************************************************************/  
    6. /*汇编 
    7. NAME    LCD 
    8.  
    9. ;Set up Code Segment and exports: 
    10.  
    11. LCD              SEGMENT CODE 
    12. RSEG             LCD 
    13.  
    14.                  PUBLIC  _output 
    15.                  PUBLIC  initialise 
    16.                  PUBLIC  clearscreen 
    17.  
    18.  
    19. ;LCD Register Addresses. 
    20. LCD_CMD_WR  equ     00h 
    21. LCD_DATA_WR equ 01h 
    22. LCD_BUSY_RD equ 02h 
    23. LCD_DATA_RD equ 03h 
    24. LCD_PAGE    equ 80h 
    25.  
    26. ;LCD Commands 
    27. LCD_CLS     equ 1 
    28. LCD_HOME    equ 2 
    29. LCD_SETMODE equ 4 
    30. LCD_SETVISIBLE  equ 8 
    31. LCD_SHIFT   equ 16 
    32. LCD_SETFUNCTION equ 32 
    33. LCD_SETCGADDR   equ 64 
    34. LCD_SETDDADDR   equ 128 
    35.  
    36.  
    37.  
    38.  
    39. ; Initialisation Routine for the LCD display. 
    40. initialise:     mov A,#030h         ;1 line, 8 bits 
    41.         call wrcmd 
    42.         mov A,#LCD_SETVISIBLE + 4 
    43.         call wrcmd 
    44.         mov A,#LCD_SETDDADDR+15     ; Start at right hand side of the display 
    45.         call wrcmd 
    46.         mov A,#LCD_SETMODE + 3      ; Automatic Increment - Display shift left.   
    47.         call wrcmd 
    48.                 ret 
    49.  
    50. ; We move the parameter (held in R7) into the Accumulator prior to writing it. 
    51. _output:    mov A,R7     
    52.         call wrdata 
    53.         ret 
    54.  
    55.  
    56. ;Clears the LCD display and sets the initialisation conditions. 
    57. clearscreen:    mov A,#LCD_CLS 
    58.         call wrcmd 
    59.         mov A,#LCD_SETDDADDR + 15 
    60.         call wrcmd 
    61.         ret 
    62.  
    63.          
    64.          
    65. ;***************************** 
    66. ;******** SUBROUTINES ******** 
    67. ;***************************** 
    68.  
    69. ;Sub routine to write command: 
    70. wrcmd:      mov P2,#LCD_PAGE 
    71.         mov R0,#LCD_CMD_WR 
    72.         movx @R0,A 
    73.         jmp wtbusy 
    74.  
    75. ; Subroutine to Write a Character to the LCD Display. 
    76. wrdata:     MOV P2,#LCD_PAGE                 
    77.         MOV R0,#LCD_DATA_WR 
    78.         MOV A,R7 
    79.         MOVX @R0,A 
    80.  
    81.  
    82. ; Subroutine to wait for a busy clear.   
    83. wtbusy:     MOV R1,#LCD_BUSY_RD 
    84.         MOVX A,@R1 
    85.         JB ACC.7,wtbusy 
    86.                 ret 
    87.  
    88.                 END 
    89.         */  
    90.   
    91. #ifndef _LCD1602_H_  
    92. #define _LCD1602_H_  
    93. #include <reg52.h>  
    94. #include <intrins.h>  
    95. #include <absacc.h>  
    96. #define clear 0x01  
    97. #define ret 0x02  
    98. #define fuction_set_usual 0x38    
    99. /********************************显示数据表*********************************/  
    100. enum Mode{in_shift,in_nshift,de_shift,de_nshift};  
    101. unsigned char Entry_Mode[]={0x07,0x06,0x05,0x04};   
    102. // Display_Control 其中几位靠位来吧,比较多,这个命令控制了是否显示,光标是否显示和闪烁功能  
    103. // 通用函数  
    104. /*********************************端口定义**********************************/  
    105. #define LCMDW       XBYTE[0x8001]       // 数据口  
    106. #define LCMCW       XBYTE[0x8000]       // 命令  
    107. #define LCMBY       XBYTE[0x8002]  
    108. //sbit ep = P2^2;  
    109. /********************************显示数据表*********************************/  
    110. //00-0h乃是GGRAM自定义库的自建位  
    111. unsigned char  CGCODE[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02,//"年"代码 0x00  
    112.    0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00,//"月"代码 0x01  
    113.    0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00,//"日"代码  0x02  
    114.    0x07,0x04,0x07,0x04,0x07,0x00,0x04,0x07,//"星"左上半部分代码 0x03  
    115.    0x1F,0x01,0x1F,0x01,0x1F,0x08,0x08,0x1F,//"星"右上半部分代码 0x04  
    116.    0x08,0x17,0x00,0x1F,0x00,0x00,0x00,0x00,//"星"左下半部分代码 0x05  
    117.    0x08,0x1F,0x08,0x1F,0x00,0x00,0x00,0x00//"星"右下半部分代码 0x06    
    118.    };  
    119. unsigned char  tab[]={'1','0',0x00,'0','3',0x01,'0','9',0x02};//显示"08年03月09日"     
    120. /***************************************************************************** 
    121. 函数功能:LCD延时子程序 
    122.  
    123. 入口参数:ms 
    124.  
    125. 出口参数: 
    126.  
    127. *****************************************************************************/  
    128.   
    129. void delay(unsigned char ms)  
    130. {  
    131. unsigned char i;  
    132.   
    133. while(ms--)  
    134.   
    135. {  
    136.   
    137. for(i = 0; i< 250; i++)  
    138.   
    139. {  
    140.   
    141. _nop_();  
    142.   
    143. _nop_();  
    144.   
    145. _nop_();  
    146.   
    147. _nop_();  
    148.   
    149. }  
    150.   
    151. }  
    152.   
    153. }  
    154.   
    155. /***************************************************************************** 
    156.  
    157. 函数功能:测试LCD忙碌状态 
    158.  
    159. 入口参数: 
    160.  
    161. 出口参数:result 
    162.  
    163. *****************************************************************************/  
    164. bit lcd_bz()  
    165. {  
    166. bit result;  
    167. //ep = 1;  
    168.   
    169. //_nop_();  
    170.   
    171. //_nop_();  
    172.   
    173. //_nop_();  
    174.   
    175. //_nop_();  
    176. result = (bit)(LCMBY&0x80);//高1就是D7  
    177. //ep=0;  
    178. return result;  
    179. }  
    180. /***************************************************************************** 
    181.  
    182. 函数功能:写指令数据到LCD子程序 
    183.  
    184. 入口参数:cmd 
    185.  
    186. 出口参数: 
    187.  
    188. *****************************************************************************/  
    189.   
    190. void lcd_wcmd(unsigned char cmd)  
    191. {  
    192.   
    193. while(lcd_bz());//判断LCD是否忙碌  
    194.   
    195.   
    196. //ep = 0;  
    197.   
    198. //_nop_();  
    199.   
    200. //_nop_();  
    201.   
    202. LCMCW = cmd;  
    203.   
    204. //_nop_();  
    205.   
    206. //_nop_();  
    207.   
    208. //_nop_();  
    209.   
    210. //_nop_();  
    211.   
    212. //ep = 1;  
    213.   
    214. //_nop_();  
    215.   
    216. //_nop_();  
    217.   
    218. //_nop_();  
    219.   
    220. //_nop_();  
    221.   
    222. //ep = 0;  
    223.   
    224. }  
    225.   
    226. /***************************************************************************** 
    227.  
    228. 函数功能:设定显示位置子程序 
    229.  
    230. 入口参数:pos 
    231.  
    232. 出口参数: 
    233.  
    234. *****************************************************************************/  
    235.   
    236. void lcd_pos(unsigned char pos)  
    237.   
    238. {  
    239.   
    240. lcd_wcmd(pos | 0x80);  
    241.   
    242. }  
    243.   
    244. /***************************************************************************** 
    245.  
    246. 函数功能:写入显示数据到LCD子程序 
    247.  
    248. 入口参数:dat 
    249.  
    250. 出口参数: 
    251.  
    252. *****************************************************************************/  
    253.   
    254. void lcd_wdat(unsigned char dat)  
    255.   
    256. {  
    257.   
    258. while(lcd_bz());//判断LCD是否忙碌  
    259.   
    260.   
    261. //ep = 0;  
    262.  LCMDW = dat;  
    263.   
    264. //_nop_();  
    265.   
    266. //_nop_();  
    267.   
    268. //_nop_();  
    269.   
    270. //_nop_();  
    271.   
    272. //ep = 1;  
    273.   
    274. //_nop_();  
    275.   
    276. //_nop_();  
    277.   
    278. //_nop_();  
    279.   
    280. //_nop_();  
    281.   
    282. //ep = 0;  
    283.   
    284. }  
    285.   
    286. /***************************************************************************** 
    287.  
    288. 函数功能:LCD初始化子程序 
    289.  
    290. 写指令38H:显示模式设置 
    291.  
    292. 写指令08H:显示关闭 
    293.  
    294. 写指令01H:显示清屏 
    295.  
    296. 写指令06H:显示光标移动设置 
    297.  
    298. 写指令0CH:显示开及光标设置 
    299.  
    300. 入口参数: 
    301.  
    302. 出口参数: 
    303.  
    304. *****************************************************************************/  
    305.   
    306. void lcd_init()  
    307.   
    308. {  
    309.   
    310. lcd_wcmd(0x38);  
    311.   
    312. delay(1);  
    313.   
    314. lcd_wcmd(0x0c);  
    315.   
    316. delay(1);  
    317.   
    318. lcd_wcmd(0x06);  
    319.   
    320. delay(1);  
    321.   
    322. lcd_wcmd(0x01);  
    323.   
    324. delay(1);  
    325.   
    326. }  
    327.   
    328.   
    329. /***************************************************************************** 
    330.  
    331. 函数功能:画图 
    332.  
    333. 入口参数: 
    334.  
    335. 出口参数: 
    336.  
    337. *****************************************************************************/  
    338.   
    339. void draw()  
    340. {  
    341.  int i;  
    342.  lcd_init();  
    343.  delay(10)   ;  
    344.  lcd_wcmd(0x40);//将自定义字符写入CGRAM   
    345.  for(i=0;i<56;i++)//循环56次写入  
    346.  {  
    347.  lcd_wdat(CGCODE[i]);     
    348.  }  
    349.  lcd_wcmd(0x80);//写入初始地址  
    350.  for(i=0;i<9;i++)  
    351.  {  
    352.   lcd_wdat(tab[i]);  
    353.  }   
    354.  }  
    355. #endif   

    详细看代码就可以了,其中汇编的关键在MOVX的使用上,时序图可以查的到,可以研究一下~其中把LCD的地址当做寄存器来看待

    每次先选好使用再给数据,就可行了~

    主要说C

    首先说明~C语言是我从以前的非总线式结构里面改写的。因此有些函数没有用到。

    C语言的关键在这里就是

    #define LCMDW  XBYTE[0x8001]  // 数据口
    #define LCMCW  XBYTE[0x8000]  // 命令
    #define LCMBY       XBYTE[0x8002] //忙检测

    XBYTE是在absacc.h库里的一个定义地址的工具

    其中有~#define XBYTE ((unsigned char volatile xdata *) 0)

    其中根据硬件连接高2位的使能打开正是80H的地址,低2位的地址根据功能(A0,A1)定义不同的地址

    然后在输出的时候协商

    LCMDW=*****;就可以实现MOVX的功能了,产生外部存储的时序来啦~

    液晶怎么使用就看数据手册吧,1602的手册可是很全很很全,网上的例子更是很多很多(把上面代码稍微改动就可以直接使用lcd了哈)

    接下来给出SAMPLE里我一点没动的核心,计算器的算法实现

     

    [c-sharp] view plaincopy
    1.          /****************************************************************************** 
    2. ************                LABCENTER ELECTRONICS                   ************                               
    3. ************             Proteus VSM Sample Design Code             ************             
    4. ************            Integer Calculator ( 2K Code Limit)         ************ 
    5. ********************************************************************************/  
    6. /*汇编 
    7. NAME    LCD 
    8.  
    9. ;Set up Code Segment and exports: 
    10.  
    11. LCD              SEGMENT CODE 
    12. RSEG             LCD 
    13.  
    14.                  PUBLIC  _output 
    15.                  PUBLIC  initialise 
    16.                  PUBLIC  clearscreen 
    17.  
    18.  
    19. ;LCD Register Addresses. 
    20. LCD_CMD_WR  equ     00h 
    21. LCD_DATA_WR equ 01h 
    22. LCD_BUSY_RD equ 02h 
    23. LCD_DATA_RD equ 03h 
    24. LCD_PAGE    equ 80h 
    25.  
    26. ;LCD Commands 
    27. LCD_CLS     equ 1 
    28. LCD_HOME    equ 2 
    29. LCD_SETMODE equ 4 
    30. LCD_SETVISIBLE  equ 8 
    31. LCD_SHIFT   equ 16 
    32. LCD_SETFUNCTION equ 32 
    33. LCD_SETCGADDR   equ 64 
    34. LCD_SETDDADDR   equ 128 
    35.  
    36.  
    37.  
    38.  
    39. ; Initialisation Routine for the LCD display. 
    40. initialise:     mov A,#030h         ;1 line, 8 bits 
    41.         call wrcmd 
    42.         mov A,#LCD_SETVISIBLE + 4 
    43.         call wrcmd 
    44.         mov A,#LCD_SETDDADDR+15     ; Start at right hand side of the display 
    45.         call wrcmd 
    46.         mov A,#LCD_SETMODE + 3      ; Automatic Increment - Display shift left.   
    47.         call wrcmd 
    48.                 ret 
    49.  
    50. ; We move the parameter (held in R7) into the Accumulator prior to writing it. 
    51. _output:    mov A,R7     
    52.         call wrdata 
    53.         ret 
    54.  
    55.  
    56. ;Clears the LCD display and sets the initialisation conditions. 
    57. clearscreen:    mov A,#LCD_CLS 
    58.         call wrcmd 
    59.         mov A,#LCD_SETDDADDR + 15 
    60.         call wrcmd 
    61.         ret 
    62.  
    63.          
    64.          
    65. ;***************************** 
    66. ;******** SUBROUTINES ******** 
    67. ;***************************** 
    68.  
    69. ;Sub routine to write command: 
    70. wrcmd:      mov P2,#LCD_PAGE 
    71.         mov R0,#LCD_CMD_WR 
    72.         movx @R0,A 
    73.         jmp wtbusy 
    74.  
    75. ; Subroutine to Write a Character to the LCD Display. 
    76. wrdata:     MOV P2,#LCD_PAGE                 
    77.         MOV R0,#LCD_DATA_WR 
    78.         MOV A,R7 
    79.         MOVX @R0,A 
    80.  
    81.  
    82. ; Subroutine to wait for a busy clear.   
    83. wtbusy:     MOV R1,#LCD_BUSY_RD 
    84.         MOVX A,@R1 
    85.         JB ACC.7,wtbusy 
    86.                 ret 
    87.  
    88.                 END 
    89.         */  
    90.  
    91. #ifndef _LCD1602_H_  
    92. #define _LCD1602_H_  
    93. #include <reg52.h>  
    94. #include <intrins.h>  
    95. #include <absacc.h>  
    96. #define clear 0x01  
    97. #define ret 0x02  
    98. #define fuction_set_usual 0x38    
    99. /********************************显示数据表*********************************/  
    100. enum Mode{in_shift,in_nshift,de_shift,de_nshift};  
    101. unsigned char Entry_Mode[]={0x07,0x06,0x05,0x04};   
    102. // Display_Control 其中几位靠位来吧,比较多,这个命令控制了是否显示,光标是否显示和闪烁功能  
    103. // 通用函数  
    104. /*********************************端口定义**********************************/  
    105. #define LCMDW       XBYTE[0x8001]       // 数据口  
    106. #define LCMCW       XBYTE[0x8000]       // 命令  
    107. #define LCMBY       XBYTE[0x8002]  
    108. //sbit ep = P2^2;  
    109. /********************************显示数据表*********************************/  
    110. //00-0h乃是GGRAM自定义库的自建位  
    111. unsigned char  CGCODE[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02,//"年"代码 0x00  
    112.    0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00,//"月"代码 0x01  
    113.    0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00,//"日"代码  0x02  
    114.    0x07,0x04,0x07,0x04,0x07,0x00,0x04,0x07,//"星"左上半部分代码 0x03  
    115.    0x1F,0x01,0x1F,0x01,0x1F,0x08,0x08,0x1F,//"星"右上半部分代码 0x04  
    116.    0x08,0x17,0x00,0x1F,0x00,0x00,0x00,0x00,//"星"左下半部分代码 0x05  
    117.    0x08,0x1F,0x08,0x1F,0x00,0x00,0x00,0x00//"星"右下半部分代码 0x06    
    118.    };  
    119. unsigned char  tab[]={'1','0',0x00,'0','3',0x01,'0','9',0x02};//显示"08年03月09日"     
    120. /***************************************************************************** 
    121. 函数功能:LCD延时子程序 
    122.  
    123. 入口参数:ms 
    124.  
    125. 出口参数: 
    126.  
    127. *****************************************************************************/  
    128.   
    129. void delay(unsigned char ms)  
    130. {  
    131. unsigned char i;  
    132.   
    133. while(ms--)  
    134.   
    135. {  
    136.   
    137. for(i = 0; i< 250; i++)  
    138.   
    139. {  
    140.   
    141. _nop_();  
    142.   
    143. _nop_();  
    144.   
    145. _nop_();  
    146.   
    147. _nop_();  
    148.   
    149. }  
    150.   
    151. }  
    152.   
    153. }  
    154.   
    155. /***************************************************************************** 
    156.  
    157. 函数功能:测试LCD忙碌状态 
    158.  
    159. 入口参数: 
    160.  
    161. 出口参数:result 
    162.  
    163. *****************************************************************************/  
    164. bit lcd_bz()  
    165. {  
    166. bit result;  
    167. //ep = 1;  
    168.   
    169. //_nop_();  
    170.   
    171. //_nop_();  
    172.   
    173. //_nop_();  
    174.   
    175. //_nop_();  
    176. result = (bit)(LCMBY&0x80);//高1就是D7  
    177. //ep=0;  
    178. return result;  
    179. }  
    180. /***************************************************************************** 
    181.  
    182. 函数功能:写指令数据到LCD子程序 
    183.  
    184. 入口参数:cmd 
    185.  
    186. 出口参数: 
    187.  
    188. *****************************************************************************/  
    189.   
    190. void lcd_wcmd(unsigned char cmd)  
    191. {  
    192.   
    193. while(lcd_bz());//判断LCD是否忙碌  
    194.   
    195.   
    196. //ep = 0;  
    197.   
    198. //_nop_();  
    199.   
    200. //_nop_();  
    201.   
    202. LCMCW = cmd;  
    203.   
    204. //_nop_();  
    205.   
    206. //_nop_();  
    207.   
    208. //_nop_();  
    209.   
    210. //_nop_();  
    211.   
    212. //ep = 1;  
    213.   
    214. //_nop_();  
    215.   
    216. //_nop_();  
    217.   
    218. //_nop_();  
    219.   
    220. //_nop_();  
    221.   
    222. //ep = 0;  
    223.   
    224. }  
    225.   
    226. /***************************************************************************** 
    227.  
    228. 函数功能:设定显示位置子程序 
    229.  
    230. 入口参数:pos 
    231.  
    232. 出口参数: 
    233.  
    234. *****************************************************************************/  
    235.   
    236. void lcd_pos(unsigned char pos)  
    237.   
    238. {  
    239.   
    240. lcd_wcmd(pos | 0x80);  
    241.   
    242. }  
    243.   
    244. /***************************************************************************** 
    245.  
    246. 函数功能:写入显示数据到LCD子程序 
    247.  
    248. 入口参数:dat 
    249.  
    250. 出口参数: 
    251.  
    252. *****************************************************************************/  
    253.   
    254. void lcd_wdat(unsigned char dat)  
    255.   
    256. {  
    257.   
    258. while(lcd_bz());//判断LCD是否忙碌  
    259.   
    260.   
    261. //ep = 0;  
    262.  LCMDW = dat;  
    263.   
    264. //_nop_();  
    265.   
    266. //_nop_();  
    267.   
    268. //_nop_();  
    269.   
    270. //_nop_();  
    271.   
    272. //ep = 1;  
    273.   
    274. //_nop_();  
    275.   
    276. //_nop_();  
    277.   
    278. //_nop_();  
    279.   
    280. //_nop_();  
    281.   
    282. //ep = 0;  
    283.   
    284. }  
    285.   
    286. /***************************************************************************** 
    287.  
    288. 函数功能:LCD初始化子程序 
    289.  
    290. 写指令38H:显示模式设置 
    291.  
    292. 写指令08H:显示关闭 
    293.  
    294. 写指令01H:显示清屏 
    295.  
    296. 写指令06H:显示光标移动设置 
    297.  
    298. 写指令0CH:显示开及光标设置 
    299.  
    300. 入口参数: 
    301.  
    302. 出口参数: 
    303.  
    304. *****************************************************************************/  
    305.   
    306. void lcd_init()  
    307.   
    308. {  
    309.   
    310. lcd_wcmd(0x30);  
    311.   
    312. delay(1);  
    313.   
    314. lcd_wcmd(0x0c);  
    315. delay(1);  
    316. lcd_wcmd(0x06);//此处最好用07调节成右侧显示模式。仿真时用07不出现。故用06  
    317. delay(1);  
    318. lcd_wcmd(0x01);    
    319. delay(1);  
    320. lcd_wcmd(0x8f);  //设置位置,上面汇编转过来的  
    321.   
    322. delay(1);  
    323.   
    324. }  
    325.   
    326.   
    327. /***************************************************************************** 
    328.  
    329. 函数功能:画图 
    330.  
    331. 入口参数: 
    332.  
    333. 出口参数: 
    334.  
    335. *****************************************************************************/  
    336.   
    337. void draw()  
    338. {  
    339.  int i;  
    340.  lcd_init();  
    341.  delay(10)   ;  
    342.  lcd_wcmd(0x40);//将自定义字符写入CGRAM     
    343.  for(i=0;i<56;i++)//循环56次写入  
    344.  {  
    345.  lcd_wdat(CGCODE[i]);     
    346.  }  
    347.  lcd_wcmd(0x80);//写入初始地址  
    348.  for(i=0;i<9;i++)  
    349.  {  
    350.   lcd_wdat(tab[i]);  
    351.  }   
    352.  }  
    353. #endif   

    这个由于里面的注释很详细,我也稍微加了一两句,就不做解释了,懒人~不过其中有个设定从右侧开始的。。我设定竟然不好用

    当然了,从右侧自然好看~从左侧是可以用的呵呵(我已经写在注释里面啦~)。很怀疑软件有点不太支持哈~

    最后是键盘的扫描,对于这个东西,用汇编实在是蛮痛苦的。呵呵~不过就像学长说过,用习惯了都是一样的!

    同样前面的汇编注释掉了

    1.          /****************************************************************************** 
    2. ************                LABCENTER ELECTRONICS                   ************                               
    3. ************             Proteus VSM Sample Design Code             ************             
    4. ************            Integer Calculator ( 2K Code Limit)         ************ 
    5. ********************************************************************************/  
    6. /*汇编 
    7. NAME    LCD 
    8.  
    9. ;Set up Code Segment and exports: 
    10.  
    11. LCD              SEGMENT CODE 
    12. RSEG             LCD 
    13.  
    14.                  PUBLIC  _output 
    15.                  PUBLIC  initialise 
    16.                  PUBLIC  clearscreen 
    17.  
    18.  
    19. ;LCD Register Addresses. 
    20. LCD_CMD_WR  equ     00h 
    21. LCD_DATA_WR equ 01h 
    22. LCD_BUSY_RD equ 02h 
    23. LCD_DATA_RD equ 03h 
    24. LCD_PAGE    equ 80h 
    25.  
    26. ;LCD Commands 
    27. LCD_CLS     equ 1 
    28. LCD_HOME    equ 2 
    29. LCD_SETMODE equ 4 
    30. LCD_SETVISIBLE  equ 8 
    31. LCD_SHIFT   equ 16 
    32. LCD_SETFUNCTION equ 32 
    33. LCD_SETCGADDR   equ 64 
    34. LCD_SETDDADDR   equ 128 
    35.  
    36.  
    37.  
    38.  
    39. ; Initialisation Routine for the LCD display. 
    40. initialise:     mov A,#030h         ;1 line, 8 bits 
    41.         call wrcmd 
    42.         mov A,#LCD_SETVISIBLE + 4 
    43.         call wrcmd 
    44.         mov A,#LCD_SETDDADDR+15     ; Start at right hand side of the display 
    45.         call wrcmd 
    46.         mov A,#LCD_SETMODE + 3      ; Automatic Increment - Display shift left.   
    47.         call wrcmd 
    48.                 ret 
    49.  
    50. ; We move the parameter (held in R7) into the Accumulator prior to writing it. 
    51. _output:    mov A,R7     
    52.         call wrdata 
    53.         ret 
    54.  
    55.  
    56. ;Clears the LCD display and sets the initialisation conditions. 
    57. clearscreen:    mov A,#LCD_CLS 
    58.         call wrcmd 
    59.         mov A,#LCD_SETDDADDR + 15 
    60.         call wrcmd 
    61.         ret 
    62.  
    63.          
    64.          
    65. ;***************************** 
    66. ;******** SUBROUTINES ******** 
    67. ;***************************** 
    68.  
    69. ;Sub routine to write command: 
    70. wrcmd:      mov P2,#LCD_PAGE 
    71.         mov R0,#LCD_CMD_WR 
    72.         movx @R0,A 
    73.         jmp wtbusy 
    74.  
    75. ; Subroutine to Write a Character to the LCD Display. 
    76. wrdata:     MOV P2,#LCD_PAGE                 
    77.         MOV R0,#LCD_DATA_WR 
    78.         MOV A,R7 
    79.         MOVX @R0,A 
    80.  
    81.  
    82. ; Subroutine to wait for a busy clear.   
    83. wtbusy:     MOV R1,#LCD_BUSY_RD 
    84.         MOVX A,@R1 
    85.         JB ACC.7,wtbusy 
    86.                 ret 
    87.  
    88.                 END 
    89.         */  
    90.   
    91. #ifndef _LCD1602_H_  
    92. #define _LCD1602_H_  
    93. #include <reg52.h>  
    94. #include <intrins.h>  
    95. #include <absacc.h>  
    96. #define clear 0x01  
    97. #define ret 0x02  
    98. #define fuction_set_usual 0x38    
    99. /********************************显示数据表*********************************/  
    100. enum Mode{in_shift,in_nshift,de_shift,de_nshift};  
    101. unsigned char Entry_Mode[]={0x07,0x06,0x05,0x04};   
    102. // Display_Control 其中几位靠位来吧,比较多,这个命令控制了是否显示,光标是否显示和闪烁功能  
    103. // 通用函数  
    104. /*********************************端口定义**********************************/  
    105. #define LCMDW       XBYTE[0x8001]       // 数据口  
    106. #define LCMCW       XBYTE[0x8000]       // 命令  
    107. #define LCMBY       XBYTE[0x8002]  
    108. //sbit ep = P2^2;  
    109. /********************************显示数据表*********************************/  
    110. //00-0h乃是GGRAM自定义库的自建位  
    111. unsigned char  CGCODE[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02,//"年"代码 0x00  
    112.    0x0F,0x09,0x0F,0x09,0x0F,0x09,0x13,0x00,//"月"代码 0x01  
    113.    0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00,//"日"代码  0x02  
    114.    0x07,0x04,0x07,0x04,0x07,0x00,0x04,0x07,//"星"左上半部分代码 0x03  
    115.    0x1F,0x01,0x1F,0x01,0x1F,0x08,0x08,0x1F,//"星"右上半部分代码 0x04  
    116.    0x08,0x17,0x00,0x1F,0x00,0x00,0x00,0x00,//"星"左下半部分代码 0x05  
    117.    0x08,0x1F,0x08,0x1F,0x00,0x00,0x00,0x00//"星"右下半部分代码 0x06    
    118.    };  
    119. unsigned char  tab[]={'1','0',0x00,'0','3',0x01,'0','9',0x02};//显示"08年03月09日"     
    120. /***************************************************************************** 
    121. 函数功能:LCD延时子程序 
    122.  
    123. 入口参数:ms 
    124.  
    125. 出口参数: 
    126.  
    127. *****************************************************************************/  
    128.   
    129. void delay(unsigned char ms)  
    130. {  
    131. unsigned char i;  
    132.   
    133. while(ms--)  
    134.   
    135. {  
    136.   
    137. for(i = 0; i< 250; i++)  
    138.   
    139. {  
    140.   
    141. _nop_();  
    142.   
    143. _nop_();  
    144.   
    145. _nop_();  
    146.   
    147. _nop_();  
    148.   
    149. }  
    150.   
    151. }  
    152.   
    153. }  
    154.   
    155. /***************************************************************************** 
    156.  
    157. 函数功能:测试LCD忙碌状态 
    158.  
    159. 入口参数: 
    160.  
    161. 出口参数:result 
    162.  
    163. *****************************************************************************/  
    164. bit lcd_bz()  
    165. {  
    166. bit result;  
    167. //ep = 1;  
    168.   
    169. //_nop_();  
    170.   
    171. //_nop_();  
    172.   
    173. //_nop_();  
    174.   
    175. //_nop_();  
    176. result = (bit)(LCMBY&0x80);//高1就是D7  
    177. //ep=0;  
    178. return result;  
    179. }  
    180. /***************************************************************************** 
    181.  
    182. 函数功能:写指令数据到LCD子程序 
    183.  
    184. 入口参数:cmd 
    185.  
    186. 出口参数: 
    187.  
    188. *****************************************************************************/  
    189.   
    190. void lcd_wcmd(unsigned char cmd)  
    191. {  
    192.   
    193. while(lcd_bz());//判断LCD是否忙碌  
    194.   
    195.   
    196. //ep = 0;  
    197.   
    198. //_nop_();  
    199.   
    200. //_nop_();  
    201.   
    202. LCMCW = cmd;  
    203.   
    204. //_nop_();  
    205.   
    206. //_nop_();  
    207.   
    208. //_nop_();  
    209.   
    210. //_nop_();  
    211.   
    212. //ep = 1;  
    213.   
    214. //_nop_();  
    215.   
    216. //_nop_();  
    217.   
    218. //_nop_();  
    219.   
    220. //_nop_();  
    221.   
    222. //ep = 0;  
    223.   
    224. }  
    225.   
    226. /***************************************************************************** 
    227.  
    228. 函数功能:设定显示位置子程序 
    229.  
    230. 入口参数:pos 
    231.  
    232. 出口参数: 
    233.  
    234. *****************************************************************************/  
    235.   
    236. void lcd_pos(unsigned char pos)  
    237.   
    238. {  
    239.   
    240. lcd_wcmd(pos | 0x80);  
    241.   
    242. }  
    243.   
    244. /***************************************************************************** 
    245.  
    246. 函数功能:写入显示数据到LCD子程序 
    247.  
    248. 入口参数:dat 
    249.  
    250. 出口参数: 
    251.  
    252. *****************************************************************************/  
    253.   
    254. void lcd_wdat(unsigned char dat)  
    255.   
    256. {  
    257.   
    258. while(lcd_bz());//判断LCD是否忙碌  
    259.   
    260.   
    261. //ep = 0;  
    262.  LCMDW = dat;  
    263.   
    264. //_nop_();  
    265.   
    266. //_nop_();  
    267.   
    268. //_nop_();  
    269.   
    270. //_nop_();  
    271.   
    272. //ep = 1;  
    273.   
    274. //_nop_();  
    275.   
    276. //_nop_();  
    277.   
    278. //_nop_();  
    279.   
    280. //_nop_();  
    281.   
    282. //ep = 0;  
    283.   
    284. }  
    285.   
    286. /***************************************************************************** 
    287.  
    288. 函数功能:LCD初始化子程序 
    289.  
    290. 写指令38H:显示模式设置 
    291.  
    292. 写指令08H:显示关闭 
    293.  
    294. 写指令01H:显示清屏 
    295.  
    296. 写指令06H:显示光标移动设置 
    297.  
    298. 写指令0CH:显示开及光标设置 
    299.  
    300. 入口参数: 
    301.  
    302. 出口参数: 
    303.  
    304. *****************************************************************************/  
    305.   
    306. void lcd_init()  
    307.   
    308. {  
    309.   
    310. lcd_wcmd(0x30);  
    311.   
    312. delay(1);  
    313.   
    314. lcd_wcmd(0x0c);  
    315. delay(1);  
    316. lcd_wcmd(0x06);//此处最好用07调节成右侧显示模式。仿真时用07不出现。故用06  
    317. delay(1);  
    318. lcd_wcmd(0x01);    
    319. delay(1);  
    320. lcd_wcmd(0x8f);  //设置位置,上面汇编转过来的  
    321.   
    322. delay(1);  
    323.   
    324. }  
    325.   
    326.   
    327. /***************************************************************************** 
    328.  
    329. 函数功能:画图 
    330.  
    331. 入口参数: 
    332.  
    333. 出口参数: 
    334.  
    335. *****************************************************************************/  
    336.   
    337. void draw()  
    338. {  
    339.  int i;  
    340.  lcd_init();  
    341.  delay(10)   ;  
    342.  lcd_wcmd(0x40);//将自定义字符写入CGRAM  for(i=0;i<56;i++)//循环56次写入  
    343.  {  
    344.  lcd_wdat(CGCODE[i]);     
    345.  }  
    346.  lcd_wcmd(0x80);//写入初始地址  
    347.  for(i=0;i<9;i++)  
    348.  {  
    349.   lcd_wdat(tab[i]);  
    350.  }   
    351.  }  
    352. #endif   

    键盘的扫描实现~没有用上拉下拉电阻~建议使用上拉下拉的电阻。做实物时总是不一样的,比如P0口总线可以不上拉

    不过事实说,自己做的时候不上拉是很不好用的~没办法,自己做的工艺太差啦。

    好了~大概就是这么多。计划下一个是以前的一个小超声波东东。串口只能再等等啦,虽然很是重要的东西。

    (*^__^*) 嘻嘻……


    展开全文
  • 用的是标准总线结构,锁存器用的74L373,RAM用的6264,液晶1602,使能用74LS00来选择。最后用7407作为了驱动。本来他们公司给的代码说的C51,实际上核心的确C,不过LCD和键盘用的都汇编。由于正在略微...

       好久好久没有写博客了~唉~最近弄得东西都是实物没什么研究可写,全部就是调试啊调试啊~还是写一点东西吧。

    最近做了一个基于51外部扩展RAM的小计算器。

     

     这是仿真SAMPLE的图

    用的是标准的总线结构,锁存器用的74L373,RAM用的是6264,液晶是1602,使能用74LS00来选择。最后用7407作为了

    驱动。

    本来他们公司给的代码说的是C51,实际上核心的确是C,不过LCD和键盘用的都是汇编。由于正在略微研究下外部扩展就拿来做出来顺便把代码都改成C的。LCD的驱动完全是总线结构,根据硬件连接来写代码。下面把LCD的代码汇编和C都放上来

    我把前面汇编的注释掉了~

    详细看代码就可以了,其中汇编的关键在MOVX的使用上,时序图可以查的到,可以研究一下~其中把LCD的地址当做寄存器来看待

    每次先选好使用再给数据,就可行了~

    主要说C

    首先说明~C语言是我从以前的非总线式结构里面改写的。因此有些函数没有用到。

    C语言的关键在这里就是

    #define LCMDW  XBYTE[0x8001]  // 数据口
    #define LCMCW  XBYTE[0x8000]  // 命令
    #define LCMBY       XBYTE[0x8002] //忙检测

    XBYTE是在absacc.h库里的一个定义地址的工具

    其中有~#define XBYTE ((unsigned char volatile xdata *) 0)

    其中根据硬件连接高2位的使能打开正是80H的地址,低2位的地址根据功能(A0,A1)定义不同的地址

    然后在输出的时候协商

    LCMDW=*****;就可以实现MOVX的功能了,产生外部存储的时序来啦~

    液晶怎么使用就看数据手册吧,1602的手册可是很全很很全,网上的例子更是很多很多(把上面代码稍微改动就可以直接使用lcd了哈)

    接下来给出SAMPLE里我一点没动的核心,计算器的算法实现

     

    这个由于里面的注释很详细,我也稍微加了一两句,就不做解释了,懒人~不过其中有个设定从右侧开始的。。我设定竟然不好用

    当然了,从右侧自然好看~从左侧是可以用的呵呵(我已经写在注释里面啦~)。很怀疑软件有点不太支持哈~

    最后是键盘的扫描,对于这个东西,用汇编实在是蛮痛苦的。呵呵~不过就像学长说过,用习惯了都是一样的!

    同样前面的汇编注释掉了

    键盘的扫描实现~没有用上拉下拉电阻~建议使用上拉下拉的电阻。做实物时总是不一样的,比如P0口总线可以不上拉

    不过事实说,自己做的时候不上拉是很不好用的~没办法,自己做的工艺太差啦。

    好了~大概就是这么多。计划下一个是以前的一个小超声波东东。串口只能再等等啦,虽然很是重要的东西。

    (*^__^*) 嘻嘻……


     

    展开全文
  • 纵谈USB总线(上)

    千次阅读 2018-05-19 10:09:00
    USB(Universal Serial Bus,通用串行总线)连接CPU与外部设备的一种串口总线标准,也一种输入输出接口的技术规范。 而USB的出现的时候,那个时候已经有很多的通信方式了,如232、485等,可是为什么还是出现了...
  • I2C总线上拉电阻--为什么

    万次阅读 2014-04-26 01:33:50
    这个就要看你使用的单片机是否有标准的IIC标准接口了,如果你使用了标准的IIC接口,这个接口在使能的时候,引脚进入漏极开路模式,不过有一些单片机内部的上拉电阻可以使能,这样就省去了外部的上拉电阻,我用过AVR...
  • 首先,我们需要知道什么是计算机总线技术?总线就是BUS.微处理器需要和一定数量的部件/外部设备连接,...采用总线结构便于部件和设备的扩充,尤其制定了统一的总线标准则容易使不同设备间实现互连。 微机中总线一般有
  • DDR2是什么意思

    2019-10-07 07:06:14
    DDR2DDR2(Double Data Rate 2) SDRAM由JEDEC(电子设备工程联合委员会)进行开发的新生代内存技术标准,它与上一代DDR内存技术标准最大的不同...换句话说,DDR2内存每个时钟能够以4倍外部总线的速度读/写数据,...
  • USB的英文全称是什么? Universal Serial Bus,即通用串行总线you sb USB的英文全称是Universal Serial Bus,即通用串行总线。它是由Intel等多家公司提出的一种计算机外部接口标准。它支持多设备连接,理论上可以带...
  • USB,英文Universal Serial Bus(通用串行总线)的缩写,一个外部总线标准,用于规范电脑与外部设备的连接和通讯。应用在PC领域的接口技术。————百度百科 2、从windows系统识别usb设备的过程,来推理这...
  • USB流量取证分析

    2020-09-22 19:28:10
    USB UniversalSerial Bus(通用串行总线)的缩写,一个外部总线标准,用于规范电脑与外部设备的连接和通讯,例如键盘、鼠标、打印机、磁盘或网络适配器等等。通过对该接口流量的监听,我们可以得到键盘的击键...
  • 3. 在8086中,逻辑地址、偏移地址、物理地址分别指的是什么?具体说明。 4. 什么是硬件中断和软件中断?在PC机中两者的处理过程有什么不同? 六、综合应用题(每题10分,共20 分) 现有16K×1位的动态...
  • I2C(smbus、pmbus)和SPI协议分析

    千次阅读 2019-08-07 17:38:54
    I2C和SPI作为两种非常常用的低速外部总线,已经不是什么新新技术了。 有些知识点,明白了,一段时间不用了,又忘记了。所以决定乘最近正好碰过这两个东西,还是写下来以备后患。 I2C I2C以前的飞利浦半导体制定...
  • AT24C02D由于不是标准的I2C总线,所以没有完全使用I2C的8字节地址总线,而是使用了5+3外部引脚设置(A2,A1,A0)来决定和哪路器件通讯的,一个i2c总线上最多能挂载8个AT24C02D,刚好2的三次方。 不明白为什么AT24C02D...
  • 答:外部总线主控模块经HOLD引线向8086发出总线请求信号;8086在每个时钟周期的上升沿采样HOLD引线;若发现HOLD=1则在当前总线周期结束时(T4结束)发出总线请求的响应信号HLDA;8086使地址、数据及控制总线进入高阻...
  • usb协议栈学习笔记

    2018-07-11 16:10:00
    1.usb 集线器为什么一般都只有4个扩展口? PC的根集线器可为每个A型连接器提供5V、500mA电源。一个总线供电的外部集线器可为每个端口提供100mA电流。由于USB为为外部集线器电路分配100mA电流,因此,一个总线供电...
  •  什么是流接口:请看文章最后 ...两种外部模型用于通用串行总线(USB)和网络驱动器接口标准(NDIS)驱动程序。其中流接口驱动程序为连接到基于WjnCE平台的外围设备而设计的,这些外围设备包...
  • 关于USB线

    2019-09-09 19:45:37
    都9012年了,今天去说清楚USB是什么样子的。 usb是通用串行总线的简称。一个外部通信的标准。 分类: 1从接口上主要分成 : mini系列,micro系列和type系列,。 2从协议上主要分成 : USB1.0,USB2.0,USB3.0...
  • 4.2 什么是CCS177 4.3 如何安装和设置CCS178 4.3.1 CCS对计算机系统的配置要求178 4.3.2 CCS的安装与设置178 4.4 CCS窗口介绍180 4.4.1 CCS窗口示例180 4.4.2 CCS的菜单栏和快捷菜单180 4.4.3 CCS的常用工具栏181 ...
  • C语言编程要点

    2017-09-18 00:10:37
    1.14 取模运算符(modulus operator)“%”的作用是什么? 17 第2章 变量和数据存储 18 2.1. 变量存储在内存(memory)中的什么地方? 18 2.2. 变量必须初始化吗? 19 2.3. 什么是页抖动(pagethrashing)? 19 2.4. 什么是...
  • GPIO简介

    2014-04-06 18:51:08
    什么是GPIO?  General Purpose Input Output (通用输入/输出)简称为GPIO,或总线扩展器,利用工业标准I2C、SMBus或SPI接口简化了I/O口的扩展。当微控制器或芯片组没有足够的I /O端口,或当系统需要采用远端...
  • 1)DSP的C语言是标准的ANSI C,它不包括同外设联系的扩展部分,如屏幕绘图等。但在CCS中,为了方便调试,可以将数据通过prinf命令虚拟输出到主机的屏幕上。   2)DSP的C语言的编译过程为,C编译为ASM,再...
  • ARM的微处理器核心适用于多种领域,目前,基于ARM技术的处理器已经占据了32 位RISC 芯片75 %市场份额,已成为移动通信、手持计算、多媒体数字消费等嵌入式解决方案的RISC 标准。国内外多家公司都推出了自己的基于ARM...
  • 嵌入式系统-硬件与软件架构(正版)

    热门讨论 2012-11-13 19:00:56
     1.1 什么是嵌入式系统   1.2 嵌入式系统设计   1.3 嵌入式系统体系结构简介   1.4 嵌入式系统体系结构的重要性   1.5 嵌入式系统模型   小结   习题   附注   第2章 了解标准   2.1 程序设计...
  • DELPHI串口编程

    2015-12-10 21:39:48
    2. 什么是接口? 3 3. 接口分类. 3 4. 为什么需要I/O接口? 3 5. I/O接口的功能 4 6. I/O接口的通信方式 5 7. I/O接口的分类 5 8. 串口的分类 8 9. 串口通信分类 11 10. 奇偶校验 12 第二章 串口通信编程简介 13 1. ...
  • 各自含义是什么? 各 1)容量:交换单元所有入线可以同时送入的总的信息量 2)接口:即交换单元自己的信号接口标准 3)功能:点到点动能、同发功能,播功能。 4)质量:包括文换单元完成交换功能的况和信息经过交换单元的损份 ...

空空如也

空空如也

1 2 3
收藏数 51
精华内容 20
关键字:

外部总线标准是什么