单片机串口接收程序

合集下载

51单片机的串口通信程序(C语言)

51单片机的串口通信程序(C语言)

51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。

本文将介绍使用C语言编写51单片机的串口通信程序。

1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。

首先,我们需要一块51单片机开发板,内置了串口通信功能。

另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。

2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。

在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。

同时,我们还需要引入头文件来定义串口通信的相关寄存器。

3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。

这些参数的配置需要根据实际需要进行调整。

在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。

4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。

初始化串口的过程包括打开串口、设置中断等。

5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。

阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。

6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。

在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。

7. 中断处理在串口通信中,中断是一种常见的处理方式。

通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。

8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。

```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。

单片机IO口模拟串口程序(发送+接收)

单片机IO口模拟串口程序(发送+接收)
*在单片机上模拟了一个串口,使用P2.1作为发送端
*把单片机中存放的数据通过P2.1作为串口TXD发送出去
***************************************************************/
#in elude<reg51.h>
#i nclude<stdio.h>
/***************************************************************
*模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际 串口
*在单片机上模拟了一个串口,使用P3.2作为发送和接收端
*以P3.2模拟串口接收端,从模拟串口接收数据发至串口
THO=OxFF;//定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps
fosc=11.0592MHz
送到TL1);T0工作在方式1,十六位定时
PCON|=0x80;//SMOD=1;
#ifdef F11_0592
TH1=0xE8 ; // Baud:2400fosc=11.0592MHz 2400bps为从串口接收数据的速率
TL1=0xE8;//计数器初始值,fosc=11.0592MHz因为TH1一直往TL1送,所以这个初值的意义不大
{
WByte(i nfo[i]);
}
}
void main()
{
UartI nit();
while (1)
{
Se ndata();
}
}
II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II

单片机串口收发时序

单片机串口收发时序

单片机串口收发时序引言单片机串口通信是一种常用的通信方式。

在这种通信方式中,通过发送和接收串口数据,可以实现单片机与外部设备之间的数据传输。

而正确的串口收发时序是保证通信正常进行的关键。

串口通信原理串口通信是通过发送和接收电平变化来传输数据的。

一般使用的是异步串口通信方式,其中包括发送端和接收端,发送端将数据进行序列化,并通过串口线发送给接收端,接收端将接收到的数据进行反序列化,得到原始数据。

串口收发时序串口收发时序是指在通信过程中各个时钟信号的变化情况。

下面详细介绍串口收发时序的每个步骤。

时钟信号串口通信中最重要的时钟信号是波特率,即每秒钟发送的比特数。

波特率决定了串口数据传输的速度。

一般常用的波特率有9600、115200等。

发送端时序发送端的时序可以分为以下几个步骤: 1. 准备数据:发送端首先要准备要发送的数据。

2. 数据序列化:发送端将准备好的数据进行序列化,转换成电平变化的串口信号。

3. 起始位:发送端在数据序列前加上一个起始位,用来标识数据的开始。

4. 数据位:发送端按照波特率将数据位一个一个发送出去。

5. 奇偶校验位:发送端可以选择是否加入奇偶校验位,用来检测数据是否传输出错。

6. 停止位:发送端在数据序列后加上一个或多个停止位,用来标识数据的结束。

7. 等待确认:发送端在发送完一个字节的数据后,等待接收端的确认信号,确保数据已经正确接收。

接收端时序接收端的时序可以分为以下几个步骤: 1. 等待起始位:接收端在接收数据前,等待起始位的到来,用来标识数据的开始。

2. 数据位:接收端按照波特率开始接收数据位。

3. 奇偶校验位:如果发送端加入了奇偶校验位,接收端会检测数据是否传输出错。

4. 停止位:接收端在接收完所有数据位后,等待停止位的到来,用来标识数据的结束。

5. 确认信号:接收端在接收完一个字节的数据后,发送确认信号给发送端,表示数据已经正确接收。

时序示意图下图是串口收发时序的示意图:发送端:起始位数据位奇偶校验位停止位低电平高低变化高低变化高电平------ ------- -------- ------接收端:起始位数据位奇偶校验位停止位确认信号低电平高低变化高低变化高电平高电平串口收发时序的注意事项在进行串口通信时,需要注意以下几点: 1. 波特率要设置一致:发送端和接收端的波特率要设置成相同的值,才能保证数据传输的准确性。

51单片机while里串口接收字符后,就不循环

51单片机while里串口接收字符后,就不循环

1、初识51单片机在学习嵌入式系统的过程中,51单片机是一个非常重要的学习对象。

它是一款由英特尔公司在上个世纪推出的一款8位单片机,具有性能稳定、功能强大的特点,因此被广泛应用于嵌入式系统领域。

2、 while循环的基本概念在C语言编程中,while循环是一种常用的循环结构,它可以根据条件来重复执行一段代码块。

它的基本语法结构如下:```cwhile(条件表达式){// 循环体}```3、 51单片机中的串口接收字符在实际应用中,我们常常需要通过串口与其他设备进行通信。

在51单片机中,串口的接收操作通常需要使用中断来进行,即当有数据到达时,单片机会触发中断,然后执行中断服务程序来处理接收到的数据。

在51单片机中,串口接收字符的过程可以简要地描述为:设置接收中断标志位→接收字符→清除中断标志位→处理接收到的字符。

4、问题的描述和分析在51单片机的while循环中,如果在循环体内执行串口接收字符的操作,很可能会导致循环被阻塞,无法正常执行。

这是因为串口接收字符需要一定的时间,而在这段时间内,while循环无法进行下一次的条件判断,因此就会导致循环被“卡住”的情况发生。

5、解决方案和建议为了解决这个问题,我们可以采取以下几种方法:- 将串口接收字符的操作放在while循环外部- 使用状态机来处理串口接收字符的过程- 使用定时器中断来进行串口接收字符的超时处理6、将串口接收字符的操作放在while循环外部将串口接收字符的操作放在while循环外部,可以避免串口接收字符的时间影响循环的正常执行。

具体的程序结构可以简要描述如下:```cvoid m本人n(){// 初始化串口// 初始化其他相关的硬件和软件while(1){// 循环体}}// 串口接收中断服务程序void serial_interrupt(){// 处理接收到的字符}```7、使用状态机来处理串口接收字符的过程使用状态机来处理串口接收字符的过程,可以更加灵活地控制串口接收字符的流程,避免阻塞循环的情况发生。

STC12C5A60S2 双串口使用程序

STC12C5A60S2 双串口使用程序

STC12C5A60S2 双串口使用程序(已经验证成功)#include <stc12c5a60s2.h>#include "intrins.h"#define uchar unsigned char#define S2RI 0x01 // 串口2接收中断请求标志位#define S2TI 0x02 // 串口2发送中断请求标志位//================================================// 对于将P4.4、P4.5当做I/O口使用必须添加的定义||//================================================sfr p4sw=0xbb; // 需在主函数文件中做相应设置4、5、6为1(作为I/O口使用)/*sbit button1=P4^3;sbit button2=P4^4;sbit button3=P4^5;sbit button4=P4^6;*/页脚内容1uchar code temp1[]={" 白云:“我可是个名人”"};uchar code temp2[]={" 黑土:“啥名人啊,你就是个人名”"}; uchar code temp3[]={" 小崔:“诶,大叔大妈,你俩都冷静冷静”"}; uchar code temp4[]={" 观众:“哈哈哈哈”"};/*void delay_1ms(uchar ii) // 误差-0.018084490741us{unsigned char a,b;for(; ii>0; ii--)for( b = 18; b>0; b--)for( a = 152; a>0; a--);_nop_(); //if Keil,require use intrins.h}void delay1s(void) //误差-0.000000000125us{unsigned char a,b,c;for( c = 212; c>0; c--)页脚内容2for( b = 160; b>0; b--)for( a = 80; a>0; a--);_nop_(); //if Keil,require use intrins.h_nop_(); //if Keil,require use intrins.h}*///************************ 串口通信部分******************************uchar wj_uun = '!'; // 用于存放串口1接收的字符uchar wj_uun2 = '?'; // 用于存放串口2接收的字符void bt_uart_init() // 单片机双串口初始化{//SCON=0X50; // SM0=0 SM1=1 SM2=0 REN=1SM0 = 0; // 串口工作方式1:1位起始位,8位数据位,1位停止位允许串口接收SM1 = 1;REN = 1; // 允许串口接收页脚内容3//RI=1; // 接收标志位,0:正在接收1:接收完毕(如果RI=1就一直执行串口中断)TMOD = 0X20; // 定时器T1工作方式2TH1 = 0XFD; // 9600bit/s下的定时器初值TL1 = 0XFD;TR1 = 1; // 启动定时器T1EA = 1; // 开总中断ES = 1; // 开串行口中断S2CON = 0x50; // 串口2工作在方式1 10位异步收发S2SM0=0 S2SM1=1 S2REN=1允许接收BRT = 0XFD; // 9600bit/s下的独立波特率发生器初值AUXR = 0x10; // 辅助寄存器:0001 0000 ->BRTR=1:独立波特率发生器开始计数,S2SMOD=0:波特率不加倍,BRTx12=0:独立波特率每12个时钟计数一次IE2 = 0x01; // 开串口2中断0000 0001->ES2=1// AUXR1 = 0x10; // 0001 0000->S2_P4=1:UART2从P1口(RxD2:P1.2 TxD2:P1.3)切换到P4口(RxD2:P4.2 TxD2:P4.3) 否则默认都为P1口}/************** 串口1发送函数*****************/页脚内容4void s1_send_char(uchar dat) // 发送端(发送的是字符){SBUF = dat; // 将字符送入发送缓冲寄存器while(!TI); // TI为发送状态标志位,0:发送中1:发送结束TI = 0; // 手动清零标志位}void s1_send_string(uchar *pt) // 通过调用发送字符函数来发送字符数组{while(*pt != '\0'){s1_send_char(*pt++);}}/************** 串口2发送函数*****************/void s2_send_char(uchar dat2) // 发送端(发送的是字符){页脚内容5S2BUF = dat2; // 将字符送入串口2的发送缓冲寄存器while(!(S2CON&S2TI)); // 判断发送是否结束:S2CON.bit2 = 0:发送中1:发送结束S2CON &= ~S2TI; // 手动清零标志位,令S2CON.bit2 = 0}void s2_send_string(uchar *pt2) // 通过调用发送字符函数来发送字符数组{while(*pt2!='\0'){s2_send_char(*pt2++);}}/************** 串口1中断程序*****************/void bt_serial_1() i nterrupt 4 // 中断编号4为串行口1中断{if(RI) // 接收标志位,0:正在接收1:接收完毕(如果RI=1就一直执行中断){页脚内容6RI = 0; // 同样需要手动清零wj_uun = SBUF; // 将接收缓冲器接收的字符送入变量中}}/************** 串口2中断程序*****************/void bt_serial_2() interrupt 8 // 中断编号8为串行口2中断{if(S2CON&S2RI) // 接收标志位: S2CON.bit1 = 0:正在接收1:接收完毕(如果RI=1就一直执行中断){S2CON &= ~S2RI; // 同样需要手动清零,令S2CON.bit1 = 0wj_uun2 = S2BUF; // 将串口2接收到的字符送入变量中}}页脚内容7void main(void){bt_uart_init(); // 串口初始化p4sw = 0x70; // 0111 0000 对应的4、5、6脚设置成功通用I/O口while(1){/*if(wj_uun != '!') // 串口1接收{s1_send_char(wj_uun); // 串口1发送wj_uun = '!';}*/if(wj_uun2 != '?') // 串口2接收{s2_send_char(wj_uun2); // 串口2发送wj_uun2 = '?';}}页脚内容8}页脚内容9。

单片机的串口接收和发送数据的程序编写

单片机的串口接收和发送数据的程序编写

单⽚机的串⼝接收和发送数据的程序编写#include "config.h"/******************************串⼝1的波特率********************************///T1作波特率发⽣器//在波特率加倍情况下#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L // 254 FF#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L // 254 FE#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L // 253 FD#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L // 252 FC#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L // 250 FA#define SYS_Fosc 11059200L //晶振频率uint32_t COMM_BAUD_RATE=9600 ; //串⼝波特率#define OSC_FREQ 11059200 //11059200static INT8U Send_buf[10] = {0} ;static INT8U Recv_buf[10] = {0} ;static INT8U SendDataLen = 0 ;static INT8U ResendDataLen = 0 ;/************************************************************************函数名:串⼝初始化功能描述: STC10L08XE 单⽚机串⼝初始化函数返回函数: none其他说明: none**************************************************************************/void UartIni(void){TMOD = 0x20; // 设置 T1 为波特率发⽣器SCON = 0x50; // 0101,0000 8位数据位, ⽆奇偶校验PCON = 0x00; //PCON=0;TH1=256-(SYS_Fosc/COMM_BAUD_RATE/32/12);//设置为9600波特率TL1=256-(SYS_Fosc/COMM_BAUD_RATE/32/12);TR1 = 1; //定时器1打开REN = 1; //串⼝1接收使能ES = 1; //串⼝1中断使能EA = 1;}//串⼝接受函数初始化1void UartIni1(void){SCON = 0x50; //8-bit variable UARTTMOD = 0x20; //Set Timer1 as 8-bit auto reload modeTH1 = TL1 = -(SYS_Fosc/12/32/COMM_BAUD_RATE); //Set auto-reload vauleTR1 = 1; //Timer1 start runES = 1; //Enable UART interruptEA = 1; //Open master interrupt switch}/************************************************************ 名称:* 功能:* ⼊⼝参数:⽆* 出⼝参数:⽆* 说明:**********************************************************/void Uart_Isr() interrupt 4 using 1{if(RI){}}/************************************************************************功能描述:串⼝发送⼀字节数据 sbuf=data接受 data=sbuf⼊⼝参数: DAT:带发送的数据返回值: none其他说明: none**************************************************************************/void Uart_PutByte(uint8_t DAT){ES = 0;TI=0;DAT=SBUF ;while(TI==0);TI=0;ES = 1;}///*****************************************************************************************************// - 功能描述:串⼝接受⼀帧数据// - ⾪属模块:内部// - 参数说明:// - 返回说明:// - 注:⽆//*****************************************************************************************************/ void SendCmd(INT8U len ){INT8U i = 0 ;for(i=0; i<len; i++)//数据{Uart_PutByte(Send_buf[i]) ;}}///********************************************************************************************// - 功能描述:求和校验// - ⾪属模块:// - 参数说明:// - 返回说明:// - 注:和校验的思路如下// 发送的指令,去掉起始和结束。

51单片机串口通信程序。。含详细例子

51单片机串口通信程序。。含详细例子

{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} 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 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();

单片机串行口接收和发送数据的过程简述

单片机串行口接收和发送数据的过程简述

单片机串行口接收和发送数据的过程简述
串行口接收和发送数据的过程简述
 答:在发送过程中,当执行一条将数据写入发送缓冲器SBUF(99H)的指令时,串行口把SBUF中8位数据以fosc/l2的波特率从RXD(P3.0)端输出,发送完毕置中断标志TI=1。

写SBUF指令在S6P1处产生一个正脉冲,在下一个机器周期的S6P2处,数据的最低位输出到RXD(P3.0)脚上;再在下一个机器周期的S3、S4和S5输出移位时钟为低电平时,在S6及下一个机器周期的Sl和S2为高电平,就这样将8位数据由低位至高位一位一位顺序通过RXD线输出。

并在TXD脚上输出fosc/12的移位时钟。

在写SBUF有效后的第10个机器周期的SlPl将发送中断标志TI置位。

 接收时,用软件置REN=1(同时,RI=0),即开始接收。

当使SCON中的REN=1(RI=0)时,产生一个正的脉冲,在下一个机器周期的S3P1~S5P2,从TXD(P3.1)脚上输出低电平的移位时钟,在此机器周期的S5P2对P3.0脚采样.并在本机器周期的S6P2通过串行口内的输入移位寄存器将采样值移位接收。

在同一个机器周期的S6P1到下一个机器周期的S2P2,输出移位时钟为高电平。

于是,将数据字节从低位至高位接收下来并装入SBUF。

在启动接收过程(即写SCON,清RI位),将SCON中的RI清0之后的第l0个机器周期的SlPl将RI置位。

这一帧数据接收完毕,可进行下一帧接收。

单片机串口识别数据的方法

单片机串口识别数据的方法

单片机串口识别数据的方法
单片机串口识别数据的方法通常涉及到以下几个步骤:
1. 初始化串口:在开始接收数据之前,需要初始化串口。

这包括设置波特率、数据位、停止位和奇偶校验等参数。

2. 检测起始位:串口通信通常以一个起始位开始,这是数据传输的标志。

单片机需要检测到这个起始位,然后开始接收数据。

3. 接收数据:一旦检测到起始位,单片机就可以开始接收数据。

这通常是通过一个循环实现的,循环中不断地从串口读取数据,直到接收到所有的数据位。

4. 处理数据:在接收到数据后,单片机需要对数据进行处理。

这可能涉及到将数据解析为特定的命令或消息,或者将数据存储在内存中。

5. 检测停止位:数据接收完成后,单片机需要检测到一个停止位,这标志着数据传输的结束。

6. 错误处理:如果在接收过程中检测到任何错误(例如,数据位不正确,或者没有检测到起始位或停止位),单片机需要进行适当的错误处理。

以上就是单片机串口识别数据的基本方法。

具体的实现可能会根据单片机的型号和使用的串口通信协议有所不同。

PIC单片机串口通讯程序

PIC单片机串口通讯程序

PIC单片机串口通讯程序单片机串口通讯是一个常用的程序模块。

PIC单片机是一款常用的单片机。

在网上搜索到一个PIC单片机串口通讯程序。

这个PIC单片机串口通讯程序站长没有验证,应该是正确的。

假如大家有更好的PIC单片机串口通讯程序,请向我推荐。

1. 单片机PIC1编程(发送部分)LIST P=16F877#INCLUDE P16F876.INCCBLOCK 0X24 ;保留三个字节作为显示用COUNT ;作计数器或暂存器用ENDCORG 0X0000 ;程序复位入口NOPSTART GOTO MAINORG 0X20MAIN MOVLW 0X30 ;以下将RAM内容初始化MOVWF FSR ;从30H单元开始MOVLW 0X30 ;将值30H赋给单元30HMOVWF COUNTINTRAM MOVF COUNT,0 ;将30H~7FH赋给单元30H~7FHMOVWF INDFINCF COUNT,1INCF FSR,1BTFSS COUNT,7GOTO INTRAMBSF STATUS,RP0 ;将SCI部件初始化MOVLW 0X19 ;将传输的波特率设为约9600 bpsMOVWF SPBRGMOVLW 0X04 ;选择异步高速方式传输8位数据MOVWF TXSTABCF STATUS,RP0MOVLW 0X80 ;允许同步串行口工作MOVWF RCSTABSF STATUS,RP0BSF TRISC,7 ;将RC6、RC7设置为输入方式,断绝与外接电路的连接BSF TRISC,6BCF STATUS,RP0MOVLW 0X30 ;30H作为同步字符发送MOVWF FSRMOVF INDF,0MOVWF TXREG ;将待发送的数据写入发送缓冲器TXREGBSF STATUS,RP0BSF TXSTA,TXEN ;发送允许BCF STATUS,RP0BSF RCSTA,CREN ;接收数据允许LOOPTX BTFSS PIR1,RCIF ;等待PIC2的响应字节GOTO LOOPTXMOVF RCREG,0 ;读响应字节,清RCIFLOOPTX1 BTFSS PIR1,TXIF ;发送下一字节GOTO LOOPTX1INCF FSRMOVF INDF,0MOVWF TXREGBTFSS FSR,7 ;30H~7FH单元的内容是否发送完?GOTO LOOPTX ;没有,继续下一字节的发送BSF STATUS,RP0 ;如果是,则停止发送BCF TXSTA,TXENBCF STATUS,RP0 ;数据发送完毕CALL LED ;调用显示子程序,将发送的数据显示出来END ;程序完2. 单片机PIC2编程(接收部分)LIST P=16F876#INCLUDE P16F876.INCCBLOCK 0X24COUNTENDCORG 0X0000NOPSTART GOTO MAINMAIN BSF STATUS,RP0 ;初始化程序同发送子程序MOVLW 0X19 ;波特率设置与PIC1相同MOVWF SPBRGMOVLW 0X04 ;异步高速传输MOVWF TXSTABCF STATUS,RP0MOVLW 0X80 ;串行口工作使能MOVWF RCSTABSF STATUS,RP0BSF TRISC,7 ;与外接电路隔离BSF TRISC,6BCF STATUS,RP0MOVLW 0X30 ;从30H单元开始存放发送来的数据MOVWF FSRBSF RCSTA,CREN ;接收允许BSF STATUS,RP0BSF TXSTA,TXEN ;发送允许BCF STATUS,RP0WAIT BTFSS PIR1,RCIF ;等待接收数据GOTO WAITMOVF RCREG,0 ;读取数据MOVWF INDF ;将接收到的响应字节存入PIC2的RAM INCF FSRMOVWF TXREG ;发送响应字节LOOPTX BTFSS PIR1,TXIF ;等待写入完成GOTO LOOPTXBTFSS FSR,7 ;全部数据接收否?GOTO WAIT1 ;没有,继续接收其它数据BCF RCSTA,RCEN ;接收完,则关断接收和发送数据允许BSF STATUS,RP0BCF PIE1,TXENBCF STATUS,RP0CALL LED ;调用显示子程序,将接受到的数据显示出来END ;程序完PIC单片机双机同步通信1. 单片机PIC1编程(主控发送)LIST P=16F876#INCLUDE P16F876.INCCBLOCK 0X24 ;保留三个字节作为显示用COUNT ;作计数器或暂存器用ENDCORG 0X0000 ;程序复位入口NOPSTART GOTO MAINORG 0X0100MAIN MOVLW 0X30MOVWF FSR ;以下将从30H单元开始的RAM内容初始化MOVLW 0X30 ;将值30H赋给单元30HMOVWF COUNTINTRAM MOVF COUNT,0 ;将30H~7FH赋给单元30H~7FH MOVWF INDFINCF COUNT,1INCF FSR,1BTFSS COUNT,7GOTO INTRAMBSF STATUS,RP0 ;将SCI部件初始化MOVLW 0X19 ;将传输的波特率设为约9600 bpsMOVWF SPBRGMOVLW 0X94 ;选择同步高速方式传输8位数据MOVWF TXSTABCF STATUS,RP0MOVLW 0X80 ;允许同步串行口工作MOVWF RCSTABSF STATUS,RP0BSF TRISC,7 ;将RC6、RC7设置为输入方式,断绝与外接电路的连接BSF TRISC,6BSF STATUS,RP0MOVLW 0X30 ;将从30H单元开始的内容传送到PIC2MOVWF FSRMOVF INDF,0MOVWF TXREG ;将待发送的数据写入发送缓冲器TXREGBSF STATUS,RP0BSF TXSTA,TXEN ;发送允许BCF STATUS,RP0TX1 BTFSS PIR1,TXIF ;等待上一个数据写完GOTO TX1INCF FSR ;准备发送下一个数据MOVF INDF,0MOVWF TXREG ;将新的数据写入TXREGBTFSS FSR,7 ;判断所有30H~7FH单元的内容是否发送完毕?GOTO TX1 ;没有,则继续发送其它字节TX2 BTFSS PIR1,TXIF ;等所有要求发送的数据已经发送完,再额外GOTO TX2 ;写一个字节到TXREG,使最后一个数据能够顺利发送MOVWF TXREGNOP ;延时几个微秒后,关发送允许NOPNOPNOPNOPBSF STATUS,RP0BCF TXSTA,TXENBCF STATUS,RP0CALL LED ;调用显示子程序,将发送的数据显示出来END ;程序完2. 单片机PIC2编程(从动接收)LIST P=16F876#INCLUDE P16F876.INCCBLOCK 0X24COUNTENDCORG 0X0000NOPSTART GOTO MAINORG 0X0100MAIN BSF STATUS,RP0MOVLW 0X10 ;选择同步从动方式MOVWF TXSTABCF STATUS,RP0MOVLW 0X80 ;串行口使能MOVWF RCSTABSF STATUS,RP0BSF TRISC,7 ;关断与外部电路的联系BSF TRISC,6BCF STATUS,RP0MOVLW 0X30 ;从30H单元开始存放接收的数据MOVWF FSRBSF RCSTA,CREN ;接收允许WAIT BTFSS PIR1,RCIF ;等待接收GOTO WAITMOVF RCREG,0 ;读取接收到的数据MOVWF INDF ;将接收到的数据存入PIC2的RAMINCF FSRBTFSS FSR,7 ;所有的数据是否已接收完?GOTO WAIT ;没有,继续接收其它字节NOP ;延时数微秒后,清接收允许位NOPNOPNOPBCF RCSTA,RCENCALL LED ;调用显示子程序,将接受到的数据显示出来END ;程序完PIC单片机与PC机通过串口通信1. PC机编程PC采用Toubr C 进行编写。

ATmega16单片机实现串口收发数据

ATmega16单片机实现串口收发数据

1、编译环境:CodeVisionAVR2、功能:实现以5AH开头的6个字节数据帧的接收及发送3、接收及发送方式:中断接收,查询发送4、校验方式:所有字节相加模除256等于0则接收正确,否则不予接收程序如下所示:#include "mega16.h"#define uchar unsigned char #define uint unsigned int #define BAUD 9600 #define F_CLK 400000 0#define MATCH_OK 1; #define MATCH_ERROR 0; #define UDRE 5volatile uchar i=0;volatile uchar recc_flag=0; //命令字节接收标志(recieve command 简写成 recc) volatile uchar comm_flag=0; //命令帧接收完毕标志(command 简写成 comm) volatile uchar comm; //定义变量,用于传递UDR0中接收到的命令字volatile uchar command[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //定义长度为6的数组用于接收长度为6字节的命令帧,并将所有元素初始化为0x00/*延时*/void delay(uint t) {while(t--); }/*****//*******帧头校验******/ uchar check_comm(void) {uchar i;uint result=0;for(i=0;i<6;i++) {result+=command[i]; }if((result%256)==0) {return MATCH_OK; } else {return MATCH_ERROR; } }/*********************/void uart_init(void) {UCSRA=0x00;UCSRB=0x98; //接收结束中断使能;数据接收使能;数据发送使能UCSRC=0x06; //工作在异步模式;无校验;1位停止位;字符长度为8位 UBRRH=(F_CLK/BAUD/16-1)/256;UBRRL=(F_CLK/BAUD/16-1)%256; //系统时钟为4MHz,波特率为9600bps }void init_device(void) {#asm("cli") //关中断PORTA=0x04; DDRA=0x04; PORTB=0xFE; DDRB=0xFF; PORTD=0xFF; DDRD=0x02; MCUCR=0x00; TIMSK=0x00;uart_init(); //串口初始化#asm("sei") //重开中断 }interrupt[USART_RXC] void usart_rec(void) {comm=UDR; recc_flag=1; }/*****USART0口发送命令字节程序*****/ void usart0_transcomm(uchar x) {while(!(UCSRA&(1<<UDRE))); //数据寄存器空时才能发送数据 UDR=command[x]; }/**********************************//*****命令帧的单个字节存储程序******/ void save_single_byte(uchar y) {if(y<6){command[y]=comm;} recc_flag=0; }/***********************************//********命令帧保存程序********/ void save_comm(void) {uchar mount=5;if(recc_flag==1) //接收标志置位,说明接收到命令字,则存储 {save_single_byte(i);i++; //指向下一个数组元素 if(command[0]!=0x5A) {i=0;#asm("cli")delay(1000000); #asm("sei") }if(i==6) //若数组存满6个字节{comm_flag=1; //命令帧接收完毕,将接收完毕标志置位 } } }/*****************************//******USART0发送命令帧程序******/ void send_comm(void) {uchar j;if(comm_flag==1) //命令帧接收完毕后才允许发送,////应在发送前进行校验,在此不予考虑//// {#asm("cli")if(check_comm()) {for(j=0;j<6;j++) {usart0_transcomm(j); //调用单字节发送程序 } }#asm("sei") i=0; }comm_flag=0; //命令帧发送完毕后,接收完毕标志清零 }/*******************************//****主程序****/ void main(void) {init_device();while(1) {save_comm(); send_comm(); }}。

keil里串口接收函数

keil里串口接收函数

keil里串口接收函数
在Keil软件中,串口接收函数通常用于从串口接收数据并进行
处理。

在使用Keil开发嵌入式系统时,我们通常会使用一些标准的
串口接收函数来实现串口通信。

在Keil中,串口接收函数的实现通
常依赖于所使用的具体的单片机型号和所选用的串口通信模块。

一般来说,串口接收函数的实现可以分为以下几个步骤:
1. 初始化串口,首先需要初始化串口通信模块,包括设置波特率、数据位、停止位和校验位等参数。

这通常可以通过Keil提供的
相关库函数或者单片机厂家提供的驱动库函数来实现。

2. 接收数据,接下来就是实际的串口接收操作。

在Keil中,
我们可以使用类似于UART_Receive()这样的函数来实现串口接收。

这些函数通常会在接收到数据后将数据存储到指定的缓冲区中。

3. 数据处理,一旦接收到数据,就可以对其进行进一步的处理。

这可能涉及到数据解析、存储或者其他操作,具体取决于项目的需求。

在Keil中,具体的串口接收函数的实现可能会有所不同,因为它取决于所使用的单片机型号和所选用的串口通信模块。

因此,建议在使用特定的单片机和串口通信模块时,参考相关的技术文档和例程来实现串口接收函数。

总的来说,Keil中的串口接收函数是实现嵌入式系统串口通信的重要部分,通过合适的初始化和数据处理,可以实现稳定可靠的串口接收功能。

stm32串口通信工作原理

stm32串口通信工作原理

stm32串口通信工作原理一、引言串口通信是一种常见的数据交换方式,在嵌入式系统中扮演着重要的角色。

本文将介绍s t m32单片机上串口通信的基本原理以及其工作流程。

二、串口通信概述串口通信是指通过串行通信接口,按照一定的协议和规则,将数据传输到另一个设备。

常用的串口通信接口有R S-232、R S-485和UA RT等。

三、s t m32串口通信的基本原理s t m32单片机具有多个串口外设,每个串口包含了发送和接收数据的功能。

串口的工作原理可以简述为以下几个步骤:1.配置串口参数在使用s tm32串口通信之前,需要先对串口进行配置。

包括波特率、数据位、停止位、校验位等参数的设定。

这些参数会影响数据的传输速率和可靠性。

2.发送数据当需要发送数据时,首先将待发送的数据写入发送缓冲区。

数据会按照之前设定的参数进行编码并传输出去。

发送完成后,会产生发送完成中断。

3.接收数据接收数据时,st m32单片机会将接收到的数据存储到接收缓冲区。

当接收缓冲区有数据时,会触发接收完成中断,应用程序可以读取缓冲区中的数据。

4.中断处理s t m32单片机支持中断功能,通过设置相应的中断使能标志位,可以实现在数据发送和接收过程中对中断的响应。

中断处理函数负责对中断进行处理,以确保数据的正确传输。

四、s t m32串口通信的工作流程下面将详细介绍s tm32串口通信的工作流程:1.配置串口参数:使用st m32提供的库函数,根据需求设置波特率、数据位、停止位和校验位等参数。

2.初始化串口:调用库函数进行串口初始化,包括G PI O引脚设置、时钟使能等。

3.发送数据:将待发送的数据写入发送缓冲区。

4.等待发送完成中断:等待发送完成中断的触发,表示数据发送完成。

5.接收数据:接收到数据后,存储到接收缓冲区。

6.判断是否有数据可读:检测接收缓冲区是否有数据可读。

7.读取数据:读取接收缓冲区中的数据。

8.中断处理:根据需要进行中断处理,如错误处理、数据处理等。

(完整版)c51单片机从串口接收发送字符串

(完整版)c51单片机从串口接收发送字符串

c51单片机从串口接收发送字符串#include 〈reg52。

h>#define uchar unsigned char#define uint unsigned intuchar data table[10]; //暂存数组,可以将10改为你需要的数值/***********************************************串行口初始化波特率9600,定时器1,工作方式2 *************************************************/void serial_init(void){TMOD=0x20;//计时器1作为比特率发生器,方式2TH1=0xfd;TL1=0xfd; //装入初值TR1=1;//计时中断允许SM0=0;SM1=1;//串行口工作于方式2ES=1;//串行口中断允许REN=1;//接收允许EA=1;// 总中断允许}/***********************************************串行口传送数据传送显示数组各字符给计算机*************************************************/void send(uchar *dis){while(*dis!='\0’){SBUF=*dis;dis++;while(!TI);TI=0; //软件请发送中断}}void main(){serial_init();//初始化while(SBUF!=0x0d);//计算机键盘按下回车键,则开始将接收到的数据回传给计算机send(table);}/***********************************************串行中断服务函数单片机接收数据,存入table数组*************************************************/ void serial() interrupt 4{int i;ES=0; //关串口中断table[i++]=SBUF;//命令存到命令数组RI=0; //软件清除接收中断ES=1;//开串口中断}已经通过proteus仿真如下。

C8051F系列单片机串口通讯程序

C8051F系列单片机串口通讯程序

C8051F系列单片机串口通讯程序采用C8051F020单片机//串口编程--接收PC发过来的字符串,回发字符串.发送期间中断控制LED灯闪烁//采用外部晶振22.1184MHz 使用定时器1,方式2产生波特率,SMOD = 0或者1 //定时器初值X=256-SYSCLK*(SMOD+1)/(BAUDRATE*384)/#include <C8051F020.h>sfr16 TMR3RL = 0x92; //定时器3重装载寄存器sfr16 TMR3 = 0x94; //定时器3计数器#define uchar unsigned char#define uint unsigned int//----------------------------------------------------------------------//参数设置区//----------------------------------------------------------------------#define BAUDRATE 4800 //波特率bps#define CLKOUT 22118400 //外部晶振,修改也要修改OSCXCN#define SMODVAL 0 //SMOD的值,修改请也修改PCONVAL#define PCONVAL 0x00 //PCON的值,=0x00时SMOD0=0; =0x80时SMOD0=1 #define TXVAL (256-CLKOUT*(SMODVAL+1)/BAUDRATE/384) //定时器初值#define MAX_LEN 10 //每次接收/发送字符串的长度//---------------------------------------------------------------------//全局变量//---------------------------------------------------------------------sbit LED = P1^6; //LED '1'亮 '0'灭bit readFlag = 0; //读标志uchar readCounts = 0; //已经读取的字符个数,与MAX_LEN比较uchar idata trdata[MAX_LEN]; //要接收/发送的字符串//----------------------------------------------------------------------//子函数声明//----------------------------------------------------------------------void SYSCLK_Init(void); //系统时钟初始化void PORT_Init(void); //端口初始化void UART0_Init(void); //串口UART0初始化void Send_Char(uchar ch); //发送单个字符void Send_String(uchar * str, uint len); //发送一个字符串void UART0_ISR(); //串口中断服务程序,接收字符void Timer3_Init(uint counts); //定时器3初始化void Timer3_ISR(void); //定时器3中断服务程序//----------------------------------------------------------------------//主函数//----------------------------------------------------------------------void main(void){WDTCN = 0xde; //禁止看门狗WDTCN = 0xad;SYSCLK_Init(); //时钟初始化PORT_Init(); //端口初始化UART0_Init(); //串口初始化Timer3_Init(CLKOUT/12/10); //定时器初始化EA = 1; //开全局中断while(1){if(readFlag) //已经读取{readFlag = 0; //清零Send_String(trdata,MAX_LEN); //发送字符串}}}//----------------------------------------------------------------------//子函数具体实现//----------------------------------------------------------------------//系统时钟初始化void SYSCLK_Init(void){uint i;OSCXCN = 0x67; //采用外部晶振22.1184MHz,不分频. 选型OSCXCN=0110,0111 for(i=0;i<256;i++); //等待>1mswhile(!(OSCXCN&0x80)); //查询直到XTLVLD=1,晶振稳定OSCICN = 0x88; //切换到外部振荡器,允许时钟失效监测器. OSCICN=1000,1000 }//端口初始化void PORT_Init(void){XBR0 = 0x04; //允许UART0,RX,TX连到2个端口引脚. XBR0=0000,0100XBR1 = 0x00;XBR2 = 0x40; //交*开关使能P0MDOUT |= 0x03; //P0.0为推拉方式输出,即TX0,RX0所在的端口 0000,0011P1MDOUT |=0x40; //P1.6为推拉方式输出,即LED所在的端口 0100,0000}//串口初始化void UART0_Init(void){SCON0 = 0x50; //选择串口方式1,波特率可变 SCON0=0101,0000 TMOD = 0x20; //选择T1,方式2,自动再装入8位计数器TH1 = (int)TXVAL; //T1初值,根据波特率,时钟等计算. 0xF4, bps=4800bps TL1 = (int)TXVAL;ES0 = 1; //UART0中断开启TR1 = 1; //启动定时器T1PCON |= PCONVAL; //PCON=0x00,SMOD = 0 ; PCON=0x80,SMOD=1 TI0 = 1; //声明TX0就绪,可以发送TR0 = 1;}//定时器初始化void Timer3_Init(uint counts){TMR3CN = 0x00; //禁止定时器T3,清TF3,采用SYSCLK/12为时基TMR3RL = -counts; //初始化重装载值TMR3 = 0xffff; //设置为立即重装载EIE2 |= 0x01; //T3中断开启TMR3CN |= 0x04; //启动T3}//发送单个字符void Send_Char(uchar ch){SBUF0 = ch; //送入缓冲区while(TI0 == 0); //等待发送完毕TI0 = 0; //软件清零}//发送字符串,调用Send_Char() len字符串长度void Send_String(uchar * str,uint len){uint k = 0;do{Send_Char(*(str + k));k++;} while(k < len);}//定时器3中断服务程序void Timer3_ISR(void) interrupt 14 using 0{TMR3CN &= ~(0x80); //清TF3LED = ~LED;}//UART0中断服务程序. 接收字符void UART0_ISR(void) interrupt 4 using 1{uchar rxch;if(RI0) //中断标志 RI0=1 数据完整接收{RI0 = 0; //软件清零rxch = SBUF0; //读缓冲if(readCounts>=MAX_LEN){readCounts = 0;readFlag = 1;}trdata[readCounts] = rxch; //存入数组,供发送readCounts++;}}//------------------------------------------------------------- //程序结束。

单片机串口通信程序

单片机串口通信程序

引言:单片机串口通信程序是一种用于实现单片机与外部设备进行数据传输的通信方式。

它通过串口接口将数据以串行的形式传输,实现了高效、可靠的数据交互。

本文将详细介绍单片机串口通信程序的实现原理、步骤和注意事项。

概述:单片机串口通信程序主要包括串口初始化、发送数据、接收数据和中断处理等部分。

其中,串口初始化是设置串口通信的参数,发送数据和接收数据是具体的数据传输操作,中断处理则是处理串口中断事件的相关操作。

正文:一、串口初始化1.确定串口通信的波特率:波特率是指单位时间内传输的比特数,需要根据通信双方的需求确定合适的波特率。

2.设置数据位、停止位和校验位:数据位决定了每个字节中实际有效数据的位数,通常为8位;停止位用于判断一个字节的结束,通常为1位;校验位用于检测和纠正数据传输过程中的错误。

3.打开串口:通过使能相应的寄存器位,开启串口功能。

二、发送数据1.准备要发送的数据:将要发送的数据存储在缓冲区中,可以是一个字节、多个字节或一个字符串。

2.判断发送缓冲区是否为空:检查发送缓冲区是否已被发送完毕,如果为空则可以开始发送新的数据。

3.将数据发送到串口寄存器:将准备好的数据写入串口寄存器,启动数据传输。

4.等待数据发送完毕:通过检查发送完成标志位,判断数据是否已经成功发送完毕。

三、接收数据1.等待接收缓冲区非空:通过检查接收缓冲区是否有新的数据接收到,判断是否可以开始接收数据。

2.读取接收缓冲区的数据:通过读取串口寄存器中的数据,获取已接收到的数据。

3.处理接收到的数据:对接收到的数据进行相应的处理操作,可以是存储、显示或其他操作。

四、中断处理1.使能串口中断:通过设置相应的中断使能标志位,允许串口中断事件的发生。

2.处理接收中断:当接收缓冲区有新的数据到达时,触发串口接收中断,通过中断服务程序对接收到的数据进行处理。

3.处理发送中断:当发送缓冲区为空时,触发串口发送中断,通过中断服务程序发送新的数据。

单片机串口工作原理

单片机串口工作原理

单片机串口工作原理
串口,即串行通信口,是一种在计算机和外设之间进行数据传输的通信接口。

单片机串口是指单片机上的串行通信接口,用于实现单片机与其他设备之间的数据传输。

单片机串口的工作原理如下:
1. 串口通信协议:串口通信需要遵循一定的通信协议,常见的串口通信协议有UART、RS-232、RS-485等。

其中UART是
一种常用的串行通信协议,用于定义数据的传输格式、波特率等。

2. 数据传输方式:串口通信采用的是串行传输方式,即将数据比特依次发送或接收。

发送端将数据按照一定的格式转换为电平信号,接收端将电平信号转换为数据。

3. 通信参数:串口通信需要设置一些通信参数,包括波特率、数据位数、校验位、停止位等。

这些参数决定了数据传输的速率和精度。

4. 数据帧:数据帧是串口通信的基本数据单位,包括起始位、数据位、校验位和停止位。

发送端将数据按照数据帧格式发送,接收端按照相同的数据帧格式接收数据。

5. 通信流程:串口通信的流程包括发送方和接收方。

发送方将数据按照一定的格式发送到串口,接收方从串口接收数据并解析。

6. 中断机制:单片机串口通信常常使用中断机制来实现异步传输。

发送和接收数据时,可以通过中断方式进行处理,提高系统的实时性。

总的来说,单片机串口工作原理就是通过一定的通信协议和参数,在一个端口上实现数据的串行传输。

发送方将数据转换为电平信号发送,接收方将电平信号转换为数据接收。

通过这种方式,单片机可以和其他设备进行数据交换和通信。

单片机多字节串口接收

单片机多字节串口接收

后来我又写了几次单片机程序,才想到了一些解决问题的方法——不过改天再接着写吧,太累了,明天还要上班呢。
在后来的项目中,真的遇到了数据位跟校验位都可能出现aa的情况。我考虑到每次数据都是连续发送的(至少我们用labwindows做的上位机程序是这样的),成功接收到了一帧数据是要有一定时间回复的,也就是说如果接收到一半,但是很长时间没接收到数据,把计数值count清零就ok啦。涉及时间的问题自然要用定时器来实现啦。
实际上我还想过其他的方法,比如缓存的数组采用移位寄存的方式。拿前面的4个字节的协议为例。
void ser()interrupt 4
{
unsigned char i;
RI=0;
for(i=0;i<3;i++)
{
receive[i]=receive[i+1];
}
else if(count==1&&g_DatRev[count]==0x55)
{
count=2;
}
else if (count==2&&g_DatRev[2] == boardAddr)
}
receive[3]=SBUF;
{
count=0;
uart_flag =1;//串口接收成功标志,为1时在主程序中回复,然后清零
ES=0; //关中断,回复完了再ES=1;
}
else
{
count=0;//判断不满足条件就将计数值清零
}
}
第一次做的串口大概就按照这个方法写完了(我后来看过其他的代码,有人用switch语句写的,逻辑跟这个也差不多,不过我还是感觉用if else来写清晰一些),

单片机经典蓝牙串口接收程序

单片机经典蓝牙串口接收程序

单⽚机经典蓝⽛串⼝接收程序#include//声明头⽂件#define uchar unsigned char//宏定义#define uint unsigned int//宏定义uchar a=0;//定义⼀个变量a,⽤来读取串⼝的数据void delay(uint z)//⼀个带参数的延时程序{int i,j;//定义两个变量for(i=10;i>0;i--)for(j=z;j>0;j--);//将参数z赋值给j}void init()//初始化⼦程序{TMOD=0x20; //设置定时器T1为⼯作⽅式2TH1=0xfd;TL1=0xfd; //T1定时器装初值TR1=1; //启动定时器T1REN=1; //允许串⼝接收SM0=0;SM1=1; //设置串⼝⼯作⽅式1 需要定时器T1产⽣波特率EA=1; //开总中断ES=1; //开串⼝中断}void main()//主程序{init();//调⽤初始化⼦程序while(1)//死循环{switch(a)//判断a从串⼝读取到的数据{case 0001://如果是0x1f就前进P2=0x01;break;case 0002://如果是0x2f就后退P2=0x02;break;case 0003://如果是0x3f就左转P2=0x04;break;case 0004://如果是0x4f就右转P2=0x0f;break;case 0x05://如果是0x00就停⽌P2=0xf0;break;}}}void chuan() interrupt 4//串⼝中断服务程序{RI=0;//软件清除串⼝响应a=SBUF;//读取单⽚机串⼝接受的蓝⽛模块发送的数据}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档