2010-08-24 15 views
5

Mam więc coś w rodzaju ignorancji (być może?). Pracuję z pisaniem na urządzenie szeregowe po raz pierwszy. Mam ramkę [12, 0, 0, 0, 0, 0, 0, 0, 7, 0, X, Y], którą muszę wysłać. X i Y są wartościami sum kontrolnych. Moje rozumienie w użyciu modułu pyserial jest to, że muszę przekonwertować tę ramkę na reprezentację ciąg. Ok to w porządku, ale jestem zdezorientowany na jaki format rzeczy mają być w. Próbowałem robićDziesiętny na szesnastkowy w pytonie

a = [12, 0, 0, 0, 0, 0, 0, 0, 7, 0, X, Y] 
send = "".join(chr(t) for t in a) 

Ale mój zamieszanie wynika z faktu, że X i Y, przy użyciu Chr, przekształcać w dziwnych ciągów (zakładając ich ascii reprezentację). Na przykład, jeśli X wynosi 36, chr (x) to "$" zamiast "\ x24". Czy istnieje sposób, aby uzyskać ciąg reprezentujący wartość "\ xnn" zamiast kodu ASCII? Najbardziej mylące jest to, że 12 i 7 poprawnie konwertują na "\ x0b" i "\ x07". Czy czegoś brakuje?

Aktualizacja:
Więc może się okazać, że nie jestem dość zrozumienia, jak pisze seryjne są robione albo co moje urządzenie oczekuje mnie. To jest część mojego kodu C, które działa:

 

fd=open("/dev/ttyS2",O_RDWR|O_NDELAY); 
char buff_out[20] 
//Next line is psuedo 
for i in buff_out print("%x ",buff_out[i]); // prints b 0 0 0 0 0 0 0 9 b3 36 
write(fd,buff_out,11); 
sleep() 
read(fd,buff_in,size); 
for i in buff_in print("%x ",buff_in[i]); // prints the correct frame that I'm expecting 

 

Python:

 


frame = [11, 0, 0, 0, 0, 0, 0, 0, 9] + [crc1, crc1] 

senddata = "".join(chr(x) for x in frame) 



IEC = serial.Serial(port='/dev/ttyS2', baudrate=1200, timeout=0) 
IEC.send(senddata) 

IEC.read(18) # number of bytes to read doesn't matter, it's always 0 
 

Czy będę o tym właściwą drogę? Oczywiście nie można dokładnie określić, ponieważ jest to specyficzne dla urządzenia i nie mogę podać zbyt wielu szczegółów. Ale czy jest to właściwy format, w którym serial.send() oczekuje danych?

+0

Z dokumentacji Pythona, chr() zwraca liczbę ty wprowadź jako znak ascii. 12 i 7 w ascii to dzwonek i forma "znaków" paszy, których python może nie być w stanie wydrukować (nie wiem na pewno). Więc może to być domyślne dla reprezentacji hex dla tych, ponieważ są one niewykrywalne. – Joel

+0

12 powinno być \ x0c, nie \ x0b ... – EOL

+0

Niestety chodziło mi o \ x0c. Mam kolejną klatkę, która zaczyna się od 11 – Falmarri

Odpowiedz

3

To zupełnie normalne, że bajty ASCII są reprezentowane przez pojedyncze znaki, jeśli można je wydrukować, a notacją \x?? jest inaczej. W obu przypadkach stanowią one jeden bajt, a możesz napisać sznurki w obu mody:

>>> '\x68\x65\x6c\x6c\x6f' 
'hello' 

Jednak jeśli używasz Pythona 2.6 lub nowszy to może okazać się łatwiejsze i bardziej naturalne w użyciu wbudowanego bytearray zamiast rozmawiać z ord lub struct.

>>> vals = [12, 0, 0, 0, 0, 0, 0, 0, 7, 0, 36, 100] 
>>> b = bytearray(vals) 
>>> b 
bytearray(b'\x0c\x00\x00\x00\x00\x00\x00\x00\x07\x00$d') 

można przekonwertować do str (lub bytes w Pythonie 3) po prostu przez odlewanie i może indeksować ByteArray aby uzyskać całkowite powrotem.

>>> str(b) 
'\x0c\x00\x00\x00\x00\x00\x00\x00\x07\x00$d' 
>>> b[0] 
12 
>>> b[-1] 
100 

Jak do szeregowego kodu Pythona, to wygląda dobrze dla mnie - nie jestem pewien, dlaczego uważasz, że jest to problem ...

+2

+1 bytearray jest o wiele bardziej naturalnym wyborem, gdy mamy do czynienia z ciągami bajtów –

+0

Istnieje problem, ponieważ działa on w C, a nie w pythonie;) Będę dalej na niego patrzył. C jest naprawdę skomplikowane, więc może coś przeoczyłem – Falmarri

1

Znak z kodem ASCII 36 to'$'. Sprawdź to w dowolnej tabeli ASCII. Python wyświetla tylko znaki heksadecymalne, jeśli znak nie jest przeznaczony do drukowania (znaki sterujące itp.).

Na najniższym poziomie, jest to ten sam wzór bitowy - niezależnie od tego, czy Python wypisze go jako ucieczkę heksadecymalną, czy jako znak o tej wartości ASCII.

Ale możesz chcieć użyć modułu struct, który zajmie się takimi konwersjami.

+0

Próbowałem również struct. Chyba po prostu nie jestem pewien, w jaki sposób moduł chce, żebym dał dane – Falmarri

0

Zgaduję, że chcesz struct.

>>> import struct 
>>> struct.pack('>B', 12) 
'\x0c' 
>>> vals = [12, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0xa, 0xb] 
>>> ''.join(struct.pack('>B', x) for x in vals) 
'\x0c\x00\x00\x00\x00\x00\x00\x00\x07\x00\n\x0b' 
+2

* Nie używaj rozumienia listy, gdzie wystarczające jest wyrażenie generatora doth. * – delnan

+0

@delnan - Uczciwie. – Seth

0

Co zrobić, to perfekcyjnie: Twój send to, co chcesz: sekwencja bajtów z wartościami, które chcesz (a).

Jeśli chcesz zobaczyć, jakie są kody szesnastkowe bohaterów send, można zrobić:

import binascii 
print binascii.hexlify(send) 

lub

print ''.join(r'\x%02x' % ord(char) for char in send) 

(jeśli chcesz \x prefiksów).

Co widzisz, gdy bezpośrednio drukowania repr(send) jest reprezentacja od send, który używa ASCII: 65 reprezentuje 'a', ale postać 12 '\ x0c'. Jest to tylko konwencja używana przez Python, co jest wygodne, gdy ciąg zawiera wyrazy, na przykład: lepiej jest wyświetlić "Cześć" niż \ x48 \ x65 \ x6c \ x6c \ x6f!

Powiązane problemy