一、 使用晶體頻率為22.1184MHz的AT89C52單片機,串行口應用工作方式1,以9600bps的波特率向外發送數據,數據為十個數字‘0’到‘9’,循環不斷地發送。
解:數字字符為增量進二進制碼,‘0’對應0x30,‘1’= ‘0’+ 1 = 0x31,從‘0’到‘9’對應編碼為0x30到0x39,記憶二進制編碼較難,實際編程中用單引號括起對應字符表示引用該字符的二進制編碼值,如‘?’表示引用?號的編碼值。
在用11.0592MHz晶體時,9600bps的初始化分頻初值為-6,現晶頻加倍,如果其它條件不變,只有分頻初始加倍為-12,才能得到9600bps;如果想得到2400bps(速率降4倍),分頻初始自然加大4倍,即為-48。根據題意編得如下程序:
#include <at89x52.h>
void main( void )
{
TMOD = (TMOD & 0x0F) | 0x20;
TH1 = -12;
PCON |= 0x80; //SMOD = 1
TR1 = 1;
SCON = 0x42;
while( 1 )
{
if( TI==1 )
{
static unsigned char Dat=‘0’;
SBUF = Dat;
TI = 0;
If( ++Dat > ‘9’) Dat=‘0’;
}
}
}
二、 在上題的基礎上,改為2400bps,循環發送小寫字母‘a’到‘z’,然后是大寫字母‘A’到‘Z’。
#include <at89x52.h>
void main( void )
{
TMOD = (TMOD & 0x0F) | 0x20;
TH1 = -96; //注意不用倍頻方式
PCON &= 0x7F; //SMOD = 0
TR1 = 1;
SCON = 0x42;
while( 1 )
{
if( TI==1 )
{
static unsigned char Dat=‘a’;
SBUF = Dat;
TI = 0;
//If( ++Dat > ‘9’) Dat=‘0’;
++Dat;
if( Dat == (‘z’+1) ) Dat=‘A’;
if( Dat == (‘Z’+1) ) Dat=‘a’;
}
}
}
上述改變值時,也可以再設一變量表示當前的大小寫狀態,比如寫成如下方式:
++Dat;
{
static unsigned char Caps=1;
if( Caps != 0 )
if( Dat>‘Z’){ Dat=‘a’; Caps=0; }
else
if( Dat>‘z’){ Dat=‘A’; Caps=1; }
}
如下寫法有錯誤:因為小b比大Z的編碼值大,所以Dat總是‘a’
++Dat;
if( Dat>‘Z’){ Dat=‘a’}
else if( Dat>‘z’){ Dat=‘A’}
三、 有A和B兩臺單片機,晶體頻率分別為13MHz和14MHz,在容易編程的條件下,以最快的速度進行雙工串行通信,A給B循環發送大寫字母從‘A’到‘Z’,B給A循環發送小寫字母從‘a’到‘z’,雙方都用中斷方式進行收發。
解:由于晶體頻率不同,又不成2倍關系,所以只有通信方式1和方式3,由于方式3的幀比方式1多一位,顯然方式3的有效數據(9/11)比方式1(8/10)高,但要用方式3的第9位TB8來發送數據,編程難度較大,這里方式1較容易編程。
在計算最高速率時,由于單方程,雙未知數,又不知道波特率為多少,所以要綜合各方面的條件,估算出A和B的分頻常數,分別為-13和-14時,速率不但相同,且為最大值。如下給出A機的程序:
#include <at89x52.h>
void main( void )
{
TMOD = (TMOD & 0x0F) | 0x20;
TH1 = -13; //注意用倍頻方式
PCON |= 0x80; //SMOD = 1
TR1 = 1;
SCON = 0x52; //REN = 1
ES = 1;
EA = 1;
while( 1 );
}
void RS232_intr( void ) interrupt 4 //注意RI和TI任一位變為1都中斷
{
unsigned char rDat;
if( RI == 1 ){ RI=0; rDat=SBUF; }
if( TI==1 )
{
static unsigned char tDat=‘a’;
SBUF = tDat;
TI = 0;
If( ++Dat > ‘z’) Dat=‘a’;
}





