什么是串行通信?
将数据字节分成一位一位的形式在一条传输线上逐位地发送。
优点:成本低,控制复杂。
什么是异步通信?
异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。 异步通信的两个关键:
第一,数据单元——帧,它是双方约定好的数据格式;
第二,波特率,它决定了‘帧’里每一位的时间长度。
异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加2~3位用于起止位,各帧之间还有间隔,因此传输效率不高。
80C51单片机串口通信
控制寄存器SCON
SM0和SM1为工作方式选择位,可选择四种工作方式:
SM2,多机通信控制位。当SM2=0时,不论收到的RB8为0和1,均可以使收到的数据进入SBUF,并激活RI(即此时RB8不具有控制RI激活的功能)。过控制SM2,可以实现多机通信。
REN,允许串行接收位。由软件置REN=1,则启动串行口接收数据;
TB8,在方式0和方式1中,该位未用。
RB8,在方式1时,若SM2=0,则RB8是接收到的停止位。
TI,发送中断标志位。在方式0时,当串行发送第8位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使TI置1,向CPU发中断申请。在中断服务程序中,必须用软件将其清0,取消此中断申请。
RI,接收中断标志位。在方式0时,当串行接收第8位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使RI置1,向CPU发中断申请。也必须在中断服务程序中,用软件将其清0,取消此中断申请。
PCON中只有一位SMOD与串行口工作有关 :
SMOD(PCON.7) 波特率倍增位。在串行口方式1、方式2、方式3时,波特率与SMOD有关,当SMOD=1时,波特率提高一倍。复位时,SMOD=0。
方式1是10位数据的异步通信口______代码实践内容
TXD为数据发送引脚,RXD为数据接收引脚,传送一帧数据的格式如图所示。其中1位起始位,8位数据位,1位停止位。
输出时序图:
输入时序图:
用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断。
波特率的计算:
在串行通信中,收发双方对发送或接收数据的速率要有约定。通过软件可对单片机串行口编程为四种工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率来决定。
至于如何计算波特率,我就不分析了,都是公式,看着烦人,查表就可以了!
在单片机的应用中,常用的晶振频率为:12MHz和11.0592MHz。所以,选用的波特率也相对固定。常用的串行口波特率以及各参数的关系如表所示
工作方式1的代码如下:(采用KeilC μVsion4编译)
/* 简介: 工作流程: 通过“串口助手”发送数据,经串口送至51单片机,51单片机收到数据后,发送数据给电脑,显示在“串口助手”! 实际效果:当给单片机发送整数(0~255),单片机返回ch,ch的值每次自增1,当ch为99时,ch重新置0 版本:1.0 完成日期:2012-7-3 17:39 作者:黄路 */ #include <reg51.h> #define uint unsigned int #define uchar unsigned char uchar re = 0; bit read_flag = 0 ;//取数标志位 void init_serialcom( void ) //串口通信初始设定 { SCON = 0x50 ; //UART为模式1,8位数据,允许接收 0101 0000 TMOD |= 0x20 ; //定时器1为模式2,8位自动重装 0010 0000 PCON |= 0x80 ; //SMOD=1; 1000 0000 TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHz 1111 1100 IE |= 0x90 ; //Enable Serial Interrupt 1001 0000 TR1 = 1 ; // timer 1 run } //向串口发送一个字符 uchar send_char_com(uchar ch) { SBUF = ch; ch++; if (ch == 99) { ch = 0; } while (TI == 0);//数据发送后,TI由硬件置1 TI = 0 ; //必须由软件清零 return ch; } //串口接收中断函数 void serial () interrupt 4 using 3 { if (RI) //当接收到数据后,由硬件自动置位 { RI = 0 ; re = SBUF; //收到的数据 read_flag = 1; } } int main() { uchar ch; init_serialcom(); //初始化串口 //关闭不用的数码 while ( 1 ) { if (read_flag == 1) //如果取数标志已置位,就将读到的数从串口发出 { read_flag = 0 ; //取数标志清0 ch = send_char_com(ch); //发送可以被接收的中断所中断 } } }