Duda comunicacion UART pic 16f887a ( Pic Simulator Ide )

Hola a todos, tengo un proyecto en mente el cual voy poco a poco y por módulos, es decir, voy probando cositas y verifico que funcionen bien antes de implementarlas al proyecto.
Ahora estoy con las comunicaciones UART entre dos pic's 16f877a.

La comunicación la he conseguido simulada en proteus, el ejemplo es sencillo.
Pic 1-> transmite un numero del 1 al 255
Pic 1-> transmite un numero del 97 al 120
Pic -> Recibe un numero del 255 al 1, muestra en lcd

Pic 2-> recibe numero y muestra en Lcd
Pic 2-> recibe numero y el lcd lo convierte a una letra ( por eso del 97 al 120 )
Pic 2> Envia un numero del 255 al 1.

Las pruebas las hago a 1.200 baudios utilizando RC7 y RC6 respectivamente ( Tx y RX ) ya que si subo los baudios el simulador del PSI de software UART dá error con el bit de parada.

Bueno, la pregunta es, ¿Hay alguna manera de poder enviar una cadena de texto y recivirla en el otro pic o solo se puede enviar un byte en cada transmision?, he probado a enviar "prueba" pero en el pic receptor no sé como meter el texto en una variable, he probado arrays y nanai.

Otra pregunta es, cuando un pic está en Serin, osea, esperando una recepción, ¿ hay alguna manera de cancelarlo? es decir:
Utilizando otro pin de los uC, puedo saber cuando uno quiere transmitir y entonces el otro pasa a modo "escucha" por decirlo de alguna manera, entoces si no se realiza la transmisión de datos por la razón que sea, ¿ habría alguna manera de cancelar el modo "escucha"?
He probado mil cosas con el PSI pero nada dá resultado, ya que cuando llega a la instruccion de SerinInv se queda hay parado hasta que le entra un dato.

Muchas gracias.
 
el 16f877 tiene usart, por lo que puedes hacer la comunicacion directamente en sus pines dedicados con hserin y hserout y puedes utilizar la interrupcion por recepcion de datos si activas el 9º bit de datos.

En cuanto al envio de series de datos, Tal como dices, enviando entre comillas y la recepcion la puedes hacer con un array de bytes.
 
Hola kmiz, voy a estudiar el tema del 9º bit de datos ya que es más interesante que ocupar un pin para "solicitar comunicación".

Respecto a lo del array, por ahora las pruebas las hago con los comandos Serin y Serout, no sé que diferencia hay entre esos comandos y los de Hserin y Hserout pero voy a probar a ver que descubro.
El tema es que cuando compilo y cargo el programa en el emulador me dice que que no admite constantes... ahora mismo acabo de probar esto:
Dim b(2) as byte

SerinInv portc.7,1200,b(2)

y lo ha aceptado... ¿...?, antes daba error en esa línea

No creo que tenga el emulador el mismo problema que tenía el Visual Basic 6.0, que a veces te daba error por cualquier cosa y sólo tenías que cerrar el programa, volverlo a abrir, cargar y compilar y todo Ok.

Bueno, pues nada seguiré trabajando en el proyecto a ver que sale.

Muchas gracias.
 
mira, prueba por ejemplo este codigo en PSI:

Código:
Define CONF_WORD = 0x3f50
'#######################################################
'Pic 16F628. 
'M.Barrera-2010 @
'Ultima actualizacion:15-10-2010
'#############CONFIGURACION LCD#########################
CMCON = CMCON Or 7  'pone a0-3 como digital
Define LCD_BITS = 4  '4lineas de datos
Define LCD_DREG = PORTB  'portb para
Define LCD_DBIT = 4  'linea de datos alta
Define LCD_RSREG = PORTA  'bit RS
Define LCD_RSBIT = 1
Define LCD_EREG = PORTA  'bit E
Define LCD_EBIT = 0
'Define LCD_INITMS = 2  'espera para inicio lcd
'##############CONFIGURACION USART#################
Dim comienzo As Bit
High comienzo
Hseropen 9600  'velocidad 9600 baudios
High RCSTA.RX9  'configura 9 bits para que funcione la interrupcion de recepcion
Dim dato(16) As Byte  'Bufer de 16 bytes
Dim tope As Byte
Dim n_dato As Byte  'Puntero de bufer de datos
n_dato = 0  'inicia puntero a 0
High PIE1.RCIE  'activa interrupcion de recepcion
Low PIR1.RCIF  '"  ""       ""             ""
High INTCON.PEIE  '""       ""             ""
Enable
Dim recibido As Bit
'#######################################################
'###################Configuracion Timer0################
OPTION_REG.PSA = 0
OPTION_REG.PS2 = 1
OPTION_REG.PS1 = 1  'Configuracion de timer0 8useg por ciclo de timer0
OPTION_REG.PS0 = 1
OPTION_REG.T0CS = 0
'#######################################################
Symbol led = PORTB.3
Low TRISB.3
Dim t As Word  'Variable de tiempos
t = 1  'poner esperas en milisegundos para tiempo real.
'arrancando LCD#########################################
Lcdinit 0  'inicializo el lcd sin cursor .
Lcdout "Valor leido LM35"
Lcdcmdout LcdLine2Home
'#######################################################
bucle:
If recibido Then
Low recibido
If n_dato = 16 Then  'Fin de buffer
Lcdcmdout LcdLine2Clear
Lcdcmdout LcdLine2Home
For n_dato = 0 To tope
Lcdout #dato(n_dato)
Next n_dato
n_dato = 0
High comienzo
Endif
Endif
WaitMs t
Goto bucle
End                                               
'Interrupciones
On Interrupt
Save System
If PIR1.RCIF Then
If comienzo Then
Low INTCON.T0IF
High INTCON.T0IE
Low comienzo
Endif
Hserget dato(n_dato)
tope = n_dato
n_dato = n_dato + 1

TMR0 = 0
Low PIR1.RCIF  'limpiamos la interrupcion

Endif
If INTCON.T0IF Then

n_dato = 16
Low INTCON.T0IE
Low INTCON.T0IF
Endif
High recibido
Resume

Funciona con 9600 b/s por hard, con interrupcion de RX y con un array de 16Bytes.
No necesita code de fin de envio. Una vez comienza la recepcion, si en determinado tiempo no recibe mas, cuenta con que ya se termino el envio, y comienza el envio a LCD.

Seguro que el codigo se puede mejorar mucho ya que soy tambien muy novato, pero funciona tanto en simulacion como en el protoboard.

Este codigo funcionaba junto con otro de un 12f683 que leia un lm35 y enviaba por serin (por soft) a este 16f628. Y sacaba datos por LCD
 
Voy a probarlo a ver que tal anda, por cierto, para simular, utilizas el proteus? te lo pregunto porque veo en el código el LCD a 4 bits y yo no lo he conseguido hacerlo funcionar en proteus a 4, sin embargo a 8 si.
Me interesa utilizar el lcd a 4 bits ya que en el proyecto final voy a utilizar 2 pic's 16f877a para poder visualizar los datos de 7 lm35 ( a poder ser con todo el rango, desde -55 hasta +150, aunque lo necesario teoricamente será desde -10 hasta +150 cinco de ellos y los otros 2 desde -10 hasta +60 ), eso por una parte, por otra, controlar el voltaje de un dispositivo y avisar cuando sea bajo )

Mucha tela veo yo aquí, jejeje, pero poco a poco todo se andará... jeje.

El código lo porbaré este fin de semana, ahora voy un poco apretado de tiempo.

Lo que tengo por ahora es un lm35 desde 0 hasta +150 con una precisión de +-0.1 grados.

Saludos!
 
He probado el circuito en el proteus, he modificado el lcd de 4 a 8 bits ya que el picsumulatoride tiene un pequeño problema de tiempos al enviar los comandos al lcd y funciona muy bien.

Gracias por el código.

Ahora llevo conseguido la lectura de 7 lm35 ( de 0 a +150 ) con unas simples líneas. Aunque repasando el proyecto puedo prescindir de 2 lm35 y utilizar esos pines para medir los voltajes de los dispositivos y de rebote prescindir de todo un pic. Pero claro, el problema es que no podría leer temperaturas negativas, eso ya lo vería más adelante.

Saludos!
 
problema de tiempos??
A que te refieres?. Yo lo simulo sin problemas en el psi.
Eso si, debes esperar un poquito al arranque, pero nada mas. Funciona bien.
Aunque si quieres simular todas las lm35 como que no vas a poder en el psi jejeje.
Suerte con el proyecto.
 
Si, bueno, estuve probando con el PicSimulatorIde a poner un Lcd a 4 bits y luego simularlo en proteus, resulta que el proteus me daba un error de que enviaba comandos al lcd cuando estaba ocupado, según he leído y he entendido cuando se define el lcd en PSI, en el hex resultante que utilizo para simular en proteus hay un pequeño problema debido a que no espera el tiempo suficiente ( 100 us mas o menos ) desde que envía un comando hasta el siguietente, entonces como el lcd no lo ha procesado marca el error.
Más o menos es lo que he entendido, ya que con otros compiladores no pasa eso, es más, el proteus trae unos ejemplos con lcd a 4 bits que funcionan perfectamente, lo malo es que sólo está el hex y puedo convertirlo a asm pero no entiendo ni papa... jeje.
Tu programa vá bien, es más ahora mismo estoy peleandome con el uart del 16f877a, estoy intentando enviar los datos de los sensores al otro pic pero no hay manera.
Resulta que tengo un array valores(7), tipo long, lo que no sé si para enviar todos los datos es necesario crear un for-next o hay que pasar los valos a bytes y enviarlos uno a uno.
Por ahora he conseguido enviarlos convirtiendo el valor a byte y mediante un for-next envio los datos de uno en uno, a traves del virtual termial del proteus veo como pasan los valores del pic1 al pic2, pero no sé extactamente como recibirlos en el pic2, he intentado varias formas pero no doy con la buena, he probado a crear otro bucle y recibir los datos 1 a 1, he probado a recivir como hserget valores(7) y nada, recibo cosas raras, con hserin más o menos ha mejorado la cosa pero no consigo recibirlos bien.

A los pic's les he puesto unos leds que indican cuando envian o reciven para hacerlo más visual...
y nada, que no hay manera.
Lo que si que he consguido es enviar un byte y recibirlo bien, pero sería interesante enviar un array entero de tamaño conocido.

Saludos!
 
Hola de nuevo, he intendado migrar tu código al 16f877a, lo que he entendido es lo siguiente:
Pic1 envia un dato ( supongo que el TX también estará a 9 bits)
Pic2 recibe y crea la interrupcion la cual con hserget recoge los datos recibidos y los mete en el array "dato" el cual el indice lo sigue otra variable que aumenta +1 en cada interrupción y vuelve a cero cuando esta llega a su maximo de 16. Cuando llega a 16 entra en el IF y presenta todos los datos mediante un for-next.

Es lo que he entendido del código, pero no me funciona, recibo datos pero no corresponden ni con el valor ni con la posicion en el array, es más me sale un numero que no sé de donde sale.
Seguiré investigando a ver que encuentro.

Respecto a lo de simular los lm35 con el psi, pues he podido 6 a la vez, ya que RA3 es el vref+ y RA4 se queda en digital, no sé porqué, claro está que sólo con temperaturas positivas.

Saludos!
 
Te explico como lo hice funcionar yo:
Leia el valor del lm35 con un pic 12f683 y enviaba el dato via serie por soft al pic 16f628 que lo recibia por hard.
El codigo de recepcion funciona del siguiente modo:
Cuando recibe el primer byte, se activa la interrupcion y detecta mediante la variable comienzo que es el primer byte, con lo que se activa el timer de fin de comando.
Cada vez que recibe otro byte el timer se reinicia. De modo que si en cierto tiempo.(no recuerdo exactamente cuanto)no recibe otro byte, el contador se pone a fin de bufer y asi toma por terminado el mensaje.
El fin de bufer esta en 16 bytes, pero se puede facilmente modificar este valor.
Si llegan regularmente 16 bytes, dara tambien por finalizado el mensaje.
Te preguntaras porque use estos pics y no un solo 16f876 por ejemplo.....
Pues para ponerme algo mas dificil la cosa, ya que lo hice por el mero hecho de comprobar que funcionaba bien. Asi practicaba de un solo golpe, la comunicacion por soft, por hard , la entrada analogica y el lcd.
Otra cosa. Si pones directas las lm35 al pic mira de que este muyyyy bien filtrada la alimentacion. Y en mi caso ademas opte por calcular valores medios, ya que sino oscilaba bastante el resultado.
 
Bueno, yo estoy probando el tx y el rx por hard, probaré el tx por soft y el rx por hard a ver que tal vá.
Una pregunta, el TX desde el 12f683 está a 9 o a 8 bits?

Lo del tema del buffer lo tengo claro.
La intención de todo esto es que pic1 se encarge de la recogida de datos de los sensores y puede darse dos casos:
1.- Cualquier sensor sobrepase un limite prefijado
2.- Que pic2 le solicite info sobre todos o algún sensor.

Para hacer esto intentaré hacer una especie de menú en pic1 para que cuando reciba un código que sepa que es lo que tiene que enviar al pic2 o desde pic2 enviar datos de rangos de trabajo de los sensores con lo cual pic1 grabará en la eeprom la info que le viene de pic2.
Por ejemplo, desde pic2 le envio "TS" ( Todos los Sensores ) y pic1 envirá las lecturas a pic2 que éste mostrará por el lcd, si le envío "S1" será solo para el sensor1.
Me imagino que tendré que crear un array y en distintos casos rellenar los "huecos" para que la transmisión siempre sea de los mismos bytes, así ahorraré unas lineas de código.

Esa es la idea, pero ya se sabe, de lo que se quiere a lo que sale.. puf, puede pasar de todo... jeje.

Voy a seguir peleandome con el UART de los ... a ver si hago algo, pero ya te digo, la transmisión desde pic1 estoy seguro que está bien, ya que hago lo siguiente:

sensor as byte
valor(7) as long
aux as byte

for sensor=0 to 7 step 1
if sensor=3 then sensor=4 ( el RA3 es el Vref+ por eso lo salto )
aux=valor(sensor)
hserout aux
waitms 200
next sensor

Cuando recibo mas o menos hago lo mismo pero valor(6) as byte y en vez de un for utilizo la interrupcion para incrementar 'sensor' que una vez llega a 6 retorna a 0.
hserin aux ( he probado con hserget y peor, no entiendo muy bien la diferencia entre los dos comandos)
valor(sensor)=aux

Así como está pic2 recibe la 1º cadena bien pero le falta el valor del último sensor ¿...? a la segunda transmisión ya se vuelve loco del todo, así que creo que algún dato debe de faltar o sobrar... no sé, si me fijo con el proteus, desde pic1 salen siete "2" que en decimal es 150, valor máx del lm35.
Me estoy volviendo majara... jeje, osea estoy bastante convencido que el problema está en la recepción y no en el envío.

El tema de las temperaturas yo también había pensado en sacar temperaturas medias de cada 15 o 20 lecturas ya que he leído sobre la oscilación de la lectura.

Ná, que seguiré con las investigaciones... saludos!

Vale, por fin lo he conseguido!!!! yupiiiiiiiiii jejeje
He visto el problema cuando he puesto el 1º lm35 a 50 y los demás a 60, el 50 se iba desplazando una posición hacia la derecha y luego volvía a empezar desde el principio, por eso no me cuadraban los numeros.
He repasado el código de pic2 y cuando he visto el fallo casi me doy de cabezazos contra la pared... ¿que burro que soy!, el array de RX lo tenía de 6 indices con lo cual, en la primera recepción todo iba bien menos el último sensor que estaba a 0, luego iban dando vueltas los numeritos. Asi que he cambiado el indice del array a 7 y voilá.
Pero sigo sin entenderlo, el pic1 tiene el array de 7 pero realmente se utilizan só..... vale, ya lo entiendo, otro fallo... madreeee como estoy... el array de pic1 debería ser de 8 indices, de 0 a 7, entonces la posicion 3 ( que es Vref+ ) se la salta, así que en el envío hago lo mismo, un for de 0 a 7 y me salto el 3, por eso no me funcionaba, porque en el pic2 ( el rx ) esperaba el rx con un array de 6 índices usease del 0 al 5 ( obviamente falta un sensor ), por eso en la 2º recepción me ponía los valores que tenía en el buffer del UART al principio, rellenaba y cuando no cabían más pues a esperar en el buffer hasta el próximo hserin.

No sé si me has entendido...

Bueno, que ya sé como funciona, ahora voy a hacer una par de pruebas más a ver si me hago con él del todo y así le escribo el menu.

Saludos y muchas gracias por todo!!!
 
Última edición:
Cuando envias mediante usart con un pic que no tiene pines dedicados a ello, y por tanto lo haces mediante software, no tienes opcion de activar el 9º byte (ni ninguno de hecho, jejeje).
La diferencia entre hserget y hserin es que hserin espera hasta recibir un byte y hserget recoge el recibido si hay y si no recoge "0".
Por tanto, si empleas la recepcion por interrupcion creo que es mas correcto usar hserget . La interrupcion te indica que hay un byte y lo recoges.
 
Ok, ahora si que lo he pillado del todo, jeje.
Es más he estado haciendo pruebas con los 2 pics y como me gusta probar todo lo probable se me ha ocurrido resetear el pic1 en medio de una transmisión, el resultado es el pic2 espera hasta llenar el array con lo cual los datos quedan desordenados, la solución bien sencilla, antes de enviar todo el array desde pic1 envío por ejemplo "a" y en el pic2 el contador que vá llenando el array de recepcion se pone a cero cuando el dato recibido es 97 ( valor ascii de "a" ).
Mas o menos es así el protocolo que he creado, más adelante en vez de "a" le pondré "#"+nºpaquete+"#"+datos
para crear una especie de tolerancia a errores, más o menos así es como funciona el tcp.

Pues nada, voy a seguir con el auto-aprendizaje a ver hasta donde llego.

Saludos!
 
Atrás
Arriba