串口通信:
軟件調試,在調試過程中需要使用虛擬串口助手。在編程中注意設計時鐘和波特率。注意程序的串口設置和串口調試助手中串口設置相同。
單串口:
mode com2 9600,0,8,1
assign com2 <sin> sout
stime = 0
多串口:
mode com2 9600,0,8,1
assign com2 <s0in> s0out
0表示單片機的串口0
編程:
STC12介紹的方法:
接收一個字節的函數和發送字符串的函數,發送字符串需要知道字符串的長度。對于接收字符串的函數,可以仿照通過調用接收一個字節的函數,寫出接收字符串函數。
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只給出了發送函數,且發送函數有瑕疵,具體見最后分析。
void UART1_ISR(void) interrupt 4 using 1
{
if (RI) //接收數據
{
RI = 0; //清除RI位
}
if (TI) //發送數據
{
TI = 0; //清除TI位
busy = 0; //清忙標志
}
}
void SendData(unsigned char dat)
{
while (busy); //等待前面的數據發送完成
busy = 1;
SBUF= dat; //寫數據到UART數據寄存器
}
void SendString(char *s)
{
while(*s) //檢測字符串結束標志
{
SendData(*s++); //發送當前字符
}
}
SendString()字符串函數,當遇到發送的字符串里面有0x00就會終止,實用性不強。SendData()函數中三條語句的順序容易引起死機。
比較好的處理串口接收一個字節數據的方法,不采用中斷處理標志位。通過關中斷,然后處理串口接收標志,從而減少在處理過程中因為觸發中斷而造成的死循環。修改好的串口接收一個字節的代碼(這是采用的串口2接收一個字節數據的處理函數,其控制寄存器不支持位操作)如下:
void SendData(BYTE dat)
{
EA = 0;
S2BUF= dat; //SBUF=dat
while (!(S2CON & S2TI)); //等待前面的數據發送完成 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++);
}
}
一個比較好的接收處理框架(利用通信協議):
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))//如果收到文件頭而且當前未接收
{
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; // 當數據送緩沖區
}
else if(Rec_Len == (REC_MAX - 1)) // 接收完成
{
/* if(uarttext[Rec_Len] == CHECK_TAIL) // 表明接收成功未出錯
{
//
}
else // 有誤碼
{
}
Rec_Flag = 0;// 接收完成,標志清0
}
}
}
else if(TI)
{
TI =0;
busy=0;
}
}