串口通信:
軟件調(diào)試,在調(diào)試過程中需要使用虛擬串口助手。在編程中注意設(shè)計時鐘和波特率。注意程序的串口設(shè)置和串口調(diào)試助手中串口設(shè)置相同。
單串口:
mode com2 9600,0,8,1
assign com2 <sin> sout
stime = 0
多串口:
mode com2 9600,0,8,1
assign com2 <s0in> s0out
0表示單片機(jī)的串口0
編程:
STC12介紹的方法:
接收一個字節(jié)的函數(shù)和發(fā)送字符串的函數(shù),發(fā)送字符串需要知道字符串的長度。對于接收字符串的函數(shù),可以仿照通過調(diào)用接收一個字節(jié)的函數(shù),寫出接收字符串函數(shù)。
void WriteUart(uchar *pucData ,ucharucLength)
{
if(ucLength== 0)
{
return;
}
if(UartBuzy== 1)
return;
ucSendLength= ucLength;
pucSendData= pucData;
SBUF= *pucSendData;
UartBuzy= 1;
ucSendedCount= 0;
}
uchar ReadUart(void)
{
ucharData;
Data= ucRecData;
ucRecData= 0;
returnData;
}
Unsigned char RString(unsigned char *s, unsigned intlen)
{
Unsigned int i;
For(i =0;i<len ;i++)
{
*s++ = ReadUart();
}
}
void UartIRQ(void) interrupt 4
{
if(RI)
{
RI = 0;
ucRecData = SBUF;
}
if(TI)
{
TI = 0;
ucSendedCount++;
if(ucSendedCount >= ucSendLength)
{
UartBuzy= 0;
return;
}
else
{
SBUF= *(pucSendData + ucSendedCount);
}
}
}
STC15:
STC15只給出了發(fā)送函數(shù),且發(fā)送函數(shù)有瑕疵,具體見最后分析。
void UART1_ISR(void) interrupt 4 using 1
{
if (RI) //接收數(shù)據(jù)
{
RI = 0; //清除RI位
}
if (TI) //發(fā)送數(shù)據(jù)
{
TI = 0; //清除TI位
busy = 0; //清忙標(biāo)志
}
}
void SendData(unsigned char dat)
{
while (busy); //等待前面的數(shù)據(jù)發(fā)送完成
busy = 1;
SBUF= dat; //寫數(shù)據(jù)到UART數(shù)據(jù)寄存器
}
void SendString(char *s)
{
while(*s) //檢測字符串結(jié)束標(biāo)志
{
SendData(*s++); //發(fā)送當(dāng)前字符
}
}
SendString()字符串函數(shù),當(dāng)遇到發(fā)送的字符串里面有0x00就會終止,實用性不強(qiáng)。SendData()函數(shù)中三條語句的順序容易引起死機(jī)。
比較好的處理串口接收一個字節(jié)數(shù)據(jù)的方法,不采用中斷處理標(biāo)志位。通過關(guān)中斷,然后處理串口接收標(biāo)志,從而減少在處理過程中因為觸發(fā)中斷而造成的死循環(huán)。修改好的串口接收一個字節(jié)的代碼(這是采用的串口2接收一個字節(jié)數(shù)據(jù)的處理函數(shù),其控制寄存器不支持位操作)如下:
void SendData(BYTE dat)
{
EA = 0;
S2BUF= dat; //SBUF=dat
while (!(S2CON & S2TI)); //等待前面的數(shù)據(jù)發(fā)送完成 while(TI);
S2CON&= ~S2TI; //TI = 0;
EA= 1;
}
Unsigned char SendString(unsigned char *s, unsignedint len)
{
Unsigned int i;
For(i =0;i<len ;i++)
{
SendData(*s++);
}
}
一個比較好的接收處理框架(利用通信協(xié)議):
void UART1_ISR(void) interrupt 4 using 1
{
unsigned char sbuffer;
if(RI)
{
RI = 0;
sbuffer = SBUF;
if(nflag == 0)
{
REC_MAX =REC_MAX_NAME ;
}
else
REC_MAX =REC_MAX_DATA;
if((sbuffer == CHECK_HEAD) && (Rec_Flag == 0))//如果收到文件頭而且當(dāng)前未接收
{
Rec_Flag = 1;
Rec_Len = 0;
uarttext[0]= sbuffer; // 這里保留了包頭
}
else if(Rec_Flag) // 開始接收
{
if(Rec_Len < (REC_MAX - 1))
{
Rec_Len++;
uarttext[Rec_Len] = sbuffer; // 當(dāng)數(shù)據(jù)送緩沖區(qū)
}
else if(Rec_Len == (REC_MAX - 1)) // 接收完成
{
/* if(uarttext[Rec_Len] == CHECK_TAIL) // 表明接收成功未出錯
{
//
}
else // 有誤碼
{
}
Rec_Flag = 0;// 接收完成,標(biāo)志清0
}
}
}
else if(TI)
{
TI =0;
busy=0;
}
}