快速读取C ++ .net中串口的常量数据流

时间:2012-07-16 23:25:05

标签: c++ .net serial-port

我正在尝试建立一个SerialPort连接,以10-20 kHz的速率传输16位数据包。我用C ++ / CLI编程。发送者只是在收到字母“s”后输入infinte while循环,并不断发送2个字节的数据。

发送方面的问题是不太可能的,因为更简单的方法可以完美地工作但速度太慢(在这种方法中,接收方首先发送“a”,然后获得1个包含2个字节的包。到大约500Hz的速度)。 以下是这种有效但又缓慢的方法的重要部分:

public: SerialPort^ port;

in main:
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();

and then doing as often as wanted:
port->Write("a");
int i = port->ReadByte();
int j = port->ReadByte();

现在这是我正在使用的实际方法:

static int values[1000000];
static int counter = 0;

void reader(void)
    {
        SerialPort^ port;
        Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
        StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
        port = gcnew SerialPort("COM16",384000,p,8,s);
        port->Open();
        unsigned int i = 0;
        unsigned int j = 0;
        port->Write("s"); //with this command, the sender starts to send constantly
        while(true)
        {
            i = port->ReadByte();
            j = port->ReadByte();
            values[counter] = j + (i*256);
            counter++;
        }
    }

in main:
Thread^ readThread = gcnew Thread(gcnew ThreadStart(reader));
readThread->Start();

计数器以18472个/秒的速度快速增加(更多),但这些值在某种程度上是错误的。 这是一个例子: 该值应如下所示,最后4位随机变化(它是模拟 - 数字转换器的信号):

111111001100111 

以下是代码中给出的线程解决方案的一些值:

1110011001100111 
1110011000100111 
1110011000100111 
1110011000100111

所以看起来连接读取包中间的数据(确切地说:3位太晚了)。我能做什么?我想避免一个解决方案,这个错误在代码中稍后修复,同时读取这样的包,因为当我稍后编辑读取代码时,我不知道转换错误是否会变得更糟,我很可能会这样做。

提前致谢,

尼古拉斯

PS:如果这有帮助,这里是发送方的代码(AtMega168),用C语言编写。

uint8_t activate = 0;

void uart_puti16(uint16_t val) //function that writes the data to serial port
{

    while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
            nop(); // wait 1 cycle
            UDR0 = val >> 8; //write first byte to sending register
    while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
            nop(); // wait 1 cycle
            UDR0 = val & 0xFF; //write second byte to sending register
}

in main:
while(1)
{
        if(active == 1)
        {   
            uart_puti16(read()); //read is the function that gives a 16bit data set
        }               
}

ISR(USART_RX_vect) //interrupt-handler for a recieved byte
{
        if(UDR0 == 'a') //if only 1 single data package is requested
        {
            uart_puti16(read());
        }
        if(UDR0 == 's') //for activating constant sending
        {
            active = 1;
        }
        if(UDR0 == 'e') //for deactivating constant sending
        {
            active = 0;
        }
}

2 个答案:

答案 0 :(得分:2)

在给定的384,000比特率下,每秒应获得38,400字节的数据(8位实数加2个帧位),或每秒19,200个双字节值。

两种情况下counter增加的速度有多快?无论是使用事件还是直接轮询,我都希望任何现代计算机都能跟上这个速度。

您没有展示您所说的更简单的方法。我建议你发帖。

另外,在

行设置断点
values[counter] = j + (i*256);

在那里,检查ij。在循环的第一次迭代中分享您为这些变量看到的值。

答案 1 :(得分:0)

完全基于阅读http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y228处的代码,这是一个猜测。有了这个警告,这是我的猜测:

当数据可供读取时,正在调用您的事件处理程序 - 但您只消耗可用数据的两个字节。您的事件处理程序可能只能每1024个字节调用一次。或类似的东西。您可能需要在事件处理程序中使用 all 可用数据,以使程序按预期继续。

尝试重新编写处理程序以包含一个读取循环,直到没有更多数据可供使用。