1 这你个案子中,波特率并不高。按理说,应该没有什么问题。2 U 转串的质量差别很大。我用过的最好的是 FT232 芯片的,自带的驱动程序还支持更改串口号。建议先用标准串口调试成功,再试 U 转串线。不用改代码,主要是测试挑选适用的 U 转串线。3 有可能的话,把协议改一下,分包传送。也就是发一个命令传一包。每一包传送 1024 字节。因为 PC 端的 RS-232 驱动缺省的缓冲区是这么大。如果一次传更多,要重新设置一下缓冲区大小。  命令可以包含包索引(也就是数据的地址偏移编码)信息。也可以在传回的数据后加校验码,出错时可以重传。  你现在的传输方式有可能丢数据。因为连续的实时传输中,你在中间插入的处理有可能导致出错。

解决方案 »

  1.   

    感谢关注和回复,先附上程序,前面发送么有问题
    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.   

    1、用标准的串口没有问题,以前用过带串口的笔记本,是没有问题的,后来的笔记本都取消了串口,只能用USB来转串口了,软件没改的情况下不好用了,而且放在不同的笔记本里面,扩展不同的串口号,运行的结果也不同,纳闷。
    2、我把缓冲区改成32167. ,怕太小会冲掉数据,发现没什么变化。
    3、试过用timer控件,1s触发一次,发一次提取数据的指令,单片机的程序也更改为每次发送1k字节(改为255个字节也试过,同样不行),VB接收处理的部分和上面程序一致,也是不行,笔记本假死,必须在任务管理器里面关掉程序,有时甚至蓝屏。
    4、试过单片机每发送一个字节后延时10个ms,怕接收不及,也没用。
      

  3.   


    采用分包的方式,你遇到的时序问题基本上都可以解决。即发一条命令,接收一包数据。不推荐用 Timer 方式。采用 FT232 芯片的 U 转串,第一次安装驱动时就设置成固定的虚拟串口号。或者,在你的程序中通过读注册表动态地查找串口号。
      

  4.   

    最好是将你这个单片机项目升级到 USB 传输。你采用 RS-232 4800 波特率,就算是满载荷,每秒也就是 480 字节。32K 数据,要传几十秒。出现软件假死,很正常。而采用 USB,即使是全速模式,这点数据也是瞬间完成。更何况,每台计算机都有 USB 口。
      

  5.   

    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        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
    这部分接收的软件没什么问题吧?
      

  6.   

    接收的中途不要做数据处理,特别是需要重新分配缓存空间的字符串连接处理。首先将数据保存到一个足够大的 Byte 数组。接收完成后,再处理。PC 机运行速度相对于 RS232 传输速率,是非常快的,这样的方式可以保证你能够及时地接收到所有数据,而不必开非常大的串口缓存。当你要对字符串进行处理时,可能发生不确定地需要磁盘交换的情况,产生延迟。
      

  7.   

    1、不可能一次接收完吧,比如说一共30k的数据,我把接收缓冲区设置为32k是不是就一次可以接收完成?这点我不是很明白,请指点。
    2、今天去试了下,还是有点迷糊,如果一次接收不完的话该怎么定义数组,是不是应该定义个多维的才行?
    3、以前用的是五线制通信,加上RTS和CTS,现在线路不够,只用三线制通信,少了CTS的握手,是不是在控制流量方面有影响啊?不太明白。
    程序附下,请指点。
      

  8.   

    单片机的主要程序如下
    #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一段时间,但这个时间如何设定,没有头绪。