新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51單片機串口程序,字符串/16進制發送與接收

        51單片機串口程序,字符串/16進制發送與接收

        作者: 時間:2016-11-19 來源:網絡 收藏
        這篇文章將說明51串口通信的發送與接收。分為:單個字符接收,字符串接收;十進制發送與接收,十六進制發送與接收。

        字符串發送與十六進制發送,參考:http://blog.csdn.net/yibu_refresh/article/details/22695063

        本文引用地址:http://www.104case.com/article/201611/318162.htm

        程序皆由PC串口工具發送,由單片機接收,并返回接收值給PC機。

        一:單個字符的發送與接收

        #include  #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  #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  #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 #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進制顯示))。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 靖边县| 吴旗县| 湘阴县| 正安县| 肇庆市| 前郭尔| 德江县| 铜陵市| 潞西市| 咸宁市| 晴隆县| 游戏| 黄浦区| 平顶山市| 吉木乃县| 铜山县| 广汉市| 普安县| 镇远县| 齐河县| 翁源县| 雷州市| 甘南县| 乌拉特前旗| 丹阳市| 祁门县| 元朗区| 荣昌县| 汝城县| 财经| 崇州市| 嫩江县| 高平市| 桂平市| 海城市| 莒南县| 玉龙| 嘉定区| 会同县| 余庆县| 南木林县|