13.2.4 串行接口仿真

51系列单片机集成了全双工的串行通信接口,KeilµVision3集成开发环境同样提供了完整的串行接口的仿真环境。通过串口的仿真,可以实时查看并更改各个寄存器的设置,也可以模拟串行数据流的输入输出。

1.串行接口的仿真界面

这里以Atmel公司的AT89S52单片机为例进行介绍,不同的单片机型号可能略有区别,但功能和操作基本一致。在KeilµVision3集成开发环境中,串行接口的仿真界面如图13.22所示。

在串行接口的仿真界面上,寄存器区域的“Mode”显示了当前串行接口的工作方式,包括如下4个选项:

❑“8-Bit Shift Register”:工作方式0,即8位同步移位寄存器方式。

❑“8-Bit var.Baudrate”:工作方式1,即8位可变波特率的串行异步通信方式。

13.2.4 串行接口仿真 - 图1

图 13.22 串行接口的仿真界面

❑“9-Bit fix Baudrate”:工作方式2,即9位固定波特率的串行异步通信方式。

❑“9-Bit var.Baudrate”:工作方式3,即9位可变波特率异步发送接收方式。

在程序仿真执行过程中,也可以在下拉列表框中选择更改串行接口的工作方式。另外,寄存器区域的其他部分显示了串行接口相关的寄存器以及标志位的值,包括如下几项。

❑寄存器“SCON”:用于选择串行通信的工作方式和某些控制功能,包括串行接口的接收/发送控制及设置状态标志等。某些特殊的标志位也可以由后面的选项单独设置。

❑寄存器“SBUF”:串行数据收发的缓冲器。

❑位“SM2”:多机串行通信的控制位。在多机串行通信方式中,而SM2用于控制从机的接收。

❑位“TB8”:在单机串行通信时,TB8可以作为奇偶校验位。而在多机串行通信时,可以作为发送地址帧和数据帧的区分标志位。

❑位“RB8”:既可以作为约定的奇偶校验位,也可以是约定的地址/数据标志位。

❑位“REN”:串行接收的允许/禁止控制位。

“Baudrate”区域显示了串行接口的运行波特率,同时也可以由SMOD位来控制波特率倍增。“Baudrate”区域包括如下几项。

❑位“SMOD”:串口波特率倍增位。如果SMOD设置为1,则波特率提高1倍;如果SMOD设置为0,则波特率不变。

❑位“RCLK”:串行接口发送时钟标志位。

❑位“TCLK”:串行接口接收时钟标志位。

❑“Transmit Baudrate”:显示了串行接口当前的发送波特率。

❑“Receive Baudrate”:显示了串行接口当前的接收波特率。

“IRQ”区域为串行接口的中断标志区,包括如下几项。

❑“T1”:串行发送的中断请求标志位。

❑“R1”:串行接收的中断请求标志位。

TI和RI,一般由硬件自动置位,在程序仿真执行的时候,也可以手工置位TI和RI,来测试

分析程序的运行情况。

2.串行接口的仿真

这里以串行接口数据发送为例介绍串行接口的仿真操作。单片机串行接口的数据发送需要用到缓冲器SBUF以及TI标志位。具体的仿真操作步骤如下。

(1)在KeilµVision3集成开发环境中,新建一个工程,并选择使用Atmel公司的AT89S52单片机。

(2)选择“File”→“New”命令,新建一个程序文件,并保存为*.C文件,在其中输入如下的程序源代码。


include<reg52.h>//头文件

void main(void)//主函数

{

SCON=0x50;//初始化串行口模式1

TMOD=0x20;//初始化T1为定时功能,模式2

PCON=0x80;//设置SMOD=1

TL1=0xF4;//波特率4800bit/s,初值

TH1=0xF4;

ES=0;//禁止串行中断

TR1=1;//启动定时器

//串口发送

SBUF=0x12;

while(!TI)//等待TI=1

{

TI=0;//TI清零

}

SBUF=0x34;

while(!TI)//等待TI=1

{

TI=0;//TI清零

}

}


在该程序中,主函数首先初始化串口为模式1,然后初始化定时器T1设置波特率,然后禁止串行中断并启动定时器。接着为SBUF赋值,数据将通过串口输出。同时,使用while循环来查询TI。当TI=1时,表示串行数据发送完毕,随后清零TI,以便于发送下一次串行数据。最后,再次通过SBUF发送数据,并清零TI。

(3)选择“Project”→“Options for Target‘Target 1’”命令,打开“Options for Target‘Target 1’”对话框。在“Target”选项页中的“Xtal(MHz)”文本框显示了单片机外接振荡器的频率。在其中输入11.0592,表示单片机使用外接的11.0592MHz晶振,如图13.23所示。

(4)选择“Debug”→“Start/Stop Debug Session”命令,进入程序仿真调试模式。

(5)选择“Peripherals”→“Serial”命令,打开单片机串行接口的仿真界面,如图13.24所示。

(6)按F10键开始单步执行程序。当完成串行口以及波特率的设置,并启动定时器后,在仿真界面中便可以看到串行口的工作模式为“8-Bit var.Baudrate”,即工作模式1。串行口的发送和接收波特率均为4800kbit/s,如图13.25所示。

13.2.4 串行接口仿真 - 图2

图 13.23 设置晶振频率

(7)在串行接口仿真界面中手工置位TI。继续按F10键,当执行SBUF=0x12语句后,从仿真界面可以看到数值0x12已经发送到缓冲区SBUF,如图13.26所示。

13.2.4 串行接口仿真 - 图3

图 13.24 串行接口仿真界面

13.2.4 串行接口仿真 - 图4

图 13.25 串行接口设置

13.2.4 串行接口仿真 - 图5

图 13.26 串行数据发送

(8)继续按F10键,此时TI=1,程序中清零TI,以便于发送下一个数据。

(9)按照同样的步骤可以将0x34发送到缓冲区SBUF。

(10)选择“Debug”→“Start/Stop Debug Session”命令,可以退出程序仿真调试环境。

3.字符串输入输出的仿真操作

在实际的程序设计中,直接采用寄存器来实现串行接口的通信比较麻烦。而在KeilµVision3集成开发环境中,提供了串行接口的输入输出库函数。对于一些复杂的程序,可以使用这些库函数来发送接收字符串。因此,KeilµVision3集成开发环境中还提供了更为强大的串口仿真调试支持。下面介绍使用库函数实现串行字符串输入输出的仿真操作。

(1)在KeilµVision3集成开发环境中,新建一个工程并选择Atmel公司的AT89S52单片机。同时,在设置单片机外接振荡器的频率为11.0592MHz。

(2)选择“File”→“New”命令,新建一个程序文件,并保存为*.C文件,在其中输入如下的程序源代码。


include<stdio.h>//头文件

include<reg52.h>

void main(void)//主函数

{

char ch;

SCON=0x50;//串口模式1,允许接收

TMOD|=0x20;//初始化T1为定时功能,模式2

PCON|=0x80;//设置SMOD=1

TL1=0xF4;//波特率4800bit/s,初值

TH1=0xF4;

IE|=0x90;//中断

TR1=1;//启动定时器

printf(“Please input a char!(a~z or A~Z)\n”);

while((ch=_getkey())!=0x0d)//获取字符

{

printf(“Input char=%c,Hex number=%bx\n”,ch,ch);//输出结果

}

printf(“The end!\n”);

}


在该程序中首先对串口进行了初始化,接着输出一个字符串,然后调用_getkey函数获取字符,并通过串口0输出该字符以及对应的十六进制数。当输入回车字符的时候,程序停止运行。

(3)选择“Debug”→“Start/Stop Debug Session”命令,进入程序仿真调试模式。

(4)选择“View”→“Serial Window”→“UART#0”命令,打开“UART#0”仿真窗口。

(5)选择“Peripherals”→“Serial”命令,打开单片机串行接口的仿真界面。

(6)按F5键,程序便开始仿真执行。

(7)此时,手工置位TI,“UART#0”仿真窗口中输出的第一个字符串“Please input a char!(a~z or A~Z)”,如图13.27所示。

(8)在“UART#0”仿真窗口输入字符B。此时,“UART#0”仿真窗口中输出该字符及其对应的十六进制数,如图13.28所示。

13.2.4 串行接口仿真 - 图6

图 13.27 仿真输出第一个字符串

13.2.4 串行接口仿真 - 图7

图 13.28 仿真输出字符及其十六进制数

(9)当输入回车字符时,程序输出字符串“The end!”,同时TI清零,程序结束,如图13.29所示。

(10)选择“Debug”→“Start/Stop Debug Session”命令,可以退出程序仿真调试模式。

13.2.4 串行接口仿真 - 图8

图 13.29 结束程序