第7章 串行通信接口(SCI)

第7章 串行通信接口(SCI)

第7章 串行通信接口(SCI)
目前几乎所有的台式电脑都带有 9 芯的异步串行通信口,简称串行口或 COM 口。 有的台式电脑带有两个串行口,分别称为 COM1、COM2 口。大部分的笔记本电脑也 带有串行口。随着 USB 接口的普及,串行口的地位逐渐变低了。但是,作为设备间的 一种简便的通信方式,在相当长的时间内,串行口还不会消失。因为简单且常用的串行 通信只需要三根线(发送线、接收线和地线),所以,串行通信可以作为 MCU 与外界通 信的简便方式之一。大部分嵌入式 MCU 都具有串行通信接口(Serial Communication Interface,SCI) ,掌握 SCI 的编程是学习 MCU 的重要内容之一。 本章从掌握规范的 SCI 基本编程角度讨论串行通信编程,把与芯片型号相关内容 和与芯片型号无关内容区别开来,便于读者融会贯通与实际应用。 本章 7.1、 节是与芯片无关的有关串行通信的通用基础知识, 7.2 只有理解这些基础 知识,才能进行串行通信的应用。7.3、7.4 节阐述 GP32 芯片的 SCI 模块的编程方法, 在此基础上,重点掌握 7.5 节给出的编程实例。注意,在汇编程序中,只有初始化子程 序与 GP32 相关,收发程序在整个 08 系列中是通用的,在 C 程序中,只有初始化子程 序与 GP32 相关,收发程序对任何芯片是通用的。当然,要注意头文件 SCI.h 相关位的 定义。关于串口程序的测试,最好利用教学资料中提供的 PC 机方的高级语言源程序进 行。根据自己对高级语言的熟悉程度选用 VB、C#、VC 或其他高级语言。实际上,掌 握一门 PC 机方的高级语言编程对嵌入式系统开发是必要的。

7.1 异步串行通信的基础知识
本节简要概括了串行通信中的通常使用的相关基本概念, 为学习 MCU 的串行接口 编程做准备。对于已经了解这方面知识的读者,可以略读本节。

7.1.1 基本概念
“位”(bit) 是单个二进制数字的简称,是可以拥有两种状态的最小二进制值,分 别用“0”和“1”表示。在计算机中,通常一个信息单位用 8 位二进制表示,称为一个 “字节”(byte) 。串行通信的特点是:数据以字节为单位,按位的顺序从一条传输线上 发送出去。这里至少涉及到以下几个问题:第一,每个字节之间是如何区分的;第二, 发送一位的持续时间是多少; 第三, 怎样知道传输是正确的; 第四, 可以传输多远等等。 这些问题属于串行通信的基本概念。 串行通信分为异步通信与同步通信两种方式, 本节 主要给出异步串行通信的一些常用概念。 正确理解这些概念, 对串行通信编程是有益的。

1.异步串行通信的格式
在 MCU 的英文芯片手册上,通常说 SCI 采用的是 NRZ 数据格式,英文全称是:
1

第7章 串行通信接口(SCI)

“standard non-return-zero mark/space data format” ,可以译为: “标准不归零传号/空号数 据格式” 。这是一个通信术语, “不归零”的最初含义是:用负电平表示一种二进制值, 正电平表示另一种二进制值,不使用零电平。 “mark/space”即“传号/空号”分别是表 示两种状态的物理名称,逻辑名称记为“1/0” 。对学习嵌入式应用的读者而言,只要理 解这种格式只有“1”“0”两种逻辑值就可以了。图 7-1 给出了 8 位数据、无校验情况 、 的传送格式。
开始位 第0位 第1位 第2位 第3位 第4位 第5位 第6位 第7位 停止位

图7-1 SCI数据格式

这种格式的空闲状态为“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”
2

第7章 串行通信接口(SCI)

的个数为奇数或偶数。奇数或偶数依据使用的是“奇校验检查”还是“偶校验检查”而 定。当使用“奇校验检查”时,如果字符数据位中“1”的数目是偶数,校验位应为“1” , 如果“1”的数目是奇数,校验位应为“0” 。当使用“偶校验检查”时,如果字符数据 位中“1”的数目是偶数,则校验位应为“0” ,如果是奇数则为“1” 。 这里列举奇偶校验检查的一个实例,看看 ASCII 字符“R” 其位构成是 1010010。 , 由于字符“R”中有三个 1 位,若使用奇校验检查,则校验位为 0;如果使用偶校验检 查,则校验位为 1。 在传输过程中,若有 1 位(或奇数个数据位) 发生错误,使用奇偶校验检查,可以 知道发生传输错误。若有 2 位(或偶数个数据位) 发生错误,使用奇偶校验检查,不能 知道发生传输错误。但是奇偶校验检查方法简单,使用方便,发生一位错误的概率远大 于发生二位错误的概率,所以“奇偶校验”这种方法还是最为常用的一种校验方法。几 乎所有 MCU 的串行异步通信接口,都提供这种功能。

4.串行通信的传输方式
在串行通信中,经常用到“单工”“双工”“半双工”等术语。它们是串行通信的 、 、 不同传输方式。下面简要介绍这些术语的基本含义。 ①单工(Simplex):数据传送是单向的,一端为发送端,另一端为接收端。这种传输 方式中,除了地线之外,只要一根数据线就可以了。有线广播就是单工的。 ②全双工(Full-duplex):数据传送是双向的,且可以同时接收与发送数据。这种传 输方式中,除了地线之外,需要两根数据线,站在任何一端的角度看,一根为发送线, 另一根为接收线。一般情况下,MCU 的异步串行通信接口均是全双工的。 ③半双工(Half-duplex):数据传送也是双向的,但是在这种传输方式中,除了地线 之外,一般只有一根数据线。任何一个时刻,只能由一方发送数据,另一方接收数据, 不能同时收发。在 Freescale 的 HC08 系列 MCU 中,监控模式的通信就采用这种方式。

7.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 采用负 逻辑,-15V~-3V 为逻辑“1” ,+3V~+15V 为逻辑“0” 。RS-232C 最大的传输距离是 30m,通信速率一般低于 20Kbps。当然,实际应用中,也有人用降低通信速率的方法, 通过 RS-232 电平,将数据传送到 300m 之外,这是很少见的,且稳定性很不好。

3

第7章 串行通信接口(SCI)

表 7-1 9 芯串行接口引脚含义表 引脚号 1 2 3 4 5 功 能 接收线信号检测(载波检测DCD) 接收数据线(RXD) 发送数据线(TXD) 数据终端准备就绪(DTR) 信号地(SG) 引脚号 6 7 8 9 功 能 数据通信设备准备就绪(DSR) 请求发送(RTS) 清除发送 振铃指示

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 芯接口。 图 7-2 给出了 9 芯串行接口的排列位置,相应引脚含义见表 7-1。

6 1 2

7 3 嵌

8 4

9 5

入 图7-2 9芯串行接口排列 式

V
图7-3 MAX232引脚

在 RS-232 通信中,常常使用精简的 RS-232 通信,通信时仅使用 3 根线:RxD(接 集 1 收线)、TxD(发送线)和 GND(地线)。其它为进行远程传输时接调制解调器之用,有的也 成 1 可作为硬件握手信号,初学时可以忽略这些信号的含义。 开 1 在 MCU 中,若用 RS-232C 总线进行串行通信,则需外接电路实现电平转换。在发 发 5 送端需要用驱动电路将 TTL 电平转换成 RS-232C 电平,在接收端需要用接收电路将 系 P RS-232C 电平转换为 TTL 电平。电平转换器不仅可以由晶体管分立元件构成,也可以 统 A 直接使用集成电路。目前使用 MAX232 芯片较多,该芯片使用单一+5V 电源供电实现 口 电平转换。图 7-3 给出了 MAX232 的引脚说明。 数 引脚含义简要说明如下: 据 方 Vcc(16 脚) :正电源端,一般接+5V 向 嵌 寄 GND(15 脚) :地 入 存 VS+(2 脚) :VS+=2Vcc-1.5V=8.5V 器 式 D VS-(6 脚) :VS-=-2Vcc-1.5V=-11.5V 集 D 成 开 发 系
R A x 位 A 4

第7章 串行通信接口(SCI)

232 TTL 电平 电平
OUT IN OUT IN

C2+、C2-(4、5 脚) :一般接 1?F 的电解电容 +5V GND C1+、C1-(1、3 脚) :一般接 1?F 的电解电容 + 输入输出引脚分两组,基本含义见表 7-2。在实际使用时,若只需要一路 SCI,可 16 15 14 13 12 11 10 9 以使用其中的任何一组。 MAX232CPE 利用 MAX232 将 TTL 电平转换为 RS-232 电平的电路接法将在下一节结合 SCI 的 1 2 3 4 5 6 7 8 + 外围硬件电路讨论。
+ +5V + 表 7-2 MAX232 芯片输入输出引脚分类与基本接法 +

组别 1

TTL电平引脚 11 12 10 9

方向 输入 输出 输入 输出

典型接口 接MCU的TxD 接MCU的RxD 同上

232电平引脚 13 14 8 7

1? F×5 方向 输入 输出 输入 输出

1 1

V TTL 电平 转为 232 电平 典型接口

连接到接口与其它设备通过 232相接 同上

2

H I N
Z

7.2 电平转换电路与SCI通用编程 原理
所 有 型 号 MCU 的 串 行 通 信 接 口 (Serial Communication Interface,SCI) ,都具有发送引脚 TxD、接收引脚 RxD,它们是 TTL 电平引脚。要利 用这两个引脚与外界实现异步串行通信, 还必须将 TTL 电平转为 RS-232 电平,这可利用上节介绍的 MAX232 来完成。 本节从通用角度讨论 SCI 的电路 设计、基本编程结构与编程原理,为实际编程做准 备。

C

V
图7-4 SCI电平转换电路

1 1

7.2.1 SCI的外围硬件电路

具有 SCI 接口的 MCU,一般具有发送引脚(TxD)与接收引脚(RxD),不同公司或不 H 同系列的 MCU,使用的引脚缩写名可能不一致,但含义相同。SCI 的外围硬件电路, 主要目的是将 MCU 的发送引脚 TxD 与接收引脚 RxD 的 TTL 电平,通过 RS-232 电平 I 转换芯片转换为 RS-232 电平。图 7-4,给出一个基本 SCI 电平转换电路。 N 基本工作过程是: 发送过程:MCU 的 TxD(TTL 电平) 经过 MAX232 的 11(T1IN) 送到 MAX232 内 Z 部,在内部 TTL 电平被“提升”为 232 电平,通过 14(T1OUT) 发送出去。 接收过程:外部 232 电平经过 MAX232 的 13(R1IN) 进入到 MAX232 的内部,在 C
5

第7章 串行通信接口(SCI)

内部 232 电平被 “降低” TTL 电平, 为 经过 12(R1OUT) 送到 MCU 的 RxD, 进入 MCU 内部。 进行 MCU 的 SCI 编程时,只针对 MCU 的发送与接收引脚,与 MAX232 无关, MAX232 只是起到电平转换作用。

7.2.2 SCI的基本编程原理
从基本原理角度看,串行通信接口 SCI 的主要功能是:接收时,把外部的单线输 入的数据变成一个字节的并行数据送入 MCU 内部;发送时,把需要发送的一个字节的 并行数据转换为单线输出。图 7-5 给出了一般 MCU 的 SCI 模块的功能描述。为了设置 波特率 SCI 应具有波特率寄存器。为了能够设置通信格式、是否校验、是否允许中断 等,SCI 应具有控制寄存器。而要知道串口是否有数据可收、数据是否发送出去等,需 要有 SCI 状态寄存器。当然,若一个寄存器不够用,控制与状态寄存器可能有多个。 而 SCI 数据寄存器存放要发送的数据,也存放接收的数据,这并不冲突,因为发送与 接收的实际工作是通过“发送移位寄存器”和“接收移位寄存器”完成的。编程时,程 序员并不直接与“发送移位寄存器”和“接收移位寄存器”打交道,只与数据寄存器打 交道,所以 MCU 中并没有设置“发送移位寄存器”和“接收移位寄存器”的映像地址。 发送时,程序员通过判定状态寄存器的相应位,了解是否可以发送一个新的数据。若可 以发送,则将待发送的数据放入“SCI 数据寄存器”中就可以了,剩下的工作由 MCU 自动完成:将数据从“SCI 数据寄存器”送到“发送移位寄存器” ,硬件驱动将“发送 移位寄存器”的数据一位一位地按照规定的波特率移到发送引脚 TxD,供对方接收。 接收时,数据一位一位地从接收引脚 RxD 进入“接收移位寄存器” ,当收到一个完整字 节时,MCU 会自动将数据送入“SCI 数据寄存器” ,并将状态寄存器的相应位改变,供 程序员判定并取出数据。
接收引脚 RxD 发送引脚 TxD

接收移位寄存器

发送移位寄存器

15 SPH
H X 0

SCI 数据寄存器
15 7 8

MCU 的 内 部 总 线 (Internal Bus)
0

7 SCI 控制寄存器

SCI状态寄存器

SCI波特率寄存器

7
0

图7-5 SCI编程模型

6

15 SPH 15

第7章 串行通信接口(SCI)

7.3 GP32 SCI模块寄存器
本节从编程角度介绍 MC908GP32 单片机的 SCI。从外部引脚来看,负责串行通信 的是 PTE0/TxD、PTE1/RxD 两个引脚,当允许 SCI 时,它们作为串行通信引脚,分别 称为串行发送引脚 TxD、串行接收引脚 RxD。从程序员角度看,涉及 SCI 的有 7 个寄 存器,其中 1 个波特率寄存器,3 个控制寄存器,2 个状态寄存器,1 个数据寄存器, 只要理解和掌握这 7 个寄存器的用法,就可以进行 SCI 编程。 表 7-3 给出了 GP32 芯片 SCI 模块的寄存器。
表 7-3 GP32 的 SCI 模块寄存器 寄存器名称 控制寄存器 缩写 SCC1 SCC2 SCC3 状态寄存器 数据寄存器 波特率寄存器 SCS1 SCS2 SCDR SCBR 地址 $0013 $0014 $0015 $0016 $0017 $0018 $0019 只读 读/写 读/写 中断标志、发送与接收状态 收发数据 设置波特率 读/写 设置传输格式、中断使能 访问权限 基本功能

1.SCI波特率寄存器(SCI Baud Rate Register,SCBR)
SCI 波特率寄存器 SCBR 的作用是设置串行通信的波特率。通常情况下,选择内部 总线时钟为串行通信的时钟源,此时利用 SCBR 对总线频率 fBUS 可以进行分频得到串 行通信的波特率。SCBR 的地址是:$0019,定义为:
数据位 定义 复位 D7 未定义 0 D6 未定义 0 D5 SCP1 0 D4 SCP0 0 D3 未定义 0 D2 SCR2 0 D1 SCR1 0 D0 SCR0 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)
7

第7章 串行通信接口(SCI)

=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× D× D) P B 例如:fBUS=2.4576MHz,取 PD=1(即 SCP1、SCP0=00)、BD=4(即 SCR2、SCR1、 SCR0=010),则波特率=2457600 /(64× 4) = 9600。 1×

2.SCI控制寄存器1(SCI Control Register 1,SCC1)
SCI 控制寄存器共有 3 个,分别称为 SCC1、SCC2、SCC3。对它们的写入,实现 对 SCI 的设置。SCC1 的地址是:$0013,定义为:
数据位 定义 复位 D7 LOOPS 0 D6 ENSCI 0 D5 TXINV 0 D4 M 0 D3 WAKE 0 D2 ILTY 0 D1 PEN 0 D0 PTY 0

初学时重点掌握其中的 D6、D4、D1 和 D0 位。 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)并不是常用功能,初学时可以不需 深入理解。对唤醒功能的介绍放在 7.6 节。 D2 — ILTY 位:空闲线类型位(Idle Line Type Bit),决定 SCI 何时开始计数“空闲 字符”的位数。ILTY=1,空闲字符位从“停止位”开始计数;ILTY=0,空闲字符位从 “起始位”开始计数。从“起始位”开始计数,则“停止位”前的一串“1”可能产生 错误的空闲线条件。从“停止位”开始计数,可避免错误的空闲线识别,但需要适当地 同步发送操作。 D1 — PEN 位: 奇偶校验允许位(Parity Enable Bit)。 PEN=1, 允许奇偶校验; PEN=0, 不进行奇偶校验。

8

第7章 串行通信接口(SCI)

D0 — PTY 位:奇偶校验类型选择位(Parity Bit)。PTY=1,奇校验;PTY=0,偶 校验。不进行奇偶校验时,该位无意义,一般写 0。

3.SCI控制寄存器2(SCI Control Register 2,SCC2)
SCC2 的地址是:$0014,定义为:
数据位 定义 复位 D7 SCTIE 0 D6 TCIE 0 D5 SCRIE 0 D4 ILIE 0 D3 TE 0 D2 RE 0 D1 RWU 0 D0 SBK 0

初学时重点掌握其中的 D3 和 D2 位。 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 R8 0 D6 T8 0 D5 DMARE 0 D4 DMATE 0 D3 ORIE 0 D2 NEIE 0 D1 FEIE 0 D0 PEIE 0

一般情况下,该寄存器不用。初学时主要了解有单字节校验时使用 D7 和 D6 位。 D7 — R8 位:接收位 8 (Received bit 8)。该位只读。 D6 — T8 位:发送位 8(Transmitted Bit 8)。 D5、D4 — 不用。 D3 — ORIE 位:接收器溢出中断允许位(Receiver Overrun Interrupt Enable Bit)。 ORIE=1,允许接收器溢出中断;反之不允许。 D2 — NEIE 位:接收器噪声错误中断允许位(Receiver Noise Error Interrupt Enable Bit)。NEIE=1,允许接收器噪声错误中断;反之不允许。
9

第7章 串行通信接口(SCI)

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 SCTE 1 D6 TC 1 D5 SCRF 0 D4 IDLE 0 D3 OR 0 D2 NF 0 D1 FE 0 D0 PE 0

初学时主要掌握其中的 D7 和 D5 位。 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,表明 接收器出现奇偶校验错误。 注意: 读取上述标志位及 SCDR 数据, 系统自动清除相应的标志位 (SCTE 位除外) 。 读取 SCTE 位及向 SCDR 写数据,系统自动清除 SCTE 标志位。

6.SCI状态寄存器2(SCI Status Register 2,SCS2)
SCS2 为只读寄存器,它的地址是:$0017,定义为:
数据位 定义(只读) 复位 D7 未定义 0 D6 未定义 0 D5 未定义 0 D4 未定义 0 D3 未定义 0 D2 未定义 0 D1 BKF 0 D0 RPF 0

该寄存器通常情况下不用。 D7~D2:未定义。 D1 — BKF 位:终止码标志位(Break Flag Bit)。该位为 1,检测到终止码。读取该
10

第7章 串行通信接口(SCI)

位或向 SCDR 写数据,系统自动清除该标志位。 D0 — RPF 位:接收进行标志位(Reception in Progress Flag Bit)。该位为 1,表明正 在接收。该位不能产生中断请求,接收器检测到错误开始位或空闲特征,复位该位。

7.SCI数据寄存器(SCI Data Register —SCDR)
SCDR 为 SCI 系统最常用的寄存器,它的地址是:$0018。写入时,为要发送的 8 位数据,记为:T7~T0;读出时,为接收的 8 位数据,记为:R7~R0。不受复位影响。 注意:不要对该寄存器使用读-修改-写命令。

7.4 串行口初始化与收发编程的基本方法
无论用查询方式还是中断方式进行串行通信编程,在程序初始化时均必须对 SCI 进行初始化,主要进行波特率设置、通信格式的设置、发送接收数据方式的设置等,本 小节给出最基本的用法,以作为 HC08 系列单片机的串行通信编程入门。下一小节将给 出规范的串行通信编程子程序, 读者可以直接将其应用于实际的嵌入式应用系统的开发 中。

1.SCI初始化
有关口地址的定义已经在头文件 GP32.H 中给出, SCC1、SCC2、SCC3、SCBR、 SCS1、SCS2、SCDR 可以直接使用。 对 SCI 进行初始化,最少由以下三步构成: 第一步:定义波特率。一般选择内部总线时钟为串行通信的时钟源(这个设置在 MCU 的系统初始化中完成,令系统设置寄存器 CONFIG2 的 SCIBDSRC 位为 1 即可, 从学习顺序角度,本书将这部分内容放在第 14 章,此处默认系统初始化时已经做了这 样的设置) 。设 MCU 的系统初始化时已经定义总线频率为 fBUS,同时准备定义串行通 信波特率, 记为 Bt。 通过选择 SCI 波特率寄存器 SCBR 的波特率预分频位 SCP (两位) 、 波特率选择位 SCR(三位) ,以便选择合适的分频系数 PD、BD,代入公式 Bt=fBUS / (64× D× D) P B ,使得 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× D× D) “拼凑” PD=1 即 SCP1、 / P B 可以 出, ( 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、数据长度、
11

第7章 串行通信接口(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,可以取出数据

12

第7章 串行通信接口(SCI)

7.5 串行通信通用函数与测试实例 7.5.1 串行通信子函数
1.串行通信头文件SCI.h
//[SCI.h]串行通信头文件----------------------------------------------------#include "GP32C.h" #include "Type.h" #define #define #define #define //GP32 MCU映像寄存器名定义 //类型别名定义 SCS1 5 7 SCDR //SCI状态寄存器 //接收缓冲区满标志位 //发送缓冲区空标志位 //数据寄存器

ReSendStatusR ReTestBit SendTestBit ReSendDataR

//串行通信函数声明 void SCIinit(void); void SCIsend1(INT8U o); void SCIsendN(INT8U n, INT8U ch[]); INT8U SCIre1(INT8U *p); INT8U SCIreN(INT8U n, INT8U ch[]);

//串行口初始化 //发送1字节 //发送n字节 //接收1字节 //接收n字节

2.串行通信驱动文件SCI.c
串行通信驱动文件包括 SCI 初始化、接收 1 字节、发送 1 字节、接收 n 字节和发 送 n 字节函数。读者可以直接使用这些函数进行 MCU 的串行通信编程。
//[SCI.c]串行通信----------------------------------------------------------* //本文件包含: * // (1)SCIinit: 串行口初始化 * // (2)SCIsend1:串行发送1个字节 * // (3)SCIsendN:串行发送n字节 * // (4)SCIre1: 串行接收1字节 * // (5)SCIreN: 串行接收n字节 * //硬件连接: * // MCU的串口与PC方的串口相连 * //-------------------------------------------------------------------------* //头文件 #include "SCI.h" //SCIinit:串行口初始化-----------------------------------------------------* //功能:对串行口进行初始化,默认为允许SCI,正常码输出,8位数据,无校验, * // 允许发送器,允许接收器.查询方式收发,波特率为9600(设fBUS = 2.4576MHz) * //参数:无 * //返回:无 * //说明:该函数与具体的芯片型号(MC68HC908GP32)有关 * 13

第7章 串行通信接口(SCI)

//-------------------------------------------------------------------------* void SCIinit(void) { //1.总线频率fBUS= 2.4576MHz,定义波特率Bt = 9600 SCBR = 0b00000010; //2.设置允许SCI,正常码输出,8位数据,无校验 SCC1 = 0b01000000; //3.设置允许发送,允许接收,查询方式收发 SCC2 = 0b00001100; } //SCIsend1:串行发送1个字节-------------------------------------------------* //功能:串行发送1个字节 * //参数:要发送的数据 * //返回:无 * //-------------------------------------------------------------------------* void SCIsend1(INT8U o) { //判断ReSendStatusR的第SendTestBit位是否为1,是1可以发送 while (1) if ((ReSendStatusR & (1<<SendTestBit)) != 0) { ReSendDataR = o; break; } } //SCIsendN:串行发送N个字节-------------------------------------------------* //功能:发送数组中的N个字节数据 * //参数:待发送数据的字节数及存放这些数据的数组首地址 * //返回:无 * //内部调用函数:SCIsend1 * //-------------------------------------------------------------------------* void SCIsendN(INT8U n, INT8U ch[]) { int i; for(i=0; i<n; i++) SCIsend1(ch[i]); } //SCIre1:串行收一个字节数据------------------------------------------------* //功能:从串行口接收1个字节的数据 * //参数:标志指针p * //返回:接收到的数据(若接收失败,返回0xff) * //说明:参数*p带回接收标志.*p = 0,收到数据;*p = 1,未收到数据 * //-------------------------------------------------------------------------* INT8U SCIre1(INT8U *p) { INT16U k; 14

第7章 串行通信接口(SCI)

INT8U i; //ReSendStatusR第ReTestBit位为1表示可接收数据 for(k=0; k < 0xfbbb; k++) if ((ReSendStatusR & (1<<ReTestBit)) != 0) { i = ReSendDataR; *p = 0x00; break; } //接收失败 if (k >= 0xfbbb) { i = 0xff; *p = 0x01; } return i; } //SCIreN:HC08串行接收N个字节-----------------------------------------------* //功能:接收N个字节数据,并存放在ch数组中 * //参数:待接收的数据字节数及其存放的数组首地址 * //返回:接收标志 = 0 收到数据, = 1 未收到数据 * //内部调用函数:SCIre1 * //-------------------------------------------------------------------------* INT8U SCIreN(INT8U n, INT8U ch[]) { int m; INT8U fp; m = 0; while (m < n) { ch[m] = SCIre1(&fp); if (fp == 1) { return 1; } m++; } return 0; }

7.5.2查询方式工程文件
1.查询方式工程(08C)文件列表
查询方式 08C 工程文件列表见表 7-4。 方以 7.5.4 节的串口调试器进行数据的收 PC 发。

15

第7章 串行通信接口(SCI)

表 7-4 查询方式测试工程文件 工程文件名 所在路径 文件类型 文件名 GP32C.h SCI.h 头文件 Type.h EnDisInt.h Includes.h C语言 子函数文件 C语言主函数 MCUinit.c SCI.c Main.c SCI_Pooling.prj MC08Ex2007\GP32\GP32C\C02_串行通信查询方式 功能简述 芯片头文件 SCI收发子函数头文件 数据类型头文件 开放或禁止MCU模块中断 总头文件 芯片系统初始化函数定义 SCI收发子函数定义 主函数 讲解章节 [08C工程文件组织]5.3 本章 [08C工程文件组织]5.3 [本章] [08C工程文件组织]5.3 [初始化及PLL编程实例]14.2.5 [本章] [本章]

2.查询方式08C语言主程序
//-------------------------------------------------------------------------* //工 程 名:SCI_Pooling.prj * //硬件连接: * // (1)MCU的串口与PC方的COM1相连 * //程序描述:利用查询方式把收到的数据发送回去 * //目 的:初步掌握利用查询方式进行串行通信的基本知识 * //------------------清华2007版《嵌入式技术基础与实践》实例-----------------* //总头文件 #include "Includes.h" //主函数 void main() { INT8U i; DisableMCUint(); //禁止总中断 //1. 芯片初始化 MCUinit(); //2. 模块初始化 SCIinit(); //(1) 串口初始化 //总循环 while (1) { //接收1个字节的数据 i=SCIreN(1,SerialBuff); //发送接到的1个字节数据 if (i == 0) { SCIsendN(1,SerialBuff); } } }

16

第7章 串行通信接口(SCI)

7.5.3 中断方式工程文件
1.中断方式08C工程文件列表
前面 7.5.2 节介绍了串行通信的查询方式,本节将介绍串行通信的中断方式。中断 方式测试工程文件列表见表 7-5。使用时的注意问题在下面讨论。
表 7-5 中断方式 08C 测试工程文件 工程文件名 所在路径 文件类型 文件名 GP32C.h Includes.h 头文件 EnDisInt.h SCI.h Type.h MCUinit.c C语言 子函数文件 C语言主函数 SCI.c Vectors.c Main.c SCI_INT.prj MC08Ex2007\GP32\GP32C\C03_串行通信中断方式 功能简述 芯片头文件 总头文件 开放或禁止MCU模块中断 串行通信头文件 数据类型头文件 芯片系统初始化函数定义 SCI收发子函数定义 中断处理及中断向量表 主函数 讲解章节 [08C工程文件组织]5.3 [08C工程文件组织]5.3 [本章] [本章] [08C工程文件组织]5.3 [初始化及PLL编程实例]14.2.5 [本章] [08C工程文件组织]5.3 [本章]

2.中断方式08C语言主程序main.c
使用中断方式进行串行通信时,在主函数中要调用宏 EnableSCIReInt(),开放串行 中断。 在系统初始化子函数 MCUInit()中有关总中断(DISABLE_INTERRUPTS), 因此在 放开串行中断后要放开总中断(ENABLE_INTERRUPTS)。
//-------------------------------------------------------------------------* //工 程 名:SCI_Int.prj * //硬件连接: * // (1)MCU的串口与PC方的串口相连 * //程序描述:利用中断方式把收到的数据发送回去 * //目 的:初步掌握利用中断方式进行串行通信的基本知识 * //------------------清华2007版《嵌入式技术基础与实践》实例-----------------* //总头文件 #include "Includes.h" //主函数 void main() { DisableMCUint(); //禁止总中断 //1. 芯片初始化 MCUinit(); //2. 模块初始化 SCIinit(); //(1) 串口初始化 //3. 开放各模块中断 EnableSCIreInt(); //(1)开放SCI接收中断

17

第7章 串行通信接口(SCI)

//4. 开放总中断 EnableMCUint(); //主循环 while (1) { } }

3.串行中断子函数声明EnDisInt.h
在该头文件中对开关总中断进行了宏定义, 并且其他各个模块的中断设置函数在此 进行声明。
//[EnDisInt.h]开放或禁止MCU各模块中断头文件--------------------------------#include "GP32C.h" //GP32 MCU映像寄存器名定义

//开放或禁止中断宏定义 #define EnableMCUint() #define DisableMCUint() #define EnableSCIreInt() #define DisableSCIreInt()

asm("CLI") asm("SEI") SCC2 |= (1 << 5) SCC2 &= ~(1 << 5)

//开放总中断 //禁止总中断 //令SCC2.5=1,开放SCI接收中断 //令SCC2.5=0,禁止SCI接收中断

4.串行中断处理函数
//[Vectors.c]中断处理函数与中断向量表------------------------------------* //功能: * // (1)定义中断处理子程序 * // (2)放置中断向量表 * //本文件包含: * // (1)SCI接收中断处理函数 * // (2)未定义的中断处理函数 * //说明:该文件与芯片具体型号有关 * // (1)芯片型号MC68HC908GP32 * //-------------------------------------------------------------------------* #include "Type.h" #include "EnDisInt.h" #include "SCI.h" //类型别名定义 //开放或禁止MCU各模块中断的宏定义 //该头文件包含串行通信函数声明

//isrSCIre:接收中断处理函数------------------------------------------------* //功能:接收1个字节数据, 发送接到的数据 * //参数:无 * //返回:无 * //内部调用函数:SCIreN, SCIsendN * //-------------------------------------------------------------------------* #pragma interrupt_handler isrSCIre void isrSCIre(void) { INT8U f; //标志是否接收到数据 18

第7章 串行通信接口(SCI)

INT8U SerialBuff[1]; //存放接收数据的数组 DisableMCUint(); //禁止总中断 //接收1个字节的数据 f = SCIreN(1, SerialBuff); //若收到数据,则发送接到的数据 if (f == 0) SCIsendN(1, SerialBuff); EnableMCUint(); //开放总中断 } //此处为用户中断处理函数的存放处 // //未定义的中断处理函数,本函数不能删除 #pragma interrupt_handler isrDummy void isrDummy(void) { } //中断矢量表,需定义中断函数,可修改下表中的相应项目 //(interrupt service routine,isr 中断处理程序) #pragma abs_address:0xffdc //中断向量表起始地址 void (* const _vectab[])(void) = { //????省略其他未使用的中断向量定义 isrSCIre, //SCI接收中断 //????省略其他未使用的中断向量定义 }; #pragma end_abs_address

5.串行中断方式矢量表文件
HC08 的中断向量表的详细说明在前面章节已经介绍。在使用中断方式时,只要将 中断向量表中串行接收中断项的 isrDummy 改为中断处理函数的函数名 isrSCIre 即可, 函数内容如上面所描述的。 本节仅讲述了串行通信的 08C 编程实例,用汇编编程的思想与之基本类似,读者 可 以 参 见 教 学 资 料 的 “ MC08Ex2007\GP32\GP32S\C02_ 串 行 通 信 查 询 方 式 ” 和 “MC08Ex2007\GP32\GP32S\C03_串行通信中断方式”下的汇编工程文件。

7.5.4 通过PC机方程序调试串行通信
1.自已动手编程序
参见教学资料中利用 VB、VC、C#语言给出的串行测试程序。

2.串口调试器(SSCOM V2.0)
串口调试工具比较多,SSCOM 是其中比较出色的一款软件,读者可以从网址
19

第7章 串行通信接口(SCI)

HTTP://www.mcu51.com/download/sscom.rar 中下载,本书教学资料的“MC08Ex2007\ 配套软件\串口调试器”文件夹下包含该软件。在一些与串口操作相关的实验中,该软 件带来很多方便。 软件运行界面如图 7-6 所示。 本书中一些与串口数据收发相关的程序, 高端软件可以用 SSCOM 配合进行,读者也可以参照前两节内容自行编写程序。

图7-6 串口调试器(SSCOM V2.0)运行界面

*7.6 串行通信进一步讨论
前面几个章节介绍了串行通信的基本知识、 串行通信编程的基本方法。 本节将介绍 一些串行通信的其他功能和扩展使用。

7.6.1 唤醒功能
关于唤醒功能(Wake-up feature) , 这里作概要介绍。 在一个典型的多处理器系统中, 软件协议通常在消息的开始判断地址。 唤醒功能允许无关的 MCU 忽略消息的剩余部分, 同时禁止这些 MCU 接收器的标志(和中断)处理,直到数据线返回到空闲状态。SCI 接 收器可以被一串包含 10 个(或 11 个)1 的空闲字符串唤醒。发送器软件必须在发送连续 消息的间隙提供必须的空闲字符串, 并保证空闲字符串不在消息中出现。 还有一种将休 眠中的 MCU 唤醒的办法:使 MCU 接收到的字符的最高位为 1。 WAKE=0,RxD 上的空闲状态能够清 RWU 位并唤醒 SCI。起始帧(或每个帧)中包 含地址信息, 所有的接收器计算出该地址信息, 与所包含地址相匹配的接收器处理接下 来的数据帧。其它接收器置 RWU 位为 1,并返回到就绪状态,直到再次在 RxD 上出现 空闲状态。 WAKE=1,当一个帧的 msb 位为逻辑 1 时清 RWU 位并唤醒 SCI。msb 位为逻辑 1
20

第7章 串行通信接口(SCI)

的帧作为地址帧(包含地址信息),所有的接收器计算出该地址信息,与所包含地址相匹 配的接收器处理接下来的数据帧。其它接收器置 RWU 位为 1,并返回到就绪状态,直 到再次在 RxD 上出现地址帧。 HC08 系列单片机的 SCI 接收器具有唤醒功能。这个功能在多处理器系统中非常有 用, 暂时没有工作的微处理器可以处于休眠状态以节省电力, 需要工作时再由主机将其 唤醒。

1.唤醒
一旦接收器进入睡眠,要响应对它寻址的信息需要一个过程。这就是唤醒过程。有 两种方法可以唤醒睡眠中的接收器。一个是只有空闲就唤醒,这就是空闲线唤醒。要选 择这种方法,软件需要清除一个寄存器 SCC1 中的 WAKE 位。另一个是地址标志唤醒。 软件通过设置控制寄存器 SCC1 中的 WAKE 位进行选择。 如果唤醒过程是自动的, 那么应用程序如何知道接收器已经唤醒?唤醒后, 接收缓 冲区会变满,会置位状态标志 SCRF。这可以通过中断(典型)或轮询接收缓冲区满标志 来检测。具体决定取决于配置。

2.空闲线唤醒
如果 SCI 系统使用空闲线唤醒,就需要建立一个协议。例如,前面几个字节表示 想要触发的接收器的地址。 接收器软件确认信息是其他接收器时, 就会使接收器重新进 入睡眠,这通过置位 SCC2 寄存器的 RWU 位来实现。接收器会在下一次接收线空闲时 再次被唤醒。当信息相对较长(大于 10 个字节)时可以使用空闲线唤醒。注意,每个信 息之间需要用一个空闲时(比一帧时间长 1 个位)来分隔。 如果应用程序不检测空闲线, 就无法得知接收器是否已经被唤醒了。 程序可以通过 轮询或有配置产生的中断来检测空闲线。 在任何一种情况下, 它都可以知道什么时候空 闲线激活了,什么时候一个字节移入接收移位寄存器了。

3.地址标志唤醒
最高位(MSB)为 1 的一个字符会唤醒所有使能地址标志唤醒的接收器。 这个字符可 以看作是一个地址字符。因此,数据字符的 MSB 应该是 0。可以使用下面的协议类型。 每个计数器软件在唤醒后读地址字符,并将它与本机地址进行比较。如果匹配,接收器 就读其余的信息字节。如果地址不匹配,接收器就可以重新进入睡眠。由于单独的信息 每个字节需要 1 个位,因此在信息较短时,适合使用地址标志唤醒。 空闲线字符由逻辑 1 组成,没有起始位、停止位和校验位,长度由 SCI 控制寄存 器 1(SCICR1) 中的 M 位决定。 TE 的上升沿后,发送初始化后前导符为同步空闲符。 当 若在发送过程中 TE 位清零,发送结束后 TxD 输出空闲符;在发送数据期间清零或设 置 TE 位,一个帧发送结束后都要发送空闲符。

21

第7章 串行通信接口(SCI)

7.6.2 协议和控制流问题
从本质上来说, 协议是建立连接和传输信息的一套规范。 流控制指的是停止数据传 输和重新开始数据传输的方法。 应答/不应答(Acknowlege/Not Acknowlege,ACK/NAK)流控制某些协议(如 Kermit 和 Bisynch)使用一个发送者,后者在发送下一组数据前,需要等待接收者对前一组数据 的应答。在一组数据发送后,接收者需要检测数据的有效性。如果数据有效,接收者就 送出应答信号(ACK)。发送者把 ACK 信号作为发送下一组数据的许可。如果数据无效, 接收者就发送一个不应答(NAK)。发送者将重新发送前一组数据。 XON/XOFF 协议。 该协议用 ASCII 字符 Ctrl+S($13, 称为 XOFF)让对方停止发 ASCII 字符, Ctrl+Q($11, 称为 XON)让对方继续发送。 使用 XON/XOFF 协议只能传送以 ASCII 码表的文本文件, 不能传送二进制文件。 例如, 计算机从串口把数据发送到一台打印机, 如果打印机缓冲区满了,就必须告诉计算机停止发送,否则数据会丢失。接收者输出一 个 XOFF 信号,告诉发送者停止发送。然后,当接收者就绪时,送出 XON 信号,告诉 发送者恢复发送。

7.6.3 用普通I/O口模拟SCI接发数据
在实际应用场合中,可能需要多个串行数据通信方式,通常 MCU 中只有 1~2 个 SCI 模块,通过专用芯片扩展可以实现多串口的通讯,但这样会使系统复杂,降低可靠 性。此时可以用普通 I/O 口模拟实现 SCI 功能。

1.硬件条件
从图 7-1 可以看出,SCI 数据传输格式中,以低电平作为起始位,所以用普通 I/O 口模拟串口时,I/O 口需要上拉,保证 I/O 口通常是高电平状态。I/O 口数目可以用 2 个,此时 1 个用于接收线,1 个用于发送线;但也可以只用 1 个,发送时,将 I/O 方向 定义为输出,接收时将 I/O 方向定义为输入。用 1 个 I/O 口进行 SCI 的模拟,显然是半 双工方式进行数据通信,但用 2 个 I/O 口时,仍然是半双工方式,难于实现全双工。

2.算法描述
用 I/O 口模拟串行数据通信,主要是实现发送和接收一个字节数据。在发送一字节 时,完全依据图 7-1 的 SCI 数据格式,在 I/O 口首先输出低电平,表示开始传输,然后 根据所发送的数据字节,输出或高或低的电平信号。在接收一字节时,首先将 I/O 口设 定为输入状态,等待对方的低电平信号,然后每隔一段时间采集 I/O 口状态,并将 I/O 口状态作为接收字节的 1 位数据。 在发送一个字节时,算法有一个改进之处,在输出 I/O 上始终设定为低电平,并且 通常保持 I/O 口为输入状态,由于有上拉,所以输出线上的实际电平信号为高,在需要 输出低电平信号, 才将方向设置为输出。 这样操作的好处在于减少输出线上电平的波动。 用 SCI 模块时,可以很方便地实现波特率设定,用 I/O 口模拟时,需要通过计算写
22

第7章 串行通信接口(SCI)

出精确的位延时程序,实现不同的波特率。假如总线频率是 2.4576MHz,实现 9600bps 的波特率,其位延时计算如下: 9600bps 意味着每秒钟传输 9600 位,则每位传输的时间是:1/9600 秒。 总线频率是 2.4576MHz,即每个时钟周期的时间是:1/(2.4576×106)秒。 所以传输一位数据时,需要延时的周期数是:

1 2.4576? 106 9600 ? ? 256 1 9600 2.4576? 106

即 1 位数据的延时周期数为 256 个。

3.发送一字节子程序
下面给出总线频率为 2.4576MHz,以 9600bps 的波特率模拟串口,8 位数据位,1 位停止位,无校验方式发送一字节的实例程序。
*------Send1Byte------发送1字节子程序----------------------------* * 功能:以9600bps发送1字节数据,总线速率:2.4756MHZ * * 入口:A—需要发送的1字节 * * 出口:无 * * 备注:位延时为256个周期 * *----------------------------------------------------------------* Send_1Byte: PSHX ;1) 起始位 BSET 0,DDRA ;A口0脚定义为输出 BCLR 0,PTA ;令A口0脚为低电平 LDX #$55 ;2 cycle 1位的延时 $55=85 DBNZX * ;85*3=255 cycle ;2) 发送数据 LDX #$08 ;2 cycle Send1Byte0: PSHX ;2 cycle RORA ;1 cycle 最低位-->C BCC Send1Byte1 ;3 cycle 发送位为0 BSET 0,PTA ;4 cycle BRA Send1Byte2 ;3 cycle Send1Byte1: BCLR 0,PTA BRA Send1Byte2 Send1Byte2: LDX #$4F ;1位的延时 DBNZX * PULX DBNZX Send1Byte0 ;3) 停止位 BSET 0,PTA 23

第7章 串行通信接口(SCI)

LDX DBNZX PULX RTS

#85 *

;1位的延时

4.接收一字节子程序
下面给出总线频率为 2.4576MHz,以 9600bps 的波特率模拟串口,8 位数据位,1 位停止位,无校验方式接收一字节的实例程序。
*------RCV_Byte_To_A------接收1字节子程序--------------------------* * 功能:以9600bps接收1字节数据,总线速率:2.4756MHZ * * 入口:无 * * 出口:A * *------------------------------------------------------------------* RCV_Byte_To_A: RCVBeginBit: ;1)等待起始位 BRSET 0,PTA,* ;2)接收起始位 BSR RCV_Bit_To_C BCS RCVBeginBit ;检验起始位,不为0继续等待 ;3)接收数据字节 LDA #$80 ;控制8次循环 RCVNextBit: BSR RCV_Bit_To_C RORA ;C-->A[7] ... a[0]-->C BCC RCVNextBit BSR RCV_Bit_To_C ;接受结束位,不检验 RTS *------RCV_Bit_To_C------接收1位子程序-----------------------------* * 功能:以9600bps接收1位数据,总线速率:2.4756MHZ * * 入口:无 * * 出口:C * * 备注:位延时为256个周期 * *------------------------------------------------------------------* RCV_Bit_To_C: PSHX ;2C PSHA ;2C LDA #$17 ;2C LDX #$17 ;2C RCV_Bit_0: BRCLR 0,PTA,RCV_Bit_1 ;5C 影响C位 RCV_Bit_1: SBC #!0 ;2C A-0-C-->A DBNZX RCV_Bit_0 ;3C CMP #!18 ;2C PULA ;2C PULX ;2C

24

第7章 串行通信接口(SCI)

RTS

;4C

上述给出的模拟串行收发 1 字节软件程序是“以软代硬”的一个实例,但“以软代 硬”是有代价的,它所需要的代价是占用 CPU 资源,如果使用 SCI 模块,收发一字节 的过程中是不需要占用 CPU 资源的。同时,在模拟串行收发 1 字节过程中,是不允许 中断程序的干扰,如果实在需要收发过程中处理中断,很难保证波特率的准确性,如果 遇到这种问题, 可以用定时器的输入比较和输出捕捉功能来模拟实现串行口。 所以在实 际使用时要注意, 用普通 I/O 口模拟收发子程序和其它程序之间的协调性, 特别是 CPU 的使用、中断的处理等问题。

练习题
【基础题】 1.什么正逻辑和负逻辑?串行通信使用哪种逻辑? 2.单片机与 PC 机进行串行通信为什么要进行电平转换?如何进行电平转换? 3.设波特率为 9600,使用 NRZ 格式的 8 个数据位、没有校验位、1 个停止位,传 输 2K 字节的文件最小需要多少时间? 4.简述串行通信收发数据的工作过程。 【实践题】 5.编写一程序,其功能是:以查询方式从串行口等待接收一个字节的数据,收到 后, 再通过串行口将收到的一个字节的数据发送出去。 验证该程序可以通过微机向 MCU 发送一字节的数据, 同时通过串行口接收一个字节的数据, 使收到的数据与发出的数据 相同。 6.用一种高级语言实现 PC 方串行数据收发的通用程序。

25


相关文档

第7章 串行通信接口SCI
第05章串行通信接口SCI
第五章 串行通信接口SCI
第05章 串行通信接口SCI
第9章 串行通信接口SCI
嵌入式技术基础与实践第7章 串行通信接口SCI
5)SCI串行通信接口
第5章 SCI串行通信接口学生用
8 串行通信接口SCI
串行通信接口SCI
电脑版