第7单 串行通信2.docx

上传人:b****6 文档编号:7567750 上传时间:2023-01-25 格式:DOCX 页数:19 大小:327.38KB
下载 相关 举报
第7单 串行通信2.docx_第1页
第1页 / 共19页
第7单 串行通信2.docx_第2页
第2页 / 共19页
第7单 串行通信2.docx_第3页
第3页 / 共19页
第7单 串行通信2.docx_第4页
第4页 / 共19页
第7单 串行通信2.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

第7单 串行通信2.docx

《第7单 串行通信2.docx》由会员分享,可在线阅读,更多相关《第7单 串行通信2.docx(19页珍藏版)》请在冰豆网上搜索。

第7单 串行通信2.docx

第7单串行通信2

【例7.1扩展2】【用中断方式】在七段LED上,循环显示0~9【CAP72LED2,已调通】

#include

sbitP10=P1^0;

unsignedcharLED=0;

unsignedcharled_mod[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

voiddelay(unsignedintcount)

{unsignedchari;

while(count--)

for(i=0;i<120;i++);

}

voidmain(void)

{SCON=0x00;

ES=1;

EA=1;

SBUF=led_mod[0];

while

(1);

}

voidserial_port()interrupt4using0

{if(TI==1)

{TI=0;

delay(1000);

LED++;

if(LED==10)LED=0;

SBUF=led_mod[LED];

}

}

【例7.1扩展3】【用中断方式】【LCAP86,已调通】要求显示如下:

#include

sbitP27=P2^7;

unsignedcharLED=0;

unsignedcharled_mod[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,

0x82,0xf8,0x80,0x90};

voiddelay(unsignedintcount)

{unsignedchari;

while(count--)

for(i=0;i<120;i++);

}

voidmain(void)

{SCON=0x00;

ES=1;

EA=1;

P27=0;

P27=1;

delay(1000);

SBUF=led_mod[0];

while

(1);

}

voidserial_port()interrupt4using0

{if(TI==1)

{TI=0;

delay(1000);

LED++;

if(LED==10)LED=0;

SBUF=led_mod[LED];

}

}

图7-6所示为方式0发送的一个具体应用,通过串行口外接8位串行输入并行输出移位寄存器74LS164,扩展两个8位并行输出口的具体电路。

方式0发送时,串行数据由P3.0(RXD端)送出,移位脉冲由P3.1(TXD端)送出。

在移位脉冲的作用下,串行口发送缓冲器的数据逐位地从P3.0串行移入74LS164中。

图7-6外接串入并出移位寄存器74LS164扩展的并行输出口

方式0接收

(1)方式0接收过程

方式0接收,REN为串行口允许接收控制位,REN = 1,允许接收;REN=0,禁止接收。

当向SCON寄存器写入方式0控制字(并使REN位置1,同时RI = 0)时,产生一个正脉冲,串行口开始接收数据。

引脚RXD为数据输入端,TXD为移位脉冲信号输出端,接收器以fosc/12的固定波特率采样RXD引脚的数据信息,当接收完8位数据时,中断标志RI置1,表示一帧数据接收完毕,可进行下一帧数据的接收,时序如图7-7所示。

图7-7方式0接收时序

在方式0时,SM2位(多机通信控制位)必须为0。

(2)方式0接收应用举例【不讲】

图7-8为串行口外接两片8位并行输入串行输出的寄存器74LS165扩展两个8位并行输入口的电路。

当74LS165的

端由高到低负跳变时,并行输入端的数据被置入寄存器;当

= 1,且时钟禁止端(第15脚)为低电平时,允许TXD(P3.1)串行移位脉冲输入,这时在移位脉冲作用下,数据由右向左方向移动,以串行方式进入串行口的接收缓冲器中。

74L165是并行输入,串行输出移位寄存器。

80C51单片机内部的串行口在方式0工作状态下,使用移位寄存器芯片可以扩展一个或多个8位并行I/O口。

A,B,C,D,E,F,G,H:

并行数据输入端。

QH(9):

串行输出端。

CLOCK

(2):

时钟输入端,正跳变有效。

CLOCKINHIBIT:

时钟禁止端。

当时钟禁止端CLK2为低电平时,允许时钟输入。

SHIFT/LOAD:

移位与置位控制端。

SER:

扩展多个74LS165的首尾连接端。

图7-8扩展74LS165作为并行输入口

在图7-8中:

TXD(P3.1)作为移位脉冲输出与所有75LS165的移位脉冲输入端CLK相连;

RXD(P3.0)作为串行数据输入端与74LS165的串行输出端SO相连;P1.0与

相连,用来控制74LS165的串行移位或并行输入;

74LS165的时钟禁止端(第15脚)接地,表示允许时钟输入。

当扩展多个8位输入口时,相邻两芯片的首尾(QH与SIN)相连。

在方式0,SCON中的TB8、RB8位没有用到,发送或接收完8位数据由硬件使TI或RI中断标志位置“1”,CPU响应TI或RI中断,在中断服务程序中向发送SBUF中送入下一个要发送的数据或从接收SBUF中把接收到的1B存入内部RAM中。

#include【L74LS165已通过】

sbitSPL=P2^5;

voiddelay(unsignedintcount)

{unsignedchari;

while(count--)

for(i=0;i<120;i++);//延时1ms

}

voidmain(void)

{SCON=0x10;//00010000;方式0,REN=1

while

(1)

{SPL=0;

SPL=1;//SH/LD端出现正跳变

while(RI==0);

RI=0;

P0=SBUF;

delay(20);

}

}

 

二.方式1:

8位数据异步通讯方式

1.设定为10位异步通信方式:

1个起始位(“0”),8位数据位,1个停止位(“1”)。

2.RXD:

接收数据端。

TXD:

发送数据端。

【注意和方式0不一样,引脚功能恢复正常了】

3.波特率:

用T1作为波特率发生器

4.发送:

在TI=0时,当把数据写入SBUF后,即可启动发送,串行口内自动把发送缓冲器中的数据送入发送移位寄存器。

发送移位寄存器先发一位起始位,接着按先低位后高位,再发停止位,从而完成一帧的发送。

串行数据均由TXT端输出,TI在发送停止位时,由硬件置TI=1。

接收:

在RI=0和REN=1的条件下。

在接收到第9数据位(即停止位)时,接收电路必须满足以下两个条件:

RI=0且SM2=0;

接收到的停止位为“1”时,

才能把接收到的8位字符存入“SBUF(接收)”中,把停止位送入RB8中,使RI=1并发出串行口中断请求(若中断开放)。

若上述条件不满足,则这次收到的数据就被舍去,不装入“SBUF(接收)”中,这是不能允许的,因为这意味着丢失了一组接收数据。

在方式1下,发送时钟、接收时钟和通信波特率都由定时器溢出率脉冲经过32分频得到,并可由SMOD=1进行倍频。

因此,方式1的波特率是可变的。

其实,SM2是用于方式2和方式3的。

在方式1下,SM2应设为“0”。

方式1时序图:

三.方式2和方式3

方式2和方式3都是11为异步收发。

两者的差异仅在于通信波特率有所不同:

方式2的波特率由fosc经过32或64分频后提供;方式3的波特率由定时器T1(或T2)的溢出率经32分频后提供。

方式2和方式3的发送过程类似于方式1,所不同的是方式2和方式3有9位有效数据位。

发送时,CPU除要把发送字符装入“SBUF(发送)”外,还要把第9位数据位预先装入SCON的TB8中。

第9数据位可由用户安排,可以是奇偶校验位,也可以是其它控制位。

第9数据位的值装入TB8后,便可用一条以SBUF为目的的传送指令把发送数据装入SBUF来启动发送过程。

一帧数据发送完后,TI=1,CPU便可通过查询TI来以同样方法发送下一个字符帧。

方式2和方式3的接收过程也和方式1类似。

所不同的是:

方式1时RB8中存放的是停止位,方式2和方式3时RB8中存放的是第9数据位。

因此,方式2和方式3时必须满足接收有效字符的条件变为:

RI=0且SM2=0或收到的第9数据位为“1”,只有上述两个条件同时满足,接收到的字符才能送入SBUF,第9数据位才能装入RB8中,并使RI=1;否则,这次收到的数据无效,RI也不置位。

其实,上述第一个条件(RI=0)是要求SBUF空,即用户应预先读走SBUF中的信息,以便让接收电路确认它已空。

第二个条件(SM2=0)是提供了利用SM2和第9数据位共同对接收加以控制:

如果第9数据位是奇偶校验位,则可令SM2=0,以保证串口能可靠接收;如果要求利用第9数据位参与接收控制,则可令SM2=1,然后依靠第9数据位的状态来决定接收是否有效。

方式2、3时序图:

7.3.4串行口的编程及应用

一.串行口的初始化编程

1.串行口控制寄存器SCON位的确定

根据工作方式确定SM0、SM1位;对于方式2和方式3还要确定SM2位;如果是接收端,则在接受数据前,应设置允许接收位REN=“1”;如果方式2和方式3发送数据,则应将发送数据的第9位写入TB8中。

2.设置波特率

串行通信,收、发双方发送或接收的波特率必须一致。

方式0和方式2的波特率是固定的;

方式1和方式3的波特率是可变的,由T1溢出率确定。

定时器的不同工作方式,得到的波特率的范围不一样,这是由T1在不同工作方式下计数位数的不同所决定。

(1)方式0时,波特率固定为晶体振荡频率fosc的1/12(fosc/12),不受SMOD位值的影响。

若fosc = 12MHz,波特率为1Mbit/s。

(2)方式2时,波特率仅与SMOD位的值有关。

方式2波特率 = 

如果SMOD=0,则所选波特率为fosc/64;如果SMOD=1,则所选波特率为fosc/32。

若fosc = 12MHz:

SMOD = 0,波特率 = 187.5kbit/s;SMOD = 1,波特率 为375kbit/s。

(3)方式1或方式3,常用T1作为波特率发生器,其表达式为 :

(7-1)

由式(7-1)见,T1溢出率和SMOD的值共同决定方式1或方式3的波特率。

【通常SMOD=0,实际上由T1的溢出率决定】

【注:

定时器T1的溢出率定义为定时时间的倒数

定时时间可参见CAP5

T1的定时时间=计数值×机器周期

T1的溢出率=1/T1定时时间=

所以:

波特率 = (2SMOD/32)×fosc/[12×(2n-初值)]

其中:

N为定时器T1的位数,它和定时器T1的设定方式有关。

如果定时器T1为方式0,则N=13;

如果定时器T1为方式1,则N=16;

如果定时器T1为方式2,则N=8。

在实际设定波特率时,T1常设置为方式2定时(自动装初值),即TL1作为8位计数器,TH1存放定时初值。

这种方式操作方便,也避免因软件重装初值带来的定时误差。

实际使用时,经常根据已知波特率和时钟频率fosc来计算T1的初值X。

为避免繁杂的初值计算,常用的波特率和初值X间的关系常列成下表的形式,以供查用。

下表列出了常用波特率与定时器T1的初值关系表

波特率

fosc

(MHz)

SMOD

定时器T1

所选方式

相应初值

模式1、3

9.6K

12

0

0

2

FD

4.8K

12

0

0

2

FB

2.4K

12

0

0

2

F3

1.2K

12

0

0

2

E6

0.6K

12

0

0

2

CC

B=9600,初值=252.74=253=FD

B=4800,初值=249.48=250=FB

B=2400,初值=242.97=243=128+64+32+16+2+1=F3

B=1200,初值=229.95=230=128+64+32+4+2=11100110=E6

B=600,初值=203.92=204=128+64+8+4=CC

4种方式比较:

方式

波特率

传送位数

发送端

接收端

用途

0

1/12Fosc

(固定不变)

8(数据)

RXD

RXR

接移位寄存器,扩充并口

1

2SMOD/32T1溢出率

10(起始位、8位数据位、

停止位)

TXD

RXR

单机通信

2

2SMOD/64T1fosc

11(第9位为1:

地址;

为0:

数据)

TXD

RXR

多机通信

3

2SMOD/32T1溢出率

11位(同方式2)

TXD

RXR

多机通信

二.串行口的应用

通常用于三种情况:

利用方式0扩展并行I/O口;

利用方式1实现点对点的双机通信;

利用方式2或方式3实现多机通信。

 

7.3.2单片机双机通信

在很多应用系统中,需要单片机之间进行通信。

在串行通信中,如果通信的两个单片机之间距离很短(1m以内),则可以将两个单片机的串口直接相连,用串行方式进行通信,这时一个单片机的发送线(TXD)应与另一个单片机的接收线(RXD)相连。

如果两个需要相互通信的单片机之间距离较远(30m以内),可采用RS232接口延长通信距离,此时必须将单片机的TTL电平与RS232标准电平进行转换。

需要在两个单片机接口部分增加RS232电平转换芯片,常用的此类芯片有MAX232等。

如果两个需要相互通信的单片机之间距离很远,可以采用RS485总线方式进行通信,该方式的传输距离一般在1500m以内,通信双方都需要采用MAX485芯片将TTL信号变为差模信号进行传送。

如果需要采用无线通信方式,可以在单片机串口上连接无线数据传输模块来实现。

只要通信双方的单片机上都有无线传输模块,模块的通信方式设定一致(波特率、无线信号频率等),且单片机通信程序中的波特率与模块的相同,则基于无线方式的串口通信也非常简单。

【例】通信双方约定发送方为甲机,接收方为乙机。

首先甲机发送一个联络数据(0XAA),乙机接收到后响应应答信号(0XBB),然后接收甲机发送的数据。

如果乙机接收到的数据不正确(检查的累加和),就向甲机发送0XFF,甲机收到0XFF后重传数据。

如果乙机接收到的数据正确(检查的累加和),就向甲机发送0X00,甲机收到0X00后重传数据。

#include【CAP73已经通过】

unsignedchardata[10],chksum;【chksum中的数据不能大于255】

voidinit(void)//甲机串口初始化程序,发送端

{

TMOD=0x20;//00100000,定时器T1,定时方式2(自动重载方式),Gate(T1)=0

TH1=0xFD;//设定波特率9600

TL1=0xFD;

SCON=0x50;//01010000,串口工作在方式1,允许接收REN=1

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

}

甲机发送“0XAA”给乙机,乙机收到后,返回“0XBB”

voidsend(void)//甲机发送子程序

{

unsignedchark;

do//循环与乙机联络,等待乙机的回答信号“0XBB”

{

SBUF=0xAA;//向乙机发送联络信号“0XAA”

while(TI==0);//等待发送“0XAA”结束

TI=0;//清除TI标志

while(RI==00);//等待乙机发送响应信号

RI=0;

}while(SBUF!

=0xBB);//判定回答信号是否是“0XBB”,如果不是,继续联络

do//接收到乙机的0XBB联络信号后,开始发送data[10]数组中的数据

{//或者接收到乙机发来的不是0X00,继续do循环

chksum=0;

for(k=0;k<10;k++)//循环10次,发送数据,并对所发数据进行累加

{

SBUF=data[k];//发送数据

chksun+=data[k];//同时累加所发数据的和

while(TI==0);//等待数据发送结束

TI=0;//清除TI标志

}

SBUF=chksun;//10个数据发送完后,再发送累加和结果

while(TI==0);

TI=0;

while(RI==0);//接收乙机发回的累加和数据校验结果

RI=0;

}while(SBUF!

=0x00);//如果接收到的不是0X00,继续do循环,重发数据

}

voidmain(void)//甲机主程序

{

init();

send();

while

(1);

}

*************************************************************************

voidinit(void)//乙机串口初始化程序,接收端

{

TMOD=0x20;//00100000,定时器T1,定时方式2(自动重载方式),Gate(T1)=0

TH1=0xFD;//设定波特率9600

TL1=0xFD;

//PCON=0x00;//设为0,可以省略

SCON=0x50;//01010000,串口工作在方式1,允许接收REN=1

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

}

乙机如果收到甲机发来的“0XAA”,则向甲机发送“0XBB”

voidrecv(void)//乙机接收程序

{

unsignedchark;

while

(1)

{

while(RI==0);//等待接收甲机的联络信号0XAA

RI=0;

if(SBUF!

=0XAA)//判断接收的数据是否是“0XAA”

{//如果不是“0XAA”,则向甲机发送“0XFF”,

SBUF=0XFF;//向甲机发送0XFF,表示没有收到“0XAA”

while(TI==0);//等待发送结束

TI=0;

}

else//接收到的是“0XAA”,则发回应答“0XBB”跳出循环,进入接收数据状态

{

SBUF=0XBB;//发回应答信号“0XBB”【自己加的】

While(TI==0);【等待发送“0XBB”结束】

TI=0;【】

break;//跳出while

(1)循环

}

}

while

(1)//接收到正确的联络信号0XAA后,开始接收数据

{

chksum=0;

for(k=0;k<10;k++)//循环接收10个数据

{

while(RI==0);//等待一个数据的接收完成

RI=0;

data[k]=SBUF;//接收到的数据放入data数组中

chksum+=data[k];//累加接收到的数据

}

while(RI==0);//等待接收甲机发送累加和数据

RI=0;

if(SBUF==chksum)//如果接收的累加和数据与本机的累加和结果一样

{

SBUF=0X00;//向甲机发送“0X00”信号,表示数据正确

while(TI==0);//等待发送0X00的完成

TI=0;

break;//退出while

(1)循环

}

else//如果接收的累加和数据与本机的累加和结果不一样

{

SBUF=0XFF;//则向甲机发送0XFF,表示累加和结果不一样

while(TI==0);//等待发送结束【只要非“0X00”,就表示结果不一样】

TI=0;

}

}

}

voidmain(void)//乙机主程序

{

init();

recv();

while

(1);

}

【P148例题】【LP151已经通过】

【注意BCD七段LED不需要段码,直接显示,右边接低位,左边接高位】

#include【发送端程序】

voiddelay(unsignedintcount)

{unsignedinti;

while(count--)

for(i=0;i<120;i++);

}

voidmain(void)

{unsignedcharcounter=0;

P2=0x3f;//0x3f=00111111

TMOD=0x20;//0x20=00100000,T1方式2,GATE=0,由TR1启动T1

TH1=0xf4;

TL1=0xf4;

PCON=0x00;//可以不要

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

SCON=0x50;//0x50=01010000,方式1,,TI=0,RI=0,REN=1允许接受

while

(1)

{SBUF=counter;//启动发送

while(TI==0);//等待发送完成,发停止位时,置TI=1

TI=0;//软件清TI

while(RI==0);//等待对方发送数据,接收停止位时,置RI=1

RI=0;//软件清RI,接收的数据在SBUF中

If(SBUF==counter)//如果发送的数据counter和接收的数据SBUF相等

{

P2=counter;//如果相等,则显示所发的数据,否则重发原来的数据

if(++counter>15)counter=0;//到F时,counter清零

delay(500);

}

}

}

#include【接收端程序】

voiddelay(unsignedintcount)

{unsignedinti;

while(count--)

for(i=0;i<120;i++);

}

voidmain(void)

{unsignedcharreceiv;

P2=0x3f;

TMOD=0x20;//0x20=00100000,T1方式2,GATE=0,由TR1启动T1

TH1=0xf4;

TL1=0xf4;

PCON=0x00;//可以不要

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

SCON=0x50;//0x50=01010000,方式1,TI=0,RI=0,REN=1,允许接受

while

(1)

{

while(RI==1)//如果接受到发送来的数据

{RI=0;//软件清RI标志

receiv=SBUF;//读入接收的数据

SBUF=receiv;//把接收到的数据再发回发送方

while(TI==0);//等待发送完成

TI=0;

P2=receiv;//显示接收的数据

}

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1