謝謝這位同學首先做的筆記,讓我明白了很多:http://www.cnblogs.com/freesblog/p/5040474.html
剛開始也是一直亂碼,直到昨天我才解決了亂碼的問題,原來這一切都是晶振頻率惹的禍,今天開始不會亂碼了。可以發送單個字符了。但是又出現了一個新的問題,一個很長的字符串怎么辦?
很多人想,那好辦啊,下面這個程序就可以:
/*發送一個字符串*/ void send_string(uchar *p){ while(*p!= '\0'){ send_byte(*p); p++; } }
這樣不就可以實現字符串的發送了嗎?是的,沒錯,但是在send_byte()這個函數里面該怎么寫?其實這個函數寫不好很容易和中斷函數沖突。
當然,你可以這樣寫:
/*發送一個字符*/ void send_byte(uchar by){ SBUF = by; while(!TI);//等待發送完畢 TI = 0; }
如果你這樣寫了,那么你要么不要打開串口中斷,要么就在串口中斷里面什么都不寫(如果你只是發送,不接收的話),這里只是講發送,接收是一個道理的。如果你在中斷函數里面寫了下面這樣的程序:
void uart_interrupt() interrupt 4{ if(RI==1)RI = 0; if(TI==1)TI = 0; }
那么,恭喜你,你不會在電腦端收到任何數據的(不對,你能收到字符串的第一個字符)。原因很簡單:
當一個字符發送/接收完畢的時候 ,發送/接收標志位TI/RI會自動置1,如果你在初始化里面打開了串口中斷的話,程序一定進入中斷函數里面去執行:if(TI==1)TI = 0;而不是先執行while(!TI);//等待發送完畢
,所以,在中斷里面TI又置了0,然后回到while(!TI);這樣,就陷入了一個死循環。你的程序就卡在這里了。
總結:
當你發現無法發送字符串的 時候,首先檢查自己的比特率是否對,就是檢查能不能發送單個字符,如果單個字符發送沒有問題,那么一定能發送字符串。
接下來檢查你的初始化程序中有沒有打開 串口中斷。如果打開,看中斷函數 有沒有和單個字符發送函數沖突。
當然,當你只是發送數據的話,不接受,不打開串口中斷也是可以的,就是自己手動清零中斷標志。
下面附上源程序(親測可用):
#include "reg52.h" #include "stdio.h" #define uchar unsigned char #define uint unsigned int void uart_cfg(); void send_byte(uchar by); void send_string(uchar *p); void delayms(uchar i); uchar str[] = "yes,you aer good!"; void main(){ uart_cfg(); //波特率4800 ,0xf9 while(1){ send_string(str); delayms(100); } } void uart_cfg(){ SCON = 0X50;//MODE 1 TMOD&= 0X0F;//清除T1的控制位 TMOD|= 0X20;//T1的工作模式2 PCON|= 0X80;//倍頻 TH1 = 0xf3; //4800 TL1 = TH1; ET1 = 0;//禁止T1中斷 // EA = 1; TR1 = 1; // ES = 1;//使能串口中斷 ,無論是TI/RI出現,只要中斷打開,單片機就進入中斷函數。 } /*中斷處理函數*/,如上面所說,寫不寫都一樣。這里我屏蔽掉了 // void uart_interrupt() interrupt 4{ // // if(RI==1)RI = 0; // // if(TI==1); // //TI = 0; // } /*發送一個 字符*/ void send_byte(uchar by){ SBUF = by; while(!TI);//當寫下這句的時候,就不要在中斷函數里面在寫TI = 0;這句了,不然進入中斷函數將TI清零之后,程序就會一直卡在這里 TI = 0; //在這里將TI清零 } /*發送一個字符串*/ void send_string(uchar *p){ while(*p!= '\0'){ send_byte(*p); p++; } } /*簡單延時*/ void delayms(uchar i) { uint j; while(i--) { for(j = 0; j < 150; j++); } }
發送成功: