1 这你个案子中,波特率并不高。按理说,应该没有什么问题。2 U 转串的质量差别很大。我用过的最好的是 FT232 芯片的,自带的驱动程序还支持更改串口号。建议先用标准串口调试成功,再试 U 转串线。不用改代码,主要是测试挑选适用的 U 转串线。3 有可能的话,把协议改一下,分包传送。也就是发一个命令传一包。每一包传送 1024 字节。因为 PC 端的 RS-232 驱动缺省的缓冲区是这么大。如果一次传更多,要重新设置一下缓冲区大小。 命令可以包含包索引(也就是数据的地址偏移编码)信息。也可以在传回的数据后加校验码,出错时可以重传。 你现在的传输方式有可能丢数据。因为连续的实时传输中,你在中间插入的处理有可能导致出错。
Private Sub Command5_Click() '串口通讯进行温度数据提取
Dim testcode() As Byte
'Dim buffer1
Dim TestData
Dim j As Integer
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
IsReceiving = False
IsReceiving = True
RecData = ""
Text1 = ""
Text2 = ""
RichTextBox1 = ""
ReDim testcode(0)
testcode(0) = &H84 '发温度提取码
MSComm1.Output = testcode
'Timer1.Enabled = True
'Sleep (100) '根据硬件情况进行不同长度的延时' j = 0
'
' IsReceiving = True
' While (IsReceiving) '置接收标志并循环判断
' 'Sleep (50)
' DoEvents
' If (MSComm1.InBufferCount >= 1) Then '如果接收缓冲区有数
' MSComm1.InputLen = 0 '全部接收
' buffer1 = MSComm1.Input '放到buffer1变量中
' For i = LBound(buffer1) To UBound(buffer1)
' TestData = Hex(buffer1(i))
' RecData = RecData & buffer1(i) & Space(2)
' Next i
' 'j = j + 1
' 'Text1 = TestData
' 'Text2 = j
' End If
' If MSComm1.InBufferCount = 0 Then
' 'Sleep (10)
' If MSComm1.InBufferCount = 0 Then '延时后判断缓冲区仍无数据,表明已经接收完毕
' IsReceiving = False
' MsgBox "over"
' End If
' End If
' Wend
' MSComm1.PortOpen = False
End Sub
2、我把缓冲区改成32167. ,怕太小会冲掉数据,发现没什么变化。
3、试过用timer控件,1s触发一次,发一次提取数据的指令,单片机的程序也更改为每次发送1k字节(改为255个字节也试过,同样不行),VB接收处理的部分和上面程序一致,也是不行,笔记本假死,必须在任务管理器里面关掉程序,有时甚至蓝屏。
4、试过单片机每发送一个字节后延时10个ms,怕接收不及,也没用。
采用分包的方式,你遇到的时序问题基本上都可以解决。即发一条命令,接收一包数据。不推荐用 Timer 方式。采用 FT232 芯片的 U 转串,第一次安装驱动时就设置成固定的虚拟串口号。或者,在你的程序中通过读注册表动态地查找串口号。
While (IsReceiving) '置接收标志并循环判断
'Sleep (50)
DoEvents
If (MSComm1.InBufferCount >= 1) Then '如果接收缓冲区有数
MSComm1.InputLen = 0 '全部接收
buffer1 = MSComm1.Input '放到buffer1变量中
For i = LBound(buffer1) To UBound(buffer1)
TestData = Hex(buffer1(i))
RecData = RecData & buffer1(i) & Space(2)
Next i End If
If MSComm1.InBufferCount = 0 Then
'Sleep (10)
If MSComm1.InBufferCount = 0 Then '延时后判断缓冲区仍无数据,表明已经接收完毕
IsReceiving = False
MsgBox "over"
End If
End If
Wend
MSComm1.PortOpen = False
这部分接收的软件没什么问题吧?
2、今天去试了下,还是有点迷糊,如果一次接收不完的话该怎么定义数组,是不是应该定义个多维的才行?
3、以前用的是五线制通信,加上RTS和CTS,现在线路不够,只用三线制通信,少了CTS的握手,是不是在控制流量方面有影响啊?不太明白。
程序附下,请指点。
#include<reg52.h>
#include<absacc.h>#define M197H XBYTE[0xffff] //MAX197高字节地址
#define M197L XBYTE[0xfffe] //MAX197低字节地址#define uchar unsigned char
#define uint unsigned intsbit CTS = P3^4;
sbit RTS = P3^3;
extern uchar xdata *xdp=0; //存储器数据指针
extern uchar xdata *xdp1=0; //用于存储温度,地址从0-0x00ff
extern uchar xdata *xdp2=0; //用于存储压力,地址从0x0100-0x7fff
extern uint t0=0;
extern bit noteb=0;void init (void) //初始化
{
Timer_Init();//定时器初始化
noteb=0;
p35=0;
}void Timer_Init()
{
TMOD |= 0x11; //均作为16位定时器
TL0 = 0x0c;//TL0 = 0x18;
TH0 = 0xfe;//TH0 = 0xfc; //T0定时1ms,0xfc18为晶振12M的初值
ET0=1;
TL1 = 0x78;//TL1 = 0xf0;
TH1 = 0xec;//TH1 = 0xd8; //T1定时10ms,0xd8f0为晶振12M的初值
ET1=1;
PCON=0X80;//波特率翻倍
SCON=0XD0;//模式3,11位波特率可编程UART=8位数据+校验位+起始位+停止位
RCLK=1;//接收时钟标志,置位表示定时器2的溢出脉冲作为串行口模式1和模式3的接收时钟
TCLK=1;//发送时钟标志,置位意义同上
RCAP2H=0XFF;
RCAP2L=0Xd9;
TH2=0XFF;
TL2=0Xd9;
TR2=1; //T2初始化,6M晶振,串行通讯4800波特率 EA=1;
}void send232(uchar shu) //串行发送字符
{
//while(!TI);
TI=0;
ACC=shu;
TB8=~P;
SBUF=ACC;
}void tishu() // 提取数据子程序
{
delay(10);
while (1)
{
if (xdp > 0x7ff0) break; // 超出存储器空间,跳出
send232(*xdp);
xdp++;
delayms(2);//实际测试中如果延时3.5ms以上可以正常发送接收*/
}
}void tongxun(void) //通讯子程序
{
unsigned char recl,rech; // 定义接收数据字符变量
rech = rec232(0); //接收数据
recl = rec232(0x88);
if((rech == 0x01)&&(recl==0x40)) //射检指令
{
shejian();
}
else if(rech == 0x83) //提取压力数据指令
{
xdp = 0x0100;
tishu();
}
}void main (void) //主程序
{
uchar j,k,l;
bit csflag;//定义出水标志位
delay(10);
//AUXR=0X02;
init();
xdp=0x0000;
j=0;
k=0;
l=0;
csflag=0;
noteb=0;
xdp=0;
xdp1=0x0000; //存储温度
xdp2=0x0100; //存储压力 while(1)
{
tongxun();//一直接收判断指令
}
while(1);
}VB的大部分程序如下:
Private Sub Form_Load()
RecData = ""
ti = 0
'MSComm1.PortOpen = False
Timer1.Enabled = False
MSComm1.CommPort = 5
MSComm1.Settings = "4800,o,8,1"
MSComm1.InputLen = 0
MSComm1.InputMode = comInputModeBinary '设置串口通信参数
MSComm1.InBufferSize = 30240 '接收缓冲区设置的大一些
MSComm1.OutBufferSize = 512
MSComm1.SThreshold = 0
MSComm1.RThreshold = 0 '不响应oncomm事件
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
If MSComm1.PortOpen = True Then
MSComm1.PortOpen = False
End If
End SubPrivate Sub Command6_Click() '串口通信进行压力数据提取
Dim testcode() As Byte
Dim buffer1 '作为中间变量存放接收到的数据
'Dim shuzu1(), shuzu2()
Dim TestData
Dim j, k As Integer
If MSComm1.PortOpen = False Then
MSComm1.PortOpen = True
End If
RecData = ""
IsReceiving = False
IsReceiving = True
Text1 = ""
Text2 = ""
RichTextBox1 = ""
ReDim testcode(0)
testcode(0) = &H83 '发压力提取码
MSComm1.Output = testcode Sleep (1000) '根据硬件情况进行不同长度的延时 j = 0
IsReceiving = True
While (IsReceiving)
Sleep (50)
DoEvents
If (MSComm1.InBufferCount >= 1) Then '如果接收缓冲区有数
MSComm1.InputLen = 0
buffer1 = MSComm1.Input
For i = LBound(buffer1) To UBound(buffer1)
TestData = Hex(buffer1(i))
RecData = RecData & buffer1(i) & Space(2)
Next i
j = j + 1 '每次接收数据大于1,这里j用于计算收到的数据总数似乎没有效果
End If
' If j > 100 Then
' IsReceiving = False
' MsgBox "over"
' End If
If MSComm1.InBufferCount = 0 Then
Sleep (10)
If MSComm1.InBufferCount = 0 Then '延时后判断缓冲区仍无数据,表明已经接收完毕
IsReceiving = False
MsgBox "over"
End If
End If
Wend MSComm1.PortOpen = False
End Sub指令的发出没有问题,通过示波器能够看到单片机接到上位机的指令后向上位机发送数据,但上位机发送指令后即处于假死状态,开始以为是在运算,后来发现半个小时多的时间都没有响应,应该算是程序死机了。该如何正确接收,请指点,多谢了。
听同事讲上位机速度过快,应该sleep一段时间,但这个时间如何设定,没有头绪。