Comunicacion Puerto Serial con PIC 18F4550

Hola, antes q nada..gracias por toda la ayuda q he recibido de todos ustedes.

Mi problema es el siguiente:
Tengo que llevar a cabo la transmision y recepcion de datos por el puerto serial con un microcontrolador (en este caso hare uso del PIC18F4550).

El programa que debo usar para la visualizacion de los datos debe ser el de Hyperterminal, que sinceramnete no se manejar.

La transmision y recepcion deben ser de la siguiente manera:
1) Del PIC tengo que mandar mi nombre (el cual debe estar grabado en un programa) al apretar una tecla predeterminada desde el teclado de la computadora.

2) Debo mandar codigo ASCII desde el teclado de la computadora hacia el PIC, el cual leera el dato en numero (por ejemplo, si mando como dato la arroba, que viene siendo ALT+64, el PIc debe desplegarme con leds el numero 64 en los leds: 01000000).

Alguien me podria orientar??

De antemano les agradezco su atensión y sus respuestas.

Gracias.
 
El HyperTerminal no tiene chiste, esta re-facil... Estas conectando el PIC al teclado directamente? si es teclado de compu ponte trucha porque los caracteres de control son 2 bytes(tal vez mas).

Para los LEDs pues solo necesitas un puerto de 8 bits y ya!
 
Mmmm....creo q no me di a entender jeje....lo que requiero d asesoria o ayuda si es posible es saber q comandos o instrucciones debo utilizar para la comunicacion entre el PIC y la Hyperterminal.....eso de los puertos y lo de los caracteres ya lo he revisado. El teclado de la computadora es la que manda las señales de entrada y salida d datos.

Gracias
 
Primero, necesitan configurar tanto el PIC como la Hypeterminal con los mismos parametros de comunicacion: Bits/palabra, bauds, paridad, start/stop bits.

Segundo, necesitan convenir cómo se van a comunicar PC y PIC, esto es, quien inicia la transmision (y entonces el otro, debe estar atento) y viceversa.

Salu2
 
que tal compañero cl.

Me tiene un poco desorientado tu proyecto, como que no ubico bien como vas a tener conectado el teclado el pic y la CPU.

Si entendi bien seria de la siguiente manera:

Teclado-> PC <-> PIC

En tal caso, solo te estan mareando con las especificaciones puesto que el Hyperterminal codifica lo que tecleas siempre como ASCII. En pocas palabras lo unico que tendrias que hacer es configurar la comunicacion entre el PIC y el HYPERTERMINAL. Te recomiendo comunicacion Full Duplex, a 8 bits con un bit de paro y sin bit de paridad es la mas facil de configurar en ambos lados (PIC y Hyperterminal).
EL Hyperterminal trabaja de la siguiente manera: Cada que tecleas algo este se envia al puerto Serial como codigo ASCII. Ejemplo si tecleas "a" en el puerto serial te mandaria un "01100001" que es un 97 si lo transformas en decimal. si tecleas "A" este te enviaria un "01000001" o 65 en decimal.
En el Hyperterminal deshabilita la opcion de ECO para evitar que te confundas quien esta enviando y quien recibiendo.
En el caso de los leds, al recibir los mensajes del Hyperterminal en el PIC; toma el dato de buffer serial y copialo directo al puerto no tienes ni que transformarlo.
 
Buenas, estoy realizando el mismo proyecto (PIC- Hyperterminal) para probar la comunicación serial asincrónica, pero en realidad quiero comunicarme (PIC-PIC por radiofrecuencia) cuando domine un poco mas la ComSerial.

Ya leí la hoja de datos pero me parece que no logro configurar bien los registros. El pic que estoy utilizando es un 18F4550 a una frecuencia de 1MHz en Proton Ide.

Adjunto un .rar con el código y la simulación. Si alguien me puede dar una mano le agradezco mucho !!

Código:
Device 18F4550 
Declare Onboard_USB No 

Config_Start
    FOSC = INTOSC_EC, PBADEN = OFF, ICPRT = On
    MCLRE = OFF, FCMEN = OFF, IESO = On, PWRT = On, WDT = OFF, LVP = OFF
Config_End

;*******************************************************************************   
OSCTUNE = %100000
OSCCON = %01000111           ; Frecuencia 1MHz del reloj interno.
;******************************************************************************* 

CMCON = 7 
INTCON = 7

Declare LCD_Type 0              
Declare LCD_DTPin PORTB.4         
Declare LCD_DTPort PORTB            
Declare LCD_ENPin PORTB.2   
Declare LCD_RSPin PORTB.1 
Declare LCD_Interface 4 
Declare LCD_Lines 2    

Declare Create_Coff = On  

Include "Modedefs.bas"

Output PORTC.6
Input PORTC.7

TXSTA.4 = 0 ; Habilitación de transmision asincronica
RCSTA.7 = 1 ; SPEN = 1
SPBRG = 10

;TXSTA.6 = 0 ; Transmision de 8-bits
TXSTA.5 = 1 ; Habilitación de transito de transmision

TXSTA.2 = 0 ; Velocidad de transmision alta.

;BAUDCON.4 = 0 ; Los datos no estan invertidos
;BAUDCON.3 = 1 ; Generador de Baudios 16-bit

Dim mMensaje As String * 150 
Dim mNumero1 As Byte
Dim mNumero2 As Byte

mMensaje = ""
mNumero1 = 1 
mNumero2 = 1

Main:
    
    mNumero1 = mNumero1 + 1
    mNumero2 = mNumero2 + 1
    
    mMensaje = mNumero1 + " " + mNumero2
    
    SerOut PORTC.6,9600,[mMensaje]
    
    Print At 1,1,"Hola "
    Print At 2,1,"Numero ", mMensaje
        
    DelayMS 500 
    
GoTo Main
 

Adjuntos

  • ComSerial18F4550.rar
    66.2 KB · Visitas: 17
Última edición:
Hay algunas cosas que debes tener en cuenta.

La primera y más importante, es que Proton IDE no permite trabajar con frecuencias inferiores a 4 MHz.
Por lo tanto, al no declarar Xtal = X, el código se compilará para 4 MHz. (Aunque configures registros.)
Nota: La configuración del registro OSCCON en el POR (Power On Reset) es a 1 MHz.
Así que no tiene caso realizar su configuración a 1 MHz.

La segunda. El módulo EUSART a 9600 Bps con el oscilador interno a 1 MHz. No funcionará correctamente.
Y de nada sirve configurar el módulo EUSART, si después usas RS-232 por software usando SerOut.
Lo correcto es que uses HSerOut, sin embargo, a 1 MHz. las cosas no irán nada bien.

La tercera. El registro CMCON en el PIC18F4550, no hace los pines con ADC, digitales.
En éste PIC se usa el registro ADCON1 y con un valor de 0x0F.
Pero en Proton IDE para tal caso, se usa: Declare All_Digital = On

La cuarta. Configurar el registro INTCON para lo que pretendes hacer, no tiene efecto.
El 18F4550 tiene tres registros de control para interrupciones. INTCON, INTCON1 e INTCON2
Un valor de 7 en el registro INTCON, activa la interrupción por cambio de estado en el puerto B
y pone en 1 dos banderas; INT0IF y TMR0IF. (Bits 0, 1 y 2, respectivamente.)

Entonces, por lo expuesto anteriormente, ese código es un caos y no servirá.
 
Última edición:
D@rkbytes gracias por responder.

Si, el codigo era un caos.
Al final configure todo en USART.
El Receptor:

Código:
Xtal 4 Mhz

Output PORTC.6
Input PORTC.7

;---------------------------------------------------------
TXSTA.4 = 0 ; Transmision asincronica
RCSTA.4 = 1 ; Habilitaci de recepción 

Symbol RX9 RCSTA.6 ; Desabilitado modo 9-bit 
Symbol ErrorFERR RCSTA.2 

RCSTA.7 = 1 ; SPEN = 1
SPBRG = 207

TXSTA.6 = 0 ; Transmision de 8-bits

TXSTA.2 = 0 ; Velocidad de transmision baja.

Y el transmisor:

Código:
Xtal 4

Output PORTC.6
Input PORTC.7
TXSTA.4 = 0 ; Transmision asincronica
RCSTA.7 = 1 ; SPEN = 1
TXSTA.6 = 0 ; Transmision de 8-bits

RCSTA.4 = 1 ; Habilitaci de recepción
SPBRG = 207
TXSTA.2 = 0 ; Velocidad de transmision baja.
 
TXSTA.5 = 1

Guardando la información en TXREG y RCREG.

Ahora, tengo otras dudas......

Si quiero tener muchos esclavos y un solo maestro. Como puedo identificar en el maestro, de que esclavo es la información que esta llegando a RCREG ?

Ademas, si quiero guardar un String que no entra en RCREG porque este contiene hasta 8-bits o 9-bits. Como puede hacer para enviar una cadena de texto por USART?

Saludos y graciass !!!!!!
 
D@rkbytes, gracias por responder.

Sí, el código era un caos.
Al final configuré todo en USART.
Saludos.
La configuración del módulo USART debe ser la misma , tanto para el transmisor, como para el receptor.
Ahora, tengo otras dudas...

Si quiero tener muchos esclavos y un solo maestro.
¿Cómo puedo identificar en el maestro, de que esclavo es la información que está llegando a RCREG?
Yo lo hago de la siguiente manera.

  • Genero un único programa para los esclavos.
  • A cada esclavo se le asigna un identificador grabado en la memoria EEPROM interna.
  • Los esclavos leerán la memoria al inicio para encontrar su identificador.
  • El maestro debe enviar 1 o dos bytes de reconocimiento, más los datos y el checksum.
  • Cada esclavo debe validar la cadena y leer el byte de datos correspondiente a su identificador.
Nota: Sólo uno de los esclavos podrá enviar datos al maestro.


Por ejemplo, 5 esclavos:
"#","$", 128, 255, 32, 86, 112, 101

Los primeros dos bytes son de reconocimiento.
Los bytes que siguen son los datos para los esclavos, siguiendo un orden por identificador.
El último byte corresponde al checksum de los datos.
El checksum se obtiene sumando los datos y haciendo un AND con 255 (0xFF)
128 + 255 + 32 + 86 + 112 = 613 (613 And 0xFF = 101)

Para el esclavo número 1, el identificador a grabar en la EEPROM, debe ser el 0
Eso hará más sencillas las cosas al hacer lo siguiente...
Después del reconocimiento y validación de datos, el esclavo leerá su identificador y siempre tendrá que omitir los primeros dos bytes.

Por ejemplo, para el esclavo número 1:
Mis_Datos = Cadena [Identificador + 2]

Si cada esclavo debe leer mas de un byte de datos, podrán ser los bytes siguientes y sólo será cuestión de aumentar el identificador para que sepa desde donde tiene que empezar a obtener los datos.

Además, si quiero guardar un String que no entra en RCREG porque este contiene hasta 8-bits o 9-bits.
¿Cómo puede hacer para enviar una cadena de texto por USART?

Usando las instrucciones nativas de Proton, puedes enviar y recibir cadenas.
La cadena la debes recibir dentro de un arreglo de datos. (Array)
Busca en el Foro sobre eso, porque ya he subido ejemplos para enviar y recibir cadenas.
 
Última edición:
Bien.. Primero que nada, disculpas, creo que tengo un error conceptual.
El maestro que yo planteaba era el receptor, pero como lo planteas son los transmisores.
Lo que planteo, por ejemplo, es tener 5 transmisores y 1 receptor.
¿Básicamente seria lo mismo verdad?

Nota: Sólo uno de los esclavos podrá enviar datos al maestro.

¿Esto quiere decir que enviaran datos uno por vez ? Primero envía el esclavo 1 y recibe el dato el maestro, envia el dato el esclavo 2 y recibe el maestro. ¿Y así sucesivamente ?

Por ejemplo, 5 esclavos:
"#","$", 128, 255, 32, 86, 112, 101

No me queda muy clara esta parte.

- ¿ Esos bits se cargan en TXREG y se envían para luego comparar su origen en el receptor con los dos primeros bits? ¿ Me quedarían los 5 bits del medio para la variable que contiene el dato?

- ¿O toda esa linea de información conformaría el identificador?
Identificador = "#","$", 128, 255, 32, 86, 112, 101

Que luego ingresa a la formula que me planteaste
Mis_Datos = Cadena [Identificador + 2]

Siendo la Cadena el dato que quiero enviar.

Saludos !!!!!
 
Bien. Primero que nada, disculpas, creo que tengo un error conceptual.
El maestro que yo planteaba era el receptor, pero como lo planteas son los transmisores.
Lo que planteo, por ejemplo, es tener 5 transmisores y 1 receptor.
¿Básicamente seria lo mismo verdad?
No, ya no es lo mismo.
Si tienes 5 transmisores, debes tener 5 terminales de recepción en el receptor.
Y ésto sólo lo lograrás usando RS-232 por software.
¿Esto quiere decir que enviaran datos uno por vez?
Primero envía el esclavo 1 y recibe el dato el maestro, envía el dato el esclavo 2 y recibe el maestro. ¿Y así sucesivamente?
Aquí puede ocurrir un problema de sincronización y tendrás que ser muy hábil para poder recibir todos los datos.
Tal vez usando un bus de CS (Chip Select) se resuelva ese inconveniente.
Lo mejor sería usar PIC's con I2C para usar ese protocolo.

No me queda muy clara esta parte.

- ¿Esos bits se cargan en TXREG y se envían para luego comparar su origen en el receptor con los dos primeros bits?
¿Me quedarían los 5 bits del medio para la variable que contiene el dato?

- ¿O toda esa linea de información conformaría el identificador?
Identificador = "#","$", 128, 255, 32, 86, 112, 101

Que luego ingresa a la formula que me planteaste.
Mis_Datos = Cadena [Identificador + 2]

Siendo la Cadena el dato que quiero enviar.
Vuelve a leer la información, ya que ahí expliqué el concepto y lugar de las variables de datos.

Y bueno, obviamente los datos se cargan en RCREG o TXREG, pero únicamente 1 Byte.
Para que se reciban más bytes de una sola vez, se usa un buffer circular, pero Proton se encarga de eso si usas sus instrucciones y funciones nativas.
 
Gracias !!
Como mencionaste que no se podia con USART tener 5 transmisores y 5 receptores. Intente con RS-232.

Aparentemente logre configurarlo bien, me envía la información perfectamente al comunicar 1 transmisor con 1 receptor. Pero cuando intento agregar mas transmisores y agrego las etiquetas, no le doy al clavo, no logro dar con la etiqueta para identificar el dispositivo.

Ya leí el manual de proton e intente varias cosas.
El manual dice:
HSERIN {ParityLabel , }{Timeout ,Label ,} [ Item { . . . } ]
HSEROUT [Item {,Item } ]

Lo que hago:

mIdentificador = 0

Envio de esta forma: HSEROUT [mNumero1{mIdentificador}]
O de esta otra forma: HSEROUT {1,mIdentificador}[mNumero1]

Recibo de esta otra: HSERIN [mNumero2{mIdentificador}]

Pero no recibo nada....
 
Última edición:
Gracias !!
Como mencionaste que no se podia con USART tener 5 transmisores y 5 receptores. Intente con RS-232.
Eso fue para el método que expliqué.
Si dispones de varios pines libres, sí puedes tener los 5 microcontroladores con Rx y Tx.

Aparentemente logre configurarlo bien, me envía la información perfectamente al comunicar 1 transmisor con 1 receptor. Pero cuando intento agregar mas transmisores y agrego las etiquetas, no le doy al clavo, no logro dar con la etiqueta para identificar el dispositivo.

Ya leí el manual de proton e intente varias cosas.
El manual dice:
HSERIN {ParityLabel , }{Timeout ,Label ,} [ Item { . . . } ]
HSEROUT [Item {,Item } ]

Lo que hago:

mIdentificador = 0

Envio de esta forma: HSEROUT [mNumero1{mIdentificador}]
O de esta otra forma: HSEROUT {1,mIdentificador}[mNumero1]

Recibo de esta otra: HSERIN [mNumero2{mIdentificador}]

Pero no recibo nada....
Para lo que requieres, que es inverso a lo que expliqué, ya no necesitas usar un identificador.
Lo que necesitas hacer, es una secuencia de recepción en sincronía.
 
Atrás
Arriba