Autor Tema: Concatenar contenido de dos registros  (Leído 3391 veces)

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

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Concatenar contenido de dos registros
« en: 24 de Enero de 2019, 02:42:16 »
Buenas tardes, estoy construyendo un sencillo proyecto para leer la temperatura de un sensor probablemente un lm35 y desplegarla  en dos displays de 7 segmentos usando multiplexacion.  El programa lo estoy planteando en C en el ide del Pic c compiler, debido a que es algo didáctico, mi intención es prescindir de las funciones del ADC que trae el compilador que a mi gusto abstraen demasiado y alejan al programador de los "fierros".
En este momento estoy atorado, ya que no se como leer el resultado obtenido de la conversion, de los registros adresl y adresh, en el modo de 10 bits que es el que quiero usar, se usaría el resultado del adresl, y los dos bits menos significativos del adresl dependiendo de la justificación usada.
Una idea que rondaba en mi cabeza era hacer una especie de concatenacion, convirtiendo el valor de cada registro a char, concatenarlos y luego castear nuevamente a int16, quizás esté diciendo alguna burrada, alguien me podría orientar?
Muchas gracias a todos.
« Última modificación: 24 de Enero de 2019, 02:45:41 por Mecátronica2012 »

Desconectado AleSergi

  • PIC16
  • ***
  • Mensajes: 177
Re:Concatenar contenido de dos registros
« Respuesta #1 en: 24 de Enero de 2019, 03:42:49 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7167
Re:Concatenar contenido de dos registros
« Respuesta #2 en: 24 de Enero de 2019, 06:47:37 »
Considero que si te planteas representarlo como entero, lo justifiques a la derecha.

Y luego en un entero de 16 bits podes desplazar las 2 cantidades:

tu_var = ADRESH << 8;
tu_var |= ADRESL;


Sino la otra, busca lo que es una union, y hace la union de 2 variables  de 8bits con una de 16 bits... De esa forma podes acceder indivualmente sin hacer Shifts.

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #3 en: 02 de Febrero de 2019, 17:59:07 »
Buenas tardes, muchas gracias por la ayuda.
En referencia al comentario de killerjc, aun no comprendo del todo los corrimientos, si hicieramos un corrimiento a la derecha 10 veces
algo asi :
 tu_var = ADRESH << 10;

Para acomodar en el segundo byte de tu_var,  los dos bits que llevamos arrastrando del  ADRESH, y dejar reservados los primeros 8 bits de la variable  tu_var , para guardar lo que tengamos en el ADRESL, realizamos la operacion or :
tu_var = tu_var | adresl;
Es correcto este planteamiento? gracias por la ayuda

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7167
Re:Concatenar contenido de dos registros
« Respuesta #4 en: 02 de Febrero de 2019, 18:26:18 »
Si no me equivoco en XC8 podes acceder a los 16bits directamente del ADC... En caso de que unicamente puedas acceder a los 8 bits podes usar:

- Una union
- Desplazamientos.


Respecto al desplazamiento, tenes que recordar que estas desplazando bits. Supongamos que tenes el valor 10 1101 0110 en el ADC ( 10 bits ), es decir:
ADRESH = 0000 0010
ADRESL = 1101 0110

Desplazar es simplemente mover todo 1 espacio a la izquierda o derecha... Por ejemplo si ADRESH lo desplazo 2 veces a la izquierda me quedaria 0000 1000
Si tuviera una variable de 16 bits y le guardo con el valor de ADRESH  desplazado 8 lugares a la izquierda quedaria asi:

ADRESH desplazado 8 veces a la izquierda:  0000 0010 0000 0000

Si luego le hago una OR con ADRESL quedaria:

my_var  0000 0010 0000 0000
ADRESL  0000 0000 1101 0110
---------------------------------------
OR ->    0000 0010  1101 0110


Quedando tu valor de 16 bits completo.

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #5 en: 05 de Febrero de 2019, 00:36:00 »
Más claro imposible, muchas gracias por la ayuda, cuando termine el proyecto pondré el código por aquí

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #6 en: 30 de Marzo de 2019, 00:52:55 »
Aqui pongo el programa terminado y funcionando, por si a alguien le sirve de algo, saludos :


#include <16f877a.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#fuses XT,NOWDT
#use delay (clock=4M)
#BYTE TRISA=0x85
#BYTE TRISB=0x86
#BYTE PORTA=0x05
#BYTE PORTB=0x06
#BYTE TRISD=0x88
#BYTE OPTION_REG=0x81
#BYTE ADCON0=0x1F    //REGISTROS del ADC
#BYTE ADCON1=0x9F
#BYTE ADRESH=0x1E
#BYTE ADRESL=0x9E
#BYTE ANSEL=0x9B
#define lcd_rs_pin pin_d0
#define lcd_rw_pin pin_d1
#define lcd_enable_pin pin_d2
#define lcd_data4 pin_d4
#define lcd_data5 pin_d5
#define lcd_data6 pin_d6
#define lcd_data7 pin_d7
#include <lcd.c>
#define resolucion 0.004882
#define resCelcius 0.4882
// 1 paso del analogico es igual a 0.4882 grados
void proceso();
int16 LectorADC();

void main()
{
    TRISD = 0x00;
    TRISA = 0x0000001;
    disable_interrupts(GLOBAL);                        //TODAS las interrupciones desactivadas
    ADCON0 = 0x81;
    ADCON1 = 0xCE;
    lcd_init();
    lcd_gotoxy(1,1);
    printf(lcd_putc, "temp = ");
   
    while(true)
    {
        proceso();           
         
    }
   
}

void proceso()
{
     float temp = 0.0;
     int16 retAnalogico = 0;
     retAnalogico = LectorADC();
     temp = resCelcius * retAnalogico;
     lcd_gotoxy(8,1);
     printf(lcd_putc, "%3.1f",temp);
     delay_ms(200);                     //tomara muestras cada 200ms
}

int16 LectorADC()
{
     int16 analogico = 0;
      delay_ms(1);                      //tiempo de establecimiento
     bit_set(ADCON0,2);                //inicia conversion
     while(bit_test(ADCON0,2));        //se espera a que termine la conversion
     analogico =  ADRESH <<8;          //desplazmos 8 veces a la izquierda
     analogico = analogico | ADRESL;   //se realiza operacion or
     return analogico;
}

Desconectado Eduardo2

  • PIC16
  • ***
  • Mensajes: 183
Re:Concatenar contenido de dos registros
« Respuesta #7 en: 30 de Marzo de 2019, 11:13:41 »
Como te dijeron,  otra manera de hacerlo es mediante union.

Definís la union:     union HL {int16 hl ; struct {int8 l, h ;};};

Y en la rutina de lectura:

int16 LectorADC()
{
     union HL analog ;

     bit_set(ADCON0,2);                //inicia conversion
     while(bit_test(ADCON0,2));        //se espera a que termine la conversion

     analog.h = ADRESH ;
     analog.l = ADRESL ;
     return analog.hl;
}
« Última modificación: 30 de Marzo de 2019, 11:19:30 por Eduardo2 »

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #8 en: 12 de Abril de 2019, 15:30:43 »
Buenos dias, estoy empezando a hacer mis primeros programas utilizando timers e interrupciones, este tiene el objetivo de capturar la tecla pulsada utilizando la interrupcion por cambio de estado del RB4-RB7, esa parte funciona bien, sin embargo le agregue el uso del timer 0, para cada segundo mardarlo a leer una temperatura y desplegarla en la parte baja del lcd, esto ultimo no lo realiza y no logro dar con el error o quizas estoy planteando mal el programa, alguien podria echarme un cable? saludos gracias.



#include <16f877a.h>
#fuses XT,NOWDT
#use delay (clock=4M)
#define lcd_data_port getenv("sfr:portd")
#define lcd_enable_pin pin_d0
#define lcd_rs_pin pin_d1
#define lcd_rw_pin pin_d2
#define use_portb_kbd true
#include <lcd.c>
#include <KBD4x4.c>
#BYTE INTCON=getenv("sfr:INTCON")
#BYTE TRISA=getenv("sfr:INTCON")
#BYTE TRISB=getenv("sfr:TRISB")
#BYTE TRISD = getenv("sfr:trisd")
#BYTE OPTION_REG=getenv("sfr:OPTION_REG")
#BYTE ADCON0=getenv("sfr:ADCON0")    //REGISTROS del ADC
#BYTE ADCON1=getenv("sfr:ADCON1")
#BYTE ADRESH=getenv("sfr:ADRESH")
#BYTE ADRESL=getenv("sfr:ADRESL")
#BYTE TMR0=getenv("sfr:TMR0")
#define resolucion 0.004882
#define resCelcius 0.4882

char k;
int contador = 0;                   //Contador usado para el timer
void muestraBoton();                //prototipos de funciones
int16 LectorADC();
void procesoLeeTemp();

#INT_RB
void servicioIntRB()                      //rutina de interrupcion
{
    k = kbd_getc();
    bit_clear(INTCON,0);;            //bandera de la interrupcion a 0 nuevamente
    muestraBoton();
}

#INT_TIMER0
void servicioInttmr0()                     //rutina de interrupcion
{
    contador++;
    TMR0=22;                      //Se recarga el timer
    bit_clear(INTCON,2);          //Se vuelve a poner a 0 el bit de bandera de desbordamiento
    if (contador == 17)           //si ha transcurrido un segundo
    {
        contador = 0;
        procesoLeeTemp();
    }

}

void main()
{
     TRISA = 0x1;           //Pin RA0 como entrada para analogico
     TRISB = 0xff;         //puerto b como entrada
     TRISD = 0x00;         //puerto d como salida
     port_b_pullups(true);
     lcd_init();
     kbd_init();
     lcd_gotoxy(1,1);
     printf(lcd_putc,"iniciando");
     delay_ms(1000);
     lcd_putc("\f");              //se borra la pantalla
     lcd_gotoxy(1,1);
     printf(lcd_putc,"Teclado con");
     lcd_gotoxy(1,2);
     printf(lcd_putc,"interrupciones");
     delay_ms(2000);
     lcd_putc("\f");
     lcd_gotoxy(1,2);
     printf(lcd_putc,"Temp = ");
     OPTION_REG=0b00000111;   //preescaler 1:256
     ADCON0 = 0x81;
     ADCON1 = 0xCE;
     INTCON = 0xA8;  ////habilitacion global de interrupcion, habilitacion de int por cambio de estado RB4-RB7,flag RBIE a 0,habilitacion int timer0
     TMR0=22;                 //se carga con un valor de 256 - 22, para contar 60ms

    while(true)
    {
             
    }

}

void muestraBoton()
{
    if (k!=0)
         {
            lcd_gotoxy(1,1);
            printf(lcd_putc,"tecla pulsada: %c",k);
         }
}

void procesoLeeTemp()
{
     float temp = 0.0;
     int16 retAnalogico = 0;
     retAnalogico = LectorADC();
     temp = resCelcius * retAnalogico;
     lcd_gotoxy(7,2);
     printf(lcd_putc, "%3.1f",temp);     
}

int16 LectorADC()
{
     int16 analogico = 0;
     delay_ms(1);                      //tiempo de establecimiento
     bit_set(ADCON0,2);                //inicia conversion
     while(bit_test(ADCON0,2));        //se espera a que termine la conversion
     analogico =  ADRESH <<8;          //desplazmos 8 veces a la izquierda
     analogico = analogico | ADRESL;   //se realiza operacion or
     return analogico;
}

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #9 en: 13 de Mayo de 2019, 16:12:11 »
Alguien sabe si en proteus está simulada la interrupción por termino de conversión ADC?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7167
Re:Concatenar contenido de dos registros
« Respuesta #10 en: 13 de Mayo de 2019, 18:13:33 »
en CSS tenes funcion para todo, asi no tocas los registros y todo se vuelve mas facil, seguramente habras visto codigos por ahi que usan read_adc()

Busca como leer el ADC.

Desconectado Mecátronica2012

  • PIC10
  • *
  • Mensajes: 10
Re:Concatenar contenido de dos registros
« Respuesta #11 en: 14 de Mayo de 2019, 18:02:56 »
Gracias por contestar, entiendo eso que comentas, pero mi duda actual es si en proteus está simulada la interrupción por ADC

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7167
Re:Concatenar contenido de dos registros
« Respuesta #12 en: 15 de Mayo de 2019, 06:39:25 »
Gracias por contestar, entiendo eso que comentas, pero mi duda actual es si en proteus está simulada la interrupción por ADC

Tengo entendido que si... En realidad no es que esta habilitada la interrupcion por ADC, en realidad esta habilitada la interrupcion, ya que salta al mismo lugar y luego es el programa quien determina que tipo de interrupcion fue. Asi que si funciona una, deberia funcionar la otra :P


 

anything