Autor Tema: AYUDA CON PIC16F877A Y PROTEUS  (Leído 4353 veces)

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

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
AYUDA CON PIC16F877A Y PROTEUS
« en: 26 de Junio de 2012, 07:23:40 »
Código: [Seleccionar]
Buenas,

Es la primera vez que uso Proteus por lo que estoy un poco perdido. He utilizado el diseño de otro proyecto, del que he quitado algunas cosas de las que prescindí para hacer mi programa. Me dan 3 errores:

DSIM model TC7X.DLL failed to authorize- Missing or invalid Customer Key.
DSIM model LCDALPHA.DLL failed to authorize- Missing or invalid Customer Key.
mixex model PIC16.DLL failed to authorize.  - Missing or invalid Customer Key.

No tengo ni idea como solventarlo.

Les subo el código main:
Código: [Seleccionar]
#include "16F877A.h"

#device adc=10
#use delay (clock=4000000)
#use I2C (MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW)
#fuses XT,NOWDT,NOPROTECT,NOLVP,BROWNOUT,NOLVP,NOCPD,NOWRT
#use fast_io(all)


//////////////////////////////////////
//////  DEFINICION DE PUERTOS  ///////
//////          Y PATAS         //////
//////////////////////////////////////
#byte PORTA=0x05 #byte PORTB=0x06
#byte TRISA=0x85 #byte TRISB=0x86

#bit RA0=PORTA.0 #bit RB0=PORTB.0
#bit RB1=PORTB.1
#bit RB2=PORTB.2
#bit RB3=PORTB.3
#bit RB4=PORTB.4
#bit RB5=PORTB.5
#bit RB6=PORTB.6
#bit RB7=PORTB.7


//////////////////////////////////////
////////  VARIABLES GLOBALES  ////////
//////////////////////////////////////

/* CONFIGURACION */
int1 config_t=0; // Variables para poder llamar a la funcion cuando
int1 config_v=0; // indico que quiero cambiar Vout o Tmáx


int cont_dt=0; // Contadores, para la configuracion del de los distintos
int cont_dv=0; // parametros, que nos permitira saber cuando se termino
// de modificar las decenas y  pasar a
// las unidades



/* TECLADO */
int fil,col; // Determinan la posición en el teclado
int paso; // Almacena el valor de PORTB
char tecla; // Guarda el valor de la tecla pulsada en el teclado
int pulsada; // Indica si se ha pulsado alguna tecla
char teclado[4][4]={{'T','V','N','E'}, // Asigno los valores y funciones de cada
    { 1,  2,  3, 'N'}, // fila y columna al teclado
{ 4,  5,  6, 'N'},
{ 7,  8,  9,  0}};


/* SENSOR */
int t_max=60; // Variable para indicar la Tmáx admitida.
int t_act; // Variable donde se guarda la temperatura actual.




/* PWM */
int1 iniciado=0; // Variable para esperar a que todos los valores sean estables
// antes de empezar a utilizar el PWM
int16 carga; // carga=(Fosc*d)/(Prescaler*Fpwm) Vout=Ve por defecto
float v_in; // Variable para indicar la Vin que tenemos
float v_out=20.0; // Variable para poner la Vout deseada
float g_v_out; // Guarda el valor de v_out por si se necesitase

int change_d=0; // Variable para indicar que queremos cambiar el duty
int actualizar_duty=1; // Variable para conseguir que el apagado del
// PWM sea progresivo si se supera la Tmáx




//////////////////////////////////////
/////////////  LIBRERIAS  ////////////
//////////////////////////////////////
#include "lcd.c"
#include "funciones.c"



//////////////////////////////////////
////////  CONFIGURACION PREVIA  //////
//////////////////////////////////////
void configuracion(){
   
   /* TEMPORIZADOR PARADA TIMER1 */
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // Reloj intero con preescaler 1
   set_timer1(15536);                  // Para contar 0.05 seg

   /* TECLADO */
   PORTB=0;                        // Define RB<7:4> como entradas y RB<3:0> como   
   set_tris_b(0b11110000);               // salidas
   delay_cycles(4);                  // Espera para estabilizar el valor de PORTB.
   port_b_pullups(TRUE);               // Habilita resistencias de pull-up.
   PORTB=PORTB;                     // Lee PORTB para preparar interrupciones.
   
   /* CONVERSOR AD */
   setup_adc_ports(AN0);               // Pone AN0 como entrada analogica   
   setup_adc(ADC_CLOCK_INTERNAL);         // Frecuencia de conversión interna   
   set_adc_channel(0);                  // Selecciona AN0<=>RA0

   /* PWM */
   g_v_out=v_out;
   carga=((v_out-(4.0/1023.0*read_adc()+8.0))/v_out)*200.0;   // Para saber la carga inicial
   setup_timer_2 (T2_DIV_BY_1,49.5,1);    // Señal PWM de 20kHz
   setup_ccp2(CCP_PWM);               // Genera PWM con el CCP2.   
   set_pwm2_duty(carga);               

   /* LCD */
   lcd_init();                        // Inicializar pantalla LCD
   
    /* I2C */
   output_float (PIN_C3);               // Dejamos flotantes los terminales
   output_float (PIN_C4);               // asociados a la comunicación I2C.

   /* GENERAL */
   enable_interrupts(INT_RB);            // Habilita interrupciones del PORTB
   enable_interrupts(GLOBAL);            // Habilita interrupciones

   
   /* CONFIGURACION DE VALORES */
   
   ponertmax();
   delay_ms(200);
   ponervoltaje();
   delay_ms(200);

   enable_interrupts(int_timer1);      // Habilita la interrupcion del T1
   set_tris_c(0b11111011);             // Asegura que RC3 es salida

}



/////////////////////////////////////////////////////////////////////////////////////////////////
//                                     PROGRAMA PRINCIPAL                                      //
/////////////////////////////////////////////////////////////////////////////////////////////////
void main(){
configuracion();

while(TRUE){
v_in=4.0/1023.0*read_adc()+8;

// Llamo a las funciones desde el programa principal para evitar llenar la memoria poniéndolas
// en las interrupciones o dentro de otras funciones. Como el tiempo de ejecución no necesito
// que sea instantaneo no importa que este chequeando continuamente si se tiene que ejecutar la
// funcion que corresponda.


/* MUESTRA LA TEMP ACTUAL Y LA TENSION DE SALIDA ESCOGIDA */
lcd_gotoxy(1,1);
printf(lcd_putc,"Tact=%d%cC       ",t_act,0xDF);
lcd_gotoxy(1,2);
printf(lcd_putc,"Vsal=%1.1fV      ",v_out);

/*COMPRUEBA SI EL USUARIO HA DECIDIDO CAMBIAR ALGUNA VARIABLE*/

if(config_t==1)
ponertmax();

if(config_v==1)
ponervoltaje();



/* CHEQUEA SI HA DE APAGARSE EL CONVERTIDOR O HAY QUE CAMBIAR EL DUTY */

if((change_d==1||(t_act>=t_max))&&iniciado){
// Si estoy en el primer caso quiere decir que la temperatura actual ha superado
// a la temperatura máxima permitida, tendrá que apagarse el convertidor y por 
// lo tanto la tensión de salida y la de entrada tendrán que ser iguales,
// lo que hace que el valor del duty sea 0% y entonces su carga tambien lo sea.
// Los cambios de la tension de salida solo seran progresivos en caso del apagado
// del convertidor. Para cambios de una tension de salida a otra posteriormente
// definida (else) el cambio será brusco. Esto es debido a
// la dificultad de hacer el cambio progresivo usando el timer en vez de delays
// para poder usar otras funciones en tiempo real.

if(t_act>=t_max){

carga=((v_out-(4.0/1023.0*read_adc()+8.0))/v_out)*200.0;
change_duty(carga,0); // Desde hasta
}

else{
change_d=0;
carga=((v_out-(4.0/1023.0*read_adc()+8.0))/v_out)*200.0;

}
}
}



}


El código de las funciones :

Código: [Seleccionar]
/////////////////////////////////////////////////////////////////////////////////////////////////
//                              FUNCION PARA LEER LA TEMPERATURA                               //
/////////////////////////////////////////////////////////////////////////////////////////////////
void lee_t_act(){
i2c_start();            // Genera secuencia de START.     
i2c_write(0b10011010); // Envía byte de control para escribir.
  i2c_write(0x00); // Envía la dirección del sensor;
i2c_start();                // Genera otra secuencia de STAR
i2c_write(0b10011011); // Envía byte de control para leer.
t_act=i2c_read(0);  // Lee el dato.
i2c_stop();                 // Genera una secuencia de STOP.                         
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                     FUNCION PARA INDICAR LA TEMPERATURA MAXIMA ADMITIDA                     //
/////////////////////////////////////////////////////////////////////////////////////////////////
void ponertmax(){
pulsada=0;
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("Introduce Tmax");

do{
if(pulsada==1&&cont_dt==0&&tecla>=0&&tecla<=9){
pulsada=0;
cont_dt++;
t_max=tecla*10;
delay_ms(200);
}
if(pulsada==1&&cont_dt==1&&tecla>=0&&tecla<=9){
pulsada=0;
cont_dt++;
t_max=t_max+tecla;
delay_ms(200);
}
lcd_gotoxy(1,2);
printf(lcd_putc,"[%u]%cC",t_max,0xDF);
}while(cont_dt<=2&&tecla!='E');
delay_ms(300);
cont_dt=0;
lcd_putc('\f');
config_t=0;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                          FUNCION PARA INDICAR EL VOLTAJE DESEADO                            //
/////////////////////////////////////////////////////////////////////////////////////////////////
void ponervoltaje(){
change_d=0;
pulsada=0;
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("Introduce Vout");

do{
if(pulsada==1&&cont_dv==0&&tecla>=1&&tecla<=9){
pulsada=0;
cont_dv++;
v_out=tecla*10;
delay_ms(200);
}
if(pulsada==1&&cont_dv==1&&tecla>=0&&tecla<=9){
pulsada=0;
cont_dv++;
v_out=v_out+tecla;
delay_ms(200);
}
if(pulsada==1&&cont_dv==2&&tecla>=0&&tecla<=9){
pulsada=0;
cont_dv++;
v_out=v_out+tecla/10.0;
delay_ms(200);
}
lcd_gotoxy(1,2);
printf(lcd_putc,"[%1.1f]V",v_out);
}while(cont_dv<=2&&tecla!='E');
delay_ms(300);
cont_dv=0;
change_d=1; // Al cambiar el voltaje deseado indica que tengo que cambiar el duty
g_v_out=v_out;
lcd_putc('\f');
config_v=0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//                      FUNCION PARA INDICAR LAS FUNCIONES DEL TECLADO                    //
/////////////////////////////////////////////////////////////////////////////////////////////////
void tecladofunc(){

switch(tecla){

case 'T':
config_t=1; // Indico que quiero configurar la Tmax
break;

case 'V':
config_v=1; // Indico que quiero configurar la V_out
break;

case 'N':              // Tecla sin función.

break;


}
pulsada=0; // Recupera el marcador de “tecla no pulsada”.
}

/////////////////////////////////////////////////////////////////////////////////////////////////
//                                 INTERRUPCION PARA PARADA (SUPERADA TMAX)                                //
/////////////////////////////////////////////////////////////////////////////////////////////////
#INT_TIMER1
void parada(){

iniciado=1; //Variable para indicar que está inicidado.
actualizar_duty=1;

}

/////////////////////////////////////////////////////////////////////////////////////////////////
//                         INTERRUPCION PARA LAS FUNCIONES DEL TECLADO                         //
///////////////////////////////////////////////////////////////////////////////////////////////// +
#INT_RB
void pulsado(){
/* Se identifica la columna en que está la tecla pulsada determinando cuál
   de los cuatro bits más altos de PORTB está a 0. Si no hay ninguno, es que
   se ha entrado en la interrupción al soltar la tecla, por lo que se sale
   inmediatamente */
if(!RB4)
col=0;
else
if(!RB5)
col=1;
else
if(!RB6)
col=2;
else
if(!RB7)
col=3;
else return;

pulsada=1; // Indica que se ha pulsado una tecla.
paso=PORTB; // Guarda el valor de PORTB.
set_tris_b(0b00001111); // Cambia entradas por salidas.
PORTB=paso; // Saca el valor almacenado a PORTB.
delay_cycles(4); // Espera para estabilizar señal.

/* Se identifica la fila en que está la tecla pulsada determinando cuál de
   los cuatro bits más bajos de PORTB está a 0. Si no hay ninguno,es que se
   ha producido algún error y se indica que no hay ninguna tecla pulsada */

if(!RB0)
fil=0;
else
if(!RB1)
fil=1;
else
if(!RB2)
fil=2;
else
if(!RB3)
fil=3;
else
pulsada=0;



tecla=teclado[fil][col]; // Se guarda el valor de la tecla pulsada.

set_tris_b(0b11110000); // Se deja todo como estaba recuperando la
PORTB=0; // definición inicial de E/S en PORTB y
delay_cycles(4); // poniendo todas las salidas a 0 y leyendo
PORTB=PORTB; // PORTB para preparar las interrupciones.
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                            FUNCION PARA CAMBIAR LA CARGA DEL PWM                            //
/////////////////////////////////////////////////////////////////////////////////////////////////
void change_duty(int16 desde,int16 hasta){
// Si la resta es positiva quiere decir que estoy apagando el PWM y por lo tanto
// debo decrementar la cargahasta llegar a 0 (lo hago en decrementos de 2 para
// sea algo mas rapido). Estos decrementos se haran cada vez que pasen 50ms
    // (en la practica tarda algo mas ya que antes de detectar como esta la variable
// actualizar_duty tiene que pasar por otras instrucciones). Cuando la carga sea
// negativa o 0 querra decir que ya se ha terminado de apagar el PWM y tendremos
// que resetear la variable change_d. Carga es una variable sin signo por lo
// tanto no podra tomar valores negativos y al restarle un valor en el momento
// que valga 0 pasara a valer 65536. Por esta razon asumo que cuando carga
// tenga un alor muy alto en realidad su valor real deberia de ser 0
if((desde-hasta)>=0&&actualizar_duty==1){
carga=carga-2;
if(carga>65000){
carga=0;
change_d=0;

}
set_pwm2_duty(carga);
actualizar_duty=0;
}

}

y por último el código del lcd:

Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////
////                            LCD_ATE4A.C                            ////
////                            (versión 01)                           ////
////                Driver para LCDs basados en HD44780                ////
////                                                                   ////
////   Basado en el driver 'LCD.C' incluido con el compilador C de CCS ////
////  versión 3.234.                                                   ////
////                                                                   ////
////   Válido para ser utilizado con la nueva versión de las tarjetas  ////
//// PICDEM2 PLUS de Microchip (las verdes).                           ////
////                                                                   ////
////   Modificaciones efectuadas por Miguel Ángel José Prieto          ////
////                                                                   ////
//// ----------------------------------------------------------------- ////
////                                                                   ////
////  FUNCIONES DEFINIDAS                                              ////
////  ===================                                              ////
////                                                                   ////
////  lcd_init()      Debe llamarse antes que cualquier otra función   ////
////                                                                   ////
////  lcd_putc(c)     Muestra 'c' en la siguiente posición del LCD     ////
////                        Caracteres con significado especial        ////
////                         \f  Borra display                         ////
////                         \n  Va al inicio de la segunda línea      ////
////                         \b  Retrocede una posición                ////
////                                                                   ////
////  lcd_gotoxy(x,y) Fija la posición del LCD donde escribir          ////
////                                                                   ////
////  lcd_getc(x,y)   Devuelve el carácter en la posición x,y del LCD  ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// v. 01  * Se pasan las líneas de datos del LCD a los cuatro bits   ////
////        más bajos del puerto.                                      ////
////        * Se traducen los comentarios al español.                  ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////

// Los pines a conectar se definen en una estructura como sigue:
//     X0  D4
//     X1  D5
//     X2  D6
//     X3  D7
//     X4  rs
//     X5  rw
//     X6  enable
//     X7  Control de la alimentación del LCD
//
// X puede ser el puerto D o el puerto B en este fichero.
// No se usan los pines D0-D3 del LCD (4 líneas de datos).
 

// Quitar el siguiente comentario para usar PORTB en vez de PORTD.
// #define use_portb_lcd TRUE


struct lcd_pin_map
       {                           // Esta estructura se mapea
           int data : 4;      // en un puerto de E/S para
           BOOLEAN rs;            // acceder a los pines del LCD.
           BOOLEAN rw;            // Los bits se definen empezando
           BOOLEAN enable;        // por el más bajo.  ENABLE es
           BOOLEAN Vcc;           // el bit X6 del PIC.
        } lcd;


#if defined(__PCH__)               // Aquí se mapea la estructura
#if defined use_portb_lcd
   #byte lcd = 0xF81               // en el puerto B (dirección F81h)
#else
   #byte lcd = 0xF83               // o en el D (dirección F83h)
#endif
#else
#if defined use_portb_lcd
   #byte lcd = 6                   // en el puerto B (dirección 6)
#else
   #byte lcd = 8                   // o en el D (dirección 8)
#endif
#endif


#if defined use_portb_lcd
   #define set_tris_lcd(x) set_tris_b(x)
#else
   #define set_tris_lcd(x) set_tris_d(x)
#endif


#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 líneas
#define lcd_line_two 0x40    // Dirección RAM del LCD para la segunda línea


// Estos bytes se mandan al LCD para inicializarlo.
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};


// Estas constantes se usan para configurar los puertos de E/S.
// En modo escritura, todos los pines son salidas.
// En modo lectura, los pines de datos son entradas.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0};
struct lcd_pin_map const LCD_READ = {15,0,0,0,0};



 
///////////////////////////////////////////////////////////////////////////
BYTE lcd_read_byte()
{
      BYTE low,high;

      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(2);
      lcd.enable = 1;
      delay_cycles(4);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(8);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}




///////////////////////////////////////////////////////////////////////////
void lcd_send_nibble(BYTE n)
{
      lcd.data = n;
      delay_cycles(3);
      lcd.enable = 1;
      delay_us(4);
      lcd.enable = 0;
}




///////////////////////////////////////////////////////////////////////////
void lcd_send_byte(BYTE address,BYTE n)
{
      lcd.rs = 0;
      delay_ms(3);                 // Espera por LCD desocupado.
      lcd.rs = address;
      delay_cycles(3);
      lcd.rw = 0;
      delay_cycles(3);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}




///////////////////////////////////////////////////////////////////////////
void lcd_init()
{
      BYTE i;

      set_tris_lcd(LCD_WRITE);
      lcd.Vcc = 1;                 // Asegura que el LCD esté alimentado.
      lcd.rs = 0;
      lcd.rw = 0;
      lcd.enable = 0;
      delay_ms(15);
      for(i=1;i<=3;++i)
      {
         lcd_send_nibble(3);
         delay_ms(5);
      }
      lcd_send_nibble(2);
      for(i=0;i<=3;++i)
         lcd_send_byte(0,LCD_INIT_STRING[i]);
}




///////////////////////////////////////////////////////////////////////////
void lcd_gotoxy(BYTE x,BYTE y)
{
      BYTE address;

      if(y!=1)
        address=lcd_line_two;
      else
        address=0;
      address+=x-1;
      lcd_send_byte(0,0x80|address);
}




///////////////////////////////////////////////////////////////////////////
void lcd_putc(char c)
{
      switch (c)
      {
        case '\f':  lcd_send_byte(0,1);
                    delay_ms(5);
                    break;

        case '\n':  lcd_gotoxy(1,2);
                    break;

        case '\b':  lcd_send_byte(0,0x10);
                    break;

        default  :  lcd_send_byte(1,c);
                    break;
      }
}




///////////////////////////////////////////////////////////////////////////
char lcd_getc(BYTE x, BYTE y)
{
      char value;
      lcd_gotoxy(x,y);
      delay_ms(3);                 // Espera por LCD desocupado.
      lcd.rs=1;
      value = lcd_read_byte();
      lcd.rs=0;
      return(value);
}

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA CON PIC16F877A Y PROTEUS
« Respuesta #1 en: 26 de Junio de 2012, 07:28:55 »
No me deja subir el archivo de conexiones Proteus, me dice que no acepta el formato. ¿Cómo lo podría mostrar para que me ayuden?

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: AYUDA CON PIC16F877A Y PROTEUS
« Respuesta #2 en: 26 de Junio de 2012, 10:39:40 »
  Podés exportar el circuito a gráfico y luego subir el gráfico.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado marqueses

  • PIC12
  • **
  • Mensajes: 80
    • Alberto Marqueses Blog
Re: AYUDA CON PIC16F877A Y PROTEUS
« Respuesta #3 en: 26 de Junio de 2012, 13:08:48 »
Parece ser que tu problema que no tienes la licencia (Costumer Key).  :P
Alberto Aragón Marqueses
albertomarqueses.wordpress.com