前言

本次讲解STC8A8K64S4A12系列MCU串行口原理、4个UART串行口外设相关寄存器配置及程序设计。

一、硬件设计

1.开发板串口硬件电路

STC8A8K64S4A12开发板上设计了USB转TTL电路(CH340),其主要作用有3个:

USB转串口通信,可用于开发板串口通信调试。

USB接口有5V电源,可为开发板供电。

可使用短路帽选择J5端子,将USB转TTL电路的TTL信号连接到MCU的和引脚,这样可用于开发板程序下载。

USB转TTL电路如下图所示,串口接收和发送的引脚上均连接了LED指示灯,收发数据或程序下载时指示灯会闪烁,这样,更方便我们从硬件的角度观察串口有没有在进行数据通信。电路中的1000mA自恢复保险丝用于保护开发板和计算机USB口。

图1:开发板USB转TTL电路

STC8A8K64S4A12开发板上还设计了RS232电路(MAX3232)及DB9接口,因为有的客户电脑有DB9接口,那么开发板也有DB9接口就可以直接连接,方便调试。同样可使用短路帽选择J5端子,将该RS232电路的TTL信号连接到MCU的和引脚,这样也可用于开发板程序下载和串口通信。

图2:开发板RS232电路

USB转TTL(RS232电路)占用的单片机的引脚如下表:

UART功能描述对应IO口说明

RXD串口接收独立GPIO

TXD串口发送独立GPIO

☆注:独立GPIO表示开发板没有其他的电路使用这个GPIO。

2.STC8A8K64S4A12系列单片机UART介绍

STC8A8K64S4A12系列单片机有4个采用UART工作方式的全双工异步串行通信接口,每个串行口由2个数据缓存器、1个移位寄存器、1个串行控制寄存器和1个波特率发生器等组成。每个串行口的数据缓存器由2个相互独立的接收、发送缓冲器构成,因此可以同时发送和接收数据。

■STC8A8K64S4A12系列单片机的4个串口引脚分配:

STC8A8K64S4A12系列单片机的4个UART是相互独立的,可以同时使用。但每个UART会有多组引脚与之对应(具体几组还取决于芯片封装引脚数),请注意同一个UART只能通过相关寄存器配置其中的一组使用,比如、是串口1,而、也是串口1,在使用串口1时必须选择一个来使用。STC8A8K64S4A12系列单片机串口的引脚分配如下表。

表2:单片机4个串口引脚分配

☆注:同一个串口各组之间切换是需要配置相关寄存器的相关位实现,如果没有对该部分寄存器配置,一般默认选择的都是第一组串口。

■STC8A8K64S4A12系列单片机的4个串口用定时器:

STC8A8K64S4A12系列单片机UART用于波特率发生器的定时器也是可以选择的,但不是任意选择哪个定时器都可以的。针对不同UART可供选择的定时器如下表所示。

表3:单片机4个串口波特率发生器用定时器

☆注:同一个串口的波特率发生器使用的定时器是需要配置相关寄存器的相关位实现,注意对寄存器按位进行操作,没有使用的位不要去配置。

3.串行口UART工作模式

STC8A8K64S4A12系列单片机4个UART均有多种工作模式,串口1有4种工作模式,其中2种工作模式的波特率是可变的,另2种工作模式的波特率是固定的,以供不同应用场合选用。串口2、串口3和串口4都只用2种工作模式,这2种工作模式的波特率都是可变的。下面列表4个UART的工作模式。

表4:单片机4个串口工作模式

☆注:艾克姆提供例程是按照“8位UART,波特率可变”模式进行配置。

■UART1工作模式1原理介绍:

“8位UART,波特率可变”的工作方式,其一帧信息为10位:1位起始位+8位数据位(低位在先)+1位停止位。

发送过程:串行通信模式发送时,数据由串行发送端TXD输出。当主机执行一条写SBUF的指令就启动串行通信的发送,写“SBUF”信号还把“1”装入发送移位寄存器的第9位,并通知TX控制单元开始发送。移位寄存器将数据不断右移送TXD端口发送,在数据的左边不断移入“0”作补充。当数据的最高位移到移位寄存器的输出位置,紧跟其后的是第9位“1”,在其左边各位全为“0”,这个状态条件,使TX控制单元作最后一次移位输出,然后使允许发送信号“SEND”失效,完成一帧信息的发送,并置位中断请求位TI,即TI=1,向主机请求中断处理。

图3:UART1工作方式1发送数据示意图

接收过程:当软件置位接收允许标志位REN,即REN=1时,接收器便对RXD端口的信号进行检测,当检测到RXD端口发送从“1”→“0”的下降沿跳变时就启动接收器准备接收数据,并立即复位波特率发生器的接收计数器,将1FFH装入移位寄存器。接收的数据从移位寄存器的右边移入,已装入的1FFH向左边移出,当起始位“0”移到移位寄存器的最左边时,使RX控制器作最后一次移位,完后一帧信息的接收。

接收数据有效需同时满足以下两个条件:

RI=0;

SM2=0或接收到的停止位为1。

☆注:若上述两条件不能同时满足,则接收到的数据作废并丢失,无论条件满足与否,接收器重新检测RXD端口上的“1”→“0”的跳变,继续下一帧信息的接收。

图4:UART1工作方式1接收数据示意图

下面举例介绍下串口1在进行工作方式选择时,需要配置的是串口1控制寄存器SCON。该寄存器支持位寻址,该寄存器的B6和B7位便是用来选择串口1工作方式的,寄存器的B5、B3和B2位是9位UART时需要配置的位,寄存器的B4位是串行接收控制位,寄存器的B0、B1位是串口接收和发送中断请求标志位。

图5:串口1控制寄存器SCON

☆注:若上述两条件不能同时满足,则接收到的数据作废并丢失,无论条件满足与否,接收器重新检测RXD端口上的“1”→“0”的跳变,继续下一帧信息的接收。

4.串行口使用引脚切换选择

在使用STC8A8K64S4A12系列单片机的4个UART时,需要确定使用串口的哪一组引脚。这需要通过操作P_SW1或P_SW2等寄存器实现。

STC8A8K64S4A12系列单片机串口1有4组串口引脚可供选择,实现引脚切换选择需要P_SW1寄存器(即外设端口切换控制寄存器1)的B6和B7位,如下图所示。

图6:P_SW1外设端口切换控制寄存器1

☆注:STC15W4K32S4系列单片机串口1只有3组供选择,STC8A8K64S4A12系列单片机串口1有4组供选择。同一时间只能使能其中的一组串口作为串口1使用。

STC8A8K64S4A12系列单片机串口2、串口3和串口4均有2组串口引脚可供选择,实现引脚切换选择需要配置外设端口切换控制寄存器2的B0、B1和B2位,如下图所示。

图7:P_SW2外围设备功能切换控制寄存器2

☆注:因为串口2、串口3和串口4只有2组串口引脚供选择,所以寄存器使用1位即可控制切换。

5.串行口1工作模式1波特率计算公式

STC8A8K64S4A12系列单片机4个UART在不同的工作模式下,选择不同的定时器作为波特率发生器时,波特率计算公式都是不同的。下面举例给出UART1工作模式1时的波特率计算公式。

表5:UART1工作模式1波特率计算

☆注:SYSclk为系统工作频率,SMOD是PCON寄存器最高位(用于波特率加倍选择),定时器1模式0为16位自动重装载模式,定时器1模式2为8位自动重装载模式(详见定时器部分介绍)。

举例,系统时钟频率为11.0592MHZ,配置定时器1为1T,工作模式为模式2,PCON寄存器SMOD位置为0,波特率预设置为9600bps,计算下定时器1重装载值。

SMOD=0,则2SMOD*SYSclk=11059200。

11059200/(32*9600)=36。

256–36=220。十进制220对应十六进制是DC。

所以对定时器1的高8位寄存器初始装载值和低8位寄存器初始装载值赋值0xDC。

如果已知定时器重装载值,计算串口波特率,则是反推过来即可(建议使用软件STC-ISP的波特率计算器)。

6.串行口中断配置步骤

针对STC8A8K64S4A12系列单片机4个串行口外设,软件的配置过程如下:

图8:串行口中断软件配置步骤

☆注:实验例程即是按照上述配置步骤操作寄存器相关位实现,后有详述

二、软件设计

1.串行口寄存器汇集

STC8A8K64S4A12系列单片机操作串行口时会用到18个寄存器,如下表所示:

表6:STC8A8K64S4A12系列串行口使用寄存器汇总

☆注:串口波特率发生器需要用到定时器,定时器相关的寄存器没有在上述表格中列举。串口3和串口4是没有中断高优先级的,所以在中断优先级控制寄存器中没有对串口3和串口4中断优先级的配置位。

2.寄存器解析

2.1.中断允许寄存器IE

外部中断允许寄存器IE支持位寻址,该寄存器的B4位是串口1的中断允许位。

图9:中断允许寄存器

2.2.中断允许寄存器IE2

中断允许寄存器IE2不支持位寻址,该寄存器的B0、B3和B4位是串口2、串口3和串口4的中断允许位。因为IE2寄存器不支持位寻址,所以举例操作该寄存器B0位时,不可以直接“ES2=0;”进行操作,参考下图。

图10:中断允许寄存器2

2.3.电源控制寄存器PCON

电源控制寄存器PCON不支持位寻址,该寄存器的B6位和B7位是UART1的帧错误检测有效控制位和波特率选择位,具体含义如下图。

图11:电源控制寄存器

☆注:PCON寄存器的SMOD位和SMOD0位是用于串口1的,换句话说,串口2、串口3和串口4没有与之对应的控制位。

2.4.辅助寄存器AUXR

辅助寄存器AUXR不支持位寻址,该寄存器的B0位是串口1的波特率发生器定时器选择控制位,寄存器的B5位是串口1模式0的通信速度设置位。

图12:辅助寄存器

☆注:AUXR寄存器的其他位用于定时器配置,操作串口时也会有对定时器的配置部分,请注意按位操作。

2.5.中断优先级控制寄存器IP

中断优先级控制寄存器IP支持位寻址,该寄存器的B4位是串口1中断优先级控制位。

图13:中断优先级控制寄存器

☆注:艾克姆例程没有对串口1中断优先级进行配置,可根据项目需要配置PS位。

2.6.中断优先级控制寄存器IP2

中断优先级控制寄存器2不支持位寻址,该寄存器的B0位是串口2中断优先级控制位。

图14:中断优先级控制寄存器2

2.7.串行口2控制寄存器S2CON

串行口2控制寄存器S2CON不支持位寻址,该寄存器的B7位是用来选择串口2工作模式的,寄存器的B5、B3和B2位是9位UART时需要配置的位,寄存器的B4位是串行接收控制位,寄存器的B0、B1位是串口接收和发送中断请求标志位。

图15:串行口2控制寄存器

2.8.串行口3控制寄存器S3CON

串行口3控制寄存器S3CON不支持位寻址,该寄存器的B7位是用来选择串口3工作模式的,寄存器的B5、B3和B2位是9位UART时需要配置的位,寄存器的B4位是串行接收控制位,寄存器的B0、B1位是串口接收和发送中断请求标志位。

图16:串行口3控制寄存器

2.9.串行口4控制寄存器S4CON

串行口4控制寄存器S4CON不支持位寻址,该寄存器的B7位是用来选择串口4工作模式的,寄存器的B5、B3和B2位是9位UART时需要配置的位,寄存器的B4位是串行接收控制位,寄存器的B0、B1位是串口接收和发送中断请求标志位。

图17:串行口4控制寄存器

3.串口1收发实验(和)

3.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

表7:实验需要用到的c文件

序号文件名后缀功能描述

1外部串行口有关的用户自定义函数。

2包含用户自定义延时函数。

3.2.头文件引用和路径设置

■需要引用的头文件

include""

1

2

■需要包含的头文件路径

本例需要包含的头文件路径如下表:

表8:头文件包含路径

序号路径描述

1…\和头文件在该路径,所以要包含。

2…\头文件在该路径,所以要包含。

图18:添加头文件包含路径

3.3.编写代码

首先,在文件中编写串口1的初始化函数Uart1_Init,代码如下。

程序清单:串口1初始化函数

/***************************************************************************

*描述:串口1初始化函数

*入参:无

*返回值:无

备注:波特率9600bps晶振11.0592MHz

**************************************************************************/

voidUart1_Init(void)

{

PCON=0x3f;//波特率不倍速,串行口工作方式由SM0、SM1决定

SCON=0x50;//8位数据,可变波特率,启动串行接收器

AUXR|=0x40;//定时器1时钟为Fosc,即1T

AUXR=0xfe;//串口1选择定时器1为波特率发生器

TMOD=0x0f;//清除定时器1模式位

TMOD|=0x20;//设定定时器1为8位自动重装方式

TL1=0xDC;//设定定时初值

TH1=0xDC;//设定定时器重装值

ET1=0;//禁止定时器1中断

TR1=1;//启动定时器1

ES=1;//串口1中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

然后,编写串口1发送数据函数,把要发送的字节存放于数据缓存寄存器中,直到数据发送完成,代码如下。

程序清单:数据发送函数函数

/***************************************************************************

*描述:串口1发送数据函数

*入参:uint8数据

*返回值:无

**************************************************************************/

voidSDataByUart1(uint8dat)

{

SBUF=dat;//写数据到UART数据寄存器

while(TI==0);//在停止位没有发送时,TI为0即一直等待

TI=0;//清除TI位(该位必须软件清零)

}

1

2

3

4

5

6

7

8

9

10

11

之后,编写串口1的中断服务函数,将接收的数据存放到用户自定义变量uart1temp中,代码如下。

程序清单:中断服务函数

/***************************************************************************

*描述:串口1中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart1()interrupt4using1

{

ES=0;//串口1中断关闭

Flag=TRUE;//接收到数据,接收标识符有效

if(RI)//串行接收到停止位的中间时刻时,该位置1

{

RI=0;//清除RI位(该位必须软件清零)

uart1temp=SBUF;

}

if(TI)//在停止位开始发送时,该位置1

{

TI=0;//清除TI位(该位必须软件清零)

}

ES=1;//串口1中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

最后,用户定义一个自定义函数UART1_Tx_Puts,该函数将接收的数据原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART1_Tx_Puts

/***************************************************************************

*描述:串口1接收到数据后发送回去

*入参:无

*返回值:无

***************************************************************************/

voidUART1_Tx_Puts(void)

{

if(Flag)//有新数据通过串口被接收到

{

ES=0;//串口1中断关闭

SDataByUart1(uart1temp);//发送字符

SDataByUart1(0x0D);//发送换行符

SDataByUart1(0x0A);//发送换行符

ES=1;//串口1中断打开

Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

代码清单:主函数

intmain()

{

P3M1=0xFE;P3M0=0xFE;//设置为准双向口

P3M1=0xFD;P3M0|=0x02;//设置为推挽输出

Uart1_Init();//串口1初始化

EA=1;//总中断打开

while(1)

{

UART1_Tx_Puts();//串口接收到一个字符后返回该字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

3.4.硬件连接

本实验需要将USB线连接至PC,因为开发板板载CH340电路连接的就是单片机和口,所以无需外接USB转TTL模块做该实验。

图19:串口1实验连接图

4.串口2收发实验(和)

4.1.编写代码

首先,在文件中编写串口2的初始化函数Uart2_Init,代码如下。

程序清单:串口2初始化函数

/***************************************************************************

*描述:串口2初始化函数

*入参:无

*返回值:无

备注:波特率9600bps晶振11.0592MHz

**************************************************************************/

voidUart2_Init(void)

{

S2CON=0x50;//8位数据,可变波特率,启动串行接收器

AUXR|=0x04;//定时器2时钟为Fosc,即1T

T2L=0xE0;//设定定时初值

T2H=0xFE;//设定定时初值

AUXR|=0x10;//启动定时器2

IE2|=0x01;//串口2中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

然后,编写串口2发送数据函数,把要发送的字节存放于数据缓存寄存器中,直到数据发送完成,代码如下。

程序清单:数据发送函数函数

/***************************************************************************

*描述:串口2发送数据函数

*入参:uint8数据

*返回值:无

**************************************************************************/

voidSDataByUart2(uint8dat)

{

S2BUF=dat;//写数据到UART数据寄存器

while(!(S2CONS2TI));//在停止位没有发送时,S2TI为0即一直等待

S2CON=~S2TI;//清除S2CON寄存器对应S2TI位(该位必须软件清零)

}

1

2

3

4

5

6

7

8

9

10

11

之后,编写串口2的中断服务函数,将接收的数据存放到用户自定义变量uart2temp中,代码如下。

程序清单:中断服务函数

/***************************************************************************

*描述:串口2中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart2()interrupt8using1

{

IE2=0xFE;//串口2中断关闭

Flag=TRUE;//接收到数据,接收标识符有效

if(S2CONS2RI)//串行接收到停止位的中间时刻时,该位置1

{

S2CON=~S2RI;//清除S2CON寄存器对应S2RI位(该位必须软件清零)

uart2temp=S2BUF;

}

if(S2CONS2TI)//在停止位开始发送时,该位置1

{

S2CON=~S2TI;//清除S2CON寄存器对应S2TI位(该位必须软件清零)

}

IE2|=0x01;//串口2中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

最后,用户定义一个自定义函数UART2_Tx_Puts,该函数将接收的数据原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART2_Tx_Puts

/***************************************************************************

*描述:串口2接收到数据后发送出去

*入参:无

*返回值:无

***************************************************************************/

voidUART2_Tx_Puts(void)

{

if(Flag)//有新数据通过串口被接收到

{

IE2=0xFE;//串口2中断关闭

SDataByUart2(uart2temp);//发送字符

SDataByUart2(0x0D);//发送换行符

SDataByUart2(0x0A);//发送换行符

IE2|=0x01;//串口2中断打开

Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

代码清单:主函数

intmain()

{

P1M1=0xFE;P1M0=0xFE;//设置为准双向口

P1M1=0xFD;P1M0|=0x02;//设置为推挽输出

Uart2_Init();//串口2初始化

EA=1;//总中断打开

while(1)

{

UART2_Tx_Puts();//串口接收到一个字符后返回该字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

4.2.硬件连接

本实验需要外接USB转TTL模块连接到开发板串口2上,该实验串口2选择的和,具体接线图如下。

图20:串口2实验连接图

5.串口3收发实验(和)

5.1.编写代码

首先,在文件中编写串口3的初始化函数Uart3_Init,代码如下。

程序清单:串口3初始化函数

/***************************************************************************

*描述:串口3初始化函数

*入参:无

*返回值:无

备注:波特率9600bps晶振11.0592MHz

**************************************************************************/

voidUart3_Init(void)

{

S3CON|=0x10;//启动串行接收器

S3CON=0x30;//8位数据,可变波特率,串口3选择定时器2为波特率发生器

AUXR|=0x04;//定时器2时钟为Fosc,即1T

T2L=0xE0;//设定定时初值

T2H=0xFE;//设定定时初值

AUXR|=0x10;//启动定时器2

IE2|=0x08;//串口3中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

然后,编写串口3发送数据函数,把要发送的字节存放于数据缓存寄存器中,直到数据发送完成,代码如下。

程序清单:数据发送函数函数

/***************************************************************************

*描述:串口3发送数据函数

*入参:uint8数据

*返回值:无

**************************************************************************/

voidSDataByUart3(uint8dat)

{

S3BUF=dat;//写数据到UART数据寄存器

while(!(S3CONS3TI));//在停止位没有发送时,S3TI为0即一直等待

S3CON=~S3TI;//清除S3CON寄存器对应S3TI位(该位必须软件清零)

}

1

2

3

4

5

6

7

8

9

10

11

之后,编写串口3的中断服务函数,将接收的数据存放到用户自定义变量uart3temp中,代码如下。

程序清单:中断服务函数

/***************************************************************************

*描述:串口3中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart3()interrupt17using1

{

IE2=0xF7;//串口3中断关闭

Flag=TRUE;//接收到数据,接收标识符有效

if(S3CONS3RI)//串行接收到停止位的中间时刻时,该位置1

{

S3CON=~S3RI;//清除S3CON寄存器对应S3RI位(该位必须软件清零)

uart3temp=S3BUF;

}

if(S3CONS3TI)//在停止位开始发送时,该位置1

{

S3CON=~S3TI;//清除S3CON寄存器对应S3TI位(该位必须软件清零)

}

IE2|=0x08;//串口3中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

最后,用户定义一个自定义函数UART3_Tx_Puts,该函数将接收的数据原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART3_Tx_Puts

/**************************************************************************

*描述:串口3接收到数据后发送出去

*入参:无

*返回值:无

*************************************************************************/

voidUART3_Tx_Puts(void)

{

if(Flag)//有新数据通过串口被接收到

{

IE2=0xF7;//串口3中断关闭

SDataByUart3(uart3temp);//发送字符

SDataByUart3(0x0D);//发送换行符

SDataByUart3(0x0A);//发送换行符

IE2|=0x08;//串口3中断打开

Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

代码清单:主函数

intmain()

{

P0M1=0xFE;P0M0=0xFE;//设置为准双向口

P0M1=0xFD;P0M0|=0x02;//设置为推挽输出

Uart3_Init();//串口3初始化

EA=1;//总中断打开

while(1)

{

UART3_Tx_Puts();//串口接收到一个字符后返回该字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

5.2.硬件连接

本实验需要外接USB转TTL模块连接到开发板串口3上,该实验串口3选择的和,具体接线图如下。

图21:串口3实验连接图

6.串口4收发实验(和)

6.1.编写代码

首先,在文件中编写串口4的初始化函数Uart4_Init,代码如下。

程序清单:串口4初始化函数

/***************************************************************************

*描述:串口4初始化函数

*入参:无

*返回值:无

备注:波特率9600bps晶振11.0592MHz

**************************************************************************/

voidUart4_Init(void)

{

S4CON|=0x10;//启动串行接收器

S4CON=0x30;//8位数据,可变波特率,串口4选择定时器2为波特率发生器

AUXR|=0x04;//定时器2时钟为Fosc,即1T

T2L=0xE0;//设定定时初值

T2H=0xFE;//设定定时初值

AUXR|=0x10;//启动定时器2

IE2|=0x10;//串口4中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

然后,编写串口4发送数据函数,把要发送的字节存放于数据缓存寄存器中,直到数据发送完成,代码如下。

程序清单:数据发送函数函数

/***************************************************************************

*描述:串口4发送数据函数

*入参:uint8数据

*返回值:无

**************************************************************************/

voidSDataByUart4(uint8dat)

{

S4BUF=dat;//写数据到UART数据寄存器

while(!(S4CONS4TI));//在停止位没有发送时,S4TI为0即一直等待

S4CON=~S4TI;//清除S4CON寄存器对应S4TI位(该位必须软件清零)

}

1

2

3

4

5

6

7

8

9

10

11

之后,编写串口4的中断服务函数,将接收的数据存放到用户自定义变量uart4temp中,代码如下。

程序清单:中断服务函数

/***************************************************************************

*描述:串口4中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart4()interrupt18using1

{

IE2=0xEF;//串口4中断关闭

Flag=TRUE;//接收到数据,接收标识符有效

if(S4CONS4RI)//串行接收到停止位的中间时刻时,该位置1

{

S4CON=~S4RI;//清除S4CON寄存器对应S4RI位(该位必须软件清零)

uart4temp=S4BUF;

}

if(S4CONS4TI)//在停止位开始发送时,该位置1

{

S4CON=~S4TI;//清除S4CON寄存器对应S4TI位(该位必须软件清零)

}

IE2|=0x10;//串口4中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

最后,用户定义一个自定义函数UART4_Tx_Puts,该函数将接收的数据原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART4_Tx_Puts

/*************************************************************************

*描述:串口4接收到数据后发送出去

*入参:无

*返回值:无

**************************************************************************/

voidUART4_Tx_Puts(void)

{

if(Flag)//有新数据通过串口被接收到

{

IE2=0xEF;//串口4中断关闭

SDataByUart4(uart4temp);//发送字符

SDataByUart4(0x0D);//发送换行符

SDataByUart4(0x0A);//发送换行符

IE2|=0x10;//串口4中断打开

Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

代码清单:主函数

intmain()

{

P0M1=0xFB;P0M0=0xFB;//设置为准双向口

P0M1=0xF7;P0M0|=0x08;//设置为推挽输出

Uart4_Init();//串口4初始化

EA=1;//总中断打开

while(1)

{

UART4_Tx_Puts();//串口接收到一个字符后返回该字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

6.2.硬件连接

本实验需要外接USB转TTL模块连接到开发板串口4上,该实验串口4选择的和,具体接线图如下。

图22:串口4实验连接图

7.串口1串口2同时收发字符串实验

7.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

表9:实验需要用到的c文件

序号文件名后缀功能描述

1外部串行口有关的用户自定义函数。

2包含用户自定义延时函数。

3包含与用户led控制有关的用户自定义函数。

7.2.头文件引用和路径设置

■需要引用的头文件

include""

1

2

■需要包含的头文件路径

本例需要包含的头文件路径如下表:

表10:头文件包含路径

序号路径描述

1…\、和头文件在该路径,所以要包含。

2…\头文件在该路径,所以要包含。

图23:添加头文件包含路径

7.3.编写代码

首先,在文件中编写串口1的初始化函数Uart1_Init和串口1发送单个字符函数SDataByUart1,这两个函数不介绍了。下面介绍下串口1清缓存函数CLR_Buf1和发送字符串函数SStringByUart1,代码如下。

程序清单:串口1发送字符串函数

/***************************************************************************

*描述:串口1发送字符串函数

*入参:字符串

*返回值:无

**************************************************************************/

voidSStringByUart1(uint8*s)

{

while(*s)

{

SDataByUart1(*s++);//将字符串中的字符一个一个发送

}

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口1清缓存函数

/*****************************************************************************

功能描述:清除串口1缓存内容函数

入口参数:无

返回值:无

******************************************************************************/voidCLR_Buf1(void)

{

uint8k;

for(k=0;kBuf1_Max;k++)//将串口1缓存数组的值都清为零

{

Rec_Buf1[k]=0;

}

i=0;//清零串口1接收数据个数变量

}

1

2

3

4

5

6

7

8

9

10

11

12

13

然后,串口2的初始化函数Uart2_Init和串口2发送单个字符函数SDataByUart2,这两个函数不介绍了。下面介绍下串口2清缓存函数CLR_Buf2和发送字符串函数SStringByUart2,代码如下。

程序清单:串口2发送字符串函数

/***************************************************************************

*描述:串口2发送字符串函数

*入参:字符串

*返回值:无

**************************************************************************/

voidSStringByUart2(uint8*s)

{

while(*s)//检测字符串结束标志

{

SDataByUart2(*s++);//发送当前字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口2清缓存函数

/**************************************************************************

功能描述:清除串口2缓存内容函数

入口参数:无

返回值:无

***************************************************************************/

voidCLR_Buf2(void)

{

uint8k;

for(k=0;kBuf2_Max;k++)//将串口2缓存数组的值都清为零

{

Rec_Buf2[k]=0;

}

j=0;//清零串口2接收数据个数变量

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

之后,编写串口1和串口2的中断服务函数,将接收的数据存放到用户自定义数组Rec_Buf1和Rec_Buf2中,代码如下。

程序清单:串口1中断服务函数

/***************************************************************************

*描述:串口1中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart1()interrupt4using1

{

uint8temp;

ES=0;//串口1中断关闭

if(RI)//串行接收到停止位的中间时刻时,该位置1

{

RI=0;//清除RI位(该位必须软件清零)

temp=SBUF;//接收到的数赋值给临时变量

if(temp!='\n')//没有接收到换行符

{

Rec_Buf1[i]=temp;//接收到的数存到接收数组中

i++;//串口1接收数据个数变量累加

}

else//接收到结束符

{

Buf1_Length=i;//接收数据长度赋值

i=0;//清零串口1接收数据个数变量

Buf1_Flag=TRUE;//接收完数据,接收标识符有效

led_toggle(LED_3);//翻转用户指示灯D3,方便观察实验现象

}

}

if(TI)//在停止位开始发送时,该位置1

{

TI=0;//清除TI位(该位必须软件清零)

}

ES=1;//串口1中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

程序清单:串口2中断服务函数

/***************************************************************************

*描述:串口2中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart2()interrupt8using1

{

uint8temp;

IE2=0xFE;//串口2中断关闭

if(S2CONS2RI)//串行接收到停止位的中间时刻时,该位置1

{

S2CON=~S2RI;//清除S2CON寄存器对应S2RI位(该位必须软件清零)

temp=S2BUF;//接收到的数赋值给临时变量

if(temp!='\n')//没有接收到换行符

{

Rec_Buf2[j]=temp;//接收到的数存到接收数组中

j++;//串口2接收数据个数变量累加

}

else//接收到结束符

{

Buf2_Length=j;//接收数据长度赋值

j=0;//清零串口2接收数据个数变量

Buf2_Flag=TRUE;//接收完数据,接收标识符有效

led_toggle(LED_4);//翻转用户指示灯D4,方便观察实验现象

}

}

if(S2CONS2TI)//在停止位开始发送时,该位置1

{

S2CON=~S2TI;//清除S2CON寄存器对应S2TI位(该位必须软件清零)

}

IE2|=0x01;//串口2中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

最后,用户定义一个自定义函数UART1_2_Tx_Puts,该函数将接收的字符串原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART1_2_Tx_Puts

/*************************************************************************

*描述:串口1和串口2接收到字符串后发送出去

*入参:无

*返回值:无

************************************************************************/

voidUART1_2_Tx_Puts(void)

{

if(Buf1_Flag)//串口1接收一组字符串完成

{

ES=0;//串口1中断关闭

SStringByUart1(Rec_Buf1);//发送字符

SDataByUart1(0x0D);//发送换行符

SDataByUart1(0x0A);//发送换行符

ES=1;//串口1中断打开

CLR_Buf1();//清除串口1缓存

Buf1_Flag=FALSE;//清除接收标识符

}

if(Buf2_Flag)//串口2接收一组字符串完成

{

IE2=0xFE;//串口2中断关闭

SStringByUart2(Rec_Buf2);//发送字符

SDataByUart2(0x0D);//发送换行符

SDataByUart2(0x0A);//发送换行符

IE2|=0x01;//串口2中断打开

CLR_Buf2();//清除串口2缓存

Buf2_Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

代码清单:主函数

intmain()

{

P3M1=0xFE;P3M0=0xFE;//设置为准双向口

P3M1=0xFD;P3M0|=0x02;//设置为推挽输出

P1M1=0xFE;P1M0=0xFE;//设置为准双向口

P1M1=0xFD;P1M0|=0x02;//设置为推挽输出

Uart1_Init();//串口1初始化

Uart2_Init();//串口2初始化

EA=1;//总中断打开

CLR_Buf1();//清除串口1缓存

CLR_Buf2();//清除串口2缓存

while(1)

{

UART1_2_Tx_Puts();//UART1和UART2接收到字符串后发送出去

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

7.4.硬件连接

图24:串口1串口2实验连接图

8.串口3串口4同时收发字符串实验

8.1.编写代码

首先,在文件中编写串口3的初始化函数Uart3_Init和串口3发送单个字符函数SDataByUart3,这两个函数不介绍了。下面介绍下串口3清缓存函数CLR_Buf3和发送字符串函数SStringByUart3,代码如下。

程序清单:串口3发送字符串函数

/***************************************************************************

*描述:串口3发送字符串函数

*入参:字符串

*返回值:无

**************************************************************************/

voidSStringByUart3(uint8*s)

{

while(*s)//检测字符串结束标志

{

SDataByUart3(*s++);//发送当前字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口3清缓存函数

/*****************************************************************************

功能描述:清除串口3缓存内容函数

入口参数:无

返回值:无

****************************************************************************/

voidCLR_Buf3(void)

{

uint8k;

for(k=0;kBuf3_Max;k++)//将串口3缓存数组的值都清为零

{

Rec_Buf3[k]=0;

}

i=0;//清零串口3接收数据个数变量

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

然后,串口4的初始化函数Uart4_Init和串口4发送单个字符函数SDataByUart4,这两个函数不介绍了。下面介绍下串口4清缓存函数CLR_Buf4和发送字符串函数SStringByUart4,代码如下。

程序清单:串口4发送字符串函数

/***************************************************************************

*描述:串口4发送字符串函数

*入参:字符串

*返回值:无

**************************************************************************/

voidSStringByUart4(char*s)

{

while(*s)//检测字符串结束标志

{

SDataByUart4(*s++);//发送当前字符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口4清缓存函数

/**************************************************************************

功能描述:清除串口4缓存内容函数

入口参数:无

返回值:无

***************************************************************************/

voidCLR_Buf4(void)

{

uint8k;

for(k=0;kBuf4_Max;k++)//将串口4缓存数组的值都清为零

{

Rec_Buf4[k]=0;

}

j=0;//清零串口4接收数据个数变量

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

之后,编写串口3和串口4的中断服务函数,将接收的数据存放到用户自定义数组Rec_Buf3和Rec_Buf4中,代码如下。

程序清单:串口3中断服务函数

/***************************************************************************

*描述:串口3中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart3()interrupt17using1

{

uint8temp;

IE2=0xF7;//串口3中断关闭

if(S3CONS3RI)//串行接收到停止位的中间时刻时,该位置1

{

S3CON=~S3RI;//清除S3CON寄存器对应S3RI位(该位必须软件清零)

temp=S3BUF;//接收到的数赋值给临时变量

if(temp!='\n')//没有接收到换行符

{

Rec_Buf3[i]=temp;//接收到的数存到接收数组中

i++;//串口3接收数据个数变量累加

}

else//接收到结束符

{

Buf3_Length=i;//接收数据长度赋值

i=0;//清零串口3接收数据个数变量

Buf3_Flag=TRUE;//接收完数据,接收标识符有效

led_toggle(LED_3);//翻转用户指示灯D3,方便观察实验现象

}

}

if(S3CONS3TI)//在停止位开始发送时,该位置1

{

S3CON=~S3TI;//清除S3CON寄存器对应S3TI位(该位必须软件清零)

}

IE2|=0x08;//串口3中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

程序清单:串口2中断服务函数

/***************************************************************************

*描述:串口4中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart4()interrupt18using1

{

uint8temp;

IE2=0xEF;//串口4中断关闭

if(S4CONS4RI)//串行接收到停止位的中间时刻时,该位置1

{

S4CON=~S4RI;//清除S4CON寄存器对应S4RI位(该位必须软件清零)

temp=S4BUF;//接收到的数赋值给临时变量

if(temp!='\n')//没有接收到换行符

{

Rec_Buf4[j]=temp;//接收到的数存到接收数组中

j++;//串口4接收数据个数变量累加

}

else//接收到结束符

{

Buf4_Length=j;//接收数据长度赋值

j=0;//清零串口4接收数据个数变量

Buf4_Flag=TRUE;//接收完数据,接收标识符有效

led_toggle(LED_4);//翻转用户指示灯D4,方便观察实验现象

}

}

if(S4CONS4TI)//在停止位开始发送时,该位置1

{

S4CON=~S4TI;//清除S4CON寄存器对应S4TI位(该位必须软件清零)

}

IE2|=0x10;//串口4中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

最后,用户定义一个自定义函数UART3_4_Tx_Puts,该函数将接收的字符串原样返回去并加上回车符。主函数main在主循环中调用该函数。具体代码如下。

代码清单:用户函数UART3_4_Tx_Puts

/*************************************************************************

*描述:串口3和串口4接收到字符串后发送出去

*入参:无

*返回值:无

***********************************************************************/

voidUART3_4_Tx_Puts(void)

{

if(Buf3_Flag)//串口3接收一组字符串完成

{

IE2=0xF7;//串口3中断关闭

SStringByUart3(Rec_Buf3);//发送字符

SDataByUart3(0x0D);//发送换行符

SDataByUart3(0x0A);//发送换行符

IE2|=0x08;//串口3中断打开

CLR_Buf3();//清除串口3缓存

Buf3_Flag=FALSE;//清除接收标识符

}

if(Buf4_Flag)//串口4接收一组字符串完成

{

IE2=0xEF;//串口4中断关闭

SStringByUart4(Rec_Buf4);//发送字符

SDataByUart4(0x0D);//发送换行符

SDataByUart4(0x0A);//发送换行符

IE2|=0x10;//串口4中断打开

CLR_Buf4();//清除串口4缓存

Buf4_Flag=FALSE;//清除接收标识符

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

代码清单:主函数

intmain()

{

P0M1=0xFA;P0M0=0xFA;//设置为准双向口

P0M1=0xF5;P0M0|=0x0A;//设置为推挽输出

Uart3_Init();//串口3初始化

Uart4_Init();//串口4初始化

EA=1;//总中断打开

CLR_Buf3();//清除串口3缓存

CLR_Buf4();//清除串口4缓存

while(1)

{

UART3_4_Tx_Puts();//UART3和UART4接收到字符串后发送出去

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

8.2.硬件连接

图26:串口3串口4实验连接图

9.串口1串口2串口3串口4同时收发实验

9.1.编写代码

首先,在文件中编写串口1、串口2、串口3和串口4的初始化函数Uart1234_Init,代码如下。

程序清单:串口初始化函数

/***************************************************************************

*描述:串口1/2/3/4初始化函数

*入参:无

*返回值:无

备注:波特率9600bps晶振11.0592MHz

**************************************************************************/

voidUart1234_Init(void)

{

//串口1配置

PCON=0x3f;//串口1波特率不倍速,串行口工作方式由SM0、SM1决定

SCON=0x50;//串口1的8位数据,可变波特率,启动串行接收器

AUXR|=0x01;//串口1选择定时器2为波特率发生器

//串口2配置

S2CON=0x50;//串口2的8位数据,可变波特率

//串口3配置

S3CON|=0x10;//串口3启动串行接收器

S3CON=0x30;//串口3选择定时器2为波特率发生器,8位数据,可变波特率

//串口4配置

S4CON|=0x10;//启动串行接收器

S4CON=0x30;//8位数据,可变波特率,串口4选择定时器2为波特率发生器

//定时器2配置

AUXR|=0x04;//定时器2时钟为Fosc,即1T

T2L=0xE0;//设定定时初值

T2H=0xFE;//设定定时初值

AUXR|=0x10;//启动定时器2

//打开串口中断

ES=1;//串口1中断打开

IE2|=0x01;//串口2中断打开

IE2|=0x08;//串口3中断打开

IE2|=0x10;//串口4中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

然后,介绍下4个串口的握手函数,代码如下。(串口1、串口2、串口3和串口4的发送函数、清缓存函数不作介绍)

程序清单:串口1握手函数

/******************************************************************************

功能描述:握手成功与否函数

入口参数:uint8*a

返回值:位

****************************************************************************/

bitHand1(uint8*a)

{

if(strstr(Rec_Buf1,a)!=NULL)//判断字符串a是否是字符串Rec_Buf1的子串

return1;//如果字符串a是字符串Rec_Buf1的子串

else

return0;//如果字符串a不是字符串Rec_Buf1的子串

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口2握手函数

/***************************************************************************

功能描述:握手成功与否函数

入口参数:uint8*a

返回值:位

****************************************************************************/

bitHand2(uint8*a)

{

if(strstr(Rec_Buf2,a)!=NULL)//判断字符串a是否是字符串Rec_Buf2的子串

return1;//如果字符串a是字符串Rec_Buf2的子串

else

return0;//如果字符串a不是字符串Rec_Buf2的子串

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口3握手函数

/*****************************************************************************

功能描述:握手成功与否函数

入口参数:uint8*a

返回值:位

************************************************************************/

bitHand3(uint8*a)

{

if(strstr(Rec_Buf3,a)!=NULL)//判断字符串a是否是字符串Rec_Buf3的子串

return1;//如果字符串a是字符串Rec_Buf3的子串

else

return0;//如果字符串a不是字符串Rec_Buf3的子串

}

1

2

3

4

5

6

7

8

9

10

11

12

程序清单:串口4握手函数

/***************************************************************************

功能描述:握手成功与否函数

入口参数:uint8*a

返回值:位

****************************************************************************/

bitHand4(uint8*a)

{

if(strstr(Rec_Buf4,a)!=NULL)//判断字符串a是否是字符串Rec_Buf4的子串

return1;//如果字符串a是字符串Rec_Buf4的子串

else

return0;//如果字符串a不是字符串Rec_Buf4的子串

}

1

2

3

4

5

6

7

8

9

10

11

12

之后,编写串口1、串口2、串口3和串口4的中断服务函数,将接收的数据存放到用户自定义数组Rec_Buf1、Rec_Buf2、Rec_Buf3和Rec_Buf4中,代码如下。

程序清单:串口1中断服务函数

/***************************************************************************

*描述:串口1中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart1()interrupt4using1

{

ES=0;//串口1中断关闭

if(RI)//串行接收到停止位的中间时刻时,该位置1

{

RI=0;//清除RI位(该位必须软件清零)

Rec_Buf1[i]=SBUF;//接收到的数存到接收数组中

i++;//串口1接收数据个数变量累加

if(iBuf_Max)//判断接收数据个数是否超限

{

i=0;//清零接收数据个数

}

}

if(TI)//在停止位开始发送时,该位置1

{

TI=0;//清除TI位(该位必须软件清零)

}

ES=1;//串口1中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

程序清单:串口2中断服务函数

/***************************************************************************

*描述:串口2中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart2()interrupt8using1

{

IE2=0xFE;//串口2中断关闭

if(S2CONS2RI)//串行接收到停止位的中间时刻时,该位置1

{

S2CON=~S2RI;//清除S2CON寄存器对应S2RI位(该位必须软件清零)

Rec_Buf2[j]=S2BUF;//把串口2缓存SBUF寄存器数据依次存放到数组Rec_Buf2中

j++;//串口2接收数据个数变量累加

if(jBuf_Max)//接收数大于定义接收数组最大个数时,覆盖接收数组之前值

{

j=0;//清零串口2接收数据个数变量

}

}

if(S2CONS2TI)//在停止位开始发送时,该位置1

{

S2CON=~S2TI;//清除S2CON寄存器对应S2TI位(该位必须软件清零)

}

IE2|=0x01;//串口2中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

程序清单:串口3中断服务函数

/***************************************************************************

*描述:串口3中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart3()interrupt17using1

{

IE2=0xF7;//串口3中断关闭

if(S3CONS3RI)//串行接收到停止位的中间时刻时,该位置1

{

S3CON=~S3RI;//清除S3CON寄存器对应S3RI位(该位必须软件清零)

Rec_Buf3[m]=S3BUF;//把串口3缓存SBUF寄存器数据依次存放到数组Rec_Buf3中

m++;//串口3接收数据个数变量累加

if(mBuf_Max)//接收数大于定义接收数组最大个数时,覆盖接收数组之前值

{

m=0;//清零串口3接收数据个数变量

}

}

if(S3CONS3TI)//在停止位开始发送时,该位置1

{

S3CON=~S3TI;//清除S3CON寄存器对应S3TI位(该位必须软件清零)

}

IE2|=0x08;//串口3中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

程序清单:串口4中断服务函数

/***************************************************************************

*描述:串口4中断服务函数

*入参:无

*返回值:无

**************************************************************************/

voidUart4()interrupt18using1

{

IE2=0xEF;//串口4中断关闭

if(S4CONS4RI)//串行接收到停止位的中间时刻时,该位置1

{

S4CON=~S4RI;//清除S4CON寄存器对应S4RI位(该位必须软件清零)

Rec_Buf4[n]=S4BUF;//把串口4缓存SBUF寄存器数据依次存放到数组Rec_Buf4中

n++;//串口4接收数据个数变量累加

if(nBuf_Max)//接收数大于定义接收数组最大个数时,覆盖接收数组之前值

{

n=0;//清零串口4接收数据个数变量

}

}

if(S4CONS4TI)//在停止位开始发送时,该位置1

{

S4CON=~S4TI;//清除S4CON寄存器对应S4TI位(该位必须软件清零)

}

IE2|=0x10;//串口4中断打开

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

最后,主函数main在主循环中判断对应串口接收到的字符串是不是规定的字符串,然后再发送另一串字符串。具体代码如下。

代码清单:主函数

intmain()

{

P3M1=0xFE;P3M0=0xFE;//设置为准双向口

P3M1=0xFD;P3M0|=0x02;//设置为推挽输出

P1M1=0xFE;P1M0=0xFE;//设置为准双向口

P1M1=0xFD;P1M0|=0x02;//设置为推挽输出

P0M1=0xFA;P0M0=0xFA;//设置为准双向口

P0M1=0xF5;P0M0|=0x0A;//设置为推挽输出

Uart1234_Init();//串口1/2/3/4初始化

EA=1;//总中断打开

CLR_Buf1();//清除串口1缓存

CLR_Buf2();//清除串口2缓存

CLR_Buf3();//清除串口3缓存

CLR_Buf4();//清除串口4缓存

while(1)

{

if(Hand1("UART1"))//串口1收到字符串UART1

{

CLR_Buf1();//将串口1缓存数组的值都清为零

ES=0;//串口1中断关闭

SStringByUart1("UART1CHECKOK!\r\n");//串口1发送字符串UART1CHECKOK!

ES=1;//串口1中断打开

}

if(Hand2("UART2"))//串口2收到字符串UART2

{

CLR_Buf2();//将串口2缓存数组的值都清为零

IE2=0xFE;//串口2中断关闭

SStringByUart2("UART2CHECKOK!\r\n");//串口2发送字符串UART2CHECKOK!

IE2|=0x01;//串口2中断打开

}

if(Hand3("UART3"))//串口3收到字符串UART3

{

CLR_Buf3();//将串口3缓存数组的值都清为零

IE2=0xF7;//串口3中断关闭

SStringByUart3("UART3CHECKOK!\r\n");//串口3发送字符串UART3CHECKOK!

IE2|=0x08;//串口3中断打开

}

if(Hand4("UART4"))//串口4收到字符串UART4

{

CLR_Buf4();//将串口4缓存数组的值都清为零

IE2=0xEF;//串口4中断关闭

SStringByUart4("UART4CHECKOK!\r\n");//串口4发送字符串UART4CHECKOK!

IE2|=0x10;//串口4中断打开

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

9.2.硬件连接

图28:4个串口同时通信实验连接图

总结

以上就是今天要讲的内容,本文仅仅简单介绍了:1、编写程序实现单个串行口收发通信的程序设计;2、编写程序实现多个串行口收发通信的程序设计。