使用半雙工通信
/************************************
使用硬件UART模塊和串口中斷
************************************/
#include
typedefunsignedintuint;
voidconfigUART(uintbaud);
voidmain(){
EA=1;
configUART(9600);
while(1);
}
voidconfigUART(uintbaud){
SCON=0x50;//配置串口為模式1,并使能串行接收
TMOD&=0x0F;//清零T1的控制位
TMOD|=0x20;//配置T1為模式2(自動重裝模式)
TH1=256-11059200/12/16/2/baud;
TL1=TH1;
ET1=0;//!?。〗筎1中斷(因為做了波特率發(fā)生器)
ES=1;//使能串口中斷
TR1=1;
}
//中斷類型碼為4,中斷向量的地址=中斷類型碼*8+3
voidinterruptUART()interrupt4{
if(RI){//如果接收到了字節(jié)
RI=0;//手動清零
SBUF++;//可以自己設(shè)置接收到后數(shù)據(jù)的處理方式
}
if(TI){//如果字節(jié)發(fā)送完畢
TI=0;//手動清零
}
}
下面的程序把書上的代碼做了點優(yōu)化,加了一個isNewInfo,在主循環(huán)里判斷只有當(dāng)接收到了新的字節(jié)數(shù)據(jù)以后才更新顯示緩沖區(qū)。
#include
typedefunsignedcharuchar;
typedefunsignedintuint;
typedefunsignedlongulong;
sbitADDR3=P1^3;
sbitENLED=P1^4;
ucharcodeLEDChar[]={//數(shù)碼管顯示字符轉(zhuǎn)換表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
ucharLEDBuf[7]={//數(shù)碼管和獨立LED的顯示緩沖區(qū)
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
ucharT0RH=0;//T0重載值的高字節(jié)
ucharT0RL=0;//T0重載值的低字節(jié)
ucharRXDByte=0;//串口接收到的字節(jié)
bitisNewInfo=0;//是否接收到了新信息
voidconfigTmr0(uintms);
voidconfigUART(uintbaud);
voidLEDScan();
//voidinterruptTmr0();
//voidinterruptUART();
voidmain(){
EA=1;//使能總中斷
ENLED=0;//選擇數(shù)碼管和獨立LED
ADDR3=1;
configTmr0(1);//配置T0定時1ms
configUART(9600);//配置波特率為9600
while(1){//將接收字節(jié)在數(shù)碼管上以十六進(jìn)制形式顯示出來
if(isNewInfo){
LEDBuf[0]=LEDChar[RXDByte&0x0F];
LEDBuf[1]=LEDChar[RXDByte>>4];
isNewInfo=0;
}
}
}
/*配置并啟動T0,ms-T0定時時間*/
voidconfigTmr0(uintms){
ulongtmp;//臨時變量
tmp=11059200/12;//定時器計數(shù)頻率
tmp=(tmp*ms)/1000;//計算所需的計數(shù)值
tmp=65536-tmp;//計算定時器重載值
tmp=tmp+13;//補償中斷響應(yīng)延時造成的誤差
T0RH=(uchar)(tmp>>8);//定時器重載值拆分為高低字節(jié)
T0RL=(uchar)tmp;
TMOD&=0xF0;//清零T0的控制位
TMOD|=0x01;//配置T0為模式1
TH0=T0RH;//加載T0重載值
TL0=T0RL;
ET0=1;//使能T0中斷
TR0=1;//啟動T0
}
/*串口配置函數(shù),baud-通信波特率*/
voidconfigUART(uintbaud){
SCON=0x50;//配置串口為模式1
TMOD&=0x0F;//清零T1的控制位
TMOD|=0x20;//配置T1為模式2
TH1=256-(11059200/12/32)/baud;//計算T1重載值
TL1=TH1;//初值等于重載值
ET1=0;//禁止T1中斷
ES=1;//使能串口中斷
TR1=1;//啟動T1
}
/*LED動態(tài)掃描刷新函數(shù),需在定時中斷中調(diào)用*/
voidLEDScan(){
staticuchari=0;//動態(tài)掃描索引
P0=0xFF;//關(guān)閉所有段選位,顯示消隱
P1=(P1&0xF8)|i;//位選索引值賦值到P1口低3位
P0=LEDBuf[i];//緩沖區(qū)中索引位置的數(shù)據(jù)送到P0口
if(i<6)//索引遞增循環(huán),遍歷整個緩沖區(qū)
i++;
else
i=0;
}
/*T0中斷服務(wù)函數(shù),完成LED掃描*/
voidinterruptTmr0()interrupt1{
TH0=T0RH;//重新加載重載值
TL0=T0RL;
LEDScan();//LED掃描顯示
}
/*UART中斷服務(wù)函數(shù)*/
voidinterruptUART()interrupt4{
if(RI){//接收到字節(jié)
RI=0;//手動清零接收中斷標(biāo)志位
RXDByte=SBUF;//接收到的數(shù)據(jù)保存到接收字節(jié)變量中
SBUF=RXDByte;//接收到的數(shù)據(jù)又直接發(fā)回,叫作-"echo",