51单片机串口通信协议(51单片机的通信协议)

      最后更新:2023-04-16 03:41:47 手机定位技术交流文章

      51单片机串口通信

      ////////////////////////////////////////////////////////////////////////////////////////////////// //E51Pro.c//Easy 51Pro编程器主程序,负责通讯,管理编程操作///////////////////////////////////////////////////////////////////////////////////////////////////#include BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用UINT nAddress;//ROM中地址计数UINT nTimeOut;//超时计数ProWork pw;//编程器一般操作void Delay_us(BYTE nUs)//微秒级延时<255us{TH0=0;TL0=0;TR0=1;while(TL010000)//后17个字节都有超时限制return 0;}ComBuf[n]=SBUF;RI=0;}return 1;}BOOL WaitResp()//等待上位机回应,1字节,有超时限制{nTimeOut=0;RI=0;while(!RI){nTimeOut++;if(nTimeOut>50000){return 0;}}RI=0;ComBuf[0]=SBUF;return 1;}BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制{BYTE n;RI=0;for(n=0;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000){return 0;}}RI=0;ComBuf[n]=SBUF;}return 1;}void SendData()//发送数据或回应操作完成,18字节{BYTE n=0;for(n;n<=17;n++){TI=0;SBUF=ComBuf[n];while(!TI){}TI=0;}}void SendResp()//回应上位机1个字节,在写器件函数中使用{TI=0;SBUF=ComBuf[0];while(!TI){}TI=0;}void SetVpp5V()//设置Vpp为5v{P3_4=0;P3_3=0;}void SetVpp0V()//设置Vpp为0v{P3_3=0;P3_4=1;}void SetVpp12V()//设置Vpp为12v{P3_4=0;P3_3=1;}void RstPro()//编程器复位{pw.fpProOver();//直接编程结束SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同}void ReadSign()//读特征字{pw.fpReadSign();SendData();//通知上位机,送出读出器件特征字}void Erase()//擦除器件{pw.fpErase();SendData();//通知上位机,擦除了器件}void Write()//写器件{BYTE n;pw.fpInitPro();//编程前的准备工作SendData();//回应上位机表示进入写器件状态,可以发来数据while(1){if(WaitData())//如果等待数据成功{if(ComBuf[0]==0x07)//判断是否继续写{for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块{if(!pw.fpWrite(ComBuf[n]))//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数{pw.fpProOver();//出错了就结束编程ComBuf[0]=0xff;SendResp();//回应上位机一个字节,表示写数据出错了WaitData();//等待上位机的回应后就结束return;}nAddress++;//下一个单元}ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续SendResp();}else if(ComBuf[0]==0x00)//写器件结束break;else//可能是通讯出错了{pw.fpProOver();return;}}else//等待数据失败{pw.fpProOver();return;}}pw.fpProOver();//编程结束后的工作Delay_ms(50);//延时等待上位机写线程结束ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Read()//读器件{BYTE n;pw.fpInitPro();//先设置成编程状态SendData();//回应上位机表示进入读状态while(1){if(WaitResp())//等待上位机回应1个字节{if(ComBuf[0]==0)//ComBuf[0]==0表示读结束{break;}else if(ComBuf[0]==0xff)//0xff表示重发{nAddress=nAddress-0x0010;}for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块{ComBuf[n]=pw.fpRead();//<<<<<<<<<<<<<<<<<<<调用写该器件一个单元的函数nAddress++;//下一个单元}ComBuf[0]=6;//向上位机发送读出的数据块SendData();}elsebreak;//等待回应失败}pw.fpProOver();//操作结束设置为运行状态ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Lock()//写锁定位{pw.fpLock();SendData();}/////////////////////////////////////////////////////////////////////////////////////////////////////所支持的FID,请在这里继续添加///////////////////////////////////////////////////////////////////////////////////////////////////extern void PreparePro00();//FID=00:AT89C51编程器extern void PreparePro01();//FID=01:AT89C2051编程器extern void PreparePro02();//FID=02:AT89S51编程器void main(){SP=0x60;SetVpp5V();//先初始化Vpp为5vSCON=0x00;TCON=0x00;//PCON=0x00;//波特率*2IE=0x00;//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0//00 10 00 01TMOD=0x21;//T0用于延时程序TH1=0xff;TL1=0xff;//波特率28800*2,注意PCON//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI//0 1 0 1 0 000SCON=0x50;TR1=1;Delay_ms(1000);//延时1秒后编程器自举ComBuf[0]=0;SendData();while(1)//串口通讯采用查询方式{if(!WaitComm())//如果超时,通讯出错{Delay_ms(500);ComBuf[0]=0;//让编程器复位,使编程器就绪}switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针{case 0://at89c51编程器PreparePro00();break;case 1://at89c2051编程器PreparePro01();break;case 2://at89s51编程器PreparePro02();break;//case 3:支持新器件时,请继续向下添加// break;//case 4:// break;default:ComBuf[0]=0xff;ComBuf[1]=0xff;//表示无效的操作break;}switch(ComBuf[0])//根据操作ID跳到不同的操作函数{case 0x00:RstPro();//编程器复位break;case 0x01:ReadSign();//读特征字break;case 0x02:Erase();//擦除器件break;case 0x03:Write();//写器件break;case 0x04:Read();//读器件break;case 0x05:Lock();//写锁定位break;default:SendData();break;}} }
      // 单片机串行口发送/接收程序,每接收到字节即发送出去 // 和微机相接后键入的字符回显示在屏幕上// 可用此程序测试//#include #define XTAL 11059200// CUP 晶振频率#define baudrate 9600// 通信波特率void main(void){unsigned char c;TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));// 定时器0赋初值SCON = 0x50;PCON = 0x00;TR1 = 1;IE = 0x00;// 禁止任何中断while(1){while(RI == 0);RI = 0;c = SBUF;// 从缓冲区中把接收的字符放入c中SBUF = c;// 要发送的字符放入缓冲区while(TI == 0);TI = 0;} }
      void InitSerial(void) {TMOD = 0x20; // T1 方式2PCON=0x00;// PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式TH1 = TL1 = BAUD_9600;// BAUD: 9600SCON = 0x50; // 串行通信方式1 REN=1 允许接收ET1 = 0;// 不允许中断TR1 = 1;// 开启定时器1IE = 0; // 关闭所有中断允许位memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN]}/**********************************************************名称:SendByte()**功能:串口发送一个字节**输入:ucData**返回:无**说明:无********************************************************/void SendByte(unsigned char ucData){SBUF = ucData;while(!TI){_CLRWDT_;}TI = 0; }
      #include #include unsigned char ch;bit read_flag= 0 ;void init_serialcom( void ) //串口通信初始设定{SCON = 0x50 ; //UART为模式1,8位数据,允许接收TMOD |= 0x20 ; //定时器1为模式2,8位自动重装PCON |= 0x80 ; //SMOD=1;TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHzIE |= 0x90 ; //Enable Serial InterruptTR1 = 1 ; // timer 1 runTI=1;}//向串口发送一个字符void send_char_com( unsigned char ch){SBUF=ch;while (TI== 0);TI= 0 ;}//串口接收中断函数void serial () interrupt 4 using 3{if (RI){RI = 0 ;ch=SBUF;read_flag= 1 ; //就置位取数标志}}main(){init_serialcom(); //初始化串口while ( 1 ){if (read_flag) //如果取数标志已置位,就将读到的数从串口发出{read_flag= 0 ; //取数标志清0send_char_com(ch);}} }
      51单片机串口通信

      51单片机通过串口实现数据的发送与接收程序

      串口收发,要有通信协议。也就是什么时候开始接收,接收到指令后,转发什么数据。这个要知道,才可以写。而且使用不同的51单片机,其内部寄存器配置是不同的。 一般来说,过程如下:1,配置串口参数、波特率等,开启串口中断;void Init_UART(){}2,中断函数里写中断响应函数,根据接收的指令或者数据,执行相应的动作;程序一般为:void UART_ISR()interruptx using y{;串口中断处理函数}x- 单片机的C51中断号y - 指定使用的当前工作寄存器组号(0-3PSW中的RS0,RS1组合)3,主程序int main(void){Init_UART();while(1){;//数据发送函数} }
      51单片机通过串口实现数据的发送与接收程序

      51单片机串口通讯

      51单片机串口通信 来源:维库 作者:关键字:51单片机 串口通信这节我们主要讲单片机上串口的工作原理和如何通过程序来对串口进行设置,以及根据所给出的实例实现与PC 机通信。一、原理简介51 单片机内部有一个全双工串行接口。什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。其缺点是传输速度较低。与之前一样,首先我们来了解单片机串口相关的寄存器。SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。串行口控制寄存器SCON(见表1) 。表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。SM2 :多机通信控制位。 该仅用于方式2 和方式3 的多机通信。其中发送机SM2 = 1(需要程序控制设置)。接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。工作于方式0 时,SM2 必须为0。REN :串行接收允许位:REN =0 时,禁止接收;REN =1 时,允许接收。TB8 :在方式2、3 中,TB8 是发送机要发送的第9 位数据。在多机通信中它代表传输的地址或数据,TB8=0 为数据,TB8=1 时为地址。RB8 :在方式2、3 中,RB8 是接收机接收到的第9 位数据,该数据正好来自发送机的TB8,从而识别接收到的数据特征。TI :串行口发送中断请求标志。当CPU 发送完一串行数据后,此时SBUF 寄存器为空,硬件使TI 置1,请求中断。CPU 响应中断后,由软件对TI 清零。RI :串行口接收中断请求标志。当串行口接收完一帧串行数据时,此时SBUF 寄存器为满,硬件使RI 置1,请求中断。CPU 响应中断后,用软件对RI 清零。电源控制寄存器PCON(见表3) 。表3 PCON寄存器表中各位(从左至右为从高位到低位)含义如下。SMOD :波特率加倍位。SMOD=1,当串行口工作于方式1、2、3 时,波特率加倍。SMOD=0,波特率不变。GF1、GF0 :通用标志位。PD(PCON.1) :掉电方式位。当PD=1 时,进入掉电方式。IDL(PCON.0) :待机方式位。当IDL=1 时,进入待机方式。另外与串行口相关的寄存器有前面文章叙述的定时器相关寄存器和中断寄存器。定时器寄存器用来设定波特率。中断允许寄存器IE 中的ES 位也用来作为串行I/O 中断允许位。当ES = 1,允许 串行I/O 中断;当ES = 0,禁止串行I/O 中断。中断优先级寄存器IP的PS 位则用作串行I/O 中断优先级控制位。当PS=1,设定为高优先级;当PS =0,设定为低优先级。波特率计算:在了解了串行口相关的寄存器之后,我们可得出其通信波特率的一些结论:① 方式0 和方式2 的波特率是固定的。在方式0 中, 波特率为时钟频率的1/12, 即fOSC/12,固定不变。在方式2 中,波特率取决于PCON 中的SMOD 值,即波特率为:当SMOD=0 时,波特率为fosc/64 ;当SMOD=1 时,波特率为fosc/32。② 方式1 和方式3 的波特率可变,由定时器1 的溢出率决定。当定时器T1 用作波特率发生器时,通常选用定时初值自动重装的工作方式2( 注意:不要把定时器的工作方式与串行口的工作方式搞混淆了)。其计数结构为8 位,假定计数初值为Count,单片机的机器周期为T,则定时时间为(256 ?Count)×T 。从而在1s内发生溢出的次数(即溢出率)可由公式(1)所示:从而波特率的计算公式由公式(2)所示:在实际应用时,通常是先确定波特率,后根据波特率求T1 定时初值,因此式(2)又可写为:51单片机串口通讯二、电路详解下面就对图1 所示电路进行详细说明。图1 串行通信实验电路图最小系统部分(时钟电路、复位电路等)第一讲已经讲过,在此不再叙述。我们重点来了解下与计算机通信的RS-232 接口电路。可以看到,在电路图中,有TXD 和RXD 两个接收和发送指示状态灯,此外用了一个叫MAX3232 的芯片,那它是用来实现什么的呢?首先我们要知道计算机上的串口是具有RS-232 标准的串行接口,而RS-232 的标准中定义了其电气特性:高电平“1”信号电压的范围为-15V~-3V,低电平“0”信号电压的范围为+3V~+15V。可能有些读者会问,它为什么要以这样的电气特性呢?这是因为高低电平用相反的电压表示,至少有6V 的压差,非常好的提高了数据传输的可靠性。由于单片机的管脚电平为TTL,单片机与RS-232 标准的串行口进行通信时,首先要解决的便是电平转换的问题。一般来说,可以选择一些专业的集成电路芯片,如图中的MAX3232。MAX3232 芯片内部集成了电压倍增电路,单电源供电即可完成电平转换,而且工作电压宽,3V~5.5V 间均能正常工作。其典型应用如图中所示,其外围所接的电容对传输速率有影响,在试验套件中采用的是0.1μF。值得一提的是MAX3232 芯片拥有两对电平转换线路,图中只用了一路,因此浪费了另一路,在一些场合可以将两路并联以获得较强的驱动抗干扰能力。此外,我们有必要了解图中与计算机相连的DB-9 型RS-232的引脚结构(见图2)。图2 DB-9连接器接口图其各管脚定义如下(见表4)。表4 DB-9型接口管脚定义三、程序设计本讲设计实例程序如下:#include "AT89X52.h" (1)void Init_Com(void) ( 2){TMOD = 0x20; ( 3)PCON = 0x00; ( 4)SCON = 0x50; ( 5)TH1 = 0xE8; ( 6)TL1 = 0xE8; ( 7)TR1 = 1; ( 8)}void main(void) ( 9){unsigned char dat; ( 10)Init_Com(); ( 11)while(1) ( 12)程序详细说明:(1)头文件包含。(2)声明串口初始化程序。(3)设置定时器1 工作在模式2,自动装载初值(详见第二讲)。(4)SMOD 位清0,波特率不加倍。(5)串行口工作在方式1,并允许接收。(6)定时器1 高8 位赋初值。波特率为1200b/s(7)定时器1 低8 位赋初值。(8)启动定时器。(9)主函数。(10)定义一个字符型变量。(11)初始化串口。(12)死循环。(13)如果接收到数据。(14)将接收到的数据赋给之前定义的变量。(15)将接收到的值输出到P0 口。(16)对接收标志位清0,准备再次接收。(17)将接收到的数据又发送出去。(18)查询是否发送完毕。(19)对发送标志位清0。四、调试要点与实验现象接好硬件,通过冷启动方式将程序所生成的。hex文件下载到单片机运行后,打开串口调试助手软件,设置好波特率1200,复位单片机,然后在通过串口调试助手往单片机发送数据(见图3),可以观察到在接收窗口有发送的数据显示,此外电路板上的串行通信指示灯也会闪烁,P0 口所接到LED 灯会闪烁所接收到的数据。图3 串口软件调试界面另外串口调试助手软件使用时应注意的是,如果单片机开发板采用串口下载而且和串口调试助手是使用同一串口,则在打开串口软件的同时不能给单片机下载程序,如需要下载,请首先点击“关闭串口”,做发送实验的时候,注意如果选中16 进制发送的就是数字或者字母的16 进制数值,比如发送“0”,实际接收的就应该是0x00,如果不选中,默认发送的是ASCII 码值,此时发送“0”,实际接收的就应该是0x30,这点可以通过观察板子P0 口上的对应的LED 指示出来。五、总结 本讲介绍了单片机串口通信的原理并给出了实例,通过该讲,读者可以了解和掌握51 单片机串口通信的原理与应用流程,利用串口通信,单片机可以与计算机相连,也可以单片机互联或者多个单片机相互通信组网等,在实际的工程应用中非常广泛。从学习的角度来说,熟练的利用串口将单片机系统中的相关信息显示在计算机上可以很直观方便的进行调试和开发。
      请看程序:的确是全双工的,发送和接收可以同时进行,区别只是程序不一样 #include#include "intrins.h"typedef unsigned char BYTE; //使用typedef为现有类型创建别名,定义易于记忆的类型名typedef unsigned int WORD;#define FOSC 18432000L#define BAUD 9600#define NONE_PARITY 0#define ODD_PARITY 1#define EVEN_PARITY 2#define MARK_PARITY 3#define SPACE_PARITY 4#define PARITYBIT EVEN_PARITYsbit bit9=P2^2;bit busy;void SendData(BYTE dat);void SendString(char *s);void main(){#if(PARITYBIT==NONE_PARITY)SCON=0x50;#elif(PARITYBIT==ODD_PARITY)||(PARITYBIT==EVEN_PARITY)||(PARITYBIT==MARK_PARITY)SCON=0x50;#elif(PARITYBIT==SPACE_PARITY)SCON=0x50;#endifTMOD=0x20;TH1=TL1=-(FOSC/12/32/BAUD);TR1=1;ES=1;EA=1;SendString("STC89-90xxrnUart Test!rn");while(1);}void Uart_Isr()interrupt 4 using 1{if(RI){RI=0;P0=SBUF;bit9=RB8;}if(TI){TI=0;busy=0;}}void SendData(BYTE dat){while(busy);ACC=dat;if(P){#if(PARITYBIT==ODD_PARITY)TB8=0;#elif(PARITYBIT==EVEN_PARITY)TB8=1;#endif}else{#if(PARITYBIT==ODD_PARITY)TB8=1;#elif(PARITYBIT==EVEN_PARITY)TB8=0;#endif}busy=1;SBUF=ACC;}void SendString(char *s){while(*s){SendData(*s++);} }
      51单片机串口通讯

      单片机串口通信是否必须要建立通信协议?单片机之间通信是否也必须建立通信协议?

      单片机进行串口通信,需要设置波特率和一些电气参数(一般定义1BIT起始位,8BIT数据位,1BIT停止位,无奇偶校验位)这些就属于通信协议的范畴。再则,单片机接收的数据,需要进行处理,所以你必须要知道接收的数据代表的意义,这也是通信协议,只是不太严格的通信协议。而比较严格的通信协议则一般会定义起始字节,数据字节,校验字节,结束字节等等,这点对单片机来说到不是必须的,你只要知道接收到相应的数据,能够进行处理就好了。
      51单片机的话可以通过外接一个max232与电脑通信通信的协议都是硬件弄好了的,用户只需要用就行了;如果是51单片机之间的通讯可以直接把两块单片机的RXD和TXD交叉连接就可以 但是这样的传输距离比较近而且容易受到干扰,想要远距离传输还是需要用到232或者是422、485传输协议。说明:232的软件协议是单片机内部固化好的,硬件协议需要用到232芯片。
      不要协议收到的是一系列的数据流。但你对数据流的处理,必须有最简单的定义,如数据流的起始字节,数据流的长度,数据流的CRC检验。这就是协议。 如果两个单片机之间的通信内容能用一个字节来表达清楚,则不需要任何协议;就相当于两个单片机之间定义了255种状态而忆。 谢谢!
      双方必须约定:波特率、位数、奇偶校验的方式。 这些是最基本的串口通信协议。
      那是必须的,没有协议怎么知道收到的数是什么意思?
      单片机串口通信是否必须要建立通信协议?单片机之间通信是否也必须建立通信协议?

      51单片机接收上位机发送的多个字节的串口通信

      具体程序可以参考楼下的例程 串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配:a,波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。 如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
      //试试以下程序 #include#define uchar unsigned charuchar i,j;unchar RX_BUF[10],TxBuf[10];void Inituart(){IE=0x90;//打开中断总开关及串口中断开关SCON = 0x50;//设定串行口工作方式1 允许接受TMOD = 0x20;//定时器1,自动重载, 产生波特率//PCON=0x80;// 加上他后波特率是19200SMOD为1TL1 = 0xfa;TH1 = 0xfa; //波特率为9600 ,22.1184MHzTR1 = 1;}/**************************接收上位机传送数据***************************************/void uart_js() interrupt 4//RI==1时执行串口中断{if(RI==1){RX_BUF[i]=SBUF; //保存数据RI=0;i++;}if(TI)TI=0;if(i==10){i=0;RXend = 1;LED0=0;//LED长亮}}void main(){Inituart();i=j=0;while(1){while(RXend==0);//waiting receive endRXend=0;for(j=0;j<10;j++){TxBuf[j] =RX_BUF[j];//将需发送数据存入无线发送缓冲区}} }
      #define FOSC 110592 //晶振频率 #define Baud 96//波特率void IE_INIT() //初始化串口{//IPH=PSH; //串口中断优先级控制PCON &= 0x7f; //波特率不倍速//PCON |= 0X80; //波特率倍速SCON= 0x50; //8位数据,可变波特率/*使用定时器1作为波特率发生器并赋值 */TMOD &= 0x0f; //清除定时器1模式位TMOD |= 0x20; //设定定时器1为8位自动重装方式TL1=TH1=256-(FOSC/Baud/32/12);//设定定时初值 设定定时器重装值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1/*使用定时器2作为波特率发生器并赋值 *///TL2=RCAP2L=(65535-FOSC/(32*Baud)); //设定定时初值//TH2=RCAP2H=(65535-FOSC/(32*Baud))>>8;//设定定时器重装值// RCLK=1; //接收时钟标志,0:使用定时器1作为串口接收发生器 1:使用定时器2作为串口接收发生器// TCLK=1; //发送时钟标志,0:使用定时器1作为串口发送发生器 1:使用定时器2作为串口发送发生器// TR2=1; //启动定时期2/*启动串口中断 总中断*/ES=1;//串口使能EA=1;//总中断开 }
      大概看了一下,你这个程序问题可能就出在 static uchar i = 0; 这个i应该是全局变量吧,不然每次进入中断 i 都等于0,那都把数据赋值给数组的第一个元素了,所以最后只能得到发送的最后一个字节数据了
      51单片机接收上位机发送的多个字节的串口通信

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/75003.html

          热门文章

          文章分类