Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Tokes

#71
Estimado Meta:

Es aquí donde debes usar el registro PCLATH, ya que la instrucción ADDWF   PCL,F suma dos registros de un byte cada  uno, por lo cual el resultado es de un byte y sólo puedes direccionar de entre 255 direcciones de una subpágina. Por tanto, si el registro PCLATH no selecciona la página correspondiente, el programa no funcionará correctamente.

Una manera de solucionarlo consiste en, antes de llamar a la tabla, sumar los valores del registro W y de la dirección (tabla + 1) (recordemos que al ejecutarse la instrucción ADDWF   PCL,F el registro PCL está direccionando la siguiente instrucción). El byte alto del resultado lo cargamos en PCLATH y, posteriormente, llamamos la tabla como siempre. Ejemplo:

Supongamos que queremos tomar los 6 bits menos significativos de PORTA como entradas de la tabla, haríamos lo siguiente:

Código (asm) [Seleccionar]
movf PORTA,W
               andlw        b'00111111'
addlw low(Tabla+.1)  ; Suma el valor de desplazamiento con la dirección (Tabla + 1).
movlw high(Tabla+.1) ; Obtiene el byte alto de la dirección (Tabla + 1).
btfsc STATUS,C ; Si la suma de bytes bajos dió acarreo...
addlw .1             ; lo suma al byte alto de la dirección (Tabla + 1)
movwf PCLATH     ; y lo carga en PCLATH para seleccionar la página correspondiente.
movf PORTA,W   ; Ahora llama la tabla normalmente.
               andlw        b'00111111'
call Tabla


Es un poco tedioso, pero funciona. Lamentablemente, ese arreglo también lo tendrás que hacer en la librería LCD_MENS.INC y en todas las librerías que usen tablas. Una vez que hagas ese arreglo, puedes quitar la directiva IF Fin_Tabla...

Espero te sirva. Saludos.
#72
¡Ya llegué de nuevo!

Ahora les traigo otro tema que es importantísimo aprender (a los novatos les da mucho dolor de cabeza al ver que sus programas no funcionan).

Tema: La palabra de configuración.

A muchos principiantes les ha sucedido esto: editan su programa, lo compilan o ensamblan, lo revisan en algún simulador y, finalmente, lo graban en el microcontrolador. Pero ¡Oh sorpresa! El microcontrolador no hace nada. ¿Qué sucede? La simulación indicaba que todo estaba bien. ¡¿Por qué no funciona el micro?!

Lo que sucede es que muchas veces olvidamos especificar la palabra de configuración del dispositivo. Esta palabra de configuración, que reside en algún lugar de la memoria de programa, habilita/deshabilita ciertos mecanismos del microcontrolador que tendrán efecto significativo en su funcionamiento. A continuación se explicarán algunos de los mecanismos controlados por la palabra de configuración.

-   Oscilador. Es necesario siempre especificar el tipo de oscilador con el que va a operar el dispositivo. Si el oscilador que se conecta al microcontrolador es diferente del especificado en la palabra de configuración, adivinen ¿qué sucede? Para el caso de los PIC, si queremos que nuestro dispositivo funcione con un cristal de 4 MHz, en la palabra de configuración debemos especificar XT. Si deseamos que trabaje con un cristal de 12 MHz, en la palabra de configuración debemos especificar HS, y de manera similar para los otros osciladores.

Cabe señalar que si no especifica el tipo de oscilador, el oscilador por defecto para los PIC es del tipo RC.

-   Detector de Brown-Out. Un Brown-Out es una baja en la tensión de alimentación del dispositivo. Todos los microcontroladores tienen un rango de voltaje de operación. Si la tensión de alimentación rebasa el límite superior el microcontrolador podría averiarse. Si la tensión de alimentación está por debajo del límite inferior, el microcontrolador trabaja, pero seguramente operará de manera inadecuada. Aquí está el detalle:

Si la tensión de alimentación del dispositivo está por debajo de lo especificado por el fabricante, el microcontrolador puede operar sin riesgo de averías, pero no es seguro que funcione correctamente; podríamos decir que el microcontrolador está "ebrio".

El usuario tiene dos opciones:

1.   Permitir que el microcontrolador opere aún cuando la tensión de alimentación esté por debajo de lo mínimo especificado. Para este caso se inhabilita el detector de Brown-Out.
2.   Impedir que el microcontrolador opere cuando la tensión está por debajo del mínimo especificado. Esto se logra activando el detector de Brown-Out.

Claro está que la activación/desactivación del detector de Brown-Out debe especificarse en la palabra de configuración.

-   Temporizador de arranque. Este temporizador, si está habilitado, inicia su ciclo de tiempo al ser conectada la alimentación y durante su temporizado mantiene al microcontrolador en estado de reset (impide la ejecución del código). Esto es con el objetivo de que el microcontrolador empiece a funcionar cuando el nivel de la tensión de alimentación sea adecuado.

-   Temporizador perro guardián (Watchdog Timer). Este temporizador comienza su temporización una vez que el microcontrolador está correctamente alimentado. Cuando dicho temporizador llega al final de la cuenta resetea al sistema, de manera que el código vuelve a ejecutarse desde el principio. Esto es muy útil para los casos en los que el programa entra en un ciclo infinito esperando que se cumpla una condición que no llega.

Al utilizar el Watchdog Timer hay que refrescar su contenido (ponerlo a 0) en el programa periódicamente para evitar que se desborde y resetee al sistema.

¿Dónde no hay que refrescar el contenido del Watchdog? En las partes de la programación donde el sistema pueda quedar atrapado en un ciclo infinito. Es ahí donde el Watchdog  se desbordará y reiniciará al sistema, sacándolo así del bucle infinito en el que estaba atrapado.

-   Protección de código. Antiguamente, y en algunos casos actuales, los diseñadores de circuitos electrónicos solían raspar la parte superior de los circuitos integrados con el objetivo de borrar la identificación del chip y así evitar que otras personas plagiaran su diseño.

No es necesario hacer esto con los dispositivos que tienen sistema de protección de código. Activando la protección de código, las instrucciones grabadas en la memoria de programa del dispositivo no pueden ser leídas por ningún dispositivo externo. El chip seguirá siendo funcional, se le puede grabar un nuevo programa, pero nunca se sabrá que programa tenía anteriormente.

-   Modo de depuración. Al activar el modo de depuración el dispositivo dedica unas cuantas de sus terminales para comunicarse con el dispositivo depurador, por lo cual estas terminales no pueden funcionar como entrada/salida.

En el modo de depuración el usuario puede controlar la velocidad con la que el microcontrolador ejecuta las instrucciones, puede ver el contenido de las memorias de programa y de datos, entre otras cosas.

-   Programación con bajo voltaje. Los microcontroladores PIC tienen dos modos de grabación:
o   Programación con voltaje alto. En este modo ocurre lo siguiente:
     I.   Si la terminal MCLR recibe un voltaje de 0 V el microcontrolador entra en estado de reset y no ejecuta instrucciones.
     II.   Si la terminal MCLR recibe un voltaje de 5 V el microcontrolador ejecuta instrucciones normalmente.
     III.   Si la terminal MCLR recibe un voltaje de 12 V el microcontrolador entra en modo de grabación y recibe las instrucciones que han de grabarse en su memoria de programa.
o   Programación con voltaje bajo. En este modo de grabación ocurre lo siguiente:
     I.   Si la terminal RB3/PGM recibe un '0' lógico el microcontrolador opera de manera normal.
     II.   Si la terminal RB3/PGM recibe un '1' lógico el microcontrolador entra en modo de grabación.

Cuando el microcontrolador está en modo de grabación las terminales RB7 y RB6 soportan los datos y el reloj, respectivamente.

- Detector de fallas de reloj. Cuando los microcontroladores operan con una señal de reloj externa hay el riesgo de perder conexión con dicha señal (por averías en la pista, porque el dispositivo que brindaba la señal dejó de funcionar, etc.).

Algunos microcontroladores tienen integrado un detector de fallas de reloj, el cual detecta si se ha perdido la señal de sincronía externa, momento en el cual realiza un switcheo hacia el reloj interno. Esto quizá requiera hacer ajustes en el programa, ya que posiblemente el reloj externo operaba a una velocidad diferente del interno.

- Protección de datos. Esto es algo similar a la protección de código. Activando la protección de datos la memoria EEPROM no puede ser leída por ningún dispositivo externo (aunque sí puede ser escrita).

Bien, eston son algunos de los mecanismos que pueden activarse o desactivarse mediante la palabra de configuración.

Ahora ¿Cómo especifico la palabra de configuración en el programa? Esto depende del software ensamblador/compilador que se utilice.

En el software MPASM del MPLAB IDE la palabra de configuración se especifica mediante la directiva __CONFIG (notar que lleva dos guiones bajos) seguida de ciertos parámetros que especifican los mecanismos a configurarse.

Pongamos como ejemplo al PIC16F84A. Los mecanismos de este microcontrolador que pueden configurarse mediante la palabra de configuración son:

- Temporizador de arranque (Power Up Timer).
- Tipo de oscilador.
- Watchdog Timer.
- Protección de código.

Supongamos que deseamos que nuestro microcontrolador:

- Opere con un cristal de 20 MHz (Oscilador HS).
- El Watchdog Timer se desactive (para que no reinicie nuestro programa a cada rato).
-  el Power Up Timer encienda (para que el micro no funcione hasta que el nivel de alimentación se estabilice).
- El código en su memoria de programa quede protegido para que nadie pueda leer el programa guardado en el dispositivo.

Esto se especifica así en el MPASM de MPLAB IDE:

   __CONFIG   _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_ON

En el compilador PCWH de la empresa CCS se especifica así:

   #fuses   HS, NOWDT, PUT, CP

Bueno, aquí acaba este tema. Nos vemos luego.
#73
Mira, mi hermano:

Para empezar, intenté buscar en la carpeta Drivers que viene con el compilador de CCS el archivo "LCD_4x20.h" y me dí cuenta que no existe; en esa carpeta sólo están los archivos "LCD.h" y "LCD420.h". Tal vez en tu versión de CCS sí se encuentre el archivo.

Otra cosa: En cualquier función o bucle hay que declarar las variables y constantes antes de poner operaciones. Una vez que pones operaciones ya no debes declarar variables o lo tomará como error.

En fín, aquí te dejo el código que según yo está corregido (nota que primero declaro las variables):

Código (asm) [Seleccionar]
#include <16F877A.h>
#device adc = 10
#FUSES XT, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT
#use delay(clock=4000000)
#use fast_io(C)
#use fast_io(D)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, bits=8, parity=N)
#include "LCD420.C"

void main()
{
//DECLARANDO VARIABLES DE CONTROL
  short control;
  short control1;
  short controlh;
//FIN VARIABLES DE CONTROL

  int16 hum1;
  int16 hum2;
  int16 hum3;
  int16 temp1;
  int16 temp2;
  float tempt1;
  float tempt2;
  float humt1;
  float humt2;
  float humt3;
  float humS;
  float tempS;
  float RH;
  float p;
 
  set_tris_c(0xB0);
  set_tris_d(0xC0);
 
  setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
  setup_adc(ADC_CLOCK_INTERNAL);
  lcd_init();
  control = 0;
  control1 = 0;
  controlh = 0;
  while(1)
  {
     set_adc_channel(0);  //CANAL 0
     delay_us(10);
     temp1 = (read_adc() * 100);
     set_adc_channel(1);  //CANAL 1
     delay_us(10);
     temp2 = (read_adc() *100);
     tempt1 = temp1 * 0.0049;
     tempt2 = temp2 * 0.0049;
     tempS = (tempt1 + tempt2) / 2.0;   //TEMPERATURA A MANEJAR
     //*********** RUTINA DE CONTROL DE TEMPERATURA ****************
     if (tempS >= 28.0)
     {
        if (control == 0)  //AQUI TESTEAR EL RC3
        {
           output_high(PIN_C1);
           // ir a sube y luego regresar
           delay_ms(3000);
           // ir a paraA y luego regresar
           output_low(PIN_C1);
           control = 1;  //aqui ver el RC3
        }
     }
     if (tempS <= 20.0)
     {
        if (control == 1)
        {
           output_high(PIN_C3);
           //ir a baja y regresar
           delay_ms(3000);
           //ir a paraB y regresar
           output_low(PIN_C3);
           control = 0;
        }
        output_high(PIN_C2); //AIRE CALIENTE
        control1 = 1;
     }
     if (control1 == 1)
     {
        if (tempS <= 25.0)
        {
           output_high(PIN_C2);  //AIRE CALIENTE
        } else
          {
             output_low(PIN_C2);  //APAGA AIRE CALIENTE
             control1 = 0;
          }
     }
     //************ FIN RUTINA CONTROL TEMPERATURA *****************
     set_adc_channel(2);  //CANAL 2
     delay_us(10);
     hum1 = read_adc();
     set_adc_channel(3);  //CANAL 3
     delay_us(10);
     hum2 = read_adc();
     set_adc_channel(4);  //CANAL 4
     delay_us(10);
     hum3 = read_adc();
     //hum1t = (5.0 * hum1) / 1024.0;
     humt1 = hum1 * 0.0049;
     humt2 = hum2 * 0.0049;
     humt3 = hum3 * 0.0049;
     humS = (humt1 + humt2 + humt3) / 3;
     RH = (humS - 0.958) / 0.0307;   // HUMEDAD HA MANEJAR
     //******* RUTINA CONTROL DE HUMEDAD ****************
     if (RH >= 80.0)
     {
        output_low(PIN_C0);
     }
     if (RH <= 75.0)
     {
        output_high(PIN_C0);
        controlh = 1;
     }
     if (controlh == 1)
     {
        if (RH <= 77.0)
        {
           output_high(PIN_C0);
        }else
        {
           output_low(PIN_C0);
           controlh = 0;
        }
     }
     //*********** FIN RUTINA CONTROL HUMEDAD **************
     //printf(lcd_putc, "\fADC = %4ld", q);
     //printf(lcd_putc, "\nVoltage = %01.2fV", p);
     printf(lcd_putc, "\f   TEMPERATURA    ");
     printf(lcd_putc, "\n     %01.2f C", tempS);
     printf(lcd_putc, "\n HUMEDAD   ");
     printf(lcd_putc, "\n%01.2f PHS", RH);
     //TRANSMISION SERIAL
     printf("ADC = %4ld", tempt1);
     printf(" Temperatura = %01.2f C\r", tempS);  // El \r permite cambiar de línea
     printf("ADC = %4ld", hum3);
     printf(" humedad = %01.2f RH\r", RH);
     delay_ms(100);
  }
}


              Saludos.
#74
andres_5:

Checa este enlace:

http://www.todopic.com.ar/foros/index.php?topic=1732.0

Es para hacer un grabador de PIC con puerto paralelo.


          Saludos.
#75
BlackZeroX:

Eso sí que estuvo buenísimo. Ahora me despertaste otra duda:

¿Por qué en modo pixel multiplicas por 15?

Espero no molestarte. Saludos.
#76
Muy bien, raul338:

He probado como me lo dijiste y me ha funcionado. Muchas gracias a ti y a PsYkE1 por contestar.
#77
Electrónica / Re: Tablas indexado de 8 bits.
29 Agosto 2010, 18:09 PM
Mi estimado Meta:

Para borrar una línea del LCD primero tienes que posicionar el cursor al principio de esa línea, luego invocas a LCD_LineaEnBlanco y luego debes volverte a posicionar al principio de esa línea. Para que no sea tan tedioso puedes hacer subrutinas que borren las líneas. Ejemplo:

Código (asm) [Seleccionar]
LCD_Linea1EnBlanco
    call LCD_Linea1
    call LCD_LineaEnBlanco
    call LCD_Linea1
    return


LCD_Linea2EnBlanco
    call LCD_Linea2
    call LCD_LineaEnBlanco
    call LCD_Linea2
    return


LCD_Linea3EnBlanco
    call LCD_Linea3
    call LCD_LineaEnBlanco
    call LCD_Linea3
    return
#78
¡Qué tal a todos!:

Hoy hablaremos de un tema necesario para poder comunicar a un microcontrolador con el exterior.

Tema: Los puertos de Entrada/Salida.

Bien, es muy usual que los microcontroladores llamen PORT a los puertos de entrada/salida, aunque no siempre es así.

Para los microcontroladores PIC, los puertos toman los nombres: PORTA, PORTB, PORTC, etc.

Para los microcontroladores AVR, los puertos se llaman: PORTA, PORTB, PORTC, etc. cuando se utilizan como salida, y toman los nombres PINA, PINB, PINC, etc. cuando se comportan como entradas.

En algunos microcontroladores, como es el caso de los PIC, los puertos de E/S se encuentran mapeados en la memoria de datos RAM. ¿Qué quiere decir esto? Pues que, simple y sencillamente, algunas direcciones de la memoria de datos están conectadas a los puertos de E/S. Cuando el microprocesador desea enviar datos a un puerto, lo que hace es enviar esa información a una dirección de la memoria de datos RAM que está conectada con ese puerto. La ventaja de esto es que se pueden manejar los puertos con las mismas instrucciones que operan sobre la memoria de datos.

Por ejemplo, para el PIC16F84A:

        clrf   5

Esta instrucción borra el contenido de la dirección 5 de la memoria de datos. Pero resulta ser que la dirección 5 de la memoria de datos está conectada al puerto A, por lo tanto, lo que esta instrucción está haciendo es borrar los bits del puerto A.

Ahora, bien, estos puertos de E/S son bidireccionales, esto quiere decir que pueden funcionar como entradas y/o salidas. Para determinar el sentido que tomarán las terminales de cada puerto (entradas o salidas) existen registros especiales, llamados TRIS en el caso de los microcontroladores PIC. Para otros microcontroladores estos registros se llaman DDR (Data Direction Register)

Enfoquémonos en los microcontroladores PIC.

El registro TRISx controla la dirección de PORTx de la siguiente manera:

-   Si un bit del registro TRISx se encuentra a '0', el correspondiente bit de PORTx funciona como salida.
-   Si un bit del registro TRISx se encuentra a '1', el correspondiente bit de PORTx funciona como entrada.

Para ejemplificar veamos la siguiente figura:


Figura 5. Ejemplo de conexiones entre microcontrolador y periféricos externos.

Antes que nada, haremos un convenio: los bits no utilizados de los puertos los configuraremos como salidas (¿Por qué? No pregunten, lo entenderán más tarde).

Podemos ver que el puerto A del PIC16F84A tiene 5 bits, desde RA0 hasta RA4. Veamos que conexiones tenemos en el PORTA.

En RA0 tenemos conectada la base de un transistor NPN, cuyo colector queda conectado a un relevador. Como ya sabemos, la base de un transistor controla el funcionamiento del mismo, llevándolo a corte o a saturación, según sea el caso. Por tanto, el microcontrolador decidirá cuándo se activará o desactivará el relevador enviándole información a la base del transistor. Ello quiere decir que el bit RA0 debe ser salida. Para ello, el bit 0 del registro TRISA debe estar en '0'.

En la terminal RA1 está conectado un buzzer, el cual puede funcionar como una pequeña alarma. Para activar o desactivar el buzzer, el microcontrolador debe enviarle información a través de RA1, por lo cual, este bit debe ser salida. Esto se logra poniendo a '0' el bit 1 del registro TRISA.

La terminal RA4 está conectada a un interruptor, SW1. Al cerrarse, el interruptor le envía un '0' al microcontrolador. Al abrirse, le envía un '1'. Por lo tanto, la terminal RA4 debe ser configurada como entrada. Poniendo a '1' el bit 4 del registro TRISA se logra esto.

Las terminales RA2 y RA3 no están conectadas a dispositivo alguno, ya quedamos que serán configuradas como salidas.

El PORTA, entonces, debe quedar configurado así:



El registro TRISA debe contener para ello:



Ahora vamos a analizar el PORTB.

La terminal RB0 está conectada a la salida de un OPAMP que funciona como detector de cruce por cero. El OPAMP le informa al microcontrolador si la señal de alterna se encuentra en el semiciclo positivo o en el negativo. Por tanto, la terminal RB0 debe ser entrada.

No hay que ser genios para darnos cuenta que las terminales RB1 y RB2, conectadas cada una a un led, deben ser salidas.

RB6 y RB7 están conectadas cada una a un pulsador. Cuando un pulsador está abierto envía un '1' a la respectiva terminal. Cuando un pulsador está cerrado envía un '0' a la respectiva terminal. Ello quiere decir que RB6 y RB7 deben ser configuradas como entradas.

Las terminales RB3, RB4 y RB5 no están conectadas a dispositivo alguno; quedarán configuradas como salidas.

El PORTB debe quedar configurado de la siguiente manera:



Para ello, el TRISB debe contener:



Pues bien, por el momento es todo. Que se la pasen bien.
#79
El software enviará la información por el puerto serie.

      Saludos.
#80
Ah, bueno, me refería a hacer eso mismo pero mediante código.

Es que quiero que, mediante un command1, el usuario pueda crear los objetos que quiera en tiempo de ejecución.

           Saludos y muchas gracias.

P.D: Sí, casi no me conecto. De hecho mi correo electrónico lo reviso una vez cada dos semanas. ¡Soy un desastre!