本章要点:SCI与SPI是MCU与外界进行串行通信的两种重要方式.相对来说,SCI使用得更多.本章的主要内容有:(1)串行异步通信基本概念:通信格式,波特率,奇偶校验,传输方式(单工,全双工,半双工),RS-232C标准及电平转换;(2)具有串行通信功能的MCU最小系统的硬件电路原理及SCI的编程原理;(3)MC68HC908GP32的SCI模块编程结构;(4)规范的汇编及C语言串行通信子程序,并给出测试实例,包括PC机方程序;(5)MC68HC908GP32的SPI模块编程原理及应用举例. 学习指导:本章重点掌握SCI的编程,同时学习编程的规范.第1,2两节给出的基本上是与芯片无关的通用知识,了解这些知识对进行串行电路设计与编程很有帮助,要求重点掌握其基本含义.对于第2节末给出的具有串行通信功能的MC68HC908GP32的最小系统,属于硬件范畴,希望在这里能够掌握.学习嵌入式应用,不能一点不涉及硬件,该部分的撰写兼顾到对硬件感到困难的读者.学习第3节时,第一遍阅读,可以根据文中的提示有重点地看,其它内容可以暂时略过,待完成第4节的实验之后再回头理解一些寄存器的含义.串行通信的PC机方程序,使用VB,VC等高级语言编程,读者可以选择自己熟悉的语言.SPI部分对于初学者,要求理解其通信与编程的基本方法,实际应用时,可参考第6节的实例. 8.1 串行通信基本知识概要 本节简要概括了串行通信中的相关概念,为学习MCU的串行接口编程做准备.对于已经了解这方面知识的读者,可以略读本节. 8.1.1 基本概念 我们知道,"位"(bit)是二进制数字的简称,是可以拥有两种状态的最小二进制值,分别用"0"和"1"表示.在计算机中,通常一个信息单位用8位二进制表示,称为一个"字节"(byte).串行通信的特点是:数据以字节为单位,按位的顺序从一条传输线上发送出去.这里至少涉及到以下几个问题:第一,每个字节之间是如何区分的 第二,发送一位的持续时间是多少 第三,怎样知道传输是正确的 第四,可以传输多远 等等.这些问题属于串行通信的基本概念.串行通信分为异步通信与同步通信两种方式,本节主要给出异步串行通信的一些常用概念.正确理解这些概念,对串行通信编程是有益的. (1)异步串行通信的格式 在MCU的英文芯片手册上,通常说SCI采用的是NRZ数据格式,英文全称是:"standard non-return-zero mark/space data format",可以译为:"标准不归零传号/空号数据格式".这是一个通信术语,"不归零"的最初含义是:用负电平表示一种二进制值,正电平表示另一种二进制值,不使用零电平."mark/space"即"传号/空号"分别是表示两种状态的物理名称,逻辑名称记为"1/0".对学习嵌入式应用的读者而言,只要理解这种格式只有"1","0"两种逻辑值就可以了.图8-1给出了8位数据,无校验情况的传送格式. 这种格式的空闲状态为"1",发送器通过发送一个"0"表示一个字节传输的开始,随后是数据位(在MCU中一般是8位或9位,可以包含校验位).最后,发送器发送1到2位的停止位,表示一个字节传送结束.若继续发送下一字节,则重新发送开始位,开始一个新的字节传送.若不发送新的字节,则维持"1"的状态,使发送数据线处于空闲.从开始位到停止位结束的时间间隔称为一帧(frame).所以,也称这种格式为帧格式. 通过这段内容,我们知道了异步串行通信中,通过"开始位"与"停止位"区分每个传送的字节.所以,每发送一个字节,都要发送"开始位"与"停止位",这是影响异步串行通信传送速度的因素之一.同时因为每发送一个字节,必须首先发送"开始位",所以称之为"异步"(asynchronous)通信. (2)串行通信的波特率 位长(bit length),也称为位的持续时间(bit duration).其倒数就是单位时间内传送的位数.人们把每秒内传送的位数叫做波特率(baud rate).波特率的单位是:位/秒,记为bps.bps是英文bit per second的缩写,习惯上这个缩写不用大写,而用小写.通常情况下,波特率的单位可以省略. 通常使用的波特率有300,600,900,1200,1800,2400,4800,9600,19200,38400.在包含开始位与停止位的情况下,发送一个字节是10位,很容易计算出,在各种波特率下,发送1K字节所需的时间.显然,这个速度相对于目前的许多通信方式是慢的,那么,异步串行通信的速度能否提得很高呢 答案是否定的.因为随着波特率的提高,位长变小,以致很容易受到电磁源的干扰,通信就不可靠了.当然,还有通信距离问题,距离小,可以适当提高波特率,后面还会涉及此问题. (3)奇偶校验 在异步串行通信中,如何知道传输是正确的 最常见的方法是增加一个位(奇偶校验位),供错误检测使用.字符奇偶校验检查(character parity checking)称为垂直冗余检查( vertical redundancy checking,VRC),它是每个字符增加一个额外位使字符中"1"的个数为奇数或偶数.奇数或偶数依据使用的是"奇校验检查"还是"偶校验检查"而定.当使用"奇校验检查"时,如果字符数据位中"1"的数目是偶数,校验位应为"1",如果"1"的数目是奇数,校验位应为"0".当使用"偶校验检查"时,如果字符数据位中"1"的数目是偶数,则校验位应为"0",如果是奇数则为"1". 这里列举奇偶校验检查的一个实例,看看ASCII字符"R", 其位构成是1010010.由于字符"R"中有三个1位,若使用奇校验检查,则校验位为0;如果使用偶校验检查,则校验位为1.因而,ASCII字符"R"如下所示: 数据位 校验位 ————————————— 1 0 1 0 0 1 0 0 奇校验检查 (要求:1的个数为奇数) 1 0 1 0 0 1 0 1 偶校验检查 (要求:1的个数为偶数) 在传输过程中,若有1位(或奇数个数据位)发生错误,使用奇偶校验检查,可以知道发生传输错误.若有2位(或偶数个数据位)发生错误,使用奇偶校验检查,不能知道发生传输错误.但是奇偶校验检查方法简单,使用方便,发生一位错误的概率远大于发生二位错误的概率,所以"奇偶校验"这种方法还是最为常用的一种校验方法.几乎所有MCU的串行异步通信接口中,都提供这种功能. (4)串行通信的传输方式 在串行通信中,经常用到"单工","双工","半双工"等术语.它们是串行通信的不同传输方式.下面简要介绍这些术语的基本含义. 单工(Simplex):数据传送是单向的,一端为发送端,另一端为接收端.这种传输方式中,除了地线之外,只要一根数据线就可以了.有线广播就是单工的. 全双工(Full-duplex):数据传送是双向的,且可以同时接收与发送数据.这种传输方式中,除了地线之外,需要两根数据线,站在任何一端的角度看,一根为发送线,另一根为接收线.一般情况下,MCU的异步串行通信接口均是全双工的. 半双工(Half-duplex):数据传送也是双向的,但是在这种传输方式中,除了地线之外,一般只有一根数据线.任何一个时刻,只能由一方发送数据,另一方接收数据,不能同时收发.在freescale的HC08系列MCU中,监控模式的通信就采用这种方式. 8.1.2 RS-232C总线标准 现在回答"可以传输多远"这个问题.MCU引脚一般输入/输出使用TTL电平,而TTL电平的"1"和"0"的特征电压分别为2.4V和0.4V(目前一些使用3V供电的MCU中,该特征值有所变动),它适用于板内数据传输.若用TTL电平将数据传输到5m之外,那么可靠性是值得考究的.为了使信号传输得更远,美国电子工业协会EIA(Electronic Industry Association) 制订了串行物理接口标准RS-232C.RS-232C采用负逻辑,-3V~-15V为逻辑"1",+3V~+15V为逻辑"0".RS-232C最大的传输距离是30m,通信速率一般低于20Kbps.当然,实际应用中,也有人用降低通信速率的方法,通过RS-232电平,将数据传送到300m之外,这是很少见的,且稳定性很不好. RS-232C总线标准最初是为远程数据通信制订的,但目前主要用于几米到几十米范围内的近距离通信.有专门的书籍介绍这个标准,但对于一般的读者,不需要掌握RS-232C标准的全部内容,只要了解本节介绍的这些基本知识就可以使用RS-232.目前一般的PC机均带有1到2个串行通信接口,人们也称之为RS-232接口,简称"串口",它主要用于连接具有同样接口的室内设备.早期的标准串行通信接口是25芯插头,这是RS-232C规定的标准连接器(其中:2条地线,4条数据线,11条控制线,3条定时信号,其余5条线备用或未定义).后来,人们发现在计算机的串行通信中,25芯线中的大部分并不使用,逐渐改为使用9芯串行接口.一段时间内,市场上还有25芯与9芯的转接头,方便了两种不同类型之间的转换.后来,使用25芯串行插头极少见到,25芯与9芯对接头也极少有售.因此,目前几乎所有计算机上的串行口都是9芯接口.图8-2给出了9芯串行接口的排列位置,相应引脚含义见表8-1.其中已用黑体字标识的是MCU中用到的三根线:接收线,发送线,地线.其它为进行远程传输时接调制解调器之用,有的也可作为硬件握手信号,初学时可以忽略这些信号的含义. 表8-1 9芯串行接口引脚含义表 引脚号 功 能 引脚号 功 能 1 2 3 4 5 接收线信号检测(载波检测DCD) 接收数据线(RXD) 发送数据线(TXD) 数据终端准备就绪(DTR) 信号地(SG) 6 7 8 9 数据通信设备准备就绪(DSR) 请求发送(RTS) 清除发送 振铃指示 在MCU中,若用RS-232C总线进行串行通信,则需外接电路实现电平转换.在发送端需要用驱动电路将TTL电平转换成RS-232C电平,在接收端需要用接收电路将RS-232C电平转换为TTL电平.电平转换器不仅可以由晶体管分立元件构成,也可以直接使用集成电路.目前使用MAX232芯片较多,该芯片使用单一+5V电源供电实现电平转换.图8-3给出了MAX232的引脚. 引脚含义简要说明如下: Vcc(16脚):正电源端,一般接+5V GND(15脚):地 VS+(2脚):VS+=2Vcc-1.5V VS-(6脚):VS-=-2Vcc-1.5V C2+,C2-(4,5脚):一般接1μF的电解电容 C1+,C1-(1,3脚):一般接1μF的电解电容 输入输出引脚分两组,基本含义见表8-2.在实际使用时,若只需要一路SCI,可以使用其中的任何一组. 表8-2 MAX232芯片输入输出引脚分类与基本接法 组别 TTL电平引脚 方向 典型接口 232电平引脚 方向 典型接口 1 11 12 输入 输出 接MCU的TxD 接MCU的RxD 13 14 输入 输出 连接到接口与其它设备通过232相接 2 10 9 输入 输出 同上 8 7 输入 输出 同上 利用MAX232将TTL电平转换为RS-232电平的电路接法将在下一节结合SCI的外围硬件电路讨论. 8.2 SCI的外围硬件电路与基本编程原理 所有型号MCU的串行通信接口(Serial Communication Interface,SCI),都具有发送引脚TxD,接收引脚RxD,它们是TTL电平引脚.要利用这两个引脚与外界实现异步串行通信,还必须将TTL电平转为RS-232电平,这可利用上节介绍的MAX232来完成.本节将以MC68HC908GP32 MCU为例,给出具有串行通信功能的MCU最小系统电路的详细设计电路.另外,还从通用角度讨论SCI的基本编程结构与编程原理,为实际编程做准备. 8.2.1 SCI的外围硬件电路 SCI的外围硬件电路,主要目的是将MCU的发送引脚TxD与接收引脚RxD,通过RS-232电平转换芯片转换为RS-232电平.这里以MC68HC908GP32为例,给出一个可以实际工作的电路,读者在此基础上,可以设计08系列MCU的其它型号的工作电路,也可在此基础上进一步扩展组成较为通用的单片机应用系统.在嵌入式应用的实际电路设计时,首先需要考虑MCU的工作支撑电路,然后是各种接口电路.图8-4给出了具有串行通信功能的MC68HC908GP32最小系统电路原理图.下面对其作一些必要的说明,希望读者对照图8-4中各个部分进行阅读.图中使用虚线框将各个功能电路进行了分割. (1)电源供给与滤波 GP32芯片的20,19脚(Vcc,Vss)为芯片的电源输入端,1,2脚(VDDA,VSSA)为内部PLL模块的电源供给.接在电源与地之间的0.1μ电容为滤波电容.PLL电路目的在于由频率小的外部晶振产生较大频率的内部总线时钟,提高芯片的抗干扰性.由于这部分内容涉及的编程内容很少,但原理较难理解,所以放入第12章介绍.这里只要知道GP32内有PLL电路就可以了,而且GP32内的PLL电路模块需要外接电源.在MCU的第3脚,接有内部PLL模块的外部滤波电路.滤波电路的作用主要是增强电路工作稳定性. (2)晶振电路 接MCU第4,5脚(OSC2,OSC1)之间的电路为晶振电路,这里选用的晶振频率为f=32.768KHz.通过内部PLL电路模块,可获得小于8MHz的内部总线频率.电路及其元件参数是由GP32参考手册确定的.实际开发中,嵌入式应用工程师往往根据参考手册提供的电路及参数,通过自己的实践,构筑MCU的外围支撑电路,而不深究其工作原理. (3)复位电路 接在MCU第6脚()的电路为芯片硬件复位电路.正常工作时该脚通过10K电阻接到电源正极(这里设为5V电源供电),所以应为高电平.若按下复位按钮RST,则第6脚通过51Ω接地,为低电平,芯片复位. (4)SCI电平转换电路 MCU的串行通信引脚12(TxD),13(RxD)分别接MAX232的11(T1IN),12(R1OUT),MAX232的13(R1IN),14(T1OUT)分别为232电平的接收与发送引脚.基本过程是: 发送过程:MCU的12(TxD)(TTL电平)经过MAX232的11(T1IN)送到MAX232内部,在内部TTL电平被"提升"为232电平,通过14(T1OUT)发送出去. 接收过程:外部232电平经过MAX232的13(R1IN)进入到MAX232的内部,在内部232电平被"降低"为TTL电平,经过12(R1OUT)送到MCU的13(RxD),进入MCU内部. 8.2.2 SCI的基本编程原理 从基本原理角度看,串行通信接口SCI的主要功能是:接收时,把外部的单线输入的数据变成一个字节的并行数据送入MCU内部;发送时,把需要发送的一个字节的并行数据转换为单线输出.图8-5给出了普遍意义上的SCI的编程结构.为了设置波特率SCI应具有波特率寄存器.为了能够设置通信格式,是否校验,是否允许中断等,SCI应具有控制寄存器.而要知道串口是否有数据可收,数据是否发送出去等,需要有SCI状态寄存器.当然,若一个寄存器不够用,控制与状态寄存器可能有多个.而SCI数据寄存器存放要发送的数据,也存放接收的数据,这并不冲突,因为发送与接收的实际工作是通过"发送移位寄存器"和"接收移位寄存器"完成的.编程时,程序员并不直接与"发送移位寄存器"和"接收移位寄存器"打交道,只与数据寄存器打交道,所以MCU中并没有设置"发送移位寄存器"和"接收移位寄存器"的映像地址.发送时,程序员通过判定状态寄存器的相应位,了解是否可以发送一个新的数据.若可以发送,则将待发送的数据放入"SCI数据寄存器"中就可以了,剩下的工作由MCU自动完成:将数据从"SCI数据寄存器"送到"发送移位寄存器",硬件驱动将"发送移位寄存器"的数据一位一位地按照规定的波特率移到发送引脚TxD,供对方接收.接收时,数据一位一位地从接收引脚RxD进入"接收移位寄存器",当收到一个完整字节时,MCU会自动将数据送入"SCI数据寄存器",并将状态寄存器的相应位改变,供程序员判定并取出数据. 8.3 SCI模块的编程结构 本节从编程角度介绍MC68HC908GP32单片机的SCI.从外部引脚来看,负责串行通信的是PTE0/TxD,PTE1/RxD两个引脚,当允许SCI时,它们作为串行通信引脚,分别称为串行发送引脚TxD,串行接收引脚RxD.从程序员角度看,涉及SCI的有7个寄存器,其中1个波特率寄存器,3个控制寄存器,2个状态寄存器,1个数据寄存器,只要理解和掌握这7个寄存器的用法,就可以进行SCI编程. 8.3.1 SCI的寄存器 MC68HC908GP32单片机的SCI有7个寄存器,地址为$0013~$0019,下面按初始化顺序分别阐述这些寄存器的功能及用法.初学者注意,为了容易理解这些寄存器的用法,请着重掌握SCI波特率寄存器的设置方法以及SCI控制寄存器和SCI状态寄存器中带有下划线的位. (1)SCI波特率寄存器(SCI Baud Rate Register,SCBR) SCI波特率寄存器SCBR的作用是设置串行通信的波特率.通常情况下,选择内部总线时钟为串行通信的时钟源,此时利用SCBR对总线频率fBUS可以进行分频得到串行通信的波特率.SCBR的地址是:$0019,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 x x SCP1 SCP0 x SCR2 SCR1 SCR0 复位 0 0 0 0 0 0 0 0 D7,D6,D3:未定义.设置时,为了方便,一般取0. D5~D4 — SCP位:波特率预分频位(SCI Baud Rate Prescaler Bits).这2位定义波特率预分频值,记为:PD,定义如下: SCP1,SCP0=00 PD=1 =01 PD=3 =10 PD=4 =11 PD=13 D2~D0 — SCR位:波特率选择位(SCI Baud Rate Select Bits).这3位定义波特率另一分频值,记为:BD,定义如下: SCR2,SCR1,SCR0=000 BD=1 (20) =001 BD =2 (21) =010 BD =4 (22) =011 BD =8 (23) =100 BD =16 (24) =101 BD =32 (25) =110 BD =64 (26) =111 BD =128 (27) 设fSCI为串行通信时钟源频率,fSCI= fBUS或CGMXCLK,取决于CONFIG2的SCIBDSRC,一般设定SCIBDSRC=1,SCI用内部总线时钟,则fSCI= fBUS,则波特率的定义公式为: Bt=fBUS /(64×PD×BD) 例如:fBUS=2.4576MHz,取PD=1(即SCP1,SCP0=00),BD=4(即SCR2,SCR1,SCR0=010),则波特率=2457600 /(64×1×4) = 9600. (2)SCI控制寄存器1(SCI Control Register 1,SCC1) SCI控制寄存器共有3个,分别称为SCC1,SCC2,SCC3.对它们的写入,实现对SCI的设置.下面分别介绍.带有下划线的位,为初学时必须重点掌握的位.SCC1的地址是:$0013,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 LOOPS ENSCI TXINV M WAKE ILTY PEN PTY 复位 0 0 0 0 0 0 0 0 D7 — LOOPS位:循环模式选择位(Loop Mode Select Bit),LOOPS=1,循环模式;LOOPS=0,正常功能.在循环模式下,接收引脚RxD与SCI内部断开,内部发送数据直接作为接收的输入,用于自测试. D6 — ENSCI位:SCI允许位(Enable SCI Bit).ENSCI=1,允许SCI,这意味着PTE0/TxD,PTE1/RxD两个引脚作为串行通信引脚使用,而不作为普通I/O.否则,若设ENSCI=0,则禁止SCI,PTE0/TxD,PTE1/RxD两个引脚则作为普通I/O使用. D5 — TXINV位:发送反转标志位(Transmit Inversion Bit).TXINV=1,发送输出为反码;TXINV=0正常码输出. D4 — M位:模式—字符长度选择位(Mode — Character Length Bit).定义收发数据格式,只有两种可能:M=1,9位字符;M=0,8位字符. D3 — WAKE位:唤醒条件位(Wakeup Condition Bit).WAKE=1,地址唤醒;WAKE=0,空闲线唤醒.关于唤醒功能(Wake-up feature),这里作概要介绍.初学时跳过此段.在一个典型的多处理器系统中,软件协议通常在消息的开始判断地址.唤醒功能允许无关的MCU忽略消息的剩余部分,同时禁止这些MCU接收器的标志(和中断)处理,直到数据线返回到空闲状态.SCI接收器可以被一串包含10个(或11个)1的空闲字符串唤醒.发送器软件必须在发送连续消息的间隙提供必须的空闲字符串,并保证空闲字符串不在消息中出现.还有一种将休眠中的MCU唤醒的办法:使MCU接收到的字符的最高位为1.MC68HC08系列单片机的SCI接收器具有唤醒功能.这个功能在多处理器系统中非常有用,暂时没有工作的微处理器可以处于休眠状态以节省电力,需要工作时再由主机将其唤醒. D2 — ILTY位:空闲线类型位(Idle Line Type Bit),决定SCI何时开始计数"空闲字符"的位数.ILTY=1,空闲字符位从"停止位"开始计数;ILTY=0,空闲字符位从"起始位"开始计数.从"起始位"开始计数,则"停止位"前的一串"1"可能产生错误的空闲线条件.从"停止位"开始计数,可避免错误的空闲线识别,但需要适当地同步发送操作. D1 — PEN位:奇偶校验允许位(Parity Enable Bit).PEN=1,允许奇偶校验;PEN=0,不进行奇偶校验. D0 — PTY位:奇偶校验类型选择位(Parity Bit).PTY=1,奇校验;PTY=0,偶校验.不进行奇偶校验时,该位无意义,一般写0. (3)SCI控制寄存器2(SCI Control Register 2,SCC2) SCC2的地址是:$0014,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 SCTIE TCIE SCRIE ILIE TE RE RWU SBK 复位 0 0 0 0 0 0 0 0 D7 — SCTIE位:发送中断允许位(SCI Transmit Interrupt Enable Bit).SCTIE=1,允许产生发送中断请求;反之不允许. D6 — TCIE位:发送完成中断允许位(Transmission Complete Interrupt Enable Bit).TCIE=1,允许发送完成产生中断;反之不允许. D5 — SCRIE位:接收中断允许位(SCI Receive Interrupt Enable Bit).SCRIE=1,允许产生接收中断请求;反之不允许. D4 — ILIE位:空闲线中断允许位(Idle Line Interrupt Enable Bit).ILIE=1,允许产生空闲中断请求;反之不允许. D3 — TE位:发送器允许位(Transmitter Enable Bit).TE=1,允许发送器发送;反之不允许发送器发送. D2 — RE位:接收器允许位(Receiver Enable Bit).RE=1,允许接收器接收;反之不允许接收器接收. D1 — RWU位:接收器唤醒位(Receiver Wakeup Bit).RWU=1,等待状态;RWU=0,正常操作. D0 — SBK位:发送终止位(Send Break Bit).SBK=1,发送终止字符(逻辑1);SBK=0,正在发送非终止字符. (4)SCI控制寄存器3(SCI Control Register 3,SCC3) SCC3的地址是:$0015,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 R8 T8 DMARE DMATE ORIE NEIE FEIE PEIE 复位 0 0 0 0 0 0 0 0 D7 — R8位:接收位8 (Received bit 8).该位只读. D6 — T8位:发送位8(Transmitted Bit 8). D5 — DMARE位:DMA接收允许位(DMA Receive Enable Bit).(本MCU无此功能,应为0). D4 — DMATE位:DMA发送允许位(DMA Transfer Enable Bit).(本MCU无此功能,应为0). D3 — ORIE位:接收器溢出中断允许位(Receiver Overrun Interrupt Enable Bit).ORIE=1,允许接收器溢出中断;反之不允许. D2 — NEIE位:接收器噪声错误中断允许位(Receiver Noise Error Interrupt Enable Bit).NEIE=1,允许接收器噪声错误中断;反之不允许. D1 — FEIE位:接收器帧错误中断允许位(Receiver Framing Error Interrupt Enable Bit).FEIE=1,允许接收器帧错误中断;反之不允许. D0 — PEIE位:接收器奇偶错误中断允许位(Receiver Parity Error Interrupt Enable Bit).PEIE=1,允许接收器奇偶错误中断;反之不允许. (5)SCI状态寄存器1(SCI Status Register 1,SCS1) SCI状态寄存器共有2个,分别称为SCS1,SCS2.对它们的读出,可以得到当前SCI的状态.SCS1为只读寄存器,它的地址是:$0016,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义(只读) SCTE TC SCRF IDLE OR NF FE PE 复位 1 1 0 0 0 0 0 0 D7 — SCTE位:发送缓冲区空标志位 (SCI Transmitter Empty bit).该位为1时表明要发送的数据已经移入发送移位寄存器,可以发送一个新的数据. D6 — TC位:发送完成标志位(Transmission Complete Bit).该位为1,表明发送已经完成,该位为0,表明发送正在进行. D5 — SCRF位:接收器满标志位(SCI Receiver Full Bit).该位为1,表明接收器已满,可以从SCI数据寄存器SCDR中读取收到的数据. D4 — IDLE位:接收器空闲标志位(Receiver Idle Bit).该位为1,表明接收器处于空闲状态. D3 — OR位:接收器溢出标志位(Receiver Overrun Bit).该位为1,表明接收器溢出. D2 — NF位:接收器噪声标志位(Receiver Noise Flag Bit).该位为1,表明接收器出现噪声错误. D1 — FE位:接收器帧错误标志位(Receiver Framing Error Bit).该位为1,表明接收器出现帧错误. D0 — PE位:接收器奇偶错误标志位(Receiver Parity Error Bit).该位为1,表明接收器出现奇偶校验错误. (6)SCI状态寄存器2(SCI Status Register 2,SCS2) SCS2为只读寄存器,它的地址是:$0017,定义为: 数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义(只读) BKF RPF 复位 0 0 0 0 0 0 0 0 D7~D2:未定义. D1 — BKF位:终止码标志位(Break Flag Bit).该位为1,检测到终止码. D0 — RPF位:接收进行标志位(Reception in Progress Flag Bit).该位为1,表明正在接收. (7)SCI数据寄存器(SCI Data Register —SCDR) SCDR为SCI系统最常用的寄存器,它的地址是:$0018.写入时,为要发送的8位数据,记为:T7~T0;读出时,为接收的8位数据,记为:R7~R0.不受复位影响. 8.3.2 串行口初始化与收发编程的基本方法 不论用查询方式还是中断方式进行串行通信编程,在程序初始化时均必须对SCI进行初始化,主要进行波特率设置,通信格式的设置,发送接收数据方式的设置等,本小节给出最基本的用法,以作为HC08系列单片机的串行通信编程入门.下一小节将给出规范的串行通信编程子程序,读者可以直接将其应用于实际的嵌入式应用系统的开发中. (1)SCI初始化 有关口地址定义已经在头文件GP32.H中给出, SCC1,SCC2,SCC3,SCBR,SCS1,SCS2,SCDR可以直接使用. 对SCI进行初始化,最少由以下三步构成: 第一步:定义波特率.一般选择内部总线时钟为串行通信的时钟源(这个设置在MCU的系统初始化中完成,令系统设置寄存器CONFIG2的SCIBDSRC位为1即可,从学习顺序角度,本书将这部分内容放在第12章,此处默认系统初始化时已经做了这样的设置).设MCU的系统初始化时已经定义总线频率为fBUS,同时准备定义串行通信波特率,记为Bt.通过选择SCI波特率寄存器SCBR的波特率预分频位SCP(两位),波特率选择位SCR(三位),以便选择合适的分频系数PD,BD,代入公式Bt=fBUS /(64×PD×BD),使得Bt等于需要的值.当然,从表面上看,由这个公式,已知fBUS,Bt,求PD,BD两个未知数不行.但只要注意到,在介绍SCI波特率寄存器SCBR时,PD,BD取值是有限制的,这样,由fBUS,Bt可以"拼凑"出PD,BD,从而得到波特率寄存器SCBR的设定值.为此,不少书籍还专门列了一个表,给出不同fBUS,Bt下的PD,BD的"拼凑"值.这里举例说明,设总线频率fBUS=2.4576MHz,准备定义波特率Bt=9600,则由公式Bt=fBUS /(64×PD×BD)可以"拼凑"出,PD=1(即SCP1,SCP0=00),BD=4(即SCR2,SCR1,SCR0=010),波特率寄存器SCBR的未定义位取0,则SCBR的值应为二进制"00000010",程序如下: ;总线频率fBUS=2.4576MHz,定义波特率Bt=9600 LDA #%00000010 STA SCBR 第二步:写控制字到SCI控制寄存器1(SCC1).设置是否允许SCI,数据长度,输出格式,选择唤醒方法,是否校验等.例如,设定允许SCI,正常码输出,8位数据,无校验,SCC1取值应为二进制"01000000",程序如下: ;设置允许SCI,正常码输出,8位数据,无校验 LDA #%01000000 STA SCC1 实际上,这种情况只是令SCC1的SCI允许位(第6位)为1,其它位取默认值. 第三步:写控制字到SCI控制寄存器2(SCC2).设置是否允许发送与接收,是中断接收还是查询接收等.例如,设置允许发送(TE=1),允许接收(RE=1),查询方式收发,SCC2取值应为二进制"00001100",程序如下: ;设置允许发送,允许接收,查询方式收发 LDA #%00001100 STA SCC2 用查询方式,可以不对SCI控制寄存器3(SCC3)初始化,另外几个寄存器供后面编程使用,不需初始化. (2)发送一个数据与接收一个数据 一般情况下,对SCI的初始化只在程序的初始化部分进行一次,串行通信的基础编程是发送与接收数据.发送数据是通过判断状态寄存器SCS1的第7位(SCTE)进行的,而接收数据是通过判断状态寄存器SCS1的第5位(SCRF)进行的.不论是发送还是接收,均使用SCI数据寄存器SCDR.发送时,将要发送的数据送入SCDR即可,接收时,从SCDR中取出的即是收到的数据. 例如,下面的程序将寄存器A中的数从串行引脚TxD发送出去.通过对状态寄存器SCS1的第7位(SCTE)判断是否可以向数据寄存器SCDR送数,若SCTE=1可以送数,否则必须等待. ;串行发送A中的数 BRCLR 7,SCS1,* ;SCS1.7=0 为0则等待 STA SCDR ;SCS1.7=1,可以发送数据 要以查询方式接收一个数据,首先通过状态寄存器SCS1的第5位(SCRF)判断有没有数据可收,若SCRF=1,则有数据可收,下面程序持续等待串行口(实际上是RxD引脚)直到接收到一个数,数据接收后放入寄存器A中: ;查询方式接收一个串行数据,接收的数据放入寄存器A中 BRCLR 5,SCS1,* ;SCS1.5=0 为0则等待 LDA SCDR ;SCS1.5=1,可以取出数据 8.4 串行通信编程实例 本节给出较规范的用08汇编语言及08C语言编的串行通信子程序,包括SCI初始化,发送一个字节,接收一个字节,发送N个字节,接收N个字节等子程序,然后给出一个使用这些子程序的测试程序,并给出PC机方程序.读者可以直接使用这些子程序进行08系列MCU的串行通信编程. 8.4.1 08汇编语言串行通信子程序 (1)SCI初始化汇编子程序 对串行口的初始化一般在主循环之前进行,即使以中断方式接收或发送,在初始化子程序中只定义查询方式收发.允许中断的设置,在进入主循环之前进行.下面给出的初始化程序,将在本教程的各个实例中使用. 串行口初始化汇编语言例 *SCIInit.asm:串行口初始化子程序------------------------* *功 能:对串行口进行初始化,允许SCI,正常码输出,8位数据, * * 无校验等,允许发送器允许接收器.查询方式收发, * * 波特率为9600(设fBUS=2.4576MHz) * *入 口:无 * *出 口:无 * *------------------------------------------------------* SCIInit: PSHA ;总线频率fBUS=2.4576MHz,定义波特率Bt=9600 LDA #%00000010 STA SCBR ;设置允许SCI,正常码输出,8位数据,无校验 LDA #%01000000 STA SCC1 ;设置允许发送,允许接收,查询方式收发 LDA #%00001100 STA SCC2 PULA RTS (2)串行发送与接收汇编通用子程序 仔细分析可以发现,与串行通信相关的程序,发送与接收使用同一个寄存器的不同位作为测试标志,发送与接收的数据寄存器地址相同.而在串行通信中,发送一个字节与发送N个字节,接收一个字节与接收N个字节的子程序是最基本的,因此这里给出这些基本子程序.为了方便实际应用,对程序做了规范,可以应用于08系列的任何一个型号MCU.读者应仔细理解这些子程序的编程思路,以便为后面的学习打下扎实的基础. 串行发送与接收汇编通用子程序HC08SCI.ASM *H08SCI.ASM--------------------------------------------* *文件描述:本文件包含了HC08串行通信子程序,分别为: * *(1)SCISend1:串行发送A中的1个字节 * *(2)SCISendN:串行发送N个字节 * *(3)SCIRe1:串行接收一个字节->A * *(4)SCIReN:串行接收N个字节 * *------------------------------------------------------* *[寄存器及相关位定义] ReSendStatusR EQU SCS1 ;SCI状态寄存器1 ReTestBit EQU 5 ;接收缓冲区满标志位 SendTestBit EQU 7 ;发送缓冲区空标志位 ReSendDataR EQU SCDR ;SCI数据寄存器 *SCISend1:串行发送A中的1个字节-------------------------* *功 能:串行口发送A中的1个字节数据 * *入 口:A=待发送的数据 * *出 口:无 * *堆栈深度:2 * *------------------------------------------------------* SCISend1: BRCLR SendTestBit,ReSendStatusR,SCISend1 STA ReSendDataR RTS *SCISendN:串行发送N个字节------------------------------* *功 能:串行发送以HX为首地址的N个字节数据 * *入 口:A=字节个数 HX=首地址 * *出 口:无 * *堆栈深度:2+1=3 * *------------------------------------------------------* SCISendN: ;在堆栈区开辟1个字节作临时变量 AIS #-!1 ;若发送字节数为0,退出 STA !1,SP CMP #!0 BEQ SCISendN_EXIT SCISendN_1: LDA ,X ;从存储器中取出待发送的数据 JSR SCISend1 AIX #!1 DBNZ !1,SP,SCISendN_1 ;N-1≠0转 SCISendN_EXIT: ;释放1个字节临时变量 AIS #!1 RTS *SCIRe1:串行接收一个字节->A----------------------------* *功 能:(1) 串行接收1个字节的数据放在A中 * * (2) 约655350时钟周期内收不到数返回, * * 若时钟周期=0.4us 大约等待2.6S * *入 口:无 * *出 口:A=接收的数据 C=是否收到数据标志 0收到 1未收到 * *堆栈深度:2+2=4 * *------------------------------------------------------* SCIRe1: PSHH PSHX ;等待接收一个字节数据 LDHX #$FFFF ;循环次数 SCIRe1_1: BRCLR ReTestBit,ReSendStatusR,SCIRe1_2 ;无数据,转 LDA ReSendDataR ;收到的数据放入A中 CLC ;C=0 BRA SCIRe1_3 ;收到数据,退出 SCIRe1_2: NOP AIX #-$1 CPHX #$0000 BNE SCIRe1_1 ;等待时间到,未收到数据,令c=1,A=FF,返回 LDA #$FF SEC ;C=1 SCIRe1_3: PULX PULH RTS *SCIReN:串行接收N个字节--------------------------------* *功 能:串行接收N个字节放在以HX为首地址的内存中 * *入 口:A=待接收数据的字节数N,HX=接收数据存放的首地址 * *出 口:C=是否收到数据标志 0收到 1未收到 * *堆栈深度:2+4+1=7 * *内部调用:SCIRe1 * *------------------------------------------------------* SCIReN: ;在堆栈区开辟1个字节作临时变量 AIS #-!1 ;若接受字节数为0,退出 STA !1,SP CMP #!0 BEQ SCIReN_EXIT SCIReN_1: JSR SCIRe1 ;调用接收1个字节的子程序 BCS SCIReN_EXIT ;C=1未收到数据,退出 STA ,X ;收到数据,放入内存 AIX #!1 ;HX+1->HX DBNZ !1,SP,SCIReN_1 SCIReN_EXIT: ;释放1个字节临时变量 AIS #!1 RTS 8.4.2 08汇编语言串行通信测试实例 为了验证子程序的正确性,这里给出简明的测试实例.由于串行通信涉及两个设备,所以本例选用MCU为一方,PC机为另一方,PC机方程序用VB编程.首先给出MCU方以查询方式进行接收,随后还给出MCU方以中断方式接收的实例,以便比较.程序中给出了详细的注释. 下列实例中,不论是查询方式,还是中断方式,也不论是汇编语言,还是08C语言,MCU方的程序功能是一致的:把通过串行口收到的数据发送回去.PC机方的VB测试程序只有一个,在各实例目录的VB_SCI子目录中. (1)查询方式MCU方主程序 实例编号:A02_1 路径:\ASM\A02_1串行通信查询方式 (H08SCI_1.ASM) *------------------------------------------------------------* *文 件 名:H08SCI_1.asm * *硬件连接:无 * *程序描述:利用查询方式把收到的数据发送回去 * *目 的:初步掌握利用查询方式进行串行通信的基本知识 * *--------------《嵌入式应用技术基础教程》教学实例----------------* *[头文件] $include "GP32ASM.H" ;包含GP32的头文件 *[两个起始地址名] RAMstartAddr equ $0040 ;RAM的起始地址 FlashStartAddr equ $8000 ;程序开始地址 *[内存变量] org RAMstartAddr ;RAM的起始地址 SerialBuff rmb 1 ;数据存储单元 *======================================================= *[主程序] org FlashStartAddr ;程序起始地址 MainInit: ;复位后程序从此开始执行 ;[系统初始化] SEI LDHX #$023F ;堆栈初始化 TXS JSR GP32Init ;调系统初始化子程序GP32Init ;[串行口初始化] JSR SCIInit ;[程序总循环入口] MainLoop: ;[等待接收1个数据] LDA #!1 LDHX #SerialBuff JSR SCIReN BCS MainLoop ;未收到数据,继续等待 ;[发送接到的一个数据] LDA #!1 LDHX #SerialBuff JSR SCISendN BRA MainLoop *[外部子程序存放处,这些子程序都在当前目录中] $INCLUDE "H08SCI.asm" $INCLUDE "GP32init.asm" $INCLUDE "SCIInit.asm" *[中断向量] ORG $FFFE ;复位矢量 DW MainInit (2)PC机方VB程序 图8-6给出了PC机方VB程序的界面.其功能是:在"发送窗口"的文本框输入字符,单击"发送"按钮,其文本框中的字符被发送出去.任何时候,只要PC机串行口收到数据,则显示在"接收窗口"."接收窗口"内的两个文本框,分别显示接收数据的字符和十六进制数.这个VB程序在本书的几个串行实例的目录中是一致的.同时,也可方便地用于整个学习过程. 实例编号:A02_1 路径:\ASM\A02_1串行通信查询方式\VB_SCI '程序描述: ' (1)把发送窗口中的数据从COM1发送出去 ' (2)把接收到的数据显示在接收窗口中 '------------------------------------------------------- Option Explicit '检查未经声明的变量 Dim SendData() As Byte '发送数据数组 Dim RecvData() As Byte '接收数据数组 Private Sub Form_Load() '串行口初始化 Call SCIinit(1, "9600,N,8,1") '清空有关文本框 TxtSEND.Text = "" TxtRECV.Text = "" '开放串行中断 MSComm1.RThreshold = 1 End Sub Private Sub CmdSEND_Click() '单击"发送"按钮 Dim i As Integer If TxtSEND.Text = "" Then TxtRECV.Text = "" GoTo CmdSEND_Click_Exit End If ReDim SendData(Len(TxtSEND.Text) - 1) For i = 0 To Len(TxtSEND.Text) - 1 SendData(i) = Asc(Mid$(TxtSEND.Text, i + 1, 1)) Next i MSComm1.Output = SendData CmdSEND_Click_Exit: End Sub Public Sub MSComm1_OnComm() '串行接收中断 Dim i As Integer Static S1 As String If Len(Trim(TxtRECV.Text)) = 0 Then S1 = "" MSComm1.RThreshold = 0 '关闭串行中断 RecvData = MSComm1.Input For i = LBound(RecvData) To UBound(RecvData) S1 = S1 & Chr$(RecvData(i)) Next i TxtRECV.Text = S1 If Len(S1) >= 70 Then S1 = "" MSComm1.RThreshold = 1 '开放串行中断 End Sub
Private Sub CmdCLR_Click() '单击"清空"按钮 TxtSEND.Text = "" TxtRECV.Text = "" End Sub
Private Sub CmdEXIT_Click() '单击"退出"按钮 If MSComm1.PortOpen = True Then MSComm1.PortOpen = False End End Sub Rem 串行口初始化 Private Sub SCIinit(ByVal COMx As Byte, ByVal SCIFormat As String) If MSComm1.PortOpen = True Then MSComm1.PortOpen = False End If MSComm1.CommPort = COMx '串行口号 MSComm1.Settings = SCIFormat '定义传输格式 MSComm1.InputMode = comInputModeBinary '二进制数据格式 MSComm1.RThreshold = 0 '关闭串行中断 MSComm1.InputLen = 0 '一次读取缓冲区全部数据 MSComm1.PortOpen = True '打开串行口 MSComm1.InBufferCount = 0 End Sub (3)中断方式MCU方主程序 实例编号:A02_2 路径:\ASM\A02_2串行通信中断方式 (H08SCI_2.ASM) *------------------------------------------------------* *文 件 名:H08SCI_2.asm * *硬件连接:无 * *程序描述:利用中断方式把收到的数据发送回去 * *目 的:初步掌握利用中断方式进行串行通信的基本知识 * *-------《嵌入式应用技术基础教程》教学实例------------*/ *[头文件] $include "GP32ASM.H" ;包含GP32的头文件 *[两个起始地址名] RAMstartAddr equ $0040 ;RAM的起始地址 FlashStartAddr equ $8000 ;程序开始地址 *[内存变量] org RAMstartAddr ;RAM的起始地址 SerialBuff rmb 8 ;缓冲区 *======================================================* *[主程序] org FlashStartAddr ;程序起始地址 MainInit: ;复位后程序从此开始执行 ;[系统初始化] SEI LDHX #$023F ;堆栈初始化 TXS JSR GP32Init ;调系统初始化子程序GP32Init ;[串行口初始化] JSR SCIInit BSET 5,SCC2 ;设置接收中断允许 ;[开放总中断] CLI ;[程序总循环入口] MainLoop: NOP NOP BRA MainLoop *[接收中断子程序] SCIRecINT: SEI ;关总中断 PSHH ;[接收1个数据] JSR SCIRe1 ;[发送接到的数据] JSR SCISend1 PULH CLI ;开总中断 RTI ;中断返回 *[以下为子程序存放处,这些子程序都在当前目录中] $INCLUDE "H08SCI.asm" $INCLUDE "GP32init.asm" $INCLUDE "SCIInit.asm" *------------------------------------------------------* ORG $FFE4 ;SCI接收中断矢量 DW SCIRecINT ORG $FFFE ;复位矢量 DW MainInit 8.4.3 08C语言串行通信子程序与测试实例 (1)SCI初始化08C语言子程序 串行口初始化08C语言例 /*SCIInit:串行口初始化子程序--------------------------------------------* *功 能: 对串行口进行初始化,默认为允许SCI,正常码输出,8位 * * 数据,无校验等,允许发送器允许接收器.查询方式收发, * * 波特率为9600 (设fBUS=2.4576MHz) * *参 数:无 * *返 回:无 * *-------------------------------------------------------------------------------*/ #include "GP32C.H" void SCIInit(void) { //总线频率fBUS=2.4576MHz,定义波特率Bt=9600 SCBR=0b00000010; //设置允许SCI,正常码输出,8位数据,无校验 SCC1=0b01000000; //设置允许发送,允许接收,查询方式收发 SCC2=0b00001100; } (2)串行发送与接收08C语言通用子程序 串行发送与接收08C语言通用子程序SCI.C /*-----------------------------------------------------* *文件描述:本文件包含了串行通信的4子程序,分别为: * *(1)SCISend1:串行发送1字节 * *(2)SCISendN:串行发送n字节 * *(3)SCIRe1:串行接收1字节 * *(4)SCIReN:串行接收n字节 * *-------------《嵌入式应用技术基础教程》--------------*/ //[以下为子程序源代码] //[包含头文件] #include "SCI.h" /*SCISend1:串行发送1个字节-----------------------------* *功 能:串行发送1个字节 * *参 数:要发送的数据 * *返 回:无 * *-----------------------------------------------------*/ void SCISend1(unsigned char o) {//判断ReStatusR的第SendTestBit位是否为1,是1可以发送 while(1) if ((ReSendStatusR & (1< { ReSendDataR=o; break;} } /*SCISendN:串行发送N个字节-----------------------------* *功 能:发送数组中的N个字节数据 * *参 数:待发送的数据字节数及其要存放的数组首地址 * *返 回:无 * *-----------------------------------------------------*/ void SCISendN(unsigned char n,unsigned char ch[]) {int i; for(i=0;i SCISend1(ch[i]); } /*SCIRe1:串行收一个字节数据----------------------------* *功 能:从串行口接收1个字节的数据 * *参 数:标志指针p * *返 回:接收到的数据(若接收失败,返回0xff) * *说 明:参数*p带回接收标志=0收到数据,=1未收到数据 * *-----------------------------------------------------*/ unsigned char SCIRe1(unsigned char *p) { unsigned int k; unsigned char i; //ReStatusR第ReTestBit位为1表示可接收数据 for(k=0;k<0xfbbb;k++) if ((ReSendStatusR & (1<=0xfbbb) {i=0xff; *p=0x01;} return i; //返回接收到的数据 } /*SCIReN:HC08串行接收N个字节---------------------------* *功 能:接收N个字节数据,并存放在ch数组中 * *参 数:待接收的数据字节数及其存放的数组首地址 * *返 回:接收标志=0收到数据,=1未收到数据 * *-----------------------------------------------------*/ unsigned char SCIReN(unsigned char n,unsigned char ch[]) {int m; unsigned char fp; m=0; while (m { ch[m]=SCIRe1(&fp); if (fp==1) return 1; m++; } return 0; } (3)查询方式08C语言主程序 实例编号:C02_1 路径:\C\C02_1串行通信查询方式 (H08SCI_1.prj) /*-----------------------------------------------------* *工 程 名:H08SCI_1 * *硬件连接:无 * *程序描述:把收到的数据发送回去 * *目 的:初步掌握利用查询方式进行串行通信的基本知识 * *-------《嵌入式应用技术基础教程》教学实例------------*/ //头文件 #include "GP32C.H" //包含头文件 #include "SCI.h" //串行通信子程序头文件 //函数声明 extern void SCIInit(void); //串行口初始化子程序 //内存变量声明 unsigned char SerialBuff[]; //存放接收数据的数组 //主程序 void main() { unsigned char i; SCIInit(); //调串行口初始化子程序 while(1) { i=SCIReN(1,SerialBuff); //等待接收1个数据 if(i==0) SCISendN(1,SerialBuff); //发送接到的数据 } } (4)中断方式08C语言主程序 实例编号:C02_2 路径:\C\C02_2串行通信中断方式 (H08SCI_2.prj) /*-----------------------------------------------------------* *工 程 名:H08SCI_2 * *硬件连接:无 * *程序描述:把收到的数据发送回去 * *目 的:初步掌握利用中断方式进行串行通信编程 * *-------------《嵌入式应用技术基础教程》教学实例--------------*/ //头文件 #include "GP32C.H" //包含头文件 #include "SCI.h" //串行通信子程序头文件 //函数声明 extern void SCIInit(void); //串行口初始化子程序 //内存变量声明 unsigned char SerialBuff[]; //存放接收数据的数组 //主程序 void main() { asm("SEI"); //禁止所有中断 SCIInit(); //串行口初始化 SCC2=(1 LDX R0 ;地址基值 INCX ;移到低8位上 ADD ADValue,X ;与上次低8位相加 STA ADValue,X ;放回原处 DECX ;地址退1,回到高8位 LDA TLC2543D ;取出高4位->A ADC ADValue,X ;与高位带进位相加 STA ADValue,X ;放回原处 INC R0 ;地址基值+2 INC R0 LDX R2 CBEQX #$00,ADP3 ;若为0,下一片TLC2543 BRA ADP0 ADP3: LDA R1 ;下一片片号 SEC ROLA STA R1 CBEQA #%11110111,ADP6 ;完成3片一次采集 BRA ADPP ADP6: ;完成3片一次采集,继续 DBNZ R3,AD16 ;求16次平均 MOV #$00,R0 MOV #!33,R1 ;共33路 ADP7: LDX R0 INCX LDA ADValue,X AND #$F0 NSA STA ADValue,X DECX LDA ADValue,X NSA PSHA AND #$0F STA ADValue,X ;高4位完成 PULA AND #$F0 INCX ADD ADValue,X STA ADValue,X ;低8位完成 INC R0 ;基址+2 INC R0 DBNZ R1,ADP7 RTS 练习与思考题 1.单片机串行通信接口为什么要进行电平转换 如何进行电平转换 2.简述串行通信收发数据的工作过程. 3.编写一程序,其功能是:以查询方式从串行口等待接收一个字节的数据,收到后,再通过串行口将收到的一个字节的数据发送出去.验证该程序可以通过微机向MCU发送一字节的数据,同时通过串行口接收一个字节的数据,使收到的数据与发出的数据相同. 4.以串行中断方式编程完成第3题的功能. 5.简要说明串行通信接口(SCI)与串行外设接口(SPI)的异同点. 6.简述SPI的收发数据的工作过程. 7.除本章给出的实例外,请另举一例说明SPI的应用方法.[提示:利用SPI可以实现两个单片机之间的连接,请给出电路设计及编程方法] 第8章 串行通信接口SCI与串行外设接口SPI 图8-2 9芯串行接口排列 9 8 7 6 图8-1 SCI数据格式 开始位 停止位 第7位 第6位 第5位 第4位 1μ×4 TTL电平 转为232电平 TTL电平 OUT IN +5V 第1位 第3位 +5V GND 第2位 5 3 2 1 4 第0位 图8-8 TLC2543的封装管脚图 Vcc EOC I/O CLOCK DATA INPUT DATA OUT REF+ REF- AIN10 AIN9 AIN0 AIN1 AIN2 AIN3 AIN4 AIN5 AIN6 AIN7 AIN8 AIN9 1 20 2 19 3 18 4 17 5 16 6 15 14 13 12 10 11 SPSCK SPSCK 图8-6 串行测试程序PC机方VB程序界面 图8-7 CPHA/时序 SCI波特率寄存器 SCI状态寄存器 SCI 控制寄存器 发送引脚TxD 接收引脚RxD 发送移位寄存器 接收移位寄存器 MCU 的 内 部 总 线 (Internal Bus) SCI 数据寄存器 图8-5 SCI编程模型 1 2 3 4 5 6 7 8 16 15 14 13 12 11 10 9 MAX232CPE 图8-3 MAX232引脚 232电平 OUT IN 1 2 3 4 5 6 7 8 9 10 40 39 38 37 36 35 34 33 32 31 MC68HC908GP32 0.1μ +5V 30 29 28 27 26 25 24 23 22 21 PLL滤波 10K 0.01μ 0.47μ 晶振电路 150K 32.768 15P 10K 20P 复位电路 0.1μ RST他TTT 51Ω 10K +5V 11 12 13 14 15 16 17 18 19 20 0.1μ +5V 图8-4 具有串行通信功能的MC68HC908G932最小系统电路原理图 MC68HC908GP32 PTC0 MISO MOSI SPSCK PTC1 PTC2 TLC2543(第0片) AIN0 : DATA OUT : DATA INPUT : I/O CLOCK AIN10 模拟量输入 : : : TLC2543(第1片) AIN0 : DATA OUT : DATA INPUT : I/O CLOCK AIN10 : : : TLC2543(第2片) AIN0 : DATA OUT : DATA INPUT : I/OCLOCK AIN10 : : : 图8-9 基于SPI的A/D转换扩展电路 从MCU 波特率发生器 MOSI MOSI 主MCU MISO MISO 移位寄存器 移位寄存器 图8-6 SPI全双工主-从连接
免责声明:作品版权归所属媒体与作者所有!!本站刊载此文仅为普及科学技术知识提供更多信息。如果您认为我们侵犯了您的版权,请告知!本站核实后立即删除。kpzsnet#126.com
(#改为@)
|