资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,第,9,章 串行通信口,第一节 概述,第二节 模式0及其应用,第三节 模式1及其应用,第四节 模式2、3及其应用,1,MCU,中常用的几种串行接口标准,串行接口:数据一位接一位顺序传送,可只用一根数据线传送多位信息。,UART:,通用异步接收器/发送器,I,2,C:,二线,芯片有地址,有总线争用机制,2,典型的,I,2,C,总线系统,3,用口线模拟串行总线,4,#,include/,要用到,sfr,#define,uchar,unsigned char,sbit,NCS=P10;,sbit,SCK=P11;,sbit,SI =P12;,void,shiftbyte(uchar,byte);,main(),uchar,data*p=0 x30;,NCS=0;,shiftbyte(0 xa);/,由图中读出第一字节为0,xa0,shiftbyte(0 x23);/,低8位地址,shiftbyte,(*p);,NCS=1;,while(1);,5,void,shiftbyte(uchar,byte)/,将1字节数据由并变串由口线移出,uchar,i;,for(i=0;i8;i+),NCK=0;,SI=(bit)(byte/,强制将,char,转换成,bit,类型并赋值给口线,NCK=1;,byte8;while(!TI);TI=0;/*,再送高8位,等移完*/,STB=1;/*,同时并行输出*/,main(),SCON=0 x0;/*,串口模式:移位寄存器方式,*/,out16(0 x1234);/*,由扩展口送出0,x1234*/,while(1);/*main,循环结束*/,编程实现,25,例2 扩展1个16位并行输入口,把由扩展口读入的16位数存入一个整型变量中。,26,#,include,sbit,P_S=P10;,unsigned,int,in16(void);/*,声明函数*/,main(),unsigned,int,dat16;,SCON=0 x0;REN=1;/*,串口模式,允许接收,*/,dat16=in16();/*,由扩展口读入的数存入变量中,*/,while(1);/*main,循环结束*/,编程实现,27,unsigned,int,in16(void),unsigned,int,tmp,;,P_S=1;,P_S=0;/*,4014并行输入后立即进入串行移位状态*/,while(!RI);RI=0;/*,查询等高8位移完*/,tmp,=SBUF;,tmp,=8;/*,读入后送到临时变量的高8位*/,while(!RI);RI=0;/*,查询等低8位移完*/,tmp,+=SBUF;/*,合成16位数*/,return(,tmp,);/*,返回得到的16位数*/,编程实现(续,),28,第一节 概述,第二节 模式0及其应用,第四节 模式2、3及其应用,第三节 模式1及其应用,29,特点:10位传输格式(1个起始位+8个数据位+1个停止位);,波特率:可变波特率,由定时器,T1,的溢出率来确定,所以在此种模式下,首先要对,T1,进行初始化以确定串行口的波特率。,30,模式1帧格式,31,模式1原理示意图(发送部分),32,由写,SBUF,启动,在8位数据后加上一个停止位。,开始发送,但,DATA,无效,送出一个起始位,当零检测器全0,再作最后一次移位,并置,TI,发送过程,33,发送时序,34,再做最后一次移位同时,TI,置1,发送1帧完成。,零检测器变化过程,35,模式1原理示意图(接收部分),36,在,REN=1,的条件下进行。串行口的接收控制器对,RXD,线进行采样,其采样频率是接收波特率的16倍。当检测到,RXD,上有负跳变后,复位16分频计数器,当计数器计到第7、8、9时,分别对,RXD,进行采样,若有2个以上的0,则认为检测到起始位并开始接收过程,此后每一位的判决都按照这种“3取2”的原则进行。,装载接收移位寄存器的数据进入,SBUF,中就完成了一帧的接收过程,但必须满足两个条件,否则数据丢失:,RI=0,,表示前面接收的数据已经被取走。,SM2=0,或第9位为1。(对于模式1,第9位是停止位),接收过程,37,接收时序,38,移位寄存器变化过程,再作最后一次移位,并装入,SBUF,同时置位,RI,,接收1帧完成。,39,波特率(,Baud Rate),计算(适用于模式1、3),在串行口的异步通讯中,发送方与接收方是两个互相独立的系统,它们的系统时钟可以各不相同。在这种条件下使通讯正确的条件是:1,要有相同的帧格式;2,要有相同或相近的波特率(4%)。,模式1、3的波特率是由定时器,T1,的溢出率来决定的(另外,PCON,中的,SMOD,位起着波特率加倍的作用)。,在编制串行口通讯(模式1、3)程序时,须对,T1,进行初始化。,40,波特率(,Baud Rate),计算(适用于模式1、3),T1,初始化的主要任务就是:,设置,T1,工作在模式2,定时。8位自重装定时器。,根据晶振频率和需要的波特率,计算重装载值,分别送给,TH1、TL1。,波特率计算公式:,BR=,T1,溢出率 =(计数速率)/,256-(,TH1),=(Fosc/12)/,256-(TH1),41,BR=,32*12*256 (TH1),2,SMOD,*,Fosc,因此得到,更多情况下,已知,Fosc,和,BR,,要计算,TH1,的重装载值,(TH1)=256-,32*12*BR,2,SMOD,*,Fosc,42,【,举例,】,设系统时钟为11.0592,MHz,,要求波特率为1200,,,求,TH1,的重装载值。,【,解,】,选,SMOD=0,,用上述公式,(TH1)=256-,32*12*1200,11059200,=232=0,E8H,因此得到,TH1,的重装载值为0,E8H。,43,注意如果晶体频率是其它值,得到的装载值4舍5入,与标准波特率有一定误差,但一般只要误差不大仍能够正常通信。,【,举例,】,设系统时钟为12,MHz,,要求波特率为1200,,,求,TH1,的重装载值。,【,解,】,选,SMOD=0,,用上述公式,(TH1)=256-,32*12*1200,12000000,=229.95=230=0,E6H,因此得到,TH1,的重装载值为0,E6H,,实际波特率为:,计算波特率的例子,BR=,32*12*256 230,12000000,=1201.9,44,常用波特率与晶体和,T1,设置对照表,45,例1,发送字符串“,Hello World!n”,至串口,要求波特率为1200,采用串口模式1,最高位约定做奇校验位,已知,Fosc,=11.0592MHz。,46,分析:奇偶校验,由于传输的是,ASCII,字符(0-7,FH),,只需要7位,对于模式1有8个数据位,将最高位做奇校验位,保证形成的8位中1的个数始终是奇数个;接收方收到每一个字节后进行奇偶判断,若为奇则认为无误,若为偶则表示出错,这种方法可以检测出奇数个误码。,例如,若要发送0,x00,,加奇校验位后变成0,x80;,若要发送0,x01,,加奇校验位后仍为0,x01。,接收方判断无错后去掉最高位,还原需要的数据。,47,回忆,PSW:,程序状态字,存放指令执行后的有关状态,P,:,(PSW.0),奇偶标志位,,用来标志累加器,ACC,中1的个数,可以用在串行通信中作奇偶校验判断。当,P=1,时,表明,A,中1的个数为奇数个,反之为偶数个。,ACC=0 x0;/*P=0*/,ACC=0 x80;/*P=1*/,48,分析:波特率,要求波特率为1200,采用串口模式1,已知,Fosc,=11.0592MHz。,由上述条件计算或查表得到,T1,的重装载值为0,E8H,49,#,include,sbit,parity=ACC7;/*,定义,ACC.7,作奇校验位*/,unsigned char tx_string14=“Hello World!n”;,/*,定义待发送字符串,也可以加,code,存储类型,如:,unsigned char code tx_string14=“Hello World!n”,*/,编程实现,50,main(),unsigned char i;/*,定义1个循环变量*/,/*,首先定义,T1,模式2 作波特率发生器,波特率为1200并启动运行*/,TMOD=0 x20;TH1=0 xE8;TL1=0 xE8;TR1=1;,SCON=0 x40;/*,串口模式1,未允许接收,*/,for(i=0;i14;i+),/*循环发送14个字符*/,ACC=,tx_stringi,;/*,取一个字符*/,parity=P;/*,获取当前的奇偶特性*/,parity=!parity;/*,一律改成奇校验,此时,P=,1*/,SBUF=ACC;/*,开始发送*/,while(!TI);TI=0;/*,等这1个字节发完才能发下1字节*/,/end of for,while(1);/*,循环结束*/,/end of main,编程实现(续),51,例2,串口不断接收发来的字符串,已知字符串长度为14字节,若14字节均无错则使接在,P1.0,引脚上的绿色,LED,闪烁3次后点亮,若有错则使接在,P1.1,引脚上的红色,LED,闪烁3次后点亮,要求波特率为1200,采用串口模式1,最高位约定做奇校验位,已知,Fosc,=11.0592MHz。,52,用2个,LED,表示状态,53,#,include,sbit,RED_LED=P11;/*,红灯*/,sbit,GREEN_LED=P10;/*,绿灯*/,unsigned char rx_string14;/*,接收缓冲区*/,bit receive_string(void);/*,声明接收14字节字符串函数*/,flash_RED_LED_3();/*,声明红灯闪烁3次函数*/,flash_GREEN_LED_3();/*,声明绿灯闪烁3次函数*/,编程实现,54,main(),/*,首先定义,T1,模式2 作波特率发生器,波特率为1200并启动运行*/,TMOD=0 x21;TH1=0 xE8;TL1=0 xE8;TR1=1;,SCON=0 x50;/*,串口模式1,允许接收,*/,for(;),if(receive_string()/,函数返回,bit,GREEN_LED=1;/,有错绿灯灭,flash_RED_LED_3();/,红灯闪烁3次,RED_LED=0;/,以后一直亮,else RED_LED=1;flash_GREEN_LED_3();GREEN_LED=0;,/end of for(;),/end of main,编程实现,55,bit receive_string(void),bit error_bit=0;/1:,有错,0:没错,unsigned char i;,for(i=0;i14;i+),while(RI=0);RI=0;/,查询接收,等收到1字节,ACC=SBUF;/,读入,ACC,便于判断,P,if(!P)error_bit=1;/,偶校验错,置标志后继续,else ACC/,未出错则去掉校验位,rx_stringi=ACC;/,存入缓冲区,return error_bit;/,返回出错标志,编程实现(续1),56,flash_RED_LED_3()/*,红灯闪烁3次函数*/,unsigned char i,j;/*,定义循环变量*/,TMOD=0 x21;TR0=1;/*T0,模式1,运行*/,for(i=0;i6;i+)/*,闪烁3次*/,for(j=0;j5;j+)/*5*50ms=0.25s*/,TH0=0 x3C;TL0=0 xB0;while(!TF0);TF0=0;,RED_LED=!RED_LED;/*,每隔0.25秒亮暗交替变化*/,TR0=0;/*,关掉定时器*/,编程实现(续2),57,flash_GREEN_LED_3()/*,绿灯闪烁3次函数*/,unsigned char i,j;/*,定义循环变量*/,TMOD=0 x21;TR0=1;/*T0,模式1,运行*/,for(i=0;i6;i+)/*,闪烁3次*/,for(j=0;j5;j+)/*5*50ms=0.25s*/,TH0=0 x3C;TL0=0 xB0;while(!TF0);TF0=0;,GREEN_LED=!GREEN_LED;/*,每隔0.25秒亮暗交替变化*/,TR0=0;/*,关掉定时器*/,编程实现(续3),58,例3,设串口每次收到上位机传来的命令55,H,,便将内部,RAM,中30,H,至3,FH,的数据发送出去,若不是55,H,便不做任何响应。要求波特率为19200,不用校验,已知,Fosc,=11.0592MHz。,59,分析,这是典型的受上位机控制的通信过程。下位机平时可以一直查询等上位机命令;也可以用中断方式响应,提高效率,采取“中断进入,查询收发”的策略,没有通信命令的时候不予理会,有通信需要的时候集中处理,而不是每个字节都采用中断方式。,60,#,include,main(),unsigned char data*p,i;,TMOD=0 x20;TH1=0 xFD;TL1=0 xFD;PCON=0 x80;TR1=1;,/T1,模式2 作波特率发生器,,SMOD=1,波特率为19200并启动运行,SCON=0 x50;/*,串口模式1,允许接收,*/,for(;),while(!RI);RI=0;,if(SBUF!=0 x55)continue;,p=0 x30;,for(i=0;i16;i+)/,查询发送30,H,开始的16字节,SBUF=*p+;while(!TI);TI=0;,编程实现(查询方式),61,#,include,main(),unsigned char data*p,i;,TMOD=0 x20;TH1=0 xFD;TL1=0 xFD;PCON=0 x80;TR1=1;,/T1,模式2 作波特率发生器,,SMOD=1,波特率为19200并启动运行,SCON=0 x50;/*,串口模式1,允许接收,*/,ES=1;EA=1;/*,允许串口中断*/,for(;);/*,循环结束,等中断*/,编程实现(中断进入、查询收发),62,void serial(void)interrupt 4,unsigned char data*p,i;,if(TI)TI=0;return;/,一般要判断是,TI,或,RI,为1,此时多余,RI=0;if(SBUF!=0 x55)return;/,不是55,H,返回,p=0 x30;,for(i=0;i16;i+)/,查询发送30,H,开始的16字节,SBUF=*p+;while(!TI);TI=0;,编程实现(中断进入、查询收发)续,63,第一节 概述,第二节 模式0及其应用,第三节 模式1及其应用,第四节 模式2、3及其应用,64,特点:模式2和,3,都是,11位传输格式,(,1个起始位+9个数据位+1个停止位),两种模式唯一不同之处是波特率;,模式2:固定为,Fosc/64,或,Fosc/32(,由,PCON,中的,SMOD,位来决定)。,SMOD=1,Fosc/32;SMOD=0,Fosc/64.,模式3:与模式1一样由定时器,T1,的溢出率来确定。,使用模式2不需要用定时器作为波特率发生器,节省一个定时器;但是波特率固定,且比较高,如果满足通信需求就可以选择这种模式。当,Fosc,=12MHz,时,波特率分别是375000和187500。,第9数据位(,TB8/RB8,),可以作为奇偶校验位,也可以用于多机通信控制,若不用校验,更多时候用模式1。,模式2、3特点,65,模式2、3帧格式,66,发送时:将,SCON,中的,TB8,作为第9位数据发送,,TB8,可编程为0或1;发送,SBUF+TB8,构成9位数据,,接收时:将接收来的第9位送到,SCON,中的,RB8,中:接收,SBUF+TB8,构成9位数据。,TB8,和,RB8,67,模式2、3的发送过程与模式1类似,主要的区别在于帧中数据是9位。这样,在发送一帧时,,CPU,除了要把8位数据送,SBUF,外,还要把第9位数据送到,TB8,中,但注意要先设定好,TB8,,然后再向,SBUF,送数,因为一写,SBUF,就开始发送。停止位单独生成,加在,TB8,之后。,模式2、3的接收过程与模式1完全相同,只不过模式1时,,SCON,中的,RB8,是接收到的停止位(“1”);而模式2、3时,,RB8,是接收到的第9位(发送方的,TB8)。,发送和接收过程,68,例4,设串口每隔1秒钟便将片内,RAM,中50,H,至5,FH,中的数据串行发送,串行口设定为模式2,,TB8,作偶校验位,已知,Fosc,=12MHz。,69,分析,将要发送的8位数据送入,ACC;,由奇偶标志,P,即可判断这8位中1的个数:,P=1,奇;,P=0,偶。,如果让,TB8=P,则9位数据中1的个数总是偶数个,这样就实现了偶校验。,TB8,作偶校验位:,TB8,作偶校验位:,串行口设定为模式2,无需用,T1,作波特率发生器;,70,分析,1,s=50ms*20,T0,模式1,,重装载值,TC=65536 50ms/1us=15536=3CB0H,71,#,include,void send16(void),unsigned char data*p,i;/*,定义指针及循环变量*/,p=0 x50;/*,指向内部,RAM 50H,单元*/,for(i=0;i16;i+),/*循环发送16个字节*/,ACC=*p+;/*,取一个字节*/,TB8=P;/*,加偶校验*/,SBUF=ACC;/*,开始发送*/,while(!TI);TI=0;/*,等这1个字节发完才能发下1字节*/,编程实现,72,main(),SCON=0 x80;/*,串口模式2,未允许接收,*/,PCON=0 x80;/*,波特率为,Fosc/32*/,TMOD=1;TR1=1;/*T0,模式1定时*/,while(1),for(i=0;i20;i+),TH0=0 x3C;TL0=0 xB0;while(!TF0);TF0=0;/*,等1秒钟*/,send16();/*,调用发送16字节函数*/,/end of main,编程实现(续),73,例5,接收上例中的数据,存入一个接收缓冲区,并进行出错判断。,74,#,include,unsigned char rx_string16;/*,接收缓冲区*/,bit receive_string(void);/*,声明接收16字节字节函数*/,编程实现,75,#,include,unsigned char rx_string16;/*,接收缓冲区*/,bit receive_string(void);/*,声明接收16字节字节函数*/,main(),SCON=0 x90;/*,串口模式2,允许接收,*/,PCON=0 x80;/*BR=Fosc/32*/,for(;),if(receive16()error();/,返回1,错,函数省略,else right();/,返回0,对,,,函数省略,编程实现,76,bit receive16(void),bit error_bit=0;/1:,有错,0:没错,unsigned char i;,for(i=0;i16;i+),while(RI=0);RI=0;/,查询接收,等收到1字节,ACC=SBUF;/,读入,ACC,便于判断,P,rx_stringi=ACC;/,存入缓冲区,if(P),if(!RB8)error_bit=1;/P=1,RB8=0,偶校验错,else,if(RB8)error_bit=1;/P=0,RB8=1,偶校验错,return error_bit;/,返回出错标志,编程实现(续),77,例6 模式3应用,串口将接收到的每一个正确数据存入外部,RAM 2000H,开始的单元中,并判断是否有校验错,同时记录正确接收的字节数和出错次数。用模式3,波特率为2400,,RB8,作为奇校验,已知,Fosc,=11.0592MHz,78,分析,由模式3,波特率为2400,已知,Fosc,=11.0592MHz:,可以得到,TH1,的重装载值为0,F4H;,奇校验:奇偶标志,P,和,RB8,不能同时为0或为1;,分别定义2个变量,初值为0,记录正确接收的字节数和出错次数;,用中断方式。,79,#,include,unsigned char,xdata,*,px,=0 x2000;/*,定义指针指向2000,H*/,unsigned,int,err_cnt,=0,ok_cnt,=0;/*,定义2个变量,初值为0,记录正确接收的字节数和出错次数*/,main(),SCON=0 xD0;/*,串口模式3,允许接收,*/,TMOD=0 x20;TH1=0 xF4;TL1=0 xF4;TR1=1;/,波特率为2400,ES=1;EA=1;/*,允许串口中断*/,while(1);/*,等待中断*/,/end of main,编程实现,80,编程实现(续),void receive(void)interrupt 4/,中断服务程序,RI=0;,ACC=SBUF;,if(P),if(RB8),err_cnt,+;return;/P=1,RB8=1,奇校验错,else,if(!RB8),err_cnt,+;return;/P=0,RB8=0,奇校验错,*,px,+=ACC;/,正确存起来,ok_cnt,+;/,字节数加1,81,作业,P202203:3,、,6,、,9,1、设串口每次收到上位机发来的16字节数据后,存入一个接收缓冲区,然后将内部,RAM,中40,H,开始的16字节数据由串口发送出去,用串口模式1,波特率为9600,无校验,已知,Fosc,=11.0592MHz。,82,
展开阅读全文