您好,欢迎来到小侦探旅游网。
搜索
您的当前位置:首页多机通信

多机通信

来源:小侦探旅游网


MCS-51的串行通信口

--------------------------------------------------------------------------------

MCS-51单片机内部有一个全双工的串行通信口,即串行接收和发送缓冲器(SBUF),这两个在物理上的接收发送器,既可以接收数据也可以发送数据。但接收缓冲器只能读出不能写入,而发送缓冲器则只能写入不能读出,它们的地址为99H。这个通信口既可以用于网络通信,亦可实现串行异步通信,还可以构成同步移位寄存器使用。如果在传行口的输入输出引脚上加上电平转换器,就可方便地构成标准的RS-232接口。下面我们分别介绍。

[1]. 基本概念

数据通信的传输方式

常用于数据通信的传输方式有单工、半双工、全双工和多工方式。

单工方式:数据仅按一个固定方向传送。因而这种传输方式的用途有限,常用于串行口的打印数据传输与简单系统间的数据采集。

半双工方式:数据可实现双向传送,但不能同时进行,实际的应用采用某种协议实现收/发开关转换。

全双工方式:允许双方同时进行数据双向传送,但一般全双工传输方式的线路和设备较复杂。

多工方式:以上三种传输方式都是用同一线路传输一种频率信号,为了充分地利用线路资源,可通过使用多路复用器或多路集线器,采用频分、时分或码分复用技术,即可实现在同一线路上资源共享功能,我们盛之为多工传输方式。

串行数据通信两种形式

异步通信

在这种通信方式中,接收器和发送器有各自的时钟,它们的工作是非同步的,异步通信用一帧来表示一个字符,其内容如下:一个起始位,仅接着是若干个数据位,图2是传输45H的数据格式。

同步通信

同步通信格式中,发送器和接收器由同一个时钟源控制,为了克服在异步通信中,每传输一帧字符都必须加上起始位和停止位,占用了传输时间,在要求传送数据量较大的场合,速度就慢得多。同步传输方式去掉了这些起始位和停止位,只在传输数据块时先送出一个同步头(字符)标志即可。

同步传输方式比异步传输方式速度快,这是它的优势。但同步传输方式也有其缺点,即它必须要用一个时钟来协调收发器的工作,所以它的设备也较复杂。

串行数据通信的传输速率

串行数据传输速率有两个概念,即每秒转送的位数bps(Bit per second)和每秒符号数—波特率(Band rate),在具有调制解调器的通信中,波特率与调制速率有关。

[2]. MCS-51的串行口和控制寄存器

串行口控制寄存器

MCS-51单片机串行口寄存器结构如图3所示。SBUF为串行口的收发缓冲器,它是一个可寻址的专用寄存器,其中包含了接收器和发送器寄存器,可以实现全双工通信。但这两个寄存器具有同一地址(99H)。MCS-51的串行数据传输很简单,只要向发送缓冲器写入数据即可发送数据。而从接收缓冲器读出数据即可接收数据。

此外,从图中可看出,接收缓冲器前还加上一级输入移位寄存器,MCS-51这种结构目的在于接收数据时避免发生数据帧重叠现象,以免出错,部分文献称这种结构为双缓冲器结构。而发送数据时就不需要这样设置,因为发送时,CPU是主动的,不可能出现这种现象。

串行通信控制寄存器

在上一节我们已经分析了SCON控制寄存器,它是一个可寻址的专用寄存器,用于串行数据的通信控制,单元地址是98H,其结构格式如下:

表1 SCON寄存器结构

SCON D7 D6 D5 D4 D3 D2 D1 D0

SM0 SM1 SM2 REN TB8 RB8 TI RI

位地址 9FH 9EH 8DH 9CH 9BH 9AH 99H 98H

下面我们对各控制位功能介绍如下:

(1).SM0、SM1:串行口工作方式控制位。

SM0,SM1 工作方式

00 方式0

01 方式1

10 方式2

11 方式3

(2).SM2:多机通信控制位。

多机通信是工作于方式2和方式3,SM2位主要用于方式2和方式3。接收状态,当串行口工作于方式2或3,以及SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接收到的前8位数据送入SBUF,且置位RI发出中断申请,否则会将接受到的数据放弃。当SM2=0时,就不管第位数据是0还是1,都难得数据送入SBUF,并发出中断申请。

工作于方式0时,SM2必须为0。

(3).REN:允许接收位。

REN用于控制数据接收的允许和禁止,REN=1时,允许接收,REN=0时,禁止接收。

(4).TB8:发送接收数据位8。

在方式2和方式3中,TB8是要发送的——即第9位数据位。在多机通信中同样亦要传输这一位,并且它代表传输的地址还是数据,TB8=0为数据,TB8=1时为地址。

(5).RB8:接收数据位8。

在方式2和方式3中,RB8存放接收到的第9位数据,用以识别接收到的数据特征。

(6).TI:发送中断标志位。

可寻址标志位。方式0时,发送完第8位数据后,由硬件置位,其它方式下,在发送或停止位之前由硬件置位,因此,TI=1表示帧发送结束,TI可由软件清“0”。

(7).RI:接收中断标志位。

可寻址标志位。接收完第8位数据后,该位由硬件置位,在其他工作方式下,该位由硬件置位,RI=1表示帧接收完成。

电源管理寄存器PCON

PCON主要是为CHMOS型单片机的电源控制而设置的专用寄存器,单元地址是87H,其结构格式如下:

表2 PCON电源管理寄存器结构

PCON D7 D6 D5 D4 D3 D2 D1 D0

位符号 SMOD - - - GF1 GF0 PD IDL

在CHMOS型单片机中,除SMOD位外,其他位均为虚设的,SMOD是串行口波特率倍增位,当SMOD=1时,串行口波特率加倍。系统复位默认为SMOD=0。

中断允许寄存器IE

中断允许寄存器在前一节中已阐述,这里重述一下对串行口有影响的位ES。ES为串行中断允许控制位,ES=1允许串行中断,ES=0,禁止串行中断。

表3 IE中断允许控制寄存器结构

位符号 EA - - ES ET1 EX1 ET0 EX0

位地址 AFH AEH ADH ACH ABH AAH A9H A8H

[完]

参考资料: http://www.zymcu.com/8051_file/series01.htm

a,b,c. a为主机,bc为从机。a上有一个外部中断0输入,按第一次a的两个LED亮500ms,再按一下,b机的两个LED灯亮500ms,第三次按下c机的两个LED灯亮500ms,然后周而复始。两个数码管分别显示0/1/2, 和abc(bc由从机反馈)

/*

主从通信基本步骤:

1. 主机从机初始化为方式2或者3,从机都置SM2=1,允许中断

2. 主机置TB8=1,发送从机地址

3. 所有从机均接收主机发送要寻址的从机地址

4. 被寻址的从机确认地址后,置本机SM2=0,向主机返回地址,供主机核对

5. 核对无误后,主机向被寻址的从机发送命令,通知从机接受或者发送数据。

6. 本次通信结束后,主从机重置SM2=1,主机可再对其他从机寻址

*/

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

主机a:

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

#include

#define uchar unsigned char

#define uint unsigned int

uchar

leddata[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x40,0x00};

uchar Mode;

sbit P10 = P1^0;

sbit P13 = P1^3;

sbit P17 = P1^7;

sbit P20 = P2^0;

sbit P21 = P2^1;

void UART_init()

{

TMOD = 0x20;

TH1 = 0xfd;

TL1 = 0xfd;

TR1 = 1;

SCON = 0xd0;

ES = 1;

EX0 = 1;

IT0 = 1; //INT0下跳触发

EA = 1;

TI = 0;

}

void DelayMs(int ms)

{

uchar i;

while(ms--)

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

}

void putc_to_SerialPort(uchar c)

{

SBUF = c;

while(TI == 0);

TI = 0;

}

void MasterControl(unsigned char Addr, unsigned char Comd)

{

TB8 = 1;

putc_to_SerialPort(Addr);

DelayMs(50);

TB8 = 0;

putc_to_SerialPort(Comd);

DelayMs(50);

}

Ex0_int(void) interrupt 0

{

P0 = leddata[Mode];

P20 = 0;

if(Mode == 0)

{

P2 = leddata[10];

P10 = 0;

P13 = 0;

DelayMs(500);

P10 = 1;

P13 = 1;

// MasterControl('b','C');

// MasterControl('c','C');

}

else if(Mode == 1)

{

P10 = 1;

P13 = 1;

MasterControl('b','O');

// MasterControl('c','C');

}

else if(Mode == 2)

{

P10 = 1;

P13 = 1;

// MasterControl('b','C');

MasterControl('c','O');

}

Mode = (Mode + 1) % 3;

}

com_int(void) interrupt 4

{

if(RI)

{

RI = 0;

if(SBUF == 'b')

{

P2 = leddata[11];

}

if(SBUF == 'c')

{

P2 = leddata[12];

}

}

}

void main(void)

{

P0 = 0x00;

P1 = 0xff;

P2 = 0x00;

UART_init();

Mode = 0;

while(1);

}

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

从机b:

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

#include

#define uchar unsigned char

uchar RecData;

sbit P10 = P1^0;

sbit P13 = P1^3;

void UART_init()

{

TMOD = 0x21;

TH1 = 0xfd;

TL1 = 0xfd;

TR1 = 1;

SCON = 0xf0;

ES = 1;

PS = 1;

EA = 1;

}

void DelayMs(int ms)

{

uchar i;

while(ms--)

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

}

void putc_to_SerialPort(uchar c)

{

SBUF = c;

while(TI == 0);

TI = 0;

}

com_int(void) interrupt 4

{

if(RI)

{

RecData = SBUF;

RI = 0;

if(RB8 == 1) //地址

{

if(RecData == 'b') //是自己的地址,置SM2=0,准备接受数据

{

SM2 = 0;

putc_to_SerialPort('b');

}

else //不是自己的地址

{

SM2 = 1;

}

}

if(RB8 == 0) //数据

{

if(RecData=='O')

{

P10 = 0;

P13 = 0;

DelayMs(500);

P10 = 1;

P13 = 1;

}

if(RecData=='C')

{

P10 = 1;

P13 = 1;

}

SM2 = 1;

}

}

}

void main(void)

{

P0 = 0xff;

P1 = 0xff;

UART_init();

while(1);

}

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

从机c:

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

#include

#define uchar unsigned char

uchar RecData;

sbit P10 = P1^0;

sbit P13 = P1^3;

void UART_init()

{

TMOD = 0x21;

TH1 = 0xfd;

TL1 = 0xfd;

TR1 = 1;

SCON = 0xf0;

ES = 1;

PS = 1;

EA = 1;

}

void DelayMs(int ms)

{

uchar i;

while(ms--)

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

}

void putc_to_SerialPort(uchar c)

{

SBUF = c;

while(TI == 0);

TI = 0;

}

com_int(void) interrupt 4

{

if(RI)

{

RecData = SBUF;

RI = 0;

if(RB8 == 1) //地址

{

if(RecData == 'c') //是自己的地址,置SM2=0,准备接受数据

{

SM2 = 0;

putc_to_SerialPort('c');

}

else //不是自己的地址

{

SM2 = 1;

}

}

if(RB8 == 0) //数据

{

if(RecData=='O')

{

P10 = 0;

P13 = 0;

DelayMs(500);

P10 = 1;

P13 = 1;

SM2 = 1;

}

if(RecData=='C')

{

P10 = 1;

P13 = 1;

SM2 = 1;

}

}

}

}

void main(void)

{

P0 = 0xff;

P1 = 0xff;

UART_init();

while(1);

}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- xiaozhentang.com 版权所有 湘ICP备2023022495号-4

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务