51单片机串口程序,字符串/16进制发送与接收

这篇文章将说明51串口通信的发送与接收。分为:单个字符接收,字符串接收;十进制发送与接收,十六进制发送与接收。

字符串发送与十六进制发送,参考:http://blog.csdn.net/yibu_refresh/article/details/22695063

程序皆由PC串口工具发送,由单片机接收,并返回接收值给PC机。


一:单个字符的发送与接收

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
//定义接收 字符
uchar Buffer;

//串口初始化函数
void   URATinit( )
{
 TMOD=0x20;
 SCON=0x50;
 EA=1;
 ES=1;
 TR1=1;
 TH1=0xfd;
 TL1=0xfd;
}
//中断函数
void receive() interrupt 4
{
 if(RI)
 { 
  Buffer=SBUF;
  RI=0;
 }
 SBUF=Buffer;
 while(!TI);
 TI=0;
}
//主函数
void  main()
{
 URATinit( );
}
在中断函数中,如果接收到数据则RI由硬件置1,这时候把SBUF缓冲区的数据赋值给Buffer,并将RI置0,等待下次接收。同时,将接收到的数据再放入缓冲区,发送给PC机。当发送完毕的时候TI会被硬件置1,这时候需要将TI置0,以待下次发送。

运行效果:


发送数据1,则返回1。


二.字符串接收

(1)

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
//定义接收 数组
uchar Buffer[5]={0};
uchar i=0,j=0;

//串口初始化函数
void   URATinit( )
{
 TMOD=0x20;
 SCON=0x50;
 EA=1;
 ES=1;
 TR1=1;
 TH1=0xfd;
 TL1=0xfd;
}
//中断函数
void receive() interrupt 4
{
 if(RI)
 { 
  Buffer[i]=SBUF;
  RI=0;
 }
 SBUF=Buffer[i];
 while(!TI)	;
 TI=0;
 i++;
 if(i>=5){
 	i=0;
 }
}
//主函数
void  main()
{
 URATinit( );
}		 
在中断函数当中用Buffer[]接收收到的数据,同时将Buffer[]再发送给上位机。这里要注意变量i的定义。 如果定义为全局变量则Buffer[0-5]都可以接收到数据,需要对i计数,防止大于5溢出。

运行效果:


(2)

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
//定义接收 数组
uchar Buffer[5];
uchar i=0,flag;

//延时函数
delay(uint  ms)
{
 uchar i;
 while(ms--)
 for(i=0;i<123;i++);
}
//串口初始化函数
void   URATinit( )
{
 TMOD=0x20;
 SCON=0x50;
 EA=1;
 ES=1;
 TR1=1;
 TH1=0xfd;
 TL1=0xfd;
}
//中断函数
void receive() interrupt 4
{
 if(RI)
 { 
  Buffer[i++]=SBUF;
  RI=0;	 
  if(i>=5){
 	i=0;
 	}
  flag=1;
 }
}
//主函数
void  main()
{
 uchar k=0;
 for(k;k<5;k++){
 Buffer[k]=0;
 }
 URATinit( );
 while(1){
 if(flag) {
 	uchar j=0;
 	for(j;j<5;j++){
 		SBUF=Buffer[j];
 		while(!TI)	;
 		TI=0;
		delay(50);
 		}
 	flag=0;
	}
}
}		 
这时不是从中断函数中发送接收到的字符串,而是在主函数中发送接收到的字符串。于是需要flag标志位来判断是否接收到数据,并且用while(1)循环来不断判断并输出接收到的字符串。

运行效果:


其实方法(1)优于方法(2),现在来发送字符串"1234"与“123456”来看看效果:

发送“1234”(发送3次)


发送“123456”(发送3次):


可以看出(1)方法总是可以正确传输回并显示所发送的字符串,而(2)方法则有一定的局限性,只有当传输5个字符的字符串时才可以出现想要的显示效果。

分析发现:(1)中在中断中直接发出收到的字符,接收一个发送一个,为实时效果。(2)则在主程序中整体发送接收到的Buffer数组,例如接收“1234”,当“1234”发过来的时候由于Buffer为5位数组,因此第一次发送会给Buffer[0-3]赋值,Buffer[4]未赋值,返回给上位机第一次输出为“1234”,但第二次发送时候会给Buffer[4]赋值,同时溢出把i归为0。再次输出Buffer时造成了传输字符串的重叠与混乱。其实(1)也有这个现象,只是(1)的返回为及时返回。


三. 字符串发送与十六进制发送:

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar num;

sbit dula=P2^6;		//申明U1锁存器的锁存端
sbit wela=P2^7;		//申明U2锁存器的锁存端

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};

void delay(uint xms)				
{
	uint i,j;
	for(i=xms;i>0;i--)		      //i=xms即延时约xms毫秒
		for(j=110;j>0;j--);
}

void display(uint value)  //显示子函数
{
	uchar wan,qian,bai,shi,ge;   //定义万千百十个位
	wan=value/10000;               
	qian=value%10000/1000;
	bai=value%1000/100;		
	shi=value%100/10;
	ge=value%10;
	
	dula=1;
	P0=table[wan];    
	dula=0;
	P0=0xff;	
	wela=1;			
	P0=0xfe;		
	wela=0;
	delay(2);	  
	
	dula=1;
	P0=table[qian];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfd;
	wela=0;
	delay(2);
	
	dula=1;
	P0=table[bai];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfb;
	wela=0;
	delay(2);
	
	dula=1;
	P0=table[shi];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xf7;
	wela=0;
	delay(2);	
	
	dula=1;
	P0=table[ge];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xef;
	wela=0;
	delay(2);	
}

void init()         //初始化函数
{
	TMOD=0x20;      //设置定时器1工作方式
	TH1=0xfd;
	TL1=0xfd;
	TR1=1;
	SM0=0;
	SM1=1;
	REN=1;
	EA=1;
	ES=1;
}

void main()
{
    init();
	while(1)
	{
	    display(num);
	}
		
}

void ser() interrupt 4     //串口中断函数
{
	if(RI){
	   num=SBUF;          
       RI=0;
	   }              //置RI为0以便接收下一个数据
	   SBUF=num;
	   while(!TI);
	   TI=0;
}
这个程序可以在数码管上显示接收到的字符/数据,同时将接收到的数据返回给上位机显示。

先发送字符‘a’,即默认的字符串发送方式:


发送字符‘a’,这时单片机返回给上位机的也为‘a’(默认的字符串显示方式)。但是数码却显示97,为‘a’的ASCII码。这说明在传输过程中,始终为ASCII码传输。数码管之所以没显示‘a’,因为数码管为十进制显示方式,故显示97。(‘a’(ASCII显示)——>97(十进制显示)——>'a'(ASCII码显示))

发送字符‘a’,选择16进制发送,16进制显示:


这时发送端为16进制‘a’,即10进制的10。数码管显示10,而返回的值用16制显示为0A。

由文章开始的参考文章知道16进制发送时每次发送两位数据,如:发送十进制20,即16进制的14,这时数码管会显示20。(14(16进制显示)——>20(10进制显示)——>14(16进制显示))。


  • 45
    点赞
  • 312
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值