Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 读取3次后进行连续冻结_Python_Serial Port_Pic_Pyserial - Fatal编程技术网

Python 读取3次后进行连续冻结

Python 读取3次后进行连续冻结,python,serial-port,pic,pyserial,Python,Serial Port,Pic,Pyserial,我们正在编程一个pic,我们已经诊断出,如果我们在串行端口试图向我们发送数据时向其发送数据,程序将锁定(我们的python代码和超级终端在测试时都将崩溃)。它在超级终端中工作,输入速度慢(笔划之间的间隔超过0.5秒),当键盘被敲击时会崩溃。所以我们所做的是引入了一个超过0.5秒的time.sleep,但它仍然不起作用 这是我们的测试代码 import serial import time ser = serial.Serial("COM1") ser.baudrate=2400 while

我们正在编程一个pic,我们已经诊断出,如果我们在串行端口试图向我们发送数据时向其发送数据,程序将锁定(我们的python代码和超级终端在测试时都将崩溃)。它在超级终端中工作,输入速度慢(笔划之间的间隔超过0.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次迭代后会冻结)。我们把它带到循环之外,看看这是否是导致问题的原因,事实并非如此。它根本不发送带有此代码的“ok”

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;
}
unsigned char receiveData(unsigned char*rxData,int-length){
//1.接收完成时将设置标志位RCIF,如果设置了启用位RCIE,将生成中断。
char send[3]=“确定”;
int指数=0;
if(rxData==(void*)0 | | rxInitialized==FALSE)返回失败;

虽然(索引来自PIC的通信是否使用串行端口的?可能PIC需要某种流量控制,并且您在没有任何流量控制的情况下向其发送数据太快。阅读限制,如果需要,打开启用的端口。

来自PIC的通信是否使用seria的l端口?可能PIC需要某种流量控制,而您在没有任何流量控制的情况下将数据发送到它的速度太快。请阅读的限制,如果需要,请打开启用的端口。

(此答案假设您使用的是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++;
第二次:

// 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在您使用该函数之前就已经满了

有几种方法可以解决这个问题

  • 在中断中执行此操作,以便更快地将传入字符移动到缓冲区中
  • 使用循环从
    RCREG
    while(RCIF)rxData[index]=RCREG;
    读取时确保在从UART缓冲区读取时清空缓冲区,但它不会停止此函数外部或延迟期间的溢出
  • 检查
    OERR
    标志-如果设置了该标志,则假设发生了不好的情况并重新开始
  • 有一个停止字符或开始字符(如行尾、标点符号等),告诉您有效命令何时开始或停止。如果您得到两个没有停止字符的开始字符,或其他一些令人困惑的组合,则假设您处于错误状态,然后重新开始
  • 一些额外的建议:你可能会疯狂地试图解释和补偿PIC代码中的每一个遗漏字符或类似问题,但最终这只是另一个通信错误。PIC代码中的优先级应该是:从错误中快速恢复,而不是锁定。错误检测和正常恢复应由客户端处理t代码,在那里它要容易得多。

    (这个答案假设您使用的是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++;
    
    第二次:

    // 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在您使用该函数之前就已经满了

    有几种方法可以解决这个问题

  • 在中断中执行此操作,以便更快地将传入字符移动到缓冲区中
  • 使用循环从
    RCREG
    while(RCIF)rxData[index]=RCREG;
    读取时确保在从UART缓冲区读取时清空缓冲区,但它不会停止此函数外部或延迟期间的溢出
  • 检查
    OERR
    标志-如果设置了该标志,则假设发生了不好的情况并重新开始
  • 有一个停止字符或开始字符(如行尾、标点符号等),告诉您有效命令何时开始或停止。如果您得到两个没有停止字符的开始字符,或其他一些令人困惑的组合,则假设您处于错误状态,然后重新开始
  • 一些额外的建议:你可能会疯狂地试图解释和补偿PIC代码中的每一个遗漏字符或类似问题,但最终这只是另一个通信错误。PIC代码中的优先级应该是:快速恢复