这篇文章是笔者在编写51单片机与PC机串口通信程序后的体会和总结。
单片机程序使用C语言开发,开发工具Keil for 51;PC机程序使用VB语言开发,开发工具VB 6。 1.小疑惑
【问题引出】
(1)单片机端程序如下:
void main(void) //主函数
{
……
Send(0x41); //调用发送函数
……
}
void Send(char signal) //发送函数
{
SBUF=signal;
while(TI==0);
TI=0;
}
单片机发送的数据为一字节,类型为char型,内容是十六进制的41,如果解读为ASCII的话,表示字母A。
之所以Send()函数的参数定为字符型,是因为考虑到单片机SBUF寄存器大小为一字节,这样能够比较好的匹配。
(2)在PC机上运行着由VB编写的串口通信软件,该软件既可接收单片机的信息,也可向单片机发送信息。
用VB实现串口通信,需要使用MSComm控件,该控件的InputMode属性可以设置读取PC机串口缓冲区数据的方式,该属性有两种取值,一种是以文本方式读取,另一种是以二进制方式读取。当设置以文本方式读取时,VB程序会把收到的数据解读为字符。
MSComm控件的事件代码如下:
Private Sub MSComm1_OnComm() '串口控件事件代码
Dim data As String
data = MSComm1.Input '接收数据
Text1.Text = data
If data = "A" Then
……
End If
End Sub
如果单片机发送的是0x41,那么VB程序的文本框 Text1 中会显示字母A,同时由于表达式 data = "A" 的真值为真,Then后面的语句也会被执行。
若将 If data = "A" Then 一句改为 If data = A Then ,结果是Then后面的语句不被执行,显然,程序认为表达式 data = A 的真值为假。
原因很简单,因为data是String类型的数据,只有加双引号的A才与之在类型上相匹配,而不加双引号就错了。
【疑惑】
不过令人感到奇怪的是,如果单片机发送的是0x30—0x39,即0—9范围内的字符,VB程序中上述表达式无论加不加双引号,真值均为真,Then后的语句都会执行。是VB对数字字符的处理和其他字符不太一样,还是有什么别的原因呢?
现在能够肯定的是,不管传送的是什么字符,VB语句一律加双引号就一定不会错。 2.串口传送字符的语句怎样写才正确
单片机与PC机串口传送字符,本质上传送的是字符的ASCII码。
(1)在单片机端
【发送语句】
发送语句Send(0x41)与Send('A')效果是相同的,Send(0x35)与Send('5')效果是相同的,它们都是正确的。
【接收语句】
以下是两个“数据接收及匹配处理”程序段,它们是等效且正确的。
程序段a:
char REC;
REC=Receive(); //接收数据,Receive()为接收函数
switch(REC) //对数据进行判断处理,点亮相应的LED
{
case 0x311=0xf0;break;
case 0x321=0x0f;break;
case 0x331=0xff;break;
}
程序段b:
char REC;
REC=Receive(); //接收数据,Receive()为接收函数
switch(REC) //对数据进行判断处理,点亮相应的LED
{
case '1'1=0xf0;break;
case '2'1=0x0f;break;
case '3'1=0xff;break;
}
在程序段a中,匹配条件以ASCII码形式给出;而在程序段b中,匹配条件则直接以字符形式给出。无论什么形式,作用是一样的。
(2)在PC机端
【发送语句】
VB利用MSComm控件发送一个数字字符“1”的语句可以写为:
MSComm1.Output = "1"
以下两种写法则是不正确的:
MSComm1.Output = &H31
MSComm1.Output = 1
&H31虽为字符“1”的ASCII码,但该句的语法有问题。
MSComm1.Output = 1 一句中丢掉了双引号,也是不对的。
【接收语句】
接收语句的正确写法详见本文的第一个问题。