2010-08-24 16 views
5

Tengo una pregunta un tanto ignorante (¿quizás?). Estoy trabajando con la escritura en un dispositivo en serie por primera vez. Tengo un marco [12, 0, 0, 0, 0, 0, 0, 0, 7, 0, X, Y] que necesito enviar. X e Y son valores de suma de comprobación. Mi comprensión al usar el módulo pyserial es que necesito convertir este marco en una representación de cadena. Ok eso está bien, pero estoy confundido sobre qué cosas formato se supone que deben estar. Intenté hacerDe decimal a hexadecimal en python

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

Pero mi confusión proviene del hecho de que X e Y, al utilizar CHR, se transforman en cadenas extrañas (asumiendo su representación ascii). Por ejemplo, si X es 36, chr (x) es '$' en lugar de '\ x24'. ¿Hay alguna manera de que pueda obtener una cadena que represente el valor '\ xnn' en lugar del código ascii? Lo que me confunde es que 12 y 7 se convierten correctamente en '\ x0b' y '\ x07'. ¿Me estoy perdiendo de algo?

Actualización:
lo tanto, podría ser que no estoy bastante entender cómo se están haciendo las escrituras de serie o lo que mi dispositivo está a la espera de mí. Esta es una parte de mi código C que está trabajando:

 

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 
 

¿Voy esto de la manera correcta? Obviamente no se puede decir exactamente porque es un dispositivo específico y realmente no puedo dar demasiados detalles. ¿Pero es ese el formato correcto en el que serial.send() espera datos?

+0

A partir de la documentación de Python, chr() devuelve el número que entrar en él como un personaje ascii. 12 y 7 en ascii son los "caracteres" de la campana y la forma, que Python puede no ser capaz de imprimir (no estoy seguro). Por lo tanto, podría ser una representación hexadecimal por defecto, ya que son indisponibles. – Joel

+0

12 debe ser \ x0c, no \ x0b ... – EOL

+0

Lo siento, quise decir \ x0c. Tengo otro marco que comienza con 11 – Falmarri

Respuesta

3

Es perfectamente normal que los bytes ASCII se representen con caracteres individuales si se pueden imprimir, y por la notación \x?? de lo contrario. En ambos casos representan un solo byte, y se puede escribir cadenas, ya sea en la moda:

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

Sin embargo, si usted está usando Python 2.6 o posterior a continuación, puede que le resulte más fácil y más natural de utilizar el built-in bytearray en lugar de meterse con ord o 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') 

Puede convertir a un str (o bytes en Python 3) justo por fundición, y puede indexar el bytearray para obtener los números enteros espalda.

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

cuanto a su código Python en serie, se ve muy bien a mí - No estoy seguro de por qué cree que hay un problema ...

+2

+1 bytearray es una opción mucho más natural cuando se trata de cadenas de bytes –

+0

Hay un problema porque funciona en C y no en python;) Seguiré mirándolo. La C es realmente compleja, así que tal vez me perdí algo – Falmarri

1

El carácter con el código ASCII 36 es'$'. Búscalo en cualquier tabla ASCII. Python solo muestra el hex escape si el carácter no es imprimible (caracteres de control, etc.).

En el nivel más bajo, es el mismo patrón de bits de todos modos, independientemente de si Python lo imprime como un escape hexadecimal o como el char con ese valor ASCII.

Pero es posible que desee utilizar el módulo struct, se encarga de tales conversiones para usted.

+0

Intenté estructura también. Supongo que no estoy seguro de cómo el módulo quiere que le dé datos. – Falmarri

0

Supongo que quiere 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

* No usará una lista de comprensión donde la expresión de un generador sea suficiente. * – delnan

+0

@delnan - Muy bien. – Seth

0

Lo que se hace es perfectamente bien: su send es lo que quiere: una secuencia de bytes con los valores que desee (a).

Si usted quiere ver lo que son los códigos hexadecimales de los caracteres en send, que puede hacer:

import binascii 
print binascii.hexlify(send) 

o

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

(si quieres \x prefijos).

Lo que se ve cuando se imprime directamente repr(send) es una representación de send, que utiliza ASCII: 65 representa 'A', pero el carácter 12 es '\ x0c'. Esto es simplemente una convención utilizada por Python, que es conveniente cuando la cadena contiene palabras, por ejemplo: ¡es mejor mostrar 'Hola' que \ x48 \ x65 \ x6c \ x6c \ x6f!

Cuestiones relacionadas