pySerial读取3次后冻结
我们正在编写一个图片,我们已经诊断出,如果我们在串行端口尝试向我们发送数据时将数据发送到串行端口,则程序将锁定(测试时我们的 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 次迭代后冻结的方式)。我们将其放在循环之外,看看这是否导致了问题,但事实并非如此。它根本不使用此代码发送“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;
}
We are programming a pic and we've diagnosed that if we send data to serial port while its trying to send data to us, the program will lock up (both our python code and hyperterminal will crash when tested). It worked in hyperterminal and inputting it slowly (>.5 seconds between strokes), and would crash when the keyboard was bashed. So what we did was introduce a time.sleep which is longer than .5 seconds, but it is still not working.
Here's our test code.
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)
our receive data function. We used to have the "ok" being sent everytime it recieved a char (which is how we know that it freezes after 3 iterations). We brought it outside of the loop to see if that was causing the problem and it was not the case. It is not sending the "ok" at all with this code.
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
(这个答案假设您使用的是 PIC16,根据某些寄存器的名称建议。)
简而言之,它看起来像是缓冲区溢出以及
receiveData
中该循环中的错误。事实上,在短时间内连续发送三个字符后它就冻结了,这可以通过手册的 p117 来解释:这可以解释幻数 3。
单步执行 PIC 代码,请考虑以下场景(仅作为示例)。第一次:
第二次:
现在循环的其余部分将继续从 RCREG 读取,直到
index == length
,但由于在 UART FIFO 已满时一些字符被丢弃,因此您永远不会得到那里似乎冻结了!更有可能的是,您在到达该函数之前就已接收字符,因此 UART FIFO 在您到达该函数之前就已满。
有几种方法可以解决这个问题。
RCREG
读取:while(RCIF) rxData[index]= RCREG;
这可以确保在从 UART 缓冲区读取时清空缓冲区,但它会但不能阻止该函数之外或延迟期间的溢出。一些额外的建议:您可能会疯狂地尝试解释和补偿 PIC 代码中的每个丢失字符或类似问题,但最终这只是另一个通信错误。 PIC 代码中的优先级应该是:从错误中快速恢复并且不锁定。错误检测和正常恢复应该由客户端代码处理,这要容易得多。
(This answer assumes that you are using a PIC16, suggested by the names of certain registers.)
In short, it looks like a buffer overflow coupled with a bug in that loop in
receiveData
. The fact that it's freezing after three characters are sent in short succession might be explained by p117 of the manual:This would explain the magic number three.
Stepping through your PIC code, consider the following scenario (just an example). First time around:
Second time around:
Now the rest of the loop will keep reading from RCREG until
index == length
, but since some characters were discarded while the UART FIFO was full, you'll never get there and appear to freeze!What is even more likely is that you are receiving characters before you even get to that function, so the UART FIFO fills up before you even get there.
There are a few ways around this.
RCREG
:while(RCIF) rxData[index]= RCREG;
this makes sure you empty the buffer when reading from the UART buffer, but it will not stop overflows outside of this function or during that delay though.OERR
flag - if it is set, assume something bad happened and start over.Some additional advice: you can go absolutely crazy trying to account and compensate for every missed character or problem like this in your PIC code, but ultimately it's just another comms error. Priorities in the PIC code should be: quick recovery from errors and not locking up. Error detection and sane recovery should be handled by the client code, where it's far, far easier.
PIC 的通信是否使用 RTS/CTS 线路< /a> 串行端口 ? PIC 可能需要某种流量控制,而您在没有任何流量控制的情况下向其发送数据的速度太快。阅读 PIC 的限制,并在需要时使用以下命令打开端口已启用流量控制。
Does the communication from the PIC make use of the RTS/CTS lines of the serial port ? Probably the PIC expects some sort of flow control and you are sending data too fast to it without any flow control. Read up on the limitations of the PIC and if needed open the port with flow control enabled.