51單片機(jī)軟件用定時(shí)器模擬串口程序
//使用硬件:定時(shí)器0,定時(shí)器0中斷,定時(shí)器1中斷,外中斷5
//波特率 9600 4800 2400 1200 600 300
//每BIT周期數(shù)9696*2 96*4 96*8 96*16 96*32
//以96為單位不同的波特率選用不同的倍率
//如果對(duì)方在每位的1/2處采樣,則發(fā)送中斷的響應(yīng)時(shí)間最多是48個(gè)時(shí)鐘周期
//也許可以置發(fā)送中斷以較高的優(yōu)先級(jí)來(lái)解決,實(shí)驗(yàn)表明發(fā)送可以工作于9600
//但若有其它中斷,并且串口工作于全雙工,則晶體頻率最好是22.1184以上
//!!實(shí)測(cè)表明當(dāng)用11.0592時(shí)鐘,標(biāo)準(zhǔn)51,收發(fā)同時(shí),最高只能到2400波特。
//但單發(fā)可以工作于9600
#define BAUD_RATE 300
//#define BAUD_RATE 600
//#define BAUD_RATE 1200
//#define BAUD_RATE 2400
//#define BAUD_RATE 4800
//#define BAUD_RATE 9600
#define clock 110592
//#define clock 221184
#define RELOAD(TIMER,SVALUE) TIMER+=SVALUE+1
bit tTI;
bit rRI;
unsigned char rSBUF;
unsigned char tSBUF;
unsigned char rSBUF0;
unsigned char RxdCnt;
unsigned char rSmpCnt;
unsigned char TxdCnt;
unsigned char tSmpCnt;
unsigned char multiple;
//-----------------------------------------------------------
void SimuUARTinit(void)
{
#if BAUD_RATE==300
if(clock==110592)
multiple=32;
else if(clock==221184)
multiple=64;
#endif
#if BAUD_RATE==600
if(clock==110592)
multiple=16;
else if(clock==221184)
multiple=32;
#endif
#if BAUD_RATE==1200
if(clock==110592)
multiple=8;
else if(clock==221184)
multiple=16;
#endif
#if BAUD_RATE==2400
if(clock==110592)
multiple=4;
else if(clock==221184)
multiple=8;
#endif
#if BAUD_RATE==4800
if(clock==110592)
multiple=2;
else if(clock==221184)
multiple=4;
#endif
#if BAUD_RATE==9600
if(clock==110592)
multiple=1;
else if(clock==221184)
multiple=2;
#endif
tTI=1;
tTXD=1;
rRXD=1;
TMOD&=0xf0;
TMOD|=0x03;
ET0=1;
ET1=1;
TR0=1;
IT0=1;
EX0=1;
TR1=1;
PT1=1; //置串口發(fā)送為高優(yōu)先級(jí)
EA=1;
}
//-----------------------------------------------------------
//模擬串口發(fā)送中斷,原定時(shí)器1中斷
void IntTH0(void) interrupt 3
{
RELOAD(TH0,-96);
if(--tSmpCnt == 0)
{
tSmpCnt=multiple;
if(tTI) return;
switch(TxdCnt++)
{
case 0:
tTXD=0;
break;
case 9:
tTXD=1;
tTI=1;
TxdCnt=0;
break;
default:
tTXD=tSBUF&0x01;
tSBUF>>=1;
break;
}
}
}
//-----------------------------------------------------------
void RxdInt0(void) interrupt 0
{
TL0=-96+4; //The time of inter interrup
ET0=1;
TF0=0;
rSmpCnt=multiple/2;
}
//----------------------------------------------------------
//模擬串口接收中斷,原定時(shí)器0中斷
void IntTL0(void) interrupt 1
{
RELOAD(TL0,-96);
if(--rSmpCnt == 0)
{
rSmpCnt=multiple;
switch(RxdCnt++)
{
case 0:
if(rRXD==1){RxdCnt=0;}//ET0=0 added,no startbitfound then stop interrup
break;
case 9:
RxdCnt=0;
if(rRXD==0) return;
rSBUF=rSBUF0;
rRI=1;
break;
default:
if(RxdCnt>9){ RxdCnt=0;return;}
rSBUF0>>=1;
rSBUF0|=rRXD?0x80:0;
break;
}
}
}
//-----------------------------------------------------------
評(píng)論