Autor Tema: AYUDA PROYECTO PIC16F877A  (Leído 4980 veces)

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

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
AYUDA PROYECTO PIC16F877A
« en: 21 de Junio de 2012, 13:16:53 »
Buenas,

Soy un estudiante de electrónica, y como proyecto me han mandado escribir un programa en C, para programar el PIC16F877A que me haga lo siguiente:
Se desea implementar un control PWM en cadena abierta para un convertidor elevador CC/CC que
permita obtener una tensión constante de salida a partir de una tensión de entrada que puede oscilar
entre 8 y 12V. Además, el sistema incorporará un dispositivo encargado de llevar a cabo un apagado
suave del convertidor en caso de superar una temperatura máxima especificada por el usuario. Todo
este proceso será controlado por un microcontrolador PIC16F877A a 4MHz que implementará los
bloques funcionales que se describen a continuación.

1. Se dispondrá de un LCD que mostrará en todo momento el valor de la tensión de salida
(expresada en V y con un decimal) y la temperatura del equipo. Este LCD funcionará asociado a
un teclado mediante el cual se implementará un menú de opciones que permitirá al usuario
seleccionar la tensión de salida deseada o la temperatura máxima permitida.

2. La tensión de entrada del convertidor se recibirá por un terminal del microcontrolador, llevando
a cabo los tratamientos previos que se precisen.

3. El sistema generará la señal PWM necesaria para conseguir la tensión de salida especificada por
el usuario. La frecuencia de la misma debe dar lugar a una resolución adecuada.

4. Un sensor de temperatura se encargará de determinar si se ha superado la temperatura máxima
admisible, en cuyo caso procederá al apagado suave del convertidor mediante la extinción
progresiva de la señal PWM (con lo que se dará lugar a una situación en la que Vs=Ve).
« Última modificación: 25 de Junio de 2012, 10:06:05 por franciscoufa »

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA
« Respuesta #1 en: 21 de Junio de 2012, 13:17:49 »
Ya tengo el código más o menos, pero tengo una serie de dudas, ¿cómo podría subirlo sin que ocupe mucho?

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: AYUDA
« Respuesta #2 en: 21 de Junio de 2012, 15:55:43 »
Lee las reglas del foro, cambia el titulo del post por alguno que de idea de que es lo que se trata en el post para que sea mas facil ayudarte.
puedes pegar tu codigo usando el boton que dice " insertar codigo"
y se veria asi:

Código: [Seleccionar]
aca pegas el codigo que quieras
"Nada es imposible, no si puedes imaginarlo"

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #3 en: 25 de Junio de 2012, 10:09:02 »
Me da los siguientes errores a la hora de compilar :


Executing: "C:\Program Files\PICC\Ccsc.exe" "main.c" +FM +DF +LN +T -A +M +Z +Y=9 +EA
*** Error 51 "C:\Users\Pacote\Desktop\Nueva carpeta (2)\funciones.c" Line 126(0,1): A numeric expression must appear here
*** Error 117 "C:\Users\Pacote\Desktop\Nueva carpeta (2)\funciones.c" Line 194(1,2): Improper use of a function identifier
*** Error 117 "main.c" Line 92(1,2): Improper use of a function identifier
*** Error 12 "main.c" Line 192(12,13): Undefined identifier  -- change_duty
*** Error 79 "main.c" Line 214(0,1): Expect }
      5 Errors,  0 Warnings.

Aquí les dejo los códigos del main y funciones.

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 indicar que quiero ajustar alguno
int1 config_v=0; // correspondiente que me permite tal accion
// de los parametros y poder llamar a la funcion


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 automaticamente se pasara a
// las unidades del valor correspondiente en el que
// estemos




/* 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 la temperatura maxima 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 el voltaje de entrada
float v_out=20.0; // Variable para poner el voltaje de salida deseado
float g_v_out; // Guarda el valor de v_out por si se necesitase

int change_d=0; // Variable que indica con que opcion tendremos que cambiar
// el duty. La primera vez que se inicia el programa debera
// hacerse segun la opcion 3
int actualizar_duty=1; // Variable para conseguir que el apagado del
// PWM sea progresivo



//////////////////////////////////////
/////////////  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 por las que saca sendos 0s.
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 (@Fosc=4MHz)
setup_ccp2(CCP_PWM); // Genera PWM con el CCP2.
set_pwm2_duty(carga);

/* LCD */
lcd_init(); // Inicializar pantalla LCD

/* 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


}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                                     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 poniendolas
// en las interrupciones o dentro de otras funciones. Como el tiempo de ejecucion 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 POR ALGUN MOTIVO */
if((change_d==1||(t_act>=t_max))&&iniciado){
// Si estoy en la opcion 1 quiere decir que he pulsado el boton de parada, se ha
// superado la temperatuma maxima permitida o que se ha llegado a la hora temporizada
// y por lo tanto el la tension de salida y la de entrada tendrán que ser iguales,
// lo que hace que el valor del duty sea 0% y por lo tanto su carga tambien lo sera
// 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 (que podra ser mayor o menor) 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;

}
}
}




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; // Al cambiar el voltaje deseado indica que tengo que cambiar el duty
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;
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                                 //
/////////////////////////////////////////////////////////////////////////////////////////////////
#INT_TIMER1
void parada(){ // Reloj normal y corriente con formato 24H que solo se muestra

iniciado=1; // en la pantalla principal si no se esta ajustando ninguna
actualizar_duty=1; // variable



/////////////////////////////////////////////////////////////////////////////////////////////////
//                         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;
}

Desconectado marqueses

  • PIC12
  • **
  • Mensajes: 80
    • Alberto Marqueses Blog
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #4 en: 25 de Junio de 2012, 10:40:45 »
Hola francis,

tienes varios errores de sintaxis, busca a ver en las lineas que te dice el compilador si tienes olvidado algun ";" o algun "{".

Mirando el codigo asi a simple vista, sin saber que linea es cada una en el codigo, en la interrupcion de timer 1 no tienes cerrado la llave de la funcion ("}")

Revisa esos errores y comentas si te funciona.  ;-)
Alberto Aragón Marqueses
albertomarqueses.wordpress.com

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #5 en: 25 de Junio de 2012, 11:46:35 »
Muchas gracias marqueses, con ese error ya finiquité 3.
Ya sólo me quedan dos!

*** Error 117 "main.c" Line 92(1,2): Improper use of a function identifier
*** Error 12 "main.c" Line 146(14,15): Undefined identifier  -- configuracion
      2 Errors,  0 Warnings.

El primero me lo señala en la primera linea de configuración del timer:
Código: [Seleccionar]
//////////////////////////////////////
////////  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


El segundo me lo señala cuando llamo a la función configuracion:
Código: [Seleccionar]
/////////////////////////////////////////////////////////////////////////////////////////////////
//                                     PROGRAMA PRINCIPAL                                      //
/////////////////////////////////////////////////////////////////////////////////////////////////
void main(){
configuracion();

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #6 en: 25 de Junio de 2012, 12:37:33 »
  El primer error te dice que estás utilizando un identificador incorrecto para la función. Mientras que el segundo error te dice que no está definido el nombre "configuración", seguramente debido al primer error.

  Prueba utilizando otro nombre para la función.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #7 en: 25 de Junio de 2012, 12:51:06 »
 :5]Acabo de probar y nada.

También he añadido a la función configuración:
    /* I2C */
   output_float (PIN_C3);               // Dejamos flotantes los terminales
   output_float (PIN_C4);

para la comunicación con el sensor de temperatura.

Desconectado franciscoufa

  • PIC10
  • *
  • Mensajes: 19
Re: AYUDA PROYECTO PIC16F877A
« Respuesta #8 en: 25 de Junio de 2012, 18:34:10 »
Ya está solucionado, era una maldita llave!

En cuanto a los flotantes que escribí en mi anterior mensaje, son necesarios?