Leer datos del puerto serial

Soy nuevo,
Mis preguntas son
1.- Al leer datos del puerto serial el pic los lee en forma binaria?
Si le mando un comando ascii por ejemplo (t), el pic lee ese símbolo o lee el dato en binario. o si le mando un dato en hexadecimal(0x01) el pic lo lee en hexadecimal o en binario(00000001).

2.- El pic solo puede leer 8 bits(1byte) a la vez? si quisiera leer más datos(2 bytes) como le haría.

El pic que tengo es el 16f876a y estoy utilizando el mikroc.

Gracias
 
hi Sydb,

1- el puerto serie solo transmite 1s y 0s digitales. si utilizas el hyperterminal de windows para enviar una "t " por el puerto se genera una serie de pulsos que equivale al valor binario (1110100) del caracter ascii.

2.- Por hardware lo mas comun es que el microcontrolador, solo tenga memoria para un byte. Si quieres recibir o transmitir mas de 1 byte tienes que hacer por software un buffer de entrada y uno de salida.

Coloca el codigo, para poder ayudarte.
:)
 
Ojo, ademas de todo eso tambien tienes que preocuparte de como se transmiten los bits... es decir si la PC transmite primero el MSB o el LSB, en el caso del RS232 se transmite primero el menos significativo, por lo que si el PIC esta configurado para recibir primero el mas significativo entonces vas a recibir el dato alrevez, (en vez de recibir la "t" con codigo 01110100, recibes 00101110 osea "/")

http://es.wikipedia.org/wiki/Endianness

Saludos..
 
Así es como puedo leer el puerto, pero como hago el buffer de lectura?

unsigned short i=0;
void main()
{
TRISA=0XFF;
ADCON1=0X06;
TRISB=0x00;
TRISC=0x40;
Usart_Init(9600);

while(1)
{
i = Usart_Read ();
}
}
 
Hi sydb,
Yo utilizaria algo así,
la idea es que la interrupcion este recibiendo el dato por el serial
y lo vaya acumulando en una cadena hasta que reciba un 0x0d
o enter y en ese momento lo copia a la variabla Data y reinicia variables.
:)



const unsigned char BUFFERSIZE = 20;
unsigned char ContBUFFER_Rx0 = 0;
unsigned char BUFFER_Rx0[BUFFERSIZE];
unsigned char Data[BUFFERSIZE];


#pragma INTERRUPT rx0_int
void rx0_int(void)
{
unsigned char dato_rx;
dato_rx = (unsigned char) (U0RB & 0xf1ff);
BUFFER_Rx0[ContBUFFER_Rx0] = dato_rx;
if(dato_rx==0x0d || ContBUFFER_Rx0==BUFFERSIZE_RX0)
{
BUFFER_Rx0[ContBUFFER_Rx0] = 0;
strcpy(Data,BUFFER_Rx0);
strcpy(BUFFER_Rx0,"");
ContBUFFER_Rx0 = 0;
}
else ContBUFFER_Rx0++;
}
 
acabo de resolver ese problema con un pequenio codigo que genere cuando se da una interrupcion en el puerto seri del micro, tengo que enviar una posicion a un servomotor que es un numero mayor a 255 por ejemplo si le quiero enviar un 3500, desde la pc le enviaria los siguientes caracteres "0003500*" y el codigo de abajo lo interpreta como 3500

Código:
 serie:   'Etiquete de rutina de interrupcion por el puerto seri
 DISABLE
 
HSerin [DATOE] ' recibo el caracter de la pc por el rs232

 DATO[INDICE]=DATOE    'lo almaceno en una variable tipo arreglo
 INDICE=INDICE+1           'cambio el indice para usar otra variabla para el siguiente caracter

 'cuando le envio un valor al final le pongo un "*"
 IF DATOE=="*" THEN  ' cuando del PC llaga un "*" interpreto el numero que recibi
  BORRAR=1
 INDICE=1
 FOR I=1 TO 7
    SELECT CASE DATO[I] 'dato que recibi
        CASE 48                 ' es un cero?
            NUM[I]=0           
        CASE 49                 ' es un uno?
            NUM[I]=1
        CASE 50                 ' es un dos?
            NUM[I]=2
        CASE 51                 'creo que ya entendiero....
            NUM[I]=3
        CASE 52
            NUM[I]=4
        CASE 53
            NUM[I]=5
        CASE 54
            NUM[I]=6
        CASE 55
            NUM[I]=7
        CASE 56
            NUM[I]=8
        CASE 57                   ' es un nueve?
            NUM[I]=9
        CASE ELSE    'CUALQUIER OTRO CARACTER LO TOMA COMO CERO "O"
            NUM[I]=0
    END SELECT 
 NEXT I
 'aqui determino que numero me enviaron por el PC
 DATOACUM=NUM[7] + NUM[6]*10 + NUM[5]*100 + NUM[4]*1000 + NUM[3]*10000 
 
 POS=DATOACUM              'asigno la posicion  
 
 ENDIF       

    INTCON = %11000000
enable    
RESUME
espero te sirva la idea...

que tal unikfriend...
me podras ayudar a pasar el codigo que tengo del servodriver a ccs?
ya lo estoy controlando
 
Hola,
Tengo otras dudas, al leer el dato por interrupción se leen 8 bits del RCREG y lo almacenaría en variable1. A la siguiente interrupción leería el RCREG y lo almacenaría en otra variable2, pero como haría para obtener el valor de 16 bits de las dos variables leidas si variable1 es LSB y variable 2 es MSb.
Gracias.
 
Última edición:
Hola sydb,
El micro siempre guarda el byte que entra en el mismo buffer, ya esta en quien programa como quiere disponer de los datos, si lo que necesitas es recibir mas de 2 datos, en mikroc esta la función UART1_Read_Text(); la puedes utilizar dentro de la interrupción sin ningún problema.
Saludos
 
Buenas.

Estoy comunicando dos micros y necesito enviar una cadena de texto mediante la instruccion :
UART1_Write_Text

////////micro emisor//////////

char dummy, old_duty,cnt;
output=cnt + dummy + old_duty; ¿ esto es posible?
UART1_Write_Text(output);



si fuese posible, como hago para que el micro receptor me identifique cada uno de estas 3 variables de manera independiente y luego poderlas comparar para asi realizar distintas operaciones con los distintos valores. he visto que la instruccion para ello es

UART1_Read_Text(output,"ok",3); La pregunta es puedo usar cualquier identificador para que termine la lectura en este caso uso un "OK" como en el ejemplo del mikro c, pero podriar usar cualquier otro?, el numero 3 esta asociado a la cantidad de datos que estoy enviando? es necesario crear una variable tipo cadena para asi guardar el dato output?

Agradezco de antemano la ayuda que me puedan brindar.
 
Hi sydb,
Yo utilizaria algo así,
la idea es que la interrupcion este recibiendo el dato por el serial
y lo vaya acumulando en una cadena hasta que reciba un 0x0d
o enter y en ese momento lo copia a la variabla Data y reinicia variables.
:)



const unsigned char BUFFERSIZE = 20;
unsigned char ContBUFFER_Rx0 = 0;
unsigned char BUFFER_Rx0[BUFFERSIZE];
unsigned char Data[BUFFERSIZE];


#pragma INTERRUPT rx0_int
void rx0_int(void)
{
unsigned char dato_rx;
dato_rx = (unsigned char) (U0RB & 0xf1ff);
BUFFER_Rx0[ContBUFFER_Rx0] = dato_rx;
if(dato_rx==0x0d || ContBUFFER_Rx0==BUFFERSIZE_RX0)
{
BUFFER_Rx0[ContBUFFER_Rx0] = 0;
strcpy(Data,BUFFER_Rx0);
strcpy(BUFFER_Rx0,"");
ContBUFFER_Rx0 = 0;
}
else ContBUFFER_Rx0++;
}

Me fue de mucha Ayuda, Gracias!!
 
Que tal, soy nuevo por este foro, me decidí a consultarlos porque ando perdido con la programación de pics, en realidad lo que necesito creo que es muy sencillo pero no logro realizarlo, el punto es que necesito enviar un byte (cualquier número) del pic al pc ya sea por puerto serial o usb, solo me interesa que el pic envie al pc y no viceversa, necesito leer ese valor en el pc y programar un timer con ese valor por software, he visto muchos ejemplos de estas conexiones pero me confundo, realmente lo que necesito es lo mas básico. ojala puedan orientarme, gracias.
 
Hola. Mi pregunta es la siguiente: ¿Cómo puedo enviar datos al PIC desde la PC?

Lo que quiero es enviar por ejemplo; el número 1 a cierta variable que tengo en mi programa.
La idea es que a través del teclado mande el número 1 al PIC, éste lo guarde en la variable que quiero y luego haga lo que debe hacer.

Tengo la tabla ASCII, pero la verdad no tengo mucha idea de como hacerlo. Gracias.
Mi PIC es el 16F887 y trabajo en ASM.

Este es el código:
Código:
;-----------------------------------------------------------------------------------------------------------
; Proyecto: Secuencia 16 colores
; Autor: Lab de digitales2
; Fecha: 2014-2015
; Micro: PIC16F887
; Clock: oscilador interno 4MHz
;-----------------------------------------------------------------------------------------------------------
    list p=16f887
    #include   <p16f887.inc>
    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
    __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
;------------------------------------------------------------------
;configuro inicio del programa con el vector reset/interrupcion
;*****************************************************************
        org 00H
           goto inicio

     org 04h
        goto Interrupcion
;-----------------------------------------------------------------------
; Inicia Programa
; CONFIGURO I/O
;**********************************************************************
inicio
 ;-------------------------------------------------------------------------
; Configuro Variables
;*************************************************************************
    CBLOCK  20H
    pwm_r, pwm_v, pwm_a         ; variables para saber si ya se cumplio mi Ton
    W2, Status2                 ; variables de respaldo
    Var_1,Var_2,Var_3           ; variables para saber si ya se cumplieron los ciclos de trabajo
    Var_C                       ; variable para saber en que color estoy
    cont1                       ; variable que decremento para saber si ya cumpli tiempo
    Var_T                       ; esta variable se cargara con 1, para T=10ms, 2 para T=20ms... 200 para T=2s
    ENDC
;---------------------------------------------------------------------
; configuro Interrupcion cada 40us
;*********************************************************************
    BANKSEL OPTION_REG
    Movlw   b'00000010'
    Movwf   OPTION_REG
    Movlw   b'10100000'
    Movwf   INTCON
    BANKSEL ANSEL
    clrf    ANSELH
    BANKSEL TRISD
    clrf    TRISB
    BANKSEL PORTA
    clrf    PORTB
;-------------------------------------------------------------------------
; Defino pin de puertos
;*************************************************************************
    #Define Led_r PORTB,0
    #Define Led_v PORTB,1
    #Define Led_a PORTB,2

;--------------------------------------------------------------------------
; Pregunto la variable "Var_C" para ver en que color me encuentro, dependiendo del valor que tome Var_C decido en que color estar
;**************************************************************************

Carga_duty
    movf    Var_C,W
    addwf   PCL, F
    goto    rojo
    goto    Azul
    goto    verde
    goto    amarillo
    goto    agua
    goto    magenta
    goto    orange
    goto    bonito
    goto    morado
    goto    marron
    goto    violeta
    goto    oscuro
    goto    verde1
    goto    rosado
    goto    verde2
    goto    blanco
;-------------------------------------------------------------------------
; Cargo las variables con los distintos dutys para generar
;los colores correspondientes
;*************************************************************************

rojo
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    goto    Pregunto_Pwm

verde
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    goto    Pregunto_Pwm

Azul
    movlw   .0
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    goto    Pregunto_Pwm

amarillo
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    goto    Pregunto_Pwm
agua
    movlw   .0
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    goto    Pregunto_Pwm

magenta
    movlw   .255
    movwf   pwm_r
    movlw   .0
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    goto    Pregunto_Pwm

orange
    movlw   .255
    movwf   pwm_r
    movlw   .140
    movwf   pwm_v
    movlw   .0
    movwf   pwm_a
    goto    Pregunto_Pwm

bonito
    movlw   .0
    movwf   pwm_r
    movlw   .250
    movwf   pwm_v
    movlw   .154
    movwf   pwm_a
    goto    Pregunto_Pwm

morado
    movlw   .147
    movwf   pwm_r
    movlw   .112
    movwf   pwm_v
    movlw   .219
    movwf   pwm_a
    goto    Pregunto_Pwm

marron
    movlw   .139
    movwf   pwm_r
    movlw   .69
    movwf   pwm_v
    movlw   .19
    movwf   pwm_a
    goto    Pregunto_Pwm

violeta
    movlw   .238
    movwf   pwm_r
    movlw   .130
    movwf   pwm_v
    movlw   .238
    movwf   pwm_a
    goto    Pregunto_Pwm

oscuro
    movlw   .25
    movwf   pwm_r
    movlw   .25
    movwf   pwm_v
    movlw   .112
    movwf   pwm_a
    goto    Pregunto_Pwm

verde1
    movlw   .46
    movwf   pwm_r
    movlw   .139
    movwf   pwm_v
    movlw   .87
    movwf   pwm_a
    goto    Pregunto_Pwm

rosado
    movlw   .220
    movwf   pwm_r
    movlw   .20
    movwf   pwm_v
    movlw   .60
    movwf   pwm_a
    goto    Pregunto_Pwm

verde2
    movlw   .144
    movwf   pwm_r
    movlw   .238
    movwf   pwm_v
    movlw   .144
    movwf   pwm_a
    goto    Pregunto_Pwm

blanco
    movlw   .255
    movwf   pwm_r
    movlw   .255
    movwf   pwm_v
    movlw   .255
    movwf   pwm_a
    goto    Pregunto_Pwm

;-------------------------------------------------------------------------
;Pregunto si ya cumplieron los ciclos de trabajo,
; configuro Interrupcion cada 40us
;*********************************************************************
Pregunto_Pwm
    movf    Var_T,W             ;cargo el valor necesario para generar los distintos
    movwf   cont1               ; tiempos de 10ms a 2s
    BANKSEL TMR0
    Movlw   .251
    Movwf   TMR0
Pregunto_Pwm1
    movf    pwm_r,0
    subwf   Var_1,0
    btfss   STATUS,C
    goto    on_r
    goto    off_r
off_r
    bcf     Led_r
    goto    Pregunto_v
on_r
    bsf     Led_r
    goto    Pregunto_v

Pregunto_v
    movf    pwm_v,0
    subwf   Var_2,0
    btfss   STATUS,C
    goto    on_v
    goto    off_v
off_v
    bcf     Led_v
    goto    Pregunto_a
on_v
    bsf     Led_v
    goto    Pregunto_a

Pregunto_a
    movf    pwm_a,0
    subwf   Var_3,0
    btfss   STATUS,C
    goto    on_a
    goto    off_a
off_a
    bcf     Led_a
    btfss   PORTB,3
    goto    Pregunto_Pwm1
    bcf     PORTB,3
    clrf    Var_1
    clrf    Var_2
    clrf    Var_3
    decfsz  cont1           ;decremento contador, para saber si ya cumpli con mi tiempo
    goto    Pregunto_Pwm1
    goto    Carga_duty
on_a
    bsf     Led_a
    btfss   PORTB,3
    goto    Pregunto_Pwm1
    bcf     PORTB,3
    clrf    Var_1
    clrf    Var_2
    clrf    Var_3
    decfsz  cont1
    goto    Pregunto_Pwm1
    goto    Carga_duty

;--------------------------------------------------------------------
;rutina de interrupcion
;********************************************************************

Interrupcion
;---------------------------------------------------------------------
;guardamos registros importantes
;*********************************************************************
    movwf    W2
    movf     STATUS,w
    movwf    Status2
;--------------------------------------------------------------------
;pregunto si Var_X llego a 255, si es si, la cargo a 0
;verifico si se cumplio el periodo correspondiente
;*********************************************************************
    incf    Var_1,f
    movlw   .255
    subwf   Var_1,0
    btfss   STATUS,Z
    goto    Pregunto_var2
    clrf    Var_1
    bsf     PORTB,3
Pregunto_var2
    incf    Var_2,f
    movlw   .255
    subwf   Var_2,0
    btfss   STATUS,Z
    goto    Pregunto_var3
    clrf    Var_2
    bsf     PORTB,3
Pregunto_var3
    incf    Var_3,f
    movlw   .255
    subwf   Var_3,0
    btfss   STATUS,Z
    goto    inte
    clrf    Var_3
    bsf     PORTB,3
;-------------------------------------------------------------------
; devuelvo valor a w y status, tambien pongo en bajo Toif
;****************************************************************
inte
    bcf     INTCON,T0IF
    Movlw   .251
    Movwf   TMR0

    movf    Status2,w
    movwf   STATUS
    movf    W2,W
    retfie
    end
 
Última edición por un moderador:
Hola. Mi pregunta es la siguiente: ¿Cómo puedo enviar datos al PIC desde la PC?
Con el hyperterminal de Windows o cualquier otro programa para comunicación RS-232

Lo que quiero es enviar por ejemplo; el número 1 a cierta variable que tengo en mi programa.
La idea es que a través del teclado mande el número 1 al PIC, éste lo guarde en la variable que quiero y luego haga lo que debe hacer.

Tengo la tabla ASCII, pero la verdad no tengo mucha idea de como hacerlo. Gracias.
Mi PIC es el 16F887 y trabajo en ASM.
En tu programa no tienes ninguna rutina de recepción y puedes usar el módulo EUSART.
 
const unsigned char BUFFERSIZE = 20;
unsigned char ContBUFFER_Rx0 = 0;
unsigned char BUFFER_Rx0[BUFFERSIZE];
unsigned char Data[BUFFERSIZE];


#pragma INTERRUPT rx0_int
void rx0_int(void)
{
unsigned char dato_rx;
dato_rx = (unsigned char) (U0RB & 0xf1ff);
BUFFER_Rx0[ContBUFFER_Rx0] = dato_rx;
if(dato_rx==0x0d || ContBUFFER_Rx0==BUFFERSIZE_RX0)
{
BUFFER_Rx0[ContBUFFER_Rx0] = 0;
strcpy(Data,BUFFER_Rx0);
strcpy(BUFFER_Rx0,"");
ContBUFFER_Rx0 = 0;
}
else ContBUFFER_Rx0++;
}

alguien podria ayudarme y decirme que hace cada linea, si no es mucha molestia. aveces no logro comprender el codigo.:eek:

// seria de mucha ayuda // muchas gracias.
 
Me parece que es así:
PHP:
const unsigned char BUFFERSIZE = 20;   // Constante de valor 20
unsigned char ContBUFFER_Rx0 = 0;      // Variable de 8 bits sin signo, con valor inicial = 0
unsigned char BUFFER_Rx0[BUFFERSIZE];  // Arreglo (Array) con el número de elementos igual a BUFFERSIZE
unsigned char Data[BUFFERSIZE];        // Igual al de arriba.

// Servicio de interrupción
#pragma INTERRUPT rx0_int
void rx0_int(void)
{
unsigned char dato_rx;                                // Variable sin signo de 8 bits
dato_rx = (unsigned char) (U0RB & 0xf1ff);            // dato_rx = U0RB And 61951 (Máscara)
BUFFER_Rx0[ContBUFFER_Rx0] = dato_rx;                 // BUFFER_Rx0[Valor actual de ContBUFFER_Rx0] = Valor de dato_rx
if(dato_rx==0x0d || ContBUFFER_Rx0==BUFFERSIZE_RX0)   // Si dato_rx = 13 (Retorno de carro) O ContBUFFER_Rx0 es igual a BUFFERSIZE_RX0, entonces...
{
BUFFER_Rx0[ContBUFFER_Rx0] = 0;                       // BUFFER_Rx0[Valor actual de ContBUFFER_Rx0] = 0
strcpy(Data,BUFFER_Rx0);                              // Se copia el contenido del arreglo BUFFER_Rx0 en el arreglo Data
strcpy(BUFFER_Rx0,"");                                // Se limpia el arreglo BUFFER_Rx0
ContBUFFER_Rx0 = 0;                                   // Se pone ContBUFFER_Rx0 en 0
}
else ContBUFFER_Rx0++;                                // Caso contrario, se incrementa ContBUFFER_Rx0 de 1 en 1
}
No sé qué sea U0RB. No sé si sea una variable o un registro.
 
Atrás
Arriba