串口通信:
软件调试,在调试过程中需要使用虚拟串口助手。在编程中注意设计时钟和波特率。注意程序的串口设置和串口调试助手中串口设置相同。
单串口:
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;
}
}