对于51单片机的串口:从逻辑上来说,SBUF独有一个,它既表示发送寄存器,又表示接管寄存器,具有同一个单元地址99H。但在物理构造上,则有两个完全独立的SBUF,一个是发送缓冲寄存器SBUF,另一个相对应的就是接管缓冲寄存器SBUF。假如CPU写SBUF,数据就会被送入发送寄存器准备发送;假如CPU读SBUF,则读入的数据一定来自接管缓冲器。即CPU对SBUF的读写,其实是分别访问上述两个不同的寄存器。a=SBUF;SBUF=a;也就是说:51单片机的sbuf寄存器是以字节为单位进行接管和发送的,一次只能接管一个字节。
我们整个程序的逻辑就是:
51单片机端每收到一个字节就发送一个字节到电脑。也就是数据全部原样返回。
电脑端是直接调用API进行底层的字节数组写入,先写入一堆字符串。然后延时500ms,然后再从串口中读取单片机返回的数据。我的猜想是电脑的串口也和51单片机的串口应该类似,有专门接管的寄存器或者其它存储格式,然后有个缓冲的字节数组进行字节缓冲。电脑直接从缓冲数组读取过来即可。
然后先来看51单片机端的代码:
defineucharunsignedchar
#defineuintunsignedint
ucharnum;
voidUART_init()
{
TMOD=0x20;//T1工作模式28位自动重装
TH1=0xfd;
TL1=0xfd;//比特率9600
TR1=1;//启动T1定时器
SM0=0;
SM1=1;//串口工作方式110位异步
REN=1;//串口允许接收
EA=1;//开总中断
ES=1;//串口中断打开
}
voidmain()
{
UART_init();//串口初始化
while(1);
}
voidUART()interrupt4
{
if(RI)//检测是否接收完成
{
num=SBUF;//num取出接收缓存器的值,接收一个字节就发送一个
RI=0;
SBUF=num;
while(!TI);//装上数据后TI为0,发送完数据后TI为1
TI=0;
}
}
这里是采用中断的方式进行串口通信。当串口一收到数据就产生中断,然后进入中断处理函数,先取出接收寄存器里的数据,然后放入发送寄存器里发生。
这里注意单片机端对串口的设置:串口为工作方式1,也就是10位异步收发器,8位数据位,也就是一个字节。专业点就是:一帧数据为10位,1位起始位(低电平),8位数据位(低位在前)和1位停止位(高电平)。比特率为9600.
我们在电脑这边打开电脑的串口的时候,也要这样进行设置串口的参数。不然会出问题。
然后来看电脑这边的java代码:
;
;
;
;
;
;
;
;
;
;
publicclassTools{
/**
*用于打开串口
*
*@paramportName
*串口名
*@parambaudrate
*波特率
*@return返回串口
*/
publicstaticfinalSerialPortportParameterOpen(StringportName,intbaudrate){
SerialPortserialPort=null;
try{//通过端口名识别串口
CommPortIdentifierportIdentifier=(portName);
//打开端口并设置端口名字serialPort和超时时间2000ms
CommPortcommPort=(portName,1000);
//进一步判断comm端口是否是串口instanceof
if(commPortinstanceofSerialPort){
("该COM端口是串口!串口名称是:"+portName);
//进一步强制类型转换
serialPort=(SerialPort)commPort;
//设置baudrate此处需要注意:波特率只能允许是int型对于57600足够
//8位数据位
//1位停止位
//无奇偶校验
(baudrate,_8,_1,
_NONE);
//串口配制完成log
("串口参数设置已完成,波特率为"+baudrate+",数据位8bits,停止位1位,无奇偶校验");
}else{//不是串口
("该com端口不是串口,请检查设备!");
//将com端口设置为null默认是null不需要操作
}
}catch(NoSuchPortExceptione){
();
}catch(PortInUseExceptione){
();
}catch(UnsupportedCommOperationExceptione){
();
}
returnserialPort;
}
/**
*发送一个字节数组到串口
*
*@paramserialPort
*串口
*@paramdataPackage
*字节数组
*/
publicstaticvoiduartSDatatoSerialPort(SerialPortserialPort,byte[]dataPackage){
OutputStreamout=null;
try{
out=();//和socket通信差不多,获取输出流然后调用write方法写入字节数组
(dataPackage);
();
}catch(IOExceptione){
();
}finally{
//关闭输出流非常标准的格式!!!
if(out!=null){
try{
();
out=null;
//("数据已发送完毕!");
}catch(IOExceptione){
();
}
}
}
}
/*
*上位机接收数据串口对象seriesPort接收数据buffer返回一个byte数组
*/
publicstaticbyte[]uartReceiveDatafromSingleChipMachine(SerialPortserialPort){
byte[]receiveDataPackage=null;
InputStreamin=null;
try{
in=();
//获取databuffer数据长度
intbufferLength=();
while(bufferLength!=0){
receiveDataPackage=newbyte[bufferLength];
(receiveDataPackage);
bufferLength=();
}
}catch(IOExceptione){
();
}
returnreceiveDataPackage;
}
publicstaticvoidmain(String[]args)throwsException{
//打开串口
SerialPortserialPort=portParameterOpen("COM3",9600);
//要发送的数据
StringdataS="Java和51单片机串口通信测试";
inti=1;
while(true){
//发送数据到单片机
byte[]datByte=();//转化为字节数组,我这边设置了默认为utf-8编码
uartSDatatoSerialPort(serialPort,datByte);
("-------------------------------------------------------");
((i++)+".发送到串口的数据:"+dataS);
//休眠500ms,等待单片机反应
(500);
//从单片机接收到的数据,返回的是一个字节数组
byte[]dat=uartReceiveDatafromSingleChipMachine(serialPort);
if(dat!=){
StringdataReceive=newString(dat,"utf-8");//字节数组以utf-8编码表编码成字符进行显示
((i++)+".从串口接收的数据:"+dataReceive);
}else{
("接收到的数据为空!");
}
}
}
}
[免责声明]本文来源于网络,不代表本站立场,如转载内容涉及版权等问题,请联系我们会予以删除相关文章,保证您的权利。转载请注明出处






