Python 读取3次后进行连续冻结
我们正在编程一个pic,我们已经诊断出,如果我们在串行端口试图向我们发送数据时向其发送数据,程序将锁定(我们的python代码和超级终端在测试时都将崩溃)。它在超级终端中工作,输入速度慢(笔划之间的间隔超过0.5秒),当键盘被敲击时会崩溃。所以我们所做的是引入了一个超过0.5秒的time.sleep,但它仍然不起作用 这是我们的测试代码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
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代码中的优先级应该是:快速恢复