Autor Tema: Puerto serie  (Leído 4919 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Puerto serie
« en: 12 de Junio de 2008, 12:19:33 »
Buenas,

La UART, cuando le llegan 8bytes por ejemplo, ¿interrumpe 8 veces las interrupciones de la UART? ¿o te interrumpen una vez y en la rutina de interrupción puedes leer los 8 bytes haciendo un "while (DataRdyUART)"? y para enviar igual, puedes enviar una cadena de 8bytes con el PutsUART()?

Gracias !!

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Puerto serie
« Respuesta #1 en: 12 de Junio de 2008, 13:16:45 »
Saludos superprp!
Bueno no he trabajado aún con los dspic (espero hacerlo pronto)... pero la interrupción ocurre después que el buffer de recepción se ha llenado.
Es decir, tu activas la interrupción, y luego que se terminan de recibir los 8 bits del dato, el interrumpe.
En la función que atiende la interrupción puedes leer los 8bits completos con unas cuantas instrucciones sencillas... no sé qué compilador usas, así que no te puedo especificar qué instrucciones son.
Para enviar es el mismo cuento, debe haber alguna instrucción con la que envias los 8 bits al buffer... algunas instrucciones hasta te permiten enviar cadenas de texto completas... por ejemplo en ccs está el puts("cadena")... o si es una variable: putc(dato)... también con el printf puedes incluso darle formato al número.
Pero te repito, no sé cómo será exactamente con los dspic.
Espero haberte ayudado aunque sea un poquito.
Nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Puerto serie
« Respuesta #2 en: 12 de Junio de 2008, 13:39:55 »
Esto es lo que dice la data:
The condition for setting the receive interrupt
flag depends on the settings specified by the
URXISEL<1:0> (UxSTA<7:6>) control bits.
a) If URXISEL<1:0> = 00 or 01, an interrupt is generated
every time a data word is transferred
from the Receive Shift register (UxRSR) to the
receive buffer. There may be one or more
characters in the receive buffer.
b) If URXISEL<1:0> = 10, an interrupt is generated
when a word is transferred from the Receive Shift
register (UxRSR) to the receive buffer, which as a
result of the transfer, contains 3 characters.
c) If URXISEL<1:0> = 11, an interrupt is set when
a word is transferred from the Receive Shift register
(UxRSR) to the receive buffer, which as a
result of the transfer, contains 4 characters (i.e.,
becomes full).


Puedes configurarlo como quieras, pero el buffer máximo es de 4 caracteres. Ten cuidado con eso porque si lo llenas y sigues recibiendo datos, el dsPIC se vuelve loco.

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Re: Puerto serie
« Respuesta #3 en: 13 de Junio de 2008, 04:37:01 »
y como suelen hacerse las rutinas para leeer cuando por ejemplo te llegan por la UART comandos de 80bytes cada 200ms?? el reloj es de 10 Mhz con un PLL x8, con lo cual 80Mhz, 20MIPS. ¿Es posible hacer una rutina sin que desborde el buffer?

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: Puerto serie
« Respuesta #4 en: 13 de Junio de 2008, 05:32:56 »
Le daría tiempo hasta tomarse una copa de ron entre byte y byte.

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Re: Puerto serie
« Respuesta #5 en: 13 de Junio de 2008, 06:56:46 »
se me ha olvidado decir que el baude rate es de 9600

Esto se pone asi???:

void __attribute__((__interrupt__)) _U2RXInterrupt(void) {
   
      atiendeRX();
      IFS1bits.U2RXIF = 0;
}

o se pone un return para que salga??? igual que en atiendeRX(); en esa función tengo que poner un return? o si llega al final vuelve sola? puede dar fallos si no pongo el return???


si envio comandos pequeños de kizas 8 bytes y cada segundo o así no pasa nada, pero si envio 80 bytes y cada 500ms , a los dos segundos o así se queda colgado y deja de hacerme caso... no se porque puede ser, el pic sigue funcionando pero deja de atenderme las interrupciones de envio, y lo mismo sucede cuando me envia muchos paquetes seguidos, llega un momento en que satura el buffer, pienso yo, y deja de enviarme datos...

fuente del problema? posibles soluciones?
« Última modificación: 13 de Junio de 2008, 09:12:31 por superprp »

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: Puerto serie
« Respuesta #6 en: 13 de Junio de 2008, 21:38:21 »
Yo utilizo el DMA para esos casos .... utilizo en este caso un buffer circular ... ahora tengo dos contadores (punteros): uno que cuenta los bytes que ingresan (RW) y otro que cuenta los bytes leidos (RR). 

Cada vez que ingresa un byte RW incrementa. Esto mediante la interrupcion de RX, en esta interrupcion no leo el byte solo incremento RW, el byte se guarda automaticamente en la pila por medio del DMA. Tambien, cada vez que leo un byte RR incrementa. Si leo strings RR aumenta de acuerdo al tamaño del string.

Ahora el problema de aplicaciones con tramas muy grandes la solucioné con un RTOS. Cree una tarea que consulta RR y RW cada 10ms, si RR=RW no hay bytes en pila. Si RW > RR significa que hay uno o mas datos.

Otro problema es cuantos bytes debo leer.!! Para ello establecí un protocolo. Cuando envio una trama desde la PC al PIC: el primer byte indica la orden, comando o funcion que deseo realizar, el segundo byte indica el tamaño total de la trama, el tercer y resto de bytes son los datos, los ultimos 2 bytes son un checksum.

Entonces si RW > RR se lee el primer byte y lo guardo en un registro llamado COMANDO, luego espero nuevamente a que RW > RR, en este lapso el RTOS me permite hacer otra cosa con el micro. Cuando RW > RR leo el byte de tamaño (recuerda que a tarea entra cada 10ms), aqui espero el tiempo adecuado para recibir el resto de la trama. Nuevamente, el RTOS me permite hacer otra cosa mientras espero la trama de datos.

Pasado el tiempo de espera, leo nuevamente RW y RR, si la diferencia es igual al tamaño indicado, leo la trama y la guardo en una pila tempora creada en memoria dinámica y luego la proceso segun sea la funcion establecida por el primer byte (COMANDO).

Claro, hay tiempos de espera por si se falla la comunicación o algo parecido. Tambien hay confirmaciones, cuando recibo el primer byte, se lee, se guarda y se envia a la PC como confirmacion de recibido; procesada la trama se envia a la PC un caracter de que se recibio bien la trama, si el checksum no coincide se envia otro caracter indicando un error, etc, etc, etc.

Saludos



Control Automático, DSP & Microcontroladores

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Re: Puerto serie
« Respuesta #7 en: 15 de Junio de 2008, 15:03:40 »
que es el DMA? como puedo implementarlo??

Desconectado Renatox_

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 541
    • máquinas cnc
Re: Puerto serie
« Respuesta #8 en: 15 de Junio de 2008, 21:42:07 »
Cuando tengo que recibir varios bytes, por ejm he recibido 8 bytes de la PC, entonces apenas llega uno interrumpe al pc y atiende la rutina, dentro hace un bucle for i=1:8 y leo todos los bytes porque se que llegarán 8, como esta rutina tiene prioridad sobre las demás termino de leer los 8 bytes y luego salgo de ello.

No suelo usar rutina de interrupción para la transmisión.

saludos
control de movimiento

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Re: Puerto serie
« Respuesta #9 en: 16 de Junio de 2008, 04:03:44 »
Lo del DMA se puede hacer con el dsPIC30f4013???? en el datasheet no aparece, lo que me ocurre es que salta el bit OERR de la recepción de la UART, ¿como puedo hacer para que no salte? Eso es porque no leo lo suficientemente rápido, no?
« Última modificación: 16 de Junio de 2008, 05:04:25 por superprp »

Desconectado superprp

  • PIC16
  • ***
  • Mensajes: 137
Re: Puerto serie
« Respuesta #10 en: 16 de Junio de 2008, 05:54:12 »
Porque no me deja compilar esto????

U2STAbits.URXISEL1 = 1;
U2STAbits.URXISEL0 = 0;