420 likes | 635 Views
第 7 章 串行通信接口 (SCI). 主要内容 异步串行通信的基础知识 电平转换电路与 SCI 通用编程原理 GP32SCI 模块寄存器 串行口初始化与收发编程的基本方法 串行通信通用函数与测试实例 串行通信进一步讨论. 停止位. 第 0 位. 第 2 位. 第 4 位. 第 6 位. 第 1 位. 第 3 位. 第 5 位. 第 7 位. 开始位. SCI 数据格式. 7.1 异步串行通信的基础知识. 7.1.1 基本概念 (1)异步串行通信的格式
E N D
第7章 串行通信接口(SCI) 主要内容 • 异步串行通信的基础知识 • 电平转换电路与SCI通用编程原理 • GP32SCI模块寄存器 • 串行口初始化与收发编程的基本方法 • 串行通信通用函数与测试实例 • 串行通信进一步讨论
停止位 第0位 第2位 第4位 第6位 第1位 第3位 第5位 第7位 开始位 SCI数据格式 7.1异步串行通信的基础知识 7.1.1 基本概念 (1)异步串行通信的格式 SCI通常采用NRZ数据格式,即:standard non-return-zero mark/space data format,译为:“标准不归零传号/空号数据格式”。“不归零”的最初含义是:用正、负电平表示二进制值,不使用零电平。“mark/space”即“传号/空号”分别是表示两种状态的物理名称,逻辑名称记为“1/0”。下图给出了8位数据、无校验情况的传送格式。
(2)串行通信的波特率 波特率(baud rate):每秒内传送的位数。 波特率单位是位/秒,记为bps。通常情况下,波特率的单位可以省略。通常使用的波特率有300、600、900、1200、1800、2400、4800、9600、19200、38400。
(3)奇偶校验 字符奇偶校验检查(character parity checking)称为垂直冗余检查( vertical redundancy checking,VRC),它是每个字符增加一个额外位使字符中“1”的个数为奇数或偶数。 奇校验:如果字符数据位中“1”的数目是偶数,校验位应为“1”,如果“1”的数目是奇数,校验位应为“0”。 偶校验:如果字符数据位中“1”的数目是偶数,则校验位应为“0”,如果是奇数则为“1”。
(4)串行通信的传输方式 单工(Simplex):数据传送是单向的,一端为发送端,另一端为接收端。这种传输方式中,除了地线之外,只要一根数据线就可以了。有线广播就是单工的。 全双工(Full-duplex):数据传送是双向的,且可以同时接收与发送数据。这种传输方式中,除了地线之外,需要两根数据线,站在任何一端的角度看,一根为发送线,另一根为接收线。一般情况下,MCU的异步串行通信接口均是全双工的。 半双工(Half-duplex):数据传送也是双向的,但是在这种传输方式中,除了地线之外,一般只有一根数据线。任何一个时刻,只能由一方发送数据,另一方接收数据,不能同时收发。在freescale的HC08系列MCU中,监控模式的通信就采用这种方式。
7.1.2 RS-232C总线标准 MCU引脚一般输入/输出使用TTL电平,而TTL电平的“1”和“0”的特征电压分别为2.4V和0.4V,适用于板内数据传输。为了使信号传输得更远,美国电子工业协会EIA(Electronic Industry Association) 制订了串行物理接口标准RS-232C。RS-232C采用负逻辑,-3V~-15V为逻辑“1”,+3V~+15V为逻辑“0”。RS-232C最大的传输距离是30m,通信速率一般低于20Kbps。
9芯串行接口排列 9 6 8 7 1 5 4 2 3 7.1.2 RS-232C总线标准 RS-232接口,简称“串口”,它主要用于连接具有同样接口的室内设备。目前几乎所有计算机上的串行口都是9芯接口。右图给出了9芯串行接口的排列位置,相应引脚含义见表7-1。 返回
TTL电平 OUT IN 232电平 OUT IN 51Ω +5V MAX232CPE 16 15 14 13 12 11 10 9 1 2 3 4 5 6 7 8 +5V TTL电平 转为232电平 1μ×4 7.2电平转换电路与SCI通用编程原理 7.2.1 SCI的外围硬件电路 具有SCI接口的MCU,一般具有发送引脚(TxD)与接收引脚(RxD),不同公司或不同系列的MCU,使用的引脚缩写名可能不一致,但含义相同。SCI的外围硬件电路,主要目的是将MCU的发送引脚TxD与接收引脚RxD的TTL电平,通过RS-232电平转换芯片转换为RS-232电平。下图给出一个基本SCI电平转换电路。
接收引脚RxD 发送引脚TxD 接收移位寄存器 发送移位寄存器 SCI 数据寄存器 MCU 的 内 部 总 线 (Internal Bus) SCI 控制寄存器 SCI状态寄存器 SCI波特率寄存器 SCI编程模型 7.2.2 SCI的基本编程原理 返回
7.3 GP32 SCI模块寄存器 • SCI的寄存器 MC68HC908GP32的SCI有7个寄存器,地址为$0013~$0019 。 (1)SCI波特率寄存器(SCI Baud Rate Register,SCBR) SCBR的作用是设置串行通信的波特率 ,其地址是$0019。 D7、D6、D3:未定义; D5~D4 — SCP:波特率预分频位(SCI Baud Rate Prescaler Bits) SCP1、SCP0=00 01 10 11 PD= 1 3 4 13
(1)SCI波特率寄存器(SCI Baud Rate Register,SCBR) D2~D0 — SCR:波特率选择位(SCI Baud Rate Select Bits),定义波特率另一分频值,记为:BD,定义如下: SCR2、1、0 =000 001 010 011 100 101 110 111 BD = 1 2 4 8 16 32 64 128 设fSCI为串行通信时钟源频率,fSCI= fBUS或CGMXCLK,取决于CONFIG2的SCIBDSRC,一般设定SCIBDSRC=1,SCI用内部总线时钟,则fSCI= fBUS,则波特率的定义公式为: Bt=fBUS /(64×PD×BD)
数据位 定义 LOOPS ENSCI TXINV M WAKE ILTY PEN PTY 复位 0 0 0 0 0 0 0 0 SCI允许位 模式-字符长度选择位 空闲线类型位 奇偶校验类型选择位 循环模式选择位 发送反转标志位 奇偶校验允许位 唤醒条件位 (2) SCI控制寄存器1(SCI Control Register 1,SCC1) SCC1的地址是:$0013 ,定义为: D7 D6 D5 D4 D3 D2 D1 D0
数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 SCTIE TCIE SCRIE ILIE TE RE RWU SBK 复位 0 0 0 0 0 0 0 0 发送完成中断允许位 空闲线中断允许位 接收器允许位 发送终止位 发送中断允许位 接收中断允许位 接收器唤醒位 发送器允许位 (3) SCI控制寄存器2(SCI Control Register 2,SCC2) SCC2的地址是:$0014 ,定义为:
数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义 R8 T8 DMARE DMATE ORIE NEIE FEIE PEIE 复位 0 0 0 0 0 0 0 0 发送位8 DMA发送允许位 接收器噪声错误中断允许位 接收器奇偶错误中断允许位 接收位8 DMA接收允许位 接收器帧错误中断允许位 接收器溢出中断允许位 (4) SCI控制寄存器3(SCI Control Register 3,SCC3) SCC3的地址是:$0015 ,定义为:
数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义(只读) SCTE TC SCRF IDLE OR NF FE PE 复位 1 1 0 0 0 0 0 0 接收器奇偶错误标志位 发送完成标志位 接收器空闲标志位 接收器噪声标志位 发送缓冲区空标志位 接收器满标志位 接收器帧错误标志位 接收器溢出标志位 (5) SCI状态寄存器1(SCI Status Register 1,SCS1 ) SCS1的地址是:$0016 ,定义为:
数据位 D7 D6 D5 D4 D3 D2 D1 D0 定义(只读) BKF RPF 未定义 复位 0 0 0 0 0 0 0 0 接收进行标志位 终止码标志位 (6) SCI状态寄存器2(SCI Status Register 2,SCS2 ) SCS2的地址是:$0017 ,定义为:
(7) SCI数据寄存器(SCI Data Register ,SCDR ) SCDR为SCI系统最常用的寄存器,它的地址是:$0018。写入时,为要发送的8位数据,记为:T7~T0;读出时,为接收的8位数据,记为:R7~R0。不受复位影响。
7.4 串行口初始化与收发编程的基本方法 (1)SCI初始化 对SCI进行初始化,最少由以下三步构成: 第一步:定义波特率。 LDA #%00000010 STA SCBR ;总线频率fBUS=2.4576MHz,定义波特率Bt=9600 第二步:写控制字到SCI控制寄存器1(SCC1)。 LDA #%01000000 STA SCC1 ;设置允许SCI,正常码输出、8位数据、无校验 第三步:写控制字到SCI控制寄存器2(SCC2)。 LDA #%00001100 STA SCC2 ;设置允许发送、允许接收,查询方式收发
(2)发送一个数据与接收一个数据 发送数据是通过判断状态寄存器SCS1的第7位(SCTE)进行的,而接收数据是通过判断状态寄存器SCS1的第5位(SCRF)进行的。不论是发送还是接收,均使用SCI数据寄存器SCDR。发送时,将要发送的数据送入SCDR即可,接收时,从SCDR中取出的即是收到的数据。 ;串行发送A中的数 BRCLR 7,SCS1,* ;SCS1.7=0? 为0则等待 STA SCDR ;SCS1.7=1,可以发送数据 ;查询方式接收一个串行数据,接收的数据放入寄存器A中 BRCLR 5,SCS1,* ;SCS1.5=0? 为0则等待 LDA SCDR ;SCS1.5=1,可以取出数据 返回
7.5 串行通信通用函数与测试实例 7.5.1 串行通信子程序 串行通信头文件 SCI.h 串行通信驱动文件 SCI.c
串行通信头文件 SCI.h //[SCI.h]串行通信头文件-------------------------- #include "GP32C.h" //GP32 MCU映像寄存器名定义 #include "Type.h" //类型别名定义 #define ReSendStatusR SCS1 //SCI状态寄存器 #define ReTestBit 5 //接收缓冲区满标志位 #define SendTestBit 7 //发送缓冲区空标志位 #define ReSendDataR SCDR //数据寄存器 //串行通信函数声明 void SCIinit(void); //串行口初始化 void SCIsend1(INT8U o); //发送1字节 void SCIsendN(INT8U n, INT8U ch[]); //发送n字节 INT8U SCIre1(INT8U *p); //接收1字节 INT8U SCIreN(INT8U n, INT8U ch[]); //接收n字节 _____________________________________________
串行通信驱动文件 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)有关 * //------------------------------------------------------------* void SCIinit(void) { //1.总线频率fBUS = 2.4576MHz,定义波特率Bt = 9600 SCBR = 0b00000010; //2.设置允许SCI,正常码输出,8位数据,无校验 SCC1 = 0b01000000; //3.设置允许发送,允许接收,查询方式收发 SCC2 = 0b00001100; }
//SCIsend1:串行发送1个字节-----------------------------*//SCIsend1:串行发送1个字节-----------------------------* //功能:串行发送1个字节 * //参数:要发送的数据 * //返回:无 * //-----------------------------------------------------* void SCIsend1(INT8U o) { //判断ReStatusR的第SendTestBit位是否为1,是1可以发送 while (1) if ((ReSendStatusR & (1<<SendTestBit)) != 0) { ReSendDataR = o; break; } }
//SCIsendN:串行发送N个字节-----------------------------------*//SCIsendN:串行发送N个字节-----------------------------------* //功能:发送数组中的N个字节数据 * //参数:待发送数据的字节数及存放这些数据的数组首地址 * //返回:无 * //内部调用函数:SCIsend1 * //-----------------------------------------------------------* void SCIsendN(INT8U n, INT8U ch[]) { int i; for(i=0; i<n; i++) SCIsend1(ch[i]); }
//SCIre1:串行收一个字节数据------------------------------------------------*//SCIre1:串行收一个字节数据------------------------------------------------* //功能:从串行口接收1个字节的数据 * //参数:标志指针p * //返回:接收到的数据(若接收失败,返回0xff) * //说明:参数*p带回接收标志.*p = 0,收到数据;*p = 1,未收到数据 * //-------------------------------------------------------------------------* INT8U SCIre1(INT8U *p) { INT16U k; INT8U i; //ReStatusR第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个字节-----------------------------------------*//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)文件列表 (2)查询方式08C语言主程序 (3)中断方式MCU方主程序
7.5.3 中断方式工程文件 • 中断方式08C工程文件列表 • 中断方式08C语言主程序main.c • 串行中断子函数声明EnDisInt.h • 串行中断处理函数 • 串行中断方式矢量表文件 返回
表7-5 中断方式08C测试工程文件 工程文件名 SCI_INT.prj 所在路径 MC08Ex2007\GP32\GP32C\C03_串行通信中断方式 文件类型 文件名 功能简述 讲解章节 头文件 GP32C.h 芯片头文件 [08C工程文件组织]5.3 Includes.h 总头文件 [08C工程文件组织]5.3 EnDisInt.h 开放或禁止MCU模块中断 [08C工程文件组织]5.3 SCI.h 串行通信头文件 [本章] Type.h 数据类型头文件 [08C工程文件组织]5.3 C语言 子函数文件 MCUinit.c 芯片系统初始化函数定义 [初始化及PLL编程实例]14.2.5 SCI.c CI收发子函数定义 [本章] Vectors.c 中断处理及中断向量表 [08C工程文件组织]5.3 C语言主函数 Main.c 主函数 [本章] 中断方式08C工程文件列表
//-----------------------------------------------------------*//-----------------------------------------------------------* //工 程 名:SCI_Int.prj * //硬件连接: * // (1)MCU的串口与PC方的串口相连 * //程序描述:利用中断方式把收到的数据发送回去 * //目 的:初步掌握利用中断方式进行串行通信的基本知识 * //------------------清华2007版《嵌入式技术基础与实践》实例---* //总头文件 #include "Includes.h" //主函数 void main() { DisableMCUint(); //禁止总中断 //1. 芯片初始化 MCUinit(); //2. 模块初始化 SCIinit(); //(1) 串口初始化 //3. 开放各模块中断 EnableSCIreInt(); //(1)开放SCI接收中断 //4. 开放总中断 EnableMCUint(); //主循环 while (1) { } } 中断方式08C语言主程序main.c
//[EnDisInt.h]开放或禁止MCU各模块中断头文件---------------------------------//[EnDisInt.h]开放或禁止MCU各模块中断头文件--------------------------------- #include "GP32C.h" //GP32 MCU映像寄存器名定义 //开放或禁止中断宏定义 #define EnableMCUint() asm("CLI") //开放总中断 #define DisableMCUint() asm("SEI") //禁止总中断 #define EnableSCIreInt() SCC2 |= (1 << 5) //令SCC2.5=1,开放SCI接收中断 #define DisableSCIreInt() SCC2 &= ~(1 << 5) //令SCC2.5=0,禁止SCI接收中断 串行中断子函数声明EnDisInt.h • 在该头文件中对开关总中断进行了宏定义,并且其他各个模块的中断设置函数在此进行声明。
//[Vectors08.c]中断处理函数与中断向量表-----------------*//[Vectors08.c]中断处理函数与中断向量表-----------------* //功能: * // (1)定义中断处理子程序 * // (2)放置中断向量表 * //本文件包含: // (1)SCI接收中断处理函数 * // (2)未定义的中断处理函数 * //说明:该文件与芯片具体型号有关 * // (1)芯片型号MC68HC908GP32 * //----------------------------------------------------- * #include "Type.h" //类型别名定义 #include "EnDisInt.h" //开放或禁止MCU各模块中断的宏定义 #include "SCI.h" //该头文件包含串行通信函数声明 //isrSCIre:接收中断处理函数--------------------------- -* //功能:接收1个字节数据, 发送接到的数据 * //参数:无 * //返回:无 * //内部调用函数:SCIreN, SCIsendN * //------------------------------------------------------* 串行中断处理函数
#pragma interrupt_handler isrSCIre void isrSCIre(void) { INT8U f; //标志是否接受到数据 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
串行中断方式矢量表文件 • HC08的中断向量表的详细说明在前面章节已经介绍。在使用中断方式时,只要将中断向量表中串行接收中断项的isrDummy该为中断处理函数的函数名isrSCIRe即可,函数内容如上面所描述的。 • 本节仅讲述了串行通信的08C编程实例,用汇编编程的思想与之基本类似,读者可以参见教学资料的“MC08Ex2007\GP32\GP32S\C02_串行通信查询方式”和“MC08Ex2007\GP32\GP32S\C03_串行通信中断方式”下的汇编工程文件。
7.5.4 串口调试器(SSCOM V3.2) 串口调试工具比较多,SSCOM是其中比较出色的一款软件 。下图是该软件的一个界面。 读者可以从网址 http://www.mcu51.com/ download/sscom.rar 中下载 。
7.6 串行通信进一步讨论 7.6.1 唤醒功能 • 唤醒:一旦接收器进入睡眠,要响应对它寻址的信息需要一个过程。 • 空闲线唤醒:SCI系统使用空闲线唤醒,就需要建立一个协议。 • 地址标志唤醒:最高位(MSB)为1的一个字符会唤醒所有使能地址标志唤醒的接收器。
7.6.2 协议和控制流问题 • 从本质上来说,协议是建立连接和传输信息的一套规范。流控制指的是停止数据传输和重新开始数据传输的方法。 • 应答/不应答(Acknowlege/Not Acknowlege,ACK/NAK)流控制 某些协议(如Kermit和Bisynch)使用一个发送者,后者在发送下一组数据前,需要等待接收者对前一组数据的应答。在一组数据发送后,接收者需要检测数据的有效性。 • XON/XOFF协议。
7.6.3 用普通I/O口模拟SCI接收数据 在实际应用场合中,可能需要多个串行数据通信方式,通常MCU中只有1~2个SCI模块,通过专用芯片扩展可以实现多串口的通讯,但这样会使系统复杂,降低可靠性。此时可以用普通I/O口模拟实现SCI功能。 • 硬件条件 • 算法描述 • 发送一字节子程序 • 接收一字节子程序