serial 9600 sin xtal funciona en asm y no en c

Hice un programa de comunicacion por puerto rs232 en un pic 16F628 con oscilador interno a 4mhz (sin cristal). a 9600 baudios.

El mismo lo hice en ASM y puedo comunicarme sin problemas. Cuando hago el mismo programa pero en CCS C (mismos pines de tx+rx) el mismo envia y recibe caracteres basura, como si no estuvieran configurados a los mismos baudios las terminales. (aclaro que es el mismo programa en la PC).

¿Alguien conoce si a este pic a 4mhz con osc interno "no le da" para esa velocidad rs232 en C? y si en ASM?
 
Hola seaarg puede ser que tu programa de la pc no reconozca los caracteres especiales que envía el ccs o este mal configurado si quieres publica el código y lo revisamos
saludos
 
Ten en cuenta que al usar C estas incluyendo algunas líneas de código en assembler adicional, al que has implementado en tu código echo en ASM. Por tal motivo los tiempos en los que procesas los bytes recibidos/enviados cambian. Y mucho mas si usas el XT interno del PIC.
Podrías solucionar eso, si el PIC te permite usar alguna forma de calibración del XT, o si reduces el % de error que se tiene al usar la comunicación RS232.

Con todo para avitarte ese problema, recomiendo usar un XT externo, ya que así te enfocas al proyecto que estas realizando.
 
En C a veces el compilador de CCS no configura bien el registro que indica el Baud..del RS232...por lo tanto lo mejor es usar un oscilador externo. Ahora si nos ponés tu código vamos a poder ver cuál es el error.
Un saludo !
 
Gracias a uds. Esta noche que este en la computadora donde tengo el codigo les adjunto el C, el lst generado y el ASM original del proyecto que funciono.

Esto es una mini terminal que tengo funcionando hace mucho en un servidorcito. La misma tiene un teclado numerico matricial y un LCD basado en hitachi. Envia las teclas pulsadas a la PC y los caracteres que envia la PC por rs232 son mostrados en el display LCD.

Intuyo que el problema es que CCS genera un codigo menos eficiente y no le da la precision para manejar 9600 baudios, con osc. interno, me juego a que si lo bajo a 4800 funciona perfecto.
 
El CCS tiene generación y ajuste de baudrate automático en función de la directiva #USE DELAY que hayas puesto. Si no puede ajustar el baudrate dentro del 3% te genera un error.
Moraleja: tenés que decirle cual es la frecuencia de clock que estás usando, por que si no, no sabe que hacer...
 
Muchas gracias por usar de sus tiempos para ayudarme. Adjunto un archivo ZIP conteniendo:
1)- lcd.asm - Programa original hecho con mplab en assembler, este funciona a 9600 sin problemas
2)- main.c - Programa hecho en CCS C, el cual funciona en simulador (al igual que el ASM) pero envia caracteres basura a la PC.
3)- main.lst - ASM Generado por CCS C
4)- lcd.DSN - Para quien tenga proteus (isis), la simulacion.

No es el primer PIC con el que me pasa esto a 9600 baudios, usando RC interno. Con un 16F873 que tenia en protoboard tambien, y hubo que ponerlo a 4800. Aclaro que el circuito conecta a traves de un MAX232.

Entonces... Ahora disponiendo del programa, y segun sus opiniones, puede ser cuestion de rendimiento del micro sin xtal (asumo que el compilado C es un poco menos eficiente) o puedo estar haciendo algo mal en el programa C?

Me olvide aclarar: En el main.c, pegue en la parte superior lo que iria en el include "main.h" por claridad y evitar tantos archivos. En la compilacion estan separados.

ezavalla:

#use delay(clock=4000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,restart_wdt,errors)

Aqui esta implementado lo que me indicas.
 

Adjuntos

  • lcd.zip
    24.7 KB · Visitas: 46
Última edición:
#use delay(clock=4000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,restart_wdt,errors)

No se....fijate el help de la directiva #use delay, por que hay una versión especial para tu caso donde no tenés que poner el bit INTRC_IO en nada ya que el compilador lo hace por vos.
Tengo miedo que se le arme bardo para calcular los tiempos del baudrate si no tiene en claro la fuente de clock. Tenés que considerar que cuando usa el clock interno, hay un byte (o par de bytes?) que tienen un valor que determina la calibración del clock de fábrica...y vaya uno a saber que corno hace el compilador con esas cosas...
Yo he usado un 16F84A a 4MHz a 9600baud hace un tiempo largo...y andaba...pero nunca le dí mucho ensayo por que era para probar otra cosa..pero era con XTAL externo.
No he mirado el código assembler que has subido, pero en otras comparaciones que he hecho, el compilador del CCS genera un código igual o con un par de instrucciones mas que el assembler, y estas se deben a cosas que haces en assembler y no podés hacer en C.
 
Tengo miedo que se le arme bardo para calcular los tiempos del baudrate si no tiene en claro la fuente de clock. Tenés que considerar que cuando usa el clock interno, hay un byte (o par de bytes?) que tienen un valor que determina la calibración del clock de fábrica

Pero ¿Eso existe en el 16F628? el bandgap y otro mas (son 2 bytes) lo vi en otras series, como el 12F675, nunca en este micro.

Estoy 99% seguro que es la compilacion de C que causa esto, me lo estas confirmando con que hiciste funcionar un F84 con xtal, y yo en ASM con el mismo integrado (mismo componente, no mismo modelo) tambien, pero sin xtal.

Voy a revisar si hay algun parametro en use_delay y les comento.

Pregunta: Para generar el baudrate se utiliza algun recurso como por ej: TMR0? se me acaba de prender la lamparita que quiza este configurado distinto en ASM y en C.
 
Última edición:
Pero ¿Eso existe en el 16F628? el bandgap y otro mas (son 2 bytes) lo vi en otras series, como el 12F675, nunca en este micro.

La verdad que no he usado ese modelo...habría que ver el datasheet, pero no suelen haber grandes diferencias. Yo lo ví en el 12F629...

Pregunta: Para generar el baudrate se utiliza algun recurso como por ej: TMR0? se me acaba de prender la lamparita que quiza este configurado distinto en ASM y en C.

Muy probablemente lo haga, por que no tiene otra base de tiempo que no sea esa o el timing del clock/4 para el ciclo de instrucción...y no creo que labure haciendo ciclos sobre NOPs para ajustar los tiempos...
 
Si quieres hacer cosas precisas, mejor usar un oscilador externo con le Cristal.

Lo entiendo y estoy de acuerdo. En este caso particular la placa ya esta hecha y montada hace un año al menos en el servidor y no da mucho para rehacerla o modificarla. La solucion mas sencilla es bajar los baudios a 4800 pero como no es la primera vez que me sucede esto en CCS, queria saber si habia un fundamento. (mas que solucionarlo en si, entenderlo)
 
Se me hace erroneo el termino "caracteres basura"... mas bien los bytes estan siendo enviados a un baudrate diferente y la PC no los reconoce ..

Si tienes un analizador lógico u osciloscopio, mide el ancho de los pulsos y determina el baudrate, luego juega con los registro de configuración de baudrate y oscilador, y ve su resultado en el analizador. De esta manera pudieses hacer una calibración, en caso de que se encuentre fuera de rango.

Repite este procedimiento con tu programa en ASM, también estaria bien, si haces una depuración paso a paso del programa en C y ASM y ver como se alteran los registros. Y así incluir esa información en tu programa en C.
 
Última edición:
Agradezco mucho sus respuestas,
Soluciones posibles entonces:
1)- Poner un xtal.
2)- Bajar el baud rate. (hare esta ultima, para no modificar la placa)
 
Agradezco mucho sus respuestas,
Soluciones posibles entonces:
1)- Poner un xtal.
2)- Bajar el baud rate. (hare esta ultima, para no modificar la placa)

Sería bueno saber cual es la causa de la falla. Habría que ver cual es la desviación del generador de baudrate para 9600 bauds usando un clock de 4MHz y luego evaluar esa desviación para el caso mas desfavorable de tolerancia del clock interno, que dicen que es del orden del 1.5%

PD: Supongo que estás usando la USART interna del 628, no? O lo estás haciendo por software?
 
Sería bueno saber cual es la causa de la falla. Habría que ver cual es la desviación del generador de baudrate para 9600 bauds usando un clock de 4MHz y luego evaluar esa desviación para el caso mas desfavorable de tolerancia del clock interno, que dicen que es del orden del 1.5%

PD: Supongo que estás usando la USART interna del 628, no? O lo estás haciendo por software?

En cuanto a la USART interna no estoy seguro en C, si en ASM, Configure el CCS para que utilice los pines de dicha usart del 628. ¿Con esto basta o hay que decirle de alguna forma al compilador que no lo haga por soft? <--- y si la falla estuviese aqui?

Por lo que comentas de la desviacion, ¿Te referis a un dato del datasheet o algo que haya que medir?

Extraido del datasheet:
Desired Baud rate = FOSC / (64(X + 1))
9600 = 16000000 / (64( +1 ))X
X = î25.042°
Calculated Baud Rate = 16000000 / (64(25 + 1))
= 9615
Error = (Calculated Baud Rate = Desired Baud Rate)
Desired Baud Rate
= (9615 - 9600)/ 9600
= 0.16%

Aqui estan poniendo un clock de 16mhz, cuando hago la misma cuenta a 4MHZ +-1.5% da cualquier cosa (si lo multiplico x 4 da cerca de 9700 pero creo que es cualquiera)

Segun una tabla del datasheet, con clock de 4MHZ a 9600 bauds es:

Sincrono = 9.615 +0.16%
Async, con BRGH = 1 = 9615.385 0.160%
Async, con BRGH = 0 = N/A

Supongo que el error empieza a ser mas considerable si el clock varia 1.5%

Estoy en problemas tambien por no tener ni la mas minima idea si el CCS configura BRGH en 1 o 0, sincrono o asincrono. ¿Habra que analizar el complejo ASM que genera o alguien sabe esto puntualmente?

Veo que hay un parametro de config del rs232 que es: brgh10k y no lo utilice, ¿sera que esto habilita el high baud rate?

Pregunto todo esto antes de desarmar otra vez el servidorcito.

Yo ya me habia rendido a bajar el baud, pero si me dan una manito lo seguimos investigando, hago las pruebas asi queda aqui documentado ya para cuando alguien mas se cruce con este problema.
 
En cuanto a la USART interna no estoy seguro en C, si en ASM, Configure el CCS para que utilice los pines de dicha usart del 628. ¿Con esto basta o hay que decirle de alguna forma al compilador que no lo haga por soft? <--- y si la falla estuviese aqui?

Help del CCS dijo:
Syntax:
#use rs232 (options)

Elements:
Options are separated by commas and may be:
STREAM=id
Associates a stream identifier with this RS232 port. The identifier may then be used in functions like fputc.

BAUD=x
Set baud rate to x

XMIT=pin
Set transmit pin

RCV=pin
Set receive pin

FORCE_SW
Will generate software serial I/O routines even when the UART pins are specified.

BRGH1OK
Allow bad baud rates on chips that have baud rate problems.

ENABLE=pin
The specified pin will be high during transmit. This may be used to enable 485 transmit.

DEBUGGER
Indicates this stream is used to send/receive data though a CCS ICD unit. The default pin used in B3, use XMIT= and RCV= to change the pin used. Both should be the same pin.

RESTART_WDT
Will cause GETC() to clear the WDT as it waits for a character.

INVERT
Invert the polarity of the serial pins (normally not needed when level converter, such as the MAX232). May not be used with the internal UART.

PARITY=X
Where x is N, E, or O.

BITS =X
Where x is 5-9 (5-7 may not be used with the SCI).

FLOAT_HIGH
The line is not driven high. This is used for open collector outputs. Bit 6 in RS232_ERRORS is set if the pin is not high at the end of the bit time.

ERRORS
Used to cause the compiler to keep receive errors in the variable RS232_ERRORS and to reset errors when they occur.

SAMPLE_EARLY
A getc() normally samples data in the middle of a bit time. This option causes the sample to be at the start of a bit time. May not be used with the UART.

RETURN=pin
For FLOAT_HIGH and MULTI_MASTER this is the pin used to read the signal back. The default for FLOAT_HIGH is the XMIT pin and for MULTI_MASTER the RCV pin.

MULTI_MASTER
Uses the RETURN pin to determine if another master on the bus is transmitting at the same time. If a collision is detected bit 6 is set in RS232_ERRORS and all future PUTC's are ignored until bit 6 is cleared. The signal is checked at the start and end of a bit time. May not be used with the UART.

LONG_DATA
Makes getc() return an int16 and putc accept an int16. This is for 9 bit data formats.

DISABLE_INTS

Will cause interrupts to be disabled when the routines get or put a character. This prevents character distortion for software implemented I/O and prevents interaction between I/O in interrupt handlers and the main program when using the UART.

STOP=X

To set the number of stop bits (default is 1). This works for both UART and
non-UART ports.

TIMEOUT=X
To set the time getc() waits for a byte in milliseconds. If no character comes in within this time the RS232_ERRORS is set to 0 as well as the return value form getc(). This works for both UART and non-UART ports.

SYNC_SLAVE
Makes the RS232 line a synchronous slave, making the receive pin a clock in, and the data pin the data in/out.

SYNC_MASTER
Makes the RS232 line a synchronous master, making the receive pin a clock out, and the data pin the data in/out.

SYNC_MATER_CONT
Makes the RS232 line a synchronous master mode in continuous receive mode. The receive pin is set as a clock out, and the data pin is set as the data in/out.

UART1
Sets the XMIT= and RCV= to the chips first hardware UART.

UART2
Sets the XMIT= and RCV= to the chips second hardware UART.


Por lo que comentas de la desviacion, ¿Te referis a un dato del datasheet o algo que haya que medir?

Son datos propios de cada chip y dependen de la relación entre la frecuencia del XTAL y la división del generador de baudrate. No hay que medir nada, pero si usando 4Mhz el baudrate se te corre mucho, nunca vas a poder comunicarte.

Si te fijás arriba, la propia directiva #use rs232 ya te permite especificar el baudrate, decir cual UART hay que usar y todo eso.
 
Última edición:
Iniciado por Help del CCS <-- UPS! ;)

¿Sabes que mire el help y le pase por arriba en aquel entonces a ciertos parametros?

bien, la directiva que estoy usando es:
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,restart_wdt,errors)

Por lo tanto, no estoy usando FORCE_SW y por otro lado, quiza haya que poner UART1 (tengo que mirar esa parte del help que no dispongo en este PC) para que use por hard.

Tambien probar con el flag BRGH1OK

Ahora bien, tengo una teoria: Si en simulador esto funciona bien, esto indicaria posiblemente problemas de clock para generar el baudrate y tendria que solucionarlo con el flag BRGH10K (o no)

Por otro lado, teniendo en cuenta que en ASM funciona, quiza no este usando la usart por hard?

Ademas, en el ASM utilizo:
BSF TXSTA,BRGH ; Async high baud rate enabled

No estoy seguro si este bit corresponde en CCS a BRGH10K, si es asi, es lo que esta faltando... y estariamos hablando tambien de que con este chip en particular voy a tener muchos errores en rs232 (Atendiendo a "allow bad baud rates...")

y tambien
BSF RCSTA,SPEN ; Activo el bit de serial port enabled
BSF RCSTA,CREN ; Habilito el continous receive bit

Esto no se si es automatico en CCS o es que no lo estoy poniendo. Aunque no estoy seguro si tiene que ver con el problema.
 
Hola seaarg:
No he leído todo pero te puede ser de ayuda, bueno yo si quiero usar el reloj interno de la familia de PIC's PIC16F6xxA lo configuro de esta forma:

PHP:
#use delay(internal=4Mhz)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)

void main(){
   Setup_oscillator(OSC_4Mhz);
   ...
}

Me funciona bien, ha también prueba configurar los pines de I/O del PIN_B2 salida y PIN_B1 entrada pero de esta manera:

PHP:
#byte TRISB = getenv("SFR:TRISB")
#use fast_io(b)
...
TRISB = 0b00000001;

El BRGH1OK mantenlo en "1" aunque esa configuración solo lo he usado para frecuencias de 10Mhz a mayores, pero inténtalo.

Y al usar la directiva #use rs232 escribe en RCSTA y TXSTA, de eso no tengas dudas... más que eso no se que pueda ser ya que ahí ya debe de funcionar todo, puede darse el caso de que sea el mismo compilador y también intenta probar con otro chip

Versión del compilador CCS V4.104

Suerte...
 
quiza haya que poner UART1 (tengo que mirar esa parte del help que no dispongo en este PC) para que use por hard.

Yo pondría UART1 como opción, ya que te configura los pines Tx y Rx en los que define el hardware...y andá a saber que más...

Por otro lado, teniendo en cuenta que en ASM funciona, quiza no este usando la usart por hard?

Ni idea :eek:...por la dudas decile que use la UART1 y quitale los pines RX y TX.

Ademas, en el ASM utilizo:
BSF TXSTA,BRGH ; Async high baud rate enabled

No estoy seguro si este bit corresponde en CCS a BRGH10K, si es asi, es lo que esta faltando... y estariamos hablando tambien de que con este chip en particular voy a tener muchos errores en rs232 (Atendiendo a "allow bad baud rates...")

y tambien
BSF RCSTA,SPEN ; Activo el bit de serial port enabled
BSF RCSTA,CREN ; Habilito el continous receive bit

Esto no se si es automatico en CCS o es que no lo estoy poniendo. Aunque no estoy seguro si tiene que ver con el problema.

Nuevamente...ni idea :eek:
Hace mucho que no estudio assembler y menos de estos micros RISC, así que le dejo al compilador el problema de la generacion de código...normalmente el tiempo de desarrollo me apremia...
 
Atrás
Arriba