新聞中心

51單片機串口程序

作者: 時間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
串口中斷服務(wù)函數(shù)集

//本函數(shù)集來自“51單片機世界”,作者斑竹丁丁(聶小猛)。
//主頁地址http://www.mcu51.com
//串口中斷服務(wù)程序,僅需做簡單調(diào)用即可完成串口輸入輸出的處理
//出入均設(shè)有緩沖區(qū),大小可任意設(shè)置。
//可供使用的函數(shù)名:
//chargetbyte(void);從接收緩沖區(qū)取一個byte,如不想等待則在調(diào)用前檢測inbufsign是否為1。
//getline(charidata*line,unsignedcharn);獲取一行數(shù)據(jù)回車結(jié)束,必須定義最大輸入字符數(shù)
//putbyte(charc);放入一個字節(jié)到發(fā)送緩沖區(qū)
//putbytes(unsignedchar*outplace,j);放一串?dāng)?shù)據(jù)到發(fā)送緩沖區(qū),自定義長度
//putstring(unsignedcharcode*puts);發(fā)送一個定義在程序存儲區(qū)的字符串到串口
//puthex(unsignedcharc);發(fā)送一個字節(jié)的hex碼,分成兩個字節(jié)發(fā)。
//putchar(ucharc,ucharj);輸出一個無符號字符數(shù)的十進制表示,必須標(biāo)示小數(shù)點的位置,自動刪除前面無用的零
//putint(uintui,ucharj);輸出一個無符號整型數(shù)的十進制表示,必須標(biāo)示小數(shù)點的位置,自動刪除前面無用的零
//delay(unsignedchard);延時nx100ns
//putinbuf(ucharc);人工輸入一個字符到輸入緩沖區(qū)
//CR;發(fā)送一個回車換行
//*
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineOLEN32/*sizeofserialtransmissionbuffer*/
idataunsignedcharoutbuf[OLEN];/*storagefortransmissionbuffer*/
unsignedcharidata*outlast=outbuf;//最后由中斷傳輸出去的字節(jié)位置
unsignedcharidata*putlast=outbuf;//最后放入發(fā)送緩沖區(qū)的字節(jié)位置
#defineILEN12/*sizeofserialreceivingbuffer*/
idataunsignedcharinbuf[ILEN];
unsignedcharidata*inlast=inbuf;//最后由中斷進入接收緩沖區(qū)的字節(jié)位置
unsignedcharidata*getlast=inbuf;//最后取走的字節(jié)位置
bitoutbufsign0;//最后一個數(shù)據(jù)覵BUF發(fā)完標(biāo)志發(fā)完=0
bitoutbufsign;//輸出緩沖區(qū)非空標(biāo)志有=1
bitinbufsign;//接收緩沖區(qū)非空標(biāo)志有=1
bitinbufful;//輸入緩沖區(qū)滿標(biāo)志滿=1
#defineCRputstring("/r/n")//CR=回車換行

//*
//延時nx100ns
voiddelay(unsignedchard)//在源程序開頭定義是否用w77e58或22。1184M晶振
{unsignedcharj;
do{d--;

//110592&89c52
#ifndefcpuw77e58
#ifndefxtal221184
j=21;//k=38cpu80320100usk=21cpu8052
#else
j=42;
#endif
#else
#ifndefxtal221184
j=38;
#else
j=76;
#endif
#endif

do{j--;}while(j!=0);
}while(d!=0);
}
//*
//放入一個字節(jié)到發(fā)送緩沖區(qū)

putbyte(charc)
{uchari,j;
ES=0;/*暫停串行中斷,以免數(shù)據(jù)比較時出錯?*/
//if(outlast=putlast)
while((((outlast-putlast)==2)&&(outlast>putlast))||((outlast{ES=1;c++;c--;ES=0;
//i=(0-TH1);
//do{i--;j=39;do{j--;}while(j!=0);}while(i!=0);//i=39
}
*putlast=c;//放字節(jié)進入緩沖區(qū)
putlast++;//發(fā)送緩沖區(qū)指針加一
if(putlast==outbuf+OLEN)putlast=outbuf;//指針到了頂部換到底部
outbufsign=1;
if(!outbufsign0){outbufsign0=1;TI=1;}//緩沖區(qū)開始為空置為有,啟動發(fā)送
ES=1;
}
//
//放一串?dāng)?shù)據(jù)到發(fā)送緩沖區(qū)
putbytes(unsignedchar*outplace,unsignedcharj)
{inti;
for(i=0;i{putbyte(*outplace);
outplace++;
}
}
//
//輸出一個無符號字符數(shù)的十進制表示,必須標(biāo)示小數(shù)點的位置,自動刪除前面無用的零
//例如putchar(0x32,2),輸出"4.8".
//putchar(0x32,3),輸出"0.48".
//putchar(0x32,1),輸出"48".
putchar(ucharc,ucharj)
{ucharidatafree[4];uchardatai;
i=0;
free[i++]=(c/100+0x30);
if(j==3)free[i++]=.;
free[i++]=(c%100)/10+0x30;
if(j==2)free[i++]=.;
if(j==2&&free[i-3]==0x30)free[i-3]=0x20;
free[i++]=(c%10)+0x30;
if(j==1&&free[i-3]==0x30)free[i-3]=0x20;
if(j==1&&free[i-3]==0x20&&free[i-2]==0x30)free[i-2]=0x20;
putbytes(free,i);
}

//
//輸出一個無符號整型數(shù)的十進制表示,必須標(biāo)示小數(shù)點的位置,自動刪除前面無用的零
putint(uintui,ucharj)
{ucharidatafree[6];
uchardatai;
i=0;
free[i++]=(ui/10000+0x30);
if(j==5)free[i++]=.;
free[i++]=((ui%10000)/1000+0x30);
if(j==4)free[i++]=.;
if(j==4&&free[i-3]==0x30)free[i-3]=0x20;
free[i++]=((ui%1000)/100+0x30);
if(j==3)free[i++]=.;
if(j==3&&free[i-4]==0x30)free[i-4]=0x20;
if(j==3&&free[i-4]==0x20&&free[i-3]==0x30)free[i-3]=0x20;
free[i++]=((ui%100)/10+0x30);
if(j==2)free[i++]=.;
if(j==2&&free[i-5]==0x30)free[i-5]=0x20;
if(j==2&&free[i-5]==0x20&&free[i-4]==0x30)free[i-4]=0x20;
if(j==2&&free[i-5]==0x20&&free[i-4]==0x20&&free[i-3]==0x30)free[i-3]=0x20;
free[i++]=(ui%10+0x30);
if(j==1&&free[i-5]==0x30)free[i-5]=0x20;
if(j==1&&free[i-5]==0x20&&free[i-4]==0x30)free[i-4]=0x20;
if(j==1&&free[i-5]==0x20&&free[i-4]==0x20&&free[i-3]==0x30)free[i-3]=0x20;
if(j==1&&free[i-5]==0x20&&free[i-4]==0x20&&free[i-3]==0x20&&free[i-2]==0x30)free[i-2]=0x20;
putbytes(free,i);
}
//*
//發(fā)送一個定義在程序存儲區(qū)的字符串到串口
putstring(unsignedchar*puts)
{for(;*puts!=0;puts++)//遇到停止符0結(jié)束
putbyte(*puts);
}
//*
//發(fā)送一個字節(jié)的hex碼,分成兩個字節(jié)發(fā)。
unsignedcharcodehex_[]={"0123456789ABCDEF"};
puthex(unsignedcharc)
{intch;
ch=(c>>4)&0x0f;
putbyte(hex_[ch]);
ch=c&0x0f;
putbyte(hex_[ch]);
}
//*
//從接收緩沖區(qū)取一個byte,如不想等待則在調(diào)用前檢測inbufsign是否為1。
uchargetbyte(void)
{charidatac;
while(!inbufsign);//緩沖區(qū)空等待
ES=0;
c=*getlast;//取數(shù)據(jù)
getlast++;//最后取走的數(shù)據(jù)位置加一
inbufful=0;//輸入緩沖區(qū)的滿標(biāo)志清零
if(getlast==inbuf+ILEN)getlast=inbuf;//地址到頂部回到底部
if(getlast==inlast)inbufsign=0;//地址相等置接收緩沖區(qū)空空標(biāo)志,再取數(shù)前要檢該標(biāo)志
ES=1;
return(c);//取回數(shù)據(jù)
}
//*
//接收一行數(shù)據(jù),必須定義放數(shù)據(jù)串的指針位置和大小del=0x7f,backspace=0x08,cr=0x0d,lf=0x0a
voidgetline(ucharidata*line,unsignedcharn)
{unsignedcharcnt=0;//定義已接收的長度
charc;
do{
if((c=getbyte())==0x0d)c=0x00;//讀一個字節(jié),如果是回車換成結(jié)束符
if(c==0x08||c==0x7f)//BACKSPACE和DEL的處理
{if(cnt!=0)//已經(jīng)輸入退掉一個字符
{cnt--;//總數(shù)目減一
line--;//指針減一
putbyte(0x08);//屏幕回顯的處理
putbyte();
putbyte(0x08);
}
}
else
{putbyte(*line=c);//其他字符取入,回顯
line++;//指針加一
cnt++;//總數(shù)目加一
}
}while(cnt*line=0;//再加上停止符0
}
//
//人工輸入一個字符到輸入緩沖區(qū)
putinbuf(ucharc)
{ES=0;if(!inbufful)
{*inlast=c;//放入數(shù)據(jù)
inlast++;//最后放入的位置加一
if(inlast==inbuf+ILEN)inlast=inbuf;//地址到頂部回到底部
if(inlast==getlast)inbufful=1;//接收緩沖區(qū)滿置滿標(biāo)志
inbufsign=1;
}
ES=1;
}
//*
//串口中斷處理
serial()interrupt4
{if(TI)
{TI=0;
if(outbufsign)
//if(putlast==outlast)outbufsign=0;
//else
{SBUF=*outlast;//未發(fā)送完繼續(xù)發(fā)送
outlast++;//最后傳出去的字節(jié)位置加一
if(outlast==outbuf+OLEN)outlast=outbuf;//地址到頂部回到底部
if(putlast==outlast)outbufsign=0;//數(shù)據(jù)發(fā)送完置發(fā)送緩沖區(qū)空標(biāo)志
}
elseoutbufsign0=0;
}
if(RI)
{RI=0;
if(!inbufful)
{
*inlast=SBUF;//放入數(shù)據(jù)
inlast++;//最后放入的位置加一
inbufsign=1;
if(inlast==inbuf+ILEN)inlast=inbuf;//地址到頂部回到底部
if(inlast==getlast)inbufful=1;//接收緩沖區(qū)滿置滿標(biāo)志

}
}
}
//*
//串口初始化0xfd=19200,0xfa=9600,0xf4=4800,0xe8=2400,0xd0=1200
serial_init(){
SCON=0x50;/*mode1:8-bitUART,enablereceiver*/
TMOD|=0x20;/*timer1mode2:8-Bitreload*/
PCON|=0x80;TH1=0xfA;//fa,//baud*2/*reloadvalue19200baud*/
TR1=1;/*timer1run*/
ES=1;REN=1;EA=1;SM2=1;//SM2=1時收到的第9位為1才置位RI標(biāo)志
TMOD|=0x01;//th1autoload2X8,th01X16
TH0=31;TL0=0;//X32=1S
TR0=1;//ET0=1;

}
//*
//測試用主函數(shù)

voidmain(void)
{charc;
idataunsignedcharfree[16];
unsignedcharidata*freep=free;
serial_init();


putstring("jdioptuejls;j;klj");
delay(10);

while(1)
{putstring("comisready!");}
c=getbyte();
putbyte(0x20);
puthex(c);
switch(c)
{caser:
putbytes(inbuf,ILEN);
break;
caseg:
getline(freep,10);
putbyte(0x20);
putstring(freep);
break;
default:
putbyte(c);
//}
}
}



關(guān)鍵詞: 51單片機串口程

評論


技術(shù)專區(qū)

關(guān)閉