260 likes | 437 Views
第 17 章 串行接口及 C51 编程 MCS-51 单片机串行通信的基本原理。 单片机串行通信的应用。. 1 、 MCS-51 单片机串行通信的基本原理。 2 、单片机串行通信的应用。. 8051 串行口结构框图. 8051 串行口结构框图如下所示:. 8051 串行口结构框图. 串行口的控制与状态寄存器 SCON. 2. 串行口控制寄存器 SCON SCON 寄存器用来控制串行口的工作方式和状态,它可以是位寻址。在复位时所有位被清零,字地址为 98H 。 其格式如下:. 串行口的控制与状态寄存器 SCON. 串行口控制寄存器 SCON
E N D
第17章 串行接口及C51编程 • MCS-51单片机串行通信的基本原理。 • 单片机串行通信的应用。 1、MCS-51单片机串行通信的基本原理。 2、单片机串行通信的应用。
8051串行口结构框图 8051串行口结构框图如下所示: 8051串行口结构框图
串行口的控制与状态寄存器SCON 2. 串行口控制寄存器SCON SCON寄存器用来控制串行口的工作方式和状态,它可以是位寻址。在复位时所有位被清零,字地址为98H。 其格式如下:
串行口的控制与状态寄存器SCON 串行口控制寄存器SCON 各位定义如下: • SM0、SM1:串行口工作方式选择位 其状态组合所对应的工作方式为: SM0 SM1 工作方式 功能说明 波特率 0 0 0 8位同步移位寄存器 fosc/12 0 1 1 8位异步收发 由定时器控制 1 0 2 9位异步收发 fosc/32或fosc/64 1 1 3 9位异步收发 由定时器控制
串行口的控制与状态寄存器SCON • SM2:多机通信控制位 因为多机通信是在方式2和方式3下进行的,因此SM2主要用于方式2和方式3。当串行口以方式2和方式3接收数据时, • SM2=1,则只有在接收到的第9位数据(RB8)为1时才将接收到的前8位数据送入SBUF,并置位RI产生中断请求;否则将接收到的前8位数据丢弃。 • SM2=0,则不论第9位数据是0还是1,都将前8位数据装入SBUF中,并产生中断请求。在方式0时,SM2必须为0。
串行口的控制与状态寄存器SCON • REN:允许接收控制位 • REN=0时禁止串行口接收。 • REN=1时允许串行口接收。 该位由软件置位或复位。 • TB8:发送数据位 • 在方式2或方式3时,TB8是发送数据的第9位,根据发送数据的需要由软件置位或复位。 • 可作为奇偶校验位(单机通信)。 • 可在多机通信中作为发送地址帧或数据帧的标志位。多机通信时,一般约定:发送地址帧时,设置TB8=1;发送数据帧时,设置TB8=0。在方式0和方式1中,该位未用。
串行口的控制与状态寄存器SCON • RB8:接收数据位 • 在方式2和方式3时,存放接收数据的第9位。 • 可以是约定的奇偶校验位。 • 可以是约定的地址/数据标志位,可根据RB8被置位的情况对接收到的数据进行某种判断。在多机通信时,若RB8=1,说明收到的数据为地址帧;RB8=0,说明收到的数据为数据帧。在方式1下,若SM2=0,则RB8用于存放接收到的停止位方式;方式0下,该位未用。
串行口的控制与状态寄存器SCON • TI:发送中断标志位 用于指示一帧数据发送完否。 • 在方式0下,发送电路发送完第8位数据时,TI由硬件置位。 • 在其他方式下,TI在发送电路开始发送停止位时置位,这就是说:TI在发送前必须由软件复位,发送完一帧后由硬件置位。因此,CPU查询TI状态便可知一帧信息是否已发送完毕。 • RI:接收中断标志位 用于指示一帧信息是否接收完。 • 在方式1下,RI在接收电路接收到第8位数据时由硬件置位。 • 在其他方式下,RI是在接收电路接收到停止位的中间位置时置位的,RI也可供CPU查询,以决定CPU是否需要从“SBUF(接收)”中提取接收到的字符或数据。RI也由软件复位。
电源控制寄存器PCON . 电源控制寄存器PCON PCON寄存器主要是为CHMOS型单片机的电源控制设置的专用寄存器,单元地址为87H,不能位寻址。 其格式如下:
电源控制寄存器PCON 各位定义如下: • SMOD:串行口波特率的倍增位。 在HMOS单片机中,该寄存器中除最高位之外,其他位都是虚设的。在单片机工作在方式1、方式2和方式3时, • SMOD=1,串行口波特率提高一倍。 • SMOD=0,则波特率不加倍。系统复位时SMOD=0。 • GF1、GF0:通用标志位,由软件置位、复位。 • PD:掉电方式控制位,PD=1,则进入掉电方式。 • IDL:待机方式控制位,IDL=1,则进入待机方式。
串行口的工作方式0 1. 方式0 串行接口工作方式0为同步移位寄存器方式,其波特率是固定的,为fosc(振荡频率)的1/12。 (1) 方式0发送 数据从RxD引脚串行输出,TxD引脚输出同步脉冲。当一个数据写入串行口发送缓冲器时,串行口将8位数据以fosc/12的固定波特率从RxD引脚输出,从低位到高位。发送后置中断标志TI为1,请求中断,在再次发送数据之前,必须用软件将TI清零。
串行口的工作方式0 (2) 方式0接收 在满足REN=1和RI=0的条件下,串行口处于方式0输入。此时,RxD为数据输入端,TXD为同步信号输出端,接收器也以fosc/12的波特率对RxD引脚输入的数据信息采样。当接收器接收完8位数据后,置中断标志RI=1为请求中断,在再次接收之前,必须用软件将RI清零。 在方式0工作时,必须使SCON寄存器中的SM2位为“0”,这并不影响TB8位和RB8位。方式0发送或接收完数据后由硬件置位TI或RI, CPU在响应中断后要用软件清除TI或RI标志。
串行口的工作方式1 2. 方式1 工作方式1时,串行口被设置为波特率可变的8位异步通信接口。 (1) 方式l发送 串行口以方式1发送数据时,数据位由TxD端输出,1帧信息包含10位,即一位起始位、八位数据位(先低位后高位)和一个停止位“1”。CPU执行一条数据写入发送缓冲器SBUF的指令,就启动发送器发送数据:发送完数据后,就置中断标志TI为1。方式1所传送的波特率取决于定时器T的溢出率和特殊功能寄存器PCON中SMOD的值。
串行口的工作方式1 (2) 方式1接收 当串行口工作在方式1下,且REN=1时,串行口处于方式1的输入状态。它以所选波特率的16倍的速率对RxD引脚状态采样。当采样到由1到0的负跳变时,启动接收器,接收的值是3次采样中至少两次相同的值,以保证可靠无误。当检测到起始位有效时,开始接收一帧的其余信息。一帧信息包含10位,即一位起始位、八位数据位(先低位后高位)和一个停止位“1”。使用方式1接收时,必须同时满足以下两个条件:即RI=0和停止位为1或SM2=0,若满足条件则接收数据进入SBUF,停止位进入RB8,并置中断请求标志RI为1。若上述两个条件不满足,则接收数据丢失,不再恢复。这时将重新检测RxD上1到0的负跳变,以接收下一帧数据。中断标志也必须由用户在中断服务程序中清零。
串行口的工作方式2 (2) 方式2接收 当串行口置为方式2,且REN=1时,串行口以方式2接收数据。方式2的接收与方式1基本相似。数据由RxD端输入,接收11位信息,其中,一位起始位(0)、八位数据位(先低位后高位)、一位附加可控位(1或0)和一位停止位“1”。当采样到RxD端由1到0的负跳变,并判断起始位有效后,便开始接收一帧信息,当接收器接收到第9位数据后,当RI=0且SM2=0或接收到的第9位数据为1时,将收到的数据送入SBUF(接收数据缓冲器),第9位数据送入RB8,并将RI置1;若以上两个条件不满足,接收信息丢失。 若附加的第9位为奇偶校验位,在接收中断服务程序中应作检验。
串行通信的波特率 • 串行口的通信波特率恰到好处地反映了串行传输数据的速率。通信波特率的选用,不仅和所选通信设备、传输距离有关,还受传输线状况所制约。用户应根据实际需要加以正确选用。 1. 方式0下的波特率 在方式0下,串行口通信的波特率是固定的,其值为fosc/12(fosc为主机频率)。
串行通信的波特率 2. 方式2下的波特率 在方式2下,通信波特率为fosc/32或fosc/64。用户可以根据PCON中SMOD位的状态来驱使串行口在哪个波特率下工作。选定公式为: 这就是说,若SMOD=0,则所选波特率为fosc/64;若SMOD=1,则波特率为fosc/32。
串行通信的波特率 3. 方式1或方式3下的波特率 在这两种方式下,串行口波特率是由定时器的溢出率决定的,因而波特率也是可变的。相应公式为: 定时器T1溢出率的计算公式为: 式中,K为定时器T1的位数,它和定时器T1的设定方式有关。若定时器T1为方式0,则K=13;若定时器T1为方式1,则K=16;若定时器T1为方式2或3,则K=8。
串行通信的应用举例 • 例一:PC机发一个字符给单片机,单片机收到后即在个位、十位数码管上显示,同时将其回送给PC机,其中,单片机收PC发来的信号用串口中断方式,单片机发给PC机时则采用查询方式 • 源程序如下: • #include <REG51.H> • #define uchar unsigned char • #define uint unsigned int
串行通信的应用举例 • uchar code SEG7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; • uchar code ACT[4]={0xfe,0xfd,0xfb,0xf7}; • /*************************************************************/ • uchar code as[]=" Receving Data:\0"; • uchar a=0x30,b; • //**************************************************** • void init(void) • { • TMOD=0x20; • TH1=0xfd; • TL1=0xfd; • SCON=0x50; • TR1=1; • ES=1; • EA=1; • } • //**********************
串行通信的应用举例 • void delay(uint k) • { • uint data i,j; • for(i=0;i<k;i++) • { • for(j=0;j<121;j++){;} • } • } • void main(void) • { uchar i; • init();
串行通信的应用举例 • while(1) • { • P0=SEG7[(a-0x30)/10]; • P2=ACT[1]; • delay(1); • P0=SEG7[(a-0x30)%10]; • P2=ACT[0]; • delay(1); • if(RI) • { • RI=0;i=0; • while(as[i]!='\0'){SBUF=as[i];while(!TI);TI=0;i++;} • SBUF=b;while(!TI);TI=0; • EA=1; • } • } • } • //***************************************** • void serial_serve(void) interrupt 4 • { • a=SBUF; • b=a; • EA=0; • }
串行通信的应用举例 • 例二:PC机发控制指令给单片机,单片机收到后即控制D0-D7这8个发光二极管的亮、灭,同时收到的指令参数在个位、百位数码管上进行显示(数码管显示发光管的亮 、灭1代表亮,0代表灭 • 源程序如下: • #include <REG51.H> • #define uchar unsigned char • #define uint unsigned int • uchar code SEG7[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; • uchar code ACT[4]={0xfe,0xfd,0xfb,0xf7};
串行通信的应用举例 • sbit D0=P1^0; • sbit D1=P1^1; • sbit D2=P1^2; • sbit D3=P1^3; • sbit D4=P1^4; • sbit D5=P1^5; • sbit D6=P1^6; • sbit D7=P1^7; • #define ON 0 • #define OFF 1 • uchar a[2]; • uchar cnt; • bit outflag; • void delay(uint k) • { • uint data i,j; • for(i=0;i<k;i++) • { • for(j=0;j<121;j++){;} • } • } • void init(void) • { • TMOD=0x20; • TH1=0xfd; • TL1=0xfd; • SCON=0x50; • TR1=1; • ES=1; • EA=1; • }
串行通信的应用举例 • void main(void) • { • init(); • while(1) • { • P0=SEG7[a[0]];P2=ACT[2];delay(1); • P0=SEG7[a[1]];P2=ACT[0];delay(1); • if(outflag==1) • { • switch(a[0]) • { • case 1:if(a[1]==1)D0=ON;else D0=OFF;break; • case 2:if(a[1]==1)D1=ON;else D1=OFF;break; • case 3:if(a[1]==1)D2=ON;else D2=OFF;break; • case 4:if(a[1]==1)D3=ON;else D3=OFF;break; • case 5:if(a[1]==1)D4=ON;else D4=OFF;break; • case 6:if(a[1]==1)D5=ON;else D5=OFF;break; • case 7:if(a[1]==1)D6=ON;else D6=OFF;break; • case 8:if(a[1]==1)D7=ON;else D7=OFF;break; • default:break; • } • outflag=0; • } • } • }
串行通信的应用举例 • void serial_serve(void) interrupt 4 • { • uchar temp; • RI=0; • EA=0; • temp=SBUF; • switch(cnt) • { • case 0:if(temp=='#')cnt=1;else outflag=0;break; • case 1:if((temp>0x30)&&(temp<0x39)){a[0]=temp-0x30;cnt=2;}else outflag=0;break; • case 2:if(temp=='(')cnt=3;else outflag=0;break; • case 3:if((temp>=0x30)&&(temp<=0x38)){a[1]=temp-0x30;cnt=4;}else outflag=0;break; • case 4:if(temp==')'){cnt=0;outflag=1;}else outflag=0;break; • default:break; • } • EA=1; • }