# 16F876A PIC C Compiler y Proteus



## Ricardo.Ojeda (Ago 31, 2009)

Hola, buenas a todo el mundo. 

Estoy realizando un proyecto en el que ya pregunté algunas dudas iniciales (https://www.forosdeelectronica.com/f24/entrenamiento-esgrima-pic-16f876a-22720/#post187787) y después de resolverlas, como no, siguen saliendo algunas cosas más, aunque ahora de diferente tipo. 

Al grano. 

El caso es que utilizo el PIC C Compiler para programar en C y simulo con el Proteus para el PIC 16F876A. Entonces, he simulado varios ejemplos y no me acaban de salir bien al 100%. Entonces, lo que haré, es poneros los ejemplos y a ver si me podéis ayudar en saber donde puedo tener el fallo, ya que tampoco sé si viene del programa en C, o fallo con el Proteus (además, es la primera vez que utilizo ambos programas). No vaya a ser que me falta por configurar algún dato o algo. 

Decir que, en el PIC C Compiler, al iniciar un nuevo proyecto, hago los siguientes pasos: 
- General: 
Device PIC16F876A 
Oscilator frequency: 4.000.000 Hz 
Marco casillas: "Use 16 bit pointers for FULL RAM use" y "One fuse per line with comments". 
Fuses Crystal osc <= 4 mhz 
Marco casillas: "Reset when bronout detected" y "Low Voltage Programing on B3 or B5". 

- Communication: 
Baud 9600 
Bits 8 

- Options: 
CCPX -> CCP1 

- I/O Pins: 
Los A y C en Input y los B en Output. 

- Lo demás todo por defecto. 


Esquema en Proteus: 
(Decir que los Switch ya están modificados por pulsadores normales y corrientes y que haciendo doble clic en el PIC, lo pongo a 4 MHz). 

Programa 1: 
(Decir que aquí lo que me hace es que si no presiono ningún botón, los leds se me encienden y apagan a gran velocidad sin parar y cuando pulso, el led correspondiente se queda apagado y los otros siguen como una “discoteca”) 

Programa 2: 
(Me hace el contrario de lo que debería hacer, donde tiene que estar encendido, está apagado y viceversa). 

En este punto, probando también otros programas, deduzco que a la salida, me sale lo contrario que quiero y no se si debo modificar o configurar algo del PIC o del Proteus. 

Y finalmente Programa 3: 
Decir que, aquí en cambio, la salida no me sale al revés de la que quiero, pero que por ejemplo, del paso 2 al 3, PIN_B1 lo ha de mantener encendido, y no lo hace. Y me pasa lo mismo con otro del mismo estilo. Es decir, como si no pudiera tener 2 LEDs encendidos a la vez). 

Por cierto, lo programas en C están sacados de Internet, pero ahora mismo no recuerdo las fuentes de donde las saqué, ya que los archivos los tengo en TXT. Así que si el creador los ve, que me perdone por no citarlo, pero es que aquí en el trabajo no puedo mirarlo. Gracias. 

En fin, estas son mis dudas de ahora. A ver si me podéis hechar una mano. Gracias a todos y saludos!


----------



## asuryan87 (Ago 31, 2009)

Aqui tienes ayuda para tu primer programa

Yo no uso el PICC de CCS pero si que tienes algunos fallos ajenos al compilador.

Con tus "if" preguntas si el pin correspondiente del PORTA es 1  pero no te has dado cuenta de que ese es el estado normal que tienen y generan un 0 cuando los pulsas por lo que debes es usar el if para saber si es 0 y no si es 1.

Ademas has configurado mal el TRISA.

Prueba con estas modificaciones, como he dicho antes yo no uso ccs para programar en C asi que no se si lo he aplicado de forma correcta para que lo comprenda el compilador


```
void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   // TODO: USER CODE!!

set_tris_a(0x0F);  // Port A como entrada
set_tris_b(0x00);    

   while(true){
   output_b(0x00);   // Ponemos a 0 Port B
   if(input(pin_a0))
   {
      output_high(pin_b0);
   }
   if(input(!pin_a1)
   {
      output_high(pin_b1);
   }
   if(input(!pin_a2))
   {
      output_high(pin_b2);
   }
   if(input(!pin_a3))
   {
      output_high(pin_b7);
   }
   };
```


un saludo


----------



## Ricardo.Ojeda (Sep 1, 2009)

Gracias por responder.
Entiendo lo que quieres decir, esta tarde lo pruebo y comento el resultado.
Lo probare también en los otros dos programas.

Muchas gracias.
Saludos.


----------



## Ricardo.Ojeda (Sep 1, 2009)

Hola buenas.

Bueno, después de aplicar las cosas, paso a los resultados obtenidos.

En el programa 1:


```
void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   // TODO: USER CODE!!
   set_tris_a(0x0F);  // Port A como entrada
   set_tris_b(0x00);    
   while(true)
   {
      output_b(0x00);   // Ponemos a 0 Port B
      if(!input(pin_a0))
      {
         output_high(pin_b0);
         delay_ms(1000);
      }
      if(!input(pin_a1))
      {
         output_high(pin_b1);
         delay_ms(1000);
      }
      if(!input(pin_a2))
      {
         output_high(pin_b2);
         delay_ms(1000);
      }
      if(!input(pin_a3))
      {
         output_high(pin_b3);
         delay_ms(1000);
      }
   }
}
```
 
Tenías razón en que por defecto tiene un 1 como entrada, por la tanto, debo mirar cuando es diferente de 1. Ese código es el que me funciona. Después le añadí unos retardos para que se viera bien del todo.

Podemos pasar al Programa 2. Respecto a lo de 1 como entrada, modifico pues la máscara para poder ver las diferentes salidas.


```
// Programa combinacional. Según el estado de los interruptores RA0 y RA1, activar
// los leds RB0-RB7 conectados a la puerta B, conforme a la siguiente tabla de
// la verdad:
//
// RA1 RA0  RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
// --- ---  --- --- --- --- --- --- --- ---
//  0   0    1   0   1   0   1   0   1   0
//  0   1    0   1   0   1   0   1   0   1
//  1   0    0   0   0   0   1   1   1   1
//  1   1    1   1   1   1   0   0   0   0
#include "C:\Archivos de programa\PICC\main8.h"
 
void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   // TODO: USER CODE!!
   output_b(0x00);              //Borra las salidas
   set_tris_a(0x3F);            //Puerta A entrada
   set_tris_b(0x00);            //Puerta B salida
   while(1)
      switch(input_a() & 0b00000000) // Mascara para RA0 y RA1
      {
         case 0: output_b(0b10101010); break;
         case 1: output_b(0b01010101); break;
         case 2: output_b(0b00001111); break;
         case 3: output_b(0b11110000); break;
         default:;
         delay_ms(100);
      }
}
```
 
Aquí el problema es que se queda clavado en el case 0. Cuando pulso los demás botones, no hace nada más. En cambio, si la máscara es "switch(input_a() & 0b00000011)" si que me responde los diferentes casos, pero a la inversa, debido al 1 de la entrada.

Y del programa 3, se me mantiene el mismo error de que no me mantiene dos LEDs encendidos a la vez, pero curiosamente, aquí no tengo que poner que me detecte cuando es diferente 1, me sigue los pasos correctamente.

Bueno, estas son mis nuevas dudas.

Saludos y muchas gracias!


----------



## Ricardo.Ojeda (Sep 7, 2009)

Buenas, a ver si me podéis hechar una mano.
Una vez resuelva estas dudas, pasaré al Visual Basic.
¿Puedo hacer la interface de Visual Basic y usarla para poder simular con Proteus?
Gracias y saludos!


----------



## Ricardo.Ojeda (Sep 9, 2009)

Hola buenas.

Bueno, me autorespondo con la corrección del programa 2 hecha:


```
// Programa combinacional. Según el estado de los interruptores RA0 y RA1, activar
// los leds RB0-RB7 conectados a la puerta B, conforme a la siguiente tabla de
// la verdad:
//
// RA1 RA0  RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
// --- ---  --- --- --- --- --- --- --- ---
//  0   0    1   0   1   0   1   0   1   0
//  0   1    0   1   0   1   0   1   0   1
//  1   0    0   0   0   0   1   1   1   1
//  1   1    1   1   1   1   0   0   0   0

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   // TODO: USER CODE!!
   output_b(0x00);              //Borra las salidas
   set_tris_a(0x3F);            //Puerta A entrada
   set_tris_b(0x00);            //Puerta B salida
   while(1)
   {
      switch(input_a() & 0b00001111) // Mascara para RA0 y RA1
      {
         case 15: output_b(0b10101010); break;
         case 14: output_b(0b01010101); break;
         case 13: output_b(0b00001111); break;
         case 12: output_b(0b11110000); break;
         default:;
         delay_ms(100);
      }
   }
}
```
 
Finalmente la máscara la realizo con 00001111 y luego juego con los casos 15 (1111), 14 (1110), 13 (1101) y 12 (1100). De esta manera, el funcionamiento del programa es correcto.


Ahora vamos con el programa 3, a ver si alguien me puede hechar una mano.

Gracias y saludos!


----------



## asuryan87 (Sep 12, 2009)

Pues solo te queda ser redundante con RB1 y volverlo a poner en estado en cada "etapa" del taladrado.

P.D. aprovecho esta ocasión  para decir ,y que no se ofenda nadie, que CCS no es ni de lejos un compilador profesional y tiene graves fallos aunque haga relativamente facil la programacion.


----------



## Ricardo.Ojeda (Sep 14, 2009)

Buenos días.
Comentar que probando con los IF y con los WHILE, con y sin llaves, no he podido solucionarlo y que lo único que me funcionaba era usando la instrucción output_b(0b00010010). Pero bueno, es un mal menor que no me afectará en principio.

Referente a lo de CCS, es lo que me han recomendado para iniciarme y bueno, supongo que para lo que necesito hacer, no necesito algo muy profesional. El programa principal es sencillo y luego necesito interrupción para comunicarme con PC vía RS232.

Ahora pasamos a cosas más difíciles. Lo que quiero es que mediante una inturrupción por teclado vía RS232 me haga funcionar un programa.
El programa que he hecho funciona correctamente (no lo tengo aquí). Ahora lo que quiero es que, por ejemplo, pulsando cualquier tecla del teclado, me inicie el programa.

A ver si me podéis hechar una mano para empezar con esto de las inturrepciones, que me cuesta un poco más.

Gracias por la ayuda!
Saludos!


----------



## AIACOS (Oct 30, 2014)

Soy nuevo en pic c  compiler y es que quisiera saber porfavor si alguien me pudier explicar para que sirve  todos estos codigo y que es lo que hace cada uno??
void main() 
{
 setup_adc_ports(NO_ANALOGS); 
setup_adc(ADC_OFF); 
setup_spi(SPI_SS_DISABLED);
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
 setup_timer_1(T1_DISABLED); 
setup_timer_2(T2_DISABLED,0,1);
 setup_ccp1(CCP_OFF); 
setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);

Esa es mi duda de antemano muchas gracias..


----------



## D@rkbytes (Oct 30, 2014)

setup_adc_ports(NO_ANALOGS);  // Configura los puertos con ADC como digitales (I/O)
setup_adc(ADC_OFF);  // Desactiva el ADC
setup_spi(SPI_SS_DISABLED); // Desactiva el módulo SPI
 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // Configuración del Timer 0
 setup_timer_1(T1_DISABLED);  // Desactiva el Timer 1
setup_timer_2(T2_DISABLED,0,1); // Desactiva el Timer 2 (Usado conjuntamente con el módulo CCP 1/2)
 setup_ccp1(CCP_OFF);  // Desactiva el módulo CCP (Ligado a la generación PWM)
setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);  // Desactiva los comparadores análogos

Esta información y más, la puedes encontrar si miras la documentación y temas de ayuda de PICC Compiler.

Suerte.


----------

