阅读3次后pySerial冻结

时间:2010-11-18 21:40:55

标签: python serial-port pic pyserial

我们正在编写一张图片,我们已经诊断出如果我们在尝试向我们发送数据时将数据发送到串口,程序将锁定(我们的python代码和超级终端在测试时都会崩溃)。它在超级终端中工作并且缓慢地输入它(在笔划之间> 5秒),并且当键盘被击打时会崩溃。所以我们所做的是引入一个超过0.5秒的time.sleep,但它仍然没有工作。

这是我们的测试代码。

import serial
import time

ser = serial.Serial("COM1")
ser.baudrate=2400

while 1:
    for i in range(23):
        ser.write(0x41)       
        time.sleep(.5)
        print("ok")

    rec = ser.read()
    rec2 = ser.read()
    rec3 = ser.read()
    print(rec)
    print(rec2)
    print(rec3)

    for i in range(23):
        data = ser.read()
        print(data)
        print("ok")
    time.sleep(5)

我们的接收数据功能。我们曾经每次收到一个字符时都会发送“ok”(这就是我们知道它在3次迭代后冻结的方式)。我们把它带到了循环之外,看看是不是导致了问题而事实并非如此。这段代码根本没有发送“确定”。

unsigned char receiveData(unsigned char *rxData, int length){
  // 1. Flag bit, RCIF, will be set when reception is complete and an interrupt will be generated if enable bit, RCIE, was set.
 char send[3] = "ok";

 int index = 0;

 if(rxData==(void*)0 || rxInitialized==FALSE) return FAILURE;
 while(index<length){
  while(PIR1bits.RCIF==0);       
  rxData[index]= RCREG;
  Delay1KTCYx(5);
  index++;
 }
    configureTransmission();
    sendData(send,3);

  // 2. Read the RCSTA register to get the 9th bit (if enabled) and   determine if any error occurred during reception.
  // 3. Read the 8-bit received data by reading the RCREG register.
  // 4. If any error occurred, clear the error by clearing enable bit   CREN.
 return SUCCESS;
}

2 个答案:

答案 0 :(得分:2)

(这个答案假定您使用的是PIC16,由某些寄存器的名称建议。)

简而言之,它似乎是缓冲区溢出,加上receiveData中该循环中的错误。在连续发送三个字符后它冻结的事实可以通过手册的第117页解释:

  

可以接收两个字节的数据并将其传送到RCREG FIFO,第三个字节开始转换到RSR寄存器

这可以解释神奇的数字三。

单步执行PIC代码,请考虑以下方案(仅作为示例)。第一次:

// One character already in RCREG - RCIF set
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF clear
rxData[index]= RCREG;
// While waiting here, two more characters are received - RCIF set
Delay1KTCYx(5);
index++;

第二次:

// RCIF set from before
while(PIR1bits.RCIF==0);
// Reads ONE character - RCIF STILL set, ONE character remains in UART FIFO!
rxData[index]= RCREG;
// While waiting here, three more characters are received
// RCIF set, RCREG fills up and the third character is discarded!
Delay1KTCYx(5);
index++;

现在,循环的其余部分将继续从RCREG读取,直到index == length,但由于某些字符在UART FIFO已满时被丢弃,所以你永远不会到达并且似乎冻结了!

更有可能的是,在你进入该功能之前,你正在接收角色,所以在你到达那里之前,UART FIFO就会填满。

有几种解决方法。

  1. 在中断中执行此操作,因此将传入的字符移动到缓冲区会更快一些。
  2. 使用循环从RCREG读取:while(RCIF) rxData[index]= RCREG;这确保在从UART缓冲区读取时清空缓冲区,但它不会在此函数之外或在此延迟期间停止溢出。
  3. 检查OERR标志 - 如果已设置,则假设发生了一些不良事件并重新开始。
  4. 有一个停止字符或开始字符(例如,行尾,标点符号等),它告诉您何时启动或停止有效命令。如果你得到两个没有停止字符的起始字符,或者其他一些令人困惑的组合,假设你处于不良状态并重新开始。
  5. 一些额外的建议:你可以绝对疯狂地试图在你的PIC代码中考虑并补偿每个错过的字符或问题,但最终它只是另一个通信错误。 PIC代码中的优先级应该是:快速从错误中恢复而不是锁定。错误检测和理智的恢复应该由客户端代码处理,在那里它更容易。

答案 1 :(得分:1)

来自PIC的通信是否使用串行端口的RTS/CTS lines?可能PIC期望某种流量控制,并且您在没有任何流量控制的情况下发送数据的速度太快。阅读PIC的限制,如果需要,请打开启用了flow control的端口。