# Programas para Pic C Compiler (Tutorial)



## frivoldeux (Jul 3, 2009)

Muy buenas tengan todos ustedes lectores de Foros de electrónica, eh bajado mucha información de este lugar y eh aprendido mucho aquí, soy estudiante de ing. electromecánica y estoy en mi segunda especialidad de Automatización y acabo de llevar microcontroladores. Todo esto pues quisiera compartirlo con ustedes. Estaré publicando varios programas en Pic C por su simplicidad, también programo en Assembler y empiezo con matlab para hacer controles sofisticados para misiles y posicionamiento de cosas muy complejas a las cuales no me meteré (porque todavía no soy un erudito en esos temas)

Bueno el día de hoy empezare con programas sencillos como prender y apagar un led por un pin del microcontrolador seré muy especifico en los comentarios y estaré trabajando con el pic 18f452 i/p , claro a lo largo del tuto sabras que en pic C y sabiendo leer los datasheets (hojas de datos) cualquier pic lo hacen jalar. OJO, me perdonaran que ponga los programas ya hechos, ya que esto es antietico porque ustedes deben de pensar para hacer las cosas, pero espero que aquí se comparta mucho conocimiento y verlo en aplicaciones reales.

Bueno sin mas por el momento empecemos: (mucho ojo con los comentarios porque ocupan muchas lineas en algunos casos para la explicación).

*1.- *//Programa para prender y apagar un led sin timer.


```
#include <18F452.h>                                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que        dependera la configuracion de los puertos y de los bytes

#fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..

#use delay(clock=20000000)                       //Cristal de 20 Mhz leer datasheet para conexión de capacitores se puede usar diferentes cristales ver datasheet una vez mas

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) //declaro esta libreria ya que usaremos mas adelante la comunicacion serial del pic, la explico de una vez, el pin Rc6 (patita 25 del pic) sera la de transmision y la Rc7 de recepcion (patita 26) estas van conectadas a un max 232 que aqui en el foro encontraran su conexión, a una velocidad de 9600 baudios esto se vera mas adelante para la configuracion de la PC y del monitor que viene incluido en el programa (Pic C compiler PCHW) para ver lo que transmitimos y recibimos, les pasare un bootloader para estar programando directamente del PC sin necesidad de programar con tarjetas (esto lo explico mas adelante)

#build (reset=0x200)       //Como usaremos un programa interno para programar jeje tenemos que mover el reset las 
#build (interrupt=0X208) //interrupciones y el home, porque el bootloader ocupa sus lugares establecidos y estas tres lineas
#ORG 0X0000, 0X01FF     //son para eso, para cambiar de banco al y que no se nos pierda el pic al funcionar.


void BOOTLOADER() {      //Esta subrrutina es solo para evitar el programa del bootloader cada vez que programemos 
      #ASM                            
         NOP 
      #ENDASM
}

#byte PORTA= 0XF80   //Aqui nombramos loa puertos en mi caso yo les puse PORTA PORTB etc, pero ustes les pueden 
#byte PORTB= 0XF81   //poner el nombre que quieran las direcciones de cada micro vienen el datasheet
#byte PORTC= 0XF82   // por eso muy importante leerlo para que no vallan a usar estas para todo pic que se les ocurra
#byte PORTD= 0XF83  //hay que leer antes de hacer.
#byte PORTE= 0XF84

void main(){                //En esta parte sera la declaracion de variables configuracion de puertos y configuracionde mas cosas como timers, ADC, pwm, entre otras cosas.

set_tris_B(0xff);          /*Configuracion de puertos , a mi me gusta mucho hacerlo de forma hexadecimal pero para los que no saben explicare como se sacan los valores, ya que tambien se puede poner en binario. 
Los puertos son de 8 patitas (1 byte u ocho bits) y se dividen en nibles (alto y bajo) para sacar la conversion hexadecimal yo lo hago de la siguiente manera (ya despues lo haran mentalmente):

Nible alto        Nible bajo (pensando para puerto A)
A7 A6 A5 A4    A3 A2 A1 A0    (es como se acomodan los puertos en los nibles)
 8   4   2   1      8   4   2   1     (estos son los valores decimales para los bits)
 0   0   0   0      0   0   0   0     (este sera el valor binario para los bits "0" significa output "1" sera input)
         0                     0                  (el valor hexadecimal para este sera 0x00)
 8   4   2   1      8   4   2   1     (Ahora por el puerto A yo quiero que A0, A1, A5 y A7 sean entradas y los demas salidas)
 1   0   1   0      0   0   1   1     (el codigo binario seria 0b1010011)
         A                     3            (Como sabemos en hexadecimal A=10 si sumamos 8+2=10 para la conversion de decimal a Hexadecimal tenemos A en el nible alto y 3 para el nible bajo 1+2=3, para eso sirven el 8 4 2 1) espero sea claro porque es muy tedioso explicar esto. */
set_tris_D(0x00);     //Todos  D como salida
set_tris_C(0x80);     //Pin C7 como entrada y todos los demas como salida por la transmision serial

while(1){                 //Aqui empezamos el programa While(True) es lo mismo para que simpre se cicle el programa

output_high(pin_D0);  //Aqui lo que decimos es que nos mande a 1 o prenda el pin D0 en el cual esta conectado el led con su respectiva resistencia de 330 ohms
delay_ms(100);           //Con una duracion de encendido de 100 milisegundos (ms) para nano micro segundos sera (us)
output_low(pin_D0);   //Ahora lo apagamos mandandolo a 0
delay_ms(100);           //Con una duracion en bajo de 100 ms tambien.

}    
}//Cerramos todos los corchetes que hallamos abierto
```
De cualquier manera el PCHW nos indicara que errores halla en caso de que los halla pero tomen en cuanta que corrige errores de sintaxis no de lógica, por otro lado verán lo fácil que son los programas ya que también hay que administrar la programación para no cargar innecesariamente el pic, recordemos que por cada instrucción ocupa un ciclo de reloj y por cada salto ocupa el doble, así que hay que hacer lo mas reducidos nuestros programas, ya verán...

En este tutorial iré poniendo cada vez mas complejos (que la verdad son muy sencillos) los programas las conexiones y la imaginación dependerá de ustedes, por ejemplo para este caso se puede conectar un relevador o transistor para accionar alga durante unos segundos y después apagarlo o depende de la imaginación de cada quien, esto se vera también después para controlar servomotores, es exactamente lo mismo para generar frecuencias de trabajo y posicionar nuestro servomotor.

Para los próximos programas ya no daré tanta explicación solo esta vez para entender lo que estamos usando, ya cuando salgan cosas nuevas la explicare en su momento.

*2.-* Ahora pongo el programa mas fácil que lo que hace es que si presiono un boton prende un led, lo suelto se apaga. super fácil pero funcional.


```
#include<18f452.h>
#fuses hs,nowdt, noprotect,no lvp
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
#build(reset=0x200)
#build(interrupt=0x208)
#org 0x0000,0x01ff


void bootloader()
{
#asm
nop
#endasm
}


#byte portA=0xF80
#byte portB=0xF81
#byte portC=0xF82
#byte portD=0xF83
#byte portE=0xF84     //Hasta aqui lo de siempre


void main()
{
set_tris_B(0xFF);
set_tris_D(0x00);
set_tris_C(0x80);

portD=0;
portB=1;

while(1)
{
portD=portB; /*Si presiono un boton en el puerto D; recuerden que los botones van con una resistencia pull-up o  pull-down depende del valor que quieran asegurar (1 o 0 sea el caso), me madara el valor al puerto B prendiendo el led que este ahi, ojo si pongo el boton en D0 el led tendra que ir en B0 */
}
}
```
Esto es para todo el puerto pero se puede hacer mas fácil solo por bits con la función if:


```
While(True)
{
  if (input(pin_D0)
     output_high(b0);
  else
     output_low(b0);
}
```
Depende de su uso.

*3.- *El siguiente programa es para hacer corrimientos  en los puertos, yo los uso mucho para controlar motores a pasos, este programa va a controlar el nible bajo el alto es lo mismo.
      Me voy a evitar todo lo anterior ya saben que es lo que va.


```
void main()
{

   int m1=16;           /*Declaramos variable tipo entero (int) recuerden que solo llega hasta 255 porque es un pic de 8 bits y la igualamos a 16*/

   set_tris_D(0x00);  //Configuracion de puertos 

   PortD=0;               //Limpiamos el pueto para que no halla basura

   while(1)
   {

      PortD=m1;        /*El puerto D es = a 16 o sea que estan todos los led apagados en 15 todos estarian prendidos la explicacion es precido a la de la configuracion de los puertos*/
      delay_ms (500);     //REtardo de medio segundo entre led y led
      m1=m1>>1 | m1 <<3;   /*Logica del programa esto >> significa que corra hacia la derecha y << hacia la izquierda lo que le digo yo es que recorra 1 y que el sume tres pa el otro lado: con manzanas:

0 0 0 0  0 0 0 0 (asi empiezo) int =16 me dice que le ponga 1 y que le quite 3 recordemos que son corrimientos
1 0 0 0  0 0 0 0 (le puse hacia la derecha)
1 0 0 0  1 0 0 0 (ahora mas 3 hacia la izq) se pone ahi el 1 porque recuerden que estamos en 16 no en 15. y volvera a hacer lo mismo*/


      m1=m1 & 0x0F;   /*Todo el nible bajo lo multiplico por 1 1 1 1 para que me gurde el dato para el siguiente, si no les convece hagan las operaciones y veran que si da.*/
   } //Cerramos todo
```
Con este programita se puede hacer girar un motor a pasos conectado al puerto D con sus respectivos transistores yo uso los TIP 125 por aguantar mucha corriente, son tipo darlington y estan protegidos internamente. recuerden que es el nible bajo D0, D1, D2, D3. estos van a las bases de los transistores. WUA eso no lo tengo que explicar.

Experimenten con este programa y pueden controlar 2 motores a pasos simultáneamente cambien la dirección de >> o << para que cambie el giro y si quieren visualizar los dos nibles cambien esto m1=m1 & 0x0F;  por esto m1=m1 & 0xFF; y analicenlo para que vean porque. También si cambian esto m1=m1>>1 | m1 <<3; por valores en ves de 3 por 5 o 7 verán lo que hace. Espero que les sirva.

Para los próximos programas veremos como contar el numero de veces que prende y apaga los led en los corrimientos esto para hacer que los motores a pasos lleguen hasta cierto punto y se paren. quiere decir que si le pongo 50, solo va a hacer 50 pasos el motor. Esto para la próxima. (y tendrán que ver la resolución de sus motores (Usamos motores Unipolares)

O si  dejo el programa bootloader para que lo carguen en su pic (este solo funciona para el 18f452, después publico el que esta en assembler para que modifiquen el bootloader y lo usen para cualquier pic de la serie 18F, sorry no tengo para otros, pero si buscan en la red encontraran para varios pics, incluso en el PCHW, en uno de los ejemplos viene uno, no lo eh calado pero chance y funcione, Chequenlo) yo lo mando en hexadecimal para que lo carguen de volada.


----------



## frivoldeux (Jul 3, 2009)

Aqui el archivo hexadecimal Bootloader para el pic y para asi programar por el puerto serial sin complicaciones. a por cierto se tienen que descar el programa para cargar el pic se llama Colt pic bootlader. Se lo descargan de esta pagina http://mdubuc.freeshell.org/Colt/


```
:08000800FFD082BEF4D0040019
:0600100082AEFED71200D3
:08001800FFD0A66AA968AA68DE
:10002000A680A84A05D0A84CEBD0066E310ECD6E46
:10003000949C900EAB6E260EAC6EAB98030ED56EF4
:10004000D76AD66AD8D8D58ED6D8D59ED6CF03F063
:10005000D7320332D8A0030603C0AFFFAB88AE503F
:10006000AE50B6D80F0AE9E100EE08F0006A016A66
:10007000AFD80F0AF6E00450040A0AE00450050A5B
:1000800001E1A6D804500026EE6E014ED6D7F0D777
:100090000052D3E1CD900A50F66EA96E0B50F76E68
:1000A000AA6E0CC0F8FF00EE0DF00950016ED8B436
:1000B000FF0008500808C1E3FA6AFB6A0844F92601
:1000C00008D01ED025D034D03ED048D019D052D040
:1000D000FF00EE50AF02F446F446FC0EF416F34671
:1000E000F346030EF314F424A86E040EA66E78D81B
:1000F000A6B2FED70C0E0A6E000E0B6E040E45D093
:100100000900F5CFEEFF012EFBD70950050F3DD0BA
:10011000F80EF616080EEECFF5FF0D00E82EFBD711
:100120000A00840EA66E5CD80900012EF1D72CD0EF
:10013000940EA66E55D8400EF626E86AF722F822ED
:10014000012EF6D721D0A66AA680A8CFEEFFA94A35
:10015000AA2A012EF8D70950050F17D0EECFA8FF15
:10016000040EA66E3DD8A6B2FED7A94AAA2A012E31
:10017000F5D70AD0C40EA66EEECFF5FF0C0030D82E
:100180000900012EF7D700D0010E016E0F0E1BD80B
:100190001AD8006A00EE08F0EE50002608D8012EAA
:1001A000FBD7006C005003D8040E0DD846D7056E5F
:1001B0000F0A06E00550040A03E00550050A02E1B3
:1001C000050E01D8055004009EA8FED7AD6E1200A2
:1001D0000400ABB2FF009EAAFED7AE50046E120020
:1001E0000400550EA76EAA0EA76EA682000012008C
:0A01F6009EA008D79E90062E05D7A4
:020000040030CA
:0E000000FFFAFCFEFFFFFBFFFFFFFFFFFFFF0D
:00000001FF
```

Ya saben copian y pegan y guardan como .HEX de todos modos ahi mando el archivo.


----------



## mecatrodatos (Jul 3, 2009)

Me parece bueno,  pero para hacerlo mas interesante postea los circuitos


----------



## frivoldeux (Jul 4, 2009)

Bueno aqui dejo por el momento la imagen de como va la conexion para la comunicacion serial con el max232.

Los pasos para programar por comunicacion serial son los siguientes:

1.-Programar pic18f452-I/P con Bootloader, con cargador normal (el que ustedes prefieran)
2.-Hacer las conexiónes necesarias para la comunicacion serial (imagen abajo) 
3.-Conectar cable a puerto Serial, y chekar que este habilitado el puerto o que no este ocupado en caso de que lo este, deshabilitarlo, reiniciar la maquina y habilitarlo nuevamente.
3.-Ya instalado el programa Colt Pic Bootloader dejarlo de la siguiente manera:

4.- Seleccionar archivo .hex que nos da una vez al compilar nuestro programa en Pic C en el PCHW y presionar el boton PROGRAM (F4).
5.-Presionar el reset del pic para que empiece a cargar el programa esto toma aproximadamente como 3 seg. varia depende del programa y la PC. (los leds del max232 parpadearan indicando que si esta programando bien)
6.-Verificar que todo funcione como lo pensamos y programamos 

No creo muy necesario el poner las imagenes de cada circuito, ya que ustedes seran los que decidan que hacer y como conectar dependiendo de su programacion los puertos y salidas y entradas, pero en caso de ser muy muy necesario lo hare, de hecho mas adelante pondre un programa que sera un contador de 0 a 99 con displays multiplexandolos y pondre su conexión como debe de ser. Y con esto ya estaremos listos para hacer un elevador con un motor a pasos, un display y no mas; bueno claro la etapa de potencia del motor a pasos que son los transistores tip125. Pero eso en un rato que tenga mas tiempo, 

Aqui la imagen.

Recomiendo mucho pasar este circuito a plaquita. ya que si lo hacen bien, podran comuniocarse con muchas pic (recordando que para cada serie de pic's el programa bootloader sera diferente, y tambien las conexiones hay que ver cada datasheet para encontrar tx y rx)

Nota : El cristal depende de ustedes, recuerden leer la hoja de datos para ver hasta cual se puede usar. y si van a hacer programas ya muy avanzados hay que hacer calculso eso ya lo pondre despues para ver cuanto tardara nuestro pic en reaccionar.

Y nuestro siguiente programa
*4.-* Programa para hacer corrimientos controlados.


```
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Este programa prendera y apagara leds en un solo nible (solo controlaremos un motor a pasos)         //
//50 veces esto queire decir que si se tiene un motor con una resolucion con 2.5° por paso tendremos // 
//50 x 2.5 = 125° con este programa (variará dependiendo de cada motor a pasos.  Todo esto pasará //
//Cuando presionemos un boton pulsador (PB) en A0, que sera nuestra entrada. al terminar se parará//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#build (reset=0x200)
#build (interrupt=0X208)
#ORG 0X0000, 0X01FF

void BOOTLOADER() {
      #ASM
         NOP
      #ENDASM
}

#byte PORTA= 0XF80
#byte PORTB= 0XF81
#byte PORTC= 0XF82
#byte PORTD= 0XF83
#byte PORTE= 0XF84

void main()
{

   int P=0;                                //definicion de variable para iniciar conteo
   int m1=8;                            //en que nible se va a hacer la funcion (1000)

   set_tris_A(0xFF);                ////////////////////////////////////
   set_tris_D(0x00);               //Configuracion de puertos//
   set_tris_B(0x00);               ////////////////////////////////////

   portd=0;     

   while(TRUE){                      //ciclo infinito


         if(!input(PIN_A0))        //negado para que nos de simpre cero con conexion pull up
                                             //espera pulso para iniciar ciclo.
            {

               for (P=0;P<=49;P++)    /*Pregunta si 0 es <= a 49, como es si la respuesta,
                                                        incremente P en 1, y P ahora es igual a 1, hace la pregunta
                                                        de si 1 es <= a 49, como es cierto incrementa P (2) y hace lo que este dentro
                                                        del for una vez mas, y asi sucesivamente hasta llegar a 50,
                                                        como 50 no es <= a 49 se sale del ciclo for y espera el pulso otra vez*/
                  {
                  PortD=m1;
                  delay_ms(100);                //retardo (para el motor a pasos sera mucho mas rapido
                  m1=m1<<1 | m1>>3;      //sentido de giro (ya explicado anteriormente
                  m1=m1 & 0x0F;               //multiplicacion por 1 1 1 1b para nible bajo (ya explicado tambien)
                  }
             }
         }
}
```

Conexion (Nota la conexion mostrano no incluye la comunicacion serial max232, esto queire decir que si lo piensas simular en Proteus como lo hago yo tendran que borrar del programa todo lo que tenga que ver con el bootloader, como el void bootloader y su subrrutina, los build y el ORG)



Bueno en la proxima ya empiezo con los displays, su conexion y programacion. Por el momento es todo en una opurtunidad mas sigo poniendo proyectos, 

Siempre hay que darle una explicacion a las cosas y tambien verle una aplicacion. Si no se sabe investigar y despues preguntar.

*tips*.-(Recuerden que los motores a pasos unipolares tienen 5 o 6 cables, si es de 5 uno de ellos es comun, si tiene 6 dos de ellos son comunes, y los demas es donde se le manda el pulso, hay que buscar la secuencia de los motores a pasos una manera es probandolos con un fuente. la otra con un multimetro.)

*tips*.- Hay que tener muy en cuenta que si se va a conectar el motor a pasos con transistores las tierras deben de ser comunes pero las alimentaciones diferentes, una para el control y otra para la potencia, si no hacen esto se les va a calentar el pic, y posiblemente se les queme lo digo por experiencia  :evil: 

Que tengan un buen dia


----------



## frivoldeux (Jul 10, 2009)

Muy bien, ya mas o menos sabesmos com controlar un motor a pasos, haciedno que llegue hasta cierto numero de vuletas pasos o grados, pues para no seguir con mas ejmeplos de esto ahora pasaremos a los displays y despues de esto haremos un elvevador con un motor a pasos y un display para que indique en que piso estamos.

Programas para contar de 0 a 9 en un display (2)
*
a)*


```
//////////////////////////////////////////////////////////////////////////////////////////
//Aqui tenemnos un programa que muestra por medio de un display  //
//conmectado al puerto B el conteo de 0 a 9 ascendentemente y        //
//conestado al pin A2 tenemos un boton con resistencia pull up para //
//al presionarlo empiece a contar descendentemente.//
/////////////////////////////////////////////////////////////////////////////////////////

#include <18F452.h>                                                     //Lo de siempre.
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000, RESTART_WDT)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#build (reset=0x200)        //Esto se queita si no van a usar el bootloader, de lo contrario se deja ya esta explicado.
#build (interrupt=0X208)
#ORG 0X0000, 0X01FF


void BOOTLOADER()
   {
      #ASM
         NOP
      #ENDASM
   }

#byte PORTA= 0XF80
#byte PORTB= 0XF81
#byte PORTC= 0XF82
#byte PORTD= 0XF83
#byte PORTE= 0XF84

void main()
{
   unsigned char const disp[10]  = {0x3f, 0x06, 0x5b, 0x4f,
                       0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};  //Declaracion de vector para display de [b]catodo comun.[/b], una breve explicaicion para sacar cada vector de los displays es muy parecida a como declarar los puertos si como salidas o como entradas, en caso de que se quieran usar displays matriciales es algo diferente, no me metere pro ahora, creo que cuando llegue al teclado matricial se entendera mejor.

   signed char i = 0;  //inicializar la variable del vector en 0, es otra manera de nombrar variables de tipo entero

   set_tris_B(0x00);   //Puerto B como salida
   portB = 0;              //limpiamos el puerto b.


   while(1)
   {

   if(input(PIN_A2))  //Si no se presiona A2 suma 1 al vector o recorre uno al vector. (Tenemos un boton en A2 como pull up)
      i++;
   else                     //Si se presiona lo resta.
      i--;

   if (i < 0)               //Creo que es muy logico, es para que solo llegue hasta 0 y regrese a 9. 
      i = 9;
   if (i > 9)               // aqui es solo para que llegue a 9 y se regrese a o
      i = 0;

   portb = disp[i];   //Sacar la variable i por el puerto B quiere decir que i toma el valor de cada uno de los vectores declarados. 

   delay_ms(500);     //Retardo entre cambios. medio segundo.
```

A continuacion haremos uno que cuente de 0 a 99, obvio con 2 diplays todo pro el puertoB.
En el ejemplo anterior que usamos el puerto b, solo conectamos al microcontrolador, de las patitas B0 a B6, que son las 7 de los 7 segmentos, ahora conectaremos todo el puerto B para hacer que los dos displays se "multiplexen" usando 2 transistores uno tipo pnp y otro tipo npn, estos haran el multiplexeo., pondre el diagrama para que se entienda mejor.



 y el programa es:


```
#include <18F4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#build (reset=0x200)
#build (interrupt=0X208)
#ORG 0X0000, 0X01FF

void BOOTLOADER() {
      #ASM
         NOP
      #ENDASM
}

#byte PORTA= 0XF80
#byte PORTB= 0XF81
#byte PORTC= 0XF82
#byte PORTD= 0XF83
#byte PORTE= 0XF84


void main()
{
   int i,j,x;                                                       //Declaracion de variables
   int const disp[10]  = {0xC0, 0xF9, 0xA4, 0xB0,                 //Se declaran como constantes
                          0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};   //Codigo Hexa para cada nuemro Inverso


   set_tris_B(0x00);

   portB = 0;


   while(TRUE)
   {

           for(i=0;i<=9;++i)            //Ciclo que indica cuando terminaron de contar las decenas.
      {
            for(j=0;j<=9;++j)           //Ciclo que indica cuando termianron de contar las unidades.

               for(x=0;x<=10;++x)       //Este ciclo sirve para no ver los parpadeos de los diplay en el multiplexado.
         {
                {
                portb=disp [i]+0x80;    //Aqui sucede el multiplexado, al sumarle al resultado 1000 0000, para hacer que
                                        //prenda D7 instantaneamente por el delay indicado.
                delay_ms(10);
                portb=disp[j];          //Aqui esta sacando las unidades multiplexadas ya anteriormente por i.
                delay_ms(10);
                }

         }
      }
   }
}
```
Bueno en caso de alguna duda me lo dicen, y como hoy ya se me acabo el tiempo despues le seguimos para hacer un elevador con todo esto que ya mas o menos sabemos.

Que tengan muy buen dia.


----------



## piojoadrian (Jul 28, 2009)

Hola. Estoy utilizando el 18F2455, despues de un dia completo de uso, se tilda. Me gustaria implementarle un reset, pero no he podido, ni con el wdt, ni e probado con el MCLR.

Me podrias ayudar?

Saludos y desde ya muchas gracias


----------



## agustinzzz (Jul 28, 2009)

frivoldeux, ¿podrías postear un link a la *página oficial* del PIC C compiler?

Gracias.


----------



## frivoldeux (Jul 28, 2009)

piojoadrian dijo:
			
		

> Hola. Estoy utilizando el 18F2455, despues de un dia completo de uso, se tilda. Me gustaria implementarle un reset, pero no he podido, ni con el wdt, ni e probado con el MCLR.
> 
> Me podrias ayudar?
> 
> Saludos y desde ya muchas gracias



Claro que si te podria ayudar pero creo que me seria muy util si me dijeras que es lo que esta haciedno tu pic (o t sistema) para ver porque te "tildea" (me gustaria saber a que te refieres con esa palabra, ¿qe te epieza a variar si setido?), lo que se me viene a la cabeza por el momento es que te esta consumiedo mas corriente de lo que el pic puede soportor por horas de trabajo y por eso te empieza a fallar, pero hay que ser mas especifico, asi que espero algo mas detallado.


----------



## frivoldeux (Jul 28, 2009)

agustinzzz dijo:
			
		

> frivoldeux, ¿podrías postear un link a la *página oficial* del PIC C compiler?
> 
> Gracias.



Hola camarada, pues no creo que sirva de mucho la pagina oficial de CSS ya que solo bajaras el trial de 30 dias y pues no sirve de mucho de todos modos para alguna información y o algo de ayuda la pagina es http://www.ccsinformación.com/, seria mas facil que algun foro lo localizaras yo lo baje de otro foro pero ya no lo encuentro para darte la direccion, seguire buscando para que lo puedan bajar. Si lo encuentras este debe de venir con dos archivos setup (pchwupd.exe y ideutilsupd.exe) y tres arcivos mas con extensión .crg los cuales deberas de cambiar por los que se instalan originalmente y listo ya tendras tu programa funcionando a la perfeccion.


----------



## frivoldeux (Jul 28, 2009)

Pues bueno lo pormetido es deuda asi que aqui les va el programa del elevador con sus conexiónes que son muy sencillas mas se tarda uno en andar armando el elevador para que quede bonito y todo eso, ustedes pueden hacerlo todavia mas bonito yo ya no tenia para mas pero lo importante es hacer el programa asi que hay va. 

*Nota:* El numero de pulsos entre piso y piso va a variar mucho dependiendo el tipo de motor a pasos que ustedes usen, los pueden sacar a prueba y error o con alguna formula matematica que relaciones los grados que se mueve su motor a pasos por paso. Deberan cambiar tanto el numero que se encuentra en la subrutina "ShowPiso" como los pasos que habra entre piso y piso, vean muy bien el programa no esta muy complicado.

Despues pondre uno que guarda en su memoria el piso al que debe de llegar ya que este programa solo les indica en el piso que se encuentra, pero si presionan otro boton por ejemplo el 1 4 3 2 solo va a irse del 1 al 4 y los demas no los hara, despues posteo el que si presionan un monton de pisos este se ira a todos los que le hallan dicho, como un verdadero elevador. Este solo es para entender un poco las sentencias y logica que hemos manejado hasta ahora.

Bueno sin mas preambulos:::::


```
/////////////////////////////////////////////////////////////////////////////////////////////
//Para el armado de este circuito el cual sera un elevador de 4 pisos      //
//se usara un pic18f452-i/p el cual llevara conectado en el puerto A        //
//los botones pulsadores en A0, A1, A2 y A3 siendo A0 para el piso 1     //
//A1 para el piso 2, A2 para el piso 3 y A3 para el piso 4, solo se            //
//usara un solo display asi que usaremos el puerto B para el display      //
//haciendo la caneccion mensionada anteriormente para el conteo de 0 //
//a 9, y en el puerto D se hara la conexión del motor a pasos (D0,        //
//D1 D2 y D3 para motor a pasos bipolar de 5 o 6 cables.                       //
////////////////////////////////////////////////////////////////////////////////////////////

#include <18f452.h>
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock=20000000)


#byte porta=0xf80
#byte portb=0xf81
#byte portc=0xf82
#byte portd=0xf83
#byte porte=0xf84

void ShowPiso (long p)   //Muestra en que piso se encuentra por medio del display
{
 if (p==1)        //Pulsos en que el display cambia a 1
    portb=0x06;   //Muestra 1 en display de 7 segmentos

 if (p==328)      //Pulsos en que el display cambia a 2
    portb=0x5b;   //Muestra 2 en display de 7 segmentos

 if (p==626)      //Pulsos en que el display cambia a 3
     portb=0x4f;  //Muestra 3 en display de 7 segmentos

 if (p==880)      //Pulsos en que el display cambia a 4
     portb=0x66;  //Muestra 4 en display de 7 segmentos
}

void main()
{
long p=1;       //Declaracion de variables
long m1=8;
set_tris_d(0);  //Configuracion de puertos
set_tris_b(0);
portd=0;       //limpianmos puertos
portb=0;

      while(1)
      {
         ShowPiso (p);
         if (p==1)  //si estoy en el piso 1 para ir al piso 2
         {
            if (!input(pin_a1))    
            {
               for(p=1;p<=327;++p) //Cantidad e pulsos necesarios para llegar al piso 2
               {
               portd=m1;
               delay_ms(20);     //Velocidad entre pulso y pulso.
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==328)   //si estoy en el piso 2 para ir al piso 1
         {
            if (!input(pin_a0))
            {
               for (p=328;p>=2;--p) //Cantidad e pulsos necesarios para ir de 2 a 1
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }

            }
         }


         if (p==1)       //si estoy en el piso 1 para ir al piso 3
         {
            if (!input(pin_a2))
            {
               for (p=1;p<=625;++p) //Cantidad e puylsos nmecesaris para ir de 1 a 3
               {
               portd=m1;
               delay_ms(20); 
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==626)    //si estoy en el piso 3 para ir al piso 2
         {
            if (!input(pin_a1))
            {
               for (p=626;p>=329;--p)
               {
               portd=m1;
               delay_ms(10);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==626)   //si estoy en el piso 3 para ir al piso 1
         {
            if (!input(pin_a0))
            {
               for (p=626;p>=2;--p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==1)  //si estoy en el piso 1 para ir al piso 4
         {
            if (!input(pin_a3))
            {
               for (p=1;p<=879;++p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==328)  //si estoy en el piso 2 para ir al piso 3
         {
            if (!input(pin_a2))
            {
               for (p=328;p<=625;++p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }



         if (p==328)   //si estoy en el piso 2 para ir al piso 4
         {
            if (!input(pin_a3))
            {
               for (p=328;p<=879;++p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==626)  //si estoy en el piso 3 para ir al piso 4
         {
            if (!input(pin_a3))
            {
               for (p=626;p<=879;++p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>1|m1<<3;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==880)    //si estoy en el piso 4 para ir al piso 3
         {
            if (!input(pin_a2))
            {
               for (p=880;p>=627;--p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==880)  // si estoy en el piso 4 para ir al piso 2
         {
            if (!input(pin_a1))
            {
               for (p=880;p>=329;--p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }


         if (p==880)    //si estoy en el piso 4 para ir al piso 1
         {
            if (!input(pin_a0))
            {
               for (p=880;p>=2;--p)
               {
               portd=m1;
               delay_ms(20);
               m1=m1>>3|m1<<1;
               m1=m1&0x0f;
               ShowPiso (p);
               }
            }
         }
      }
}
```


----------



## frivoldeux (Jul 28, 2009)

A por cierto para esto deberan de hacer la conexión para el motor a pasos como ya lo habia mensionado antes, con sus respectivos Transistores TIP120, donde D0, D1 D2 y D3 iran a la base del transistor. o puede ser TIP125, el que ustedes quieran uno es NPN y otro PNP, yo uso el 120 para esto. Recuerden que van alimentados por separado 5V para el pic y el motor a pasos en otro etapa (potencia) con sus transistores, ya sea a 5 o a 9 o a 12 depende de sus motores a pasos. Oh si! con las tierras puenteadas para que no haya ruidos e interferencias. No se que mas se me olvida, pero espero les funcione muy bien. De todos modos aqui ando para lo que necesiten y claro, yo sepa, jejeje. Posteo fotos de rato de mi elevador.

Buena vibra


----------



## piojoadrian (Jul 28, 2009)

> piojoadrian escribió: Hola. Estoy utilizando el 18F2455, despues de un dia completo de uso, se tilda. Me gustaria implementarle un reset, pero no he podido, ni con el wdt, ni e probado con el MCLR.
> 
> Me podrias ayudar?
> 
> ...



Gracias frivoldeux por responder...

Adjunto el codigo.

Intente programar el WDT pero no me resetea el PIC al parecer.
Luego de un dia de encuestar el pic, es probable que en la planta industrial el generador o algo se prenda y haga que todo claudique.
Con un reseteo periodico andariamos barbaro!

Saludos cordiales y desde ya muchas gracias



```
#include <18F2455.h>
#fuses HSPLL,WDT,WDT512,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000, restart_wdt)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#int_RDA
void  RDA_isr(void) 
{
   char caracter;
   int8 canal0,canal1,canal2,canal3,canal4,canal8,canal9,canal10,canal11,canal12;
   
   caracter=getchar();

   if (caracter=='c')
   {
        restart_wdt()             //Canal 0
        set_adc_channel(0);
        delay_us(10);
        restart_wdt()
        canal0 = read_adc(); //read_adc(ADC_START_ONLY);
        delay_ms( 10 );
        restart_wdt()
        canal0 = read_adc(); //read_adc(ADC_READ_ONLY);
 
        restart_wdt()
        printf("00=%3u",canal0);
        restart_wdt()
        



        restart_wdt()             //Canal 1
        set_adc_channel(1);
        delay_us(10);
        restart_wdt()
        canal1 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal1 = read_adc(); 
        
        restart_wdt()
        printf("01=%3u",canal1);
        restart_wdt()
        
        
        
        
        restart_wdt()              //Canal 2
        set_adc_channel(2);
        delay_us(10);
        restart_wdt()
        canal2 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal2 = read_adc(); 
        
        restart_wdt()
        printf("02=%3u",canal2);
        restart_wdt()
        
        
        
        restart_wdt()               //Canal 3
        set_adc_channel(3);
        delay_us(10);
        restart_wdt()
        canal3 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal3 = read_adc(); 
        
        restart_wdt()
        printf("03=%3u",canal3);
        restart_wdt()
        
        
        
        restart_wdt()               //Canal 4
        set_adc_channel(4);
        delay_us(10);
        restart_wdt()
        canal4 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal4 = read_adc(); 
        
        restart_wdt()
        printf("04=%3u",canal4);
        restart_wdt()
      
      
      
        restart_wdt()               //Canal 8
        set_adc_channel(8);
        delay_us(10);
        restart_wdt()
        canal8 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal8 = read_adc(); 
 
        restart_wdt()
        printf("08=%3u",canal8);
        restart_wdt()
        
        
        
        restart_wdt()               //Canal 9
        set_adc_channel(9);
        delay_us(10);
        restart_wdt()
        canal9 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal9 = read_adc(); 
        
        restart_wdt()
        printf("09=%3u",canal9);
        restart_wdt()
      
      
      
        restart_wdt()                 //Canal 10
        set_adc_channel(10);
        delay_us(10);
        restart_wdt()
        canal10 = read_adc(); 
        delay_ms( 10 );.
        restart_wdt()
        canal10 = read_adc(); 
 
        restart_wdt()
        printf("10=%3u",canal10);
        restart_wdt()
        
        
        
        
        restart_wdt()                  //Canal 11
        set_adc_channel(11);
        delay_us(10);
        restart_wdt()
        canal11 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal11 = read_adc(); 
 
        
        restart_wdt()
        printf("11=%3u",canal11);   
        restart_wdt()
        
        
        
        
        restart_wdt()                     //Canal 12
        set_adc_channel(12);
        delay_us(10);
        restart_wdt()
        canal12 = read_adc(); 
        delay_ms( 10 );
        restart_wdt()
        canal12 = read_adc(); 
        
        restart_wdt()
        printf("12=%3u\r",canal12);      //El ultimo canal termina con un retorno de carro;
        restart_wdt()
       
        
   }

   
}


void main(void) {
   
   setup_adc_ports(ALL_ANALOG|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_2);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   

  
   while (TRUE) {}
  
}
```


----------



## frivoldeux (Jul 29, 2009)

De acuerdo con lo que vi en tu programa para hechar a jalar el perro guardian o WDT esta bien, no hay problema con tu configuracion, aunque es muy larga y se puede hacer mas corta, pero asi esta bien, lo unico que esta mal es que te faltan muchos puntos y comas en cada "restart_wdt()*;* " , en fin al parecer como lo predecia, tu pones que cada vez que arranca un generador o algo que jala mucha corriente falla o tildea el pic, eso es porque al haber una caida de tension o un jalon de mucha corriente el pic se desstabiliza, ahi es dodne biene la parte de CONTROL, esto significa que tienes que diseñar en este caso un control tipo PID para hacer que tu PIC nop tildie, esto lo puedes hacer con Op. Amp. (amplificador operacionales) o incluso con otro pic que resguarde al controlador principal. 

A mi me llego a pasar algo similar pero con motores de corriente directa que despues de estrar un funcionamiento por largo timpo era cuestion de que algo mas se encendiera para que el pic se apagara y reseteara. 

Recuerda que al usar el WDT que tu propones te jala 6% en ROM, puedes usar sentencias para hacerlo mas efectivo sin necesidad de que se resetee, aunque vuelvo a lo mismo tu WDT esta bien, no es problema de la programacion es problema del Circuito exterior. necesitas hacer algunos calculos para ver en que anda fallando no estoy muy seguro pero creo que el pic que usas te puede entregar hasta 50 mA por patita (no estoy seguro ver el datasheet) si en tus calculos te sale que jala mas corriente cuando entra un generador hay puede estar el problema, o la caida de tensión es mucha que el pic no recive lo que debe de ser y tambien por eso falla. Para eso aplica el Control en la industria.

Espero que sea por ahi porque tu configuracion de WDT esta bien reitero.

En los proximos programas entraremos a lo que es manejo de señales Analogas y Digitales con salida a display y a LCD. para sensores de cualquier tipo, (temperatura, humedad, presion, flujo, etc...) y una breve explicacion de los de Efecto Hall.

Hasta la proxima.


----------



## frivoldeux (Jul 29, 2009)

piojoadrian dijo:
			
		

> > piojoadrian escribió: Hola. Estoy utilizando el 18F2455, despues de un dia completo de uso, se tilda. Me gustaria implementarle un reset, pero no he podido, ni con el wdt, ni e probado con el MCLR.
> >
> > Me podrias ayudar?
> >
> ...



Jajajaja que onda de nuevo piojoadrian, me pusiste a pensar un rato y analice mas detenidamente tu configuracionde programa y algunas aplicaiones que le vi, me voy por partes para que las cheques y talves tambien una de estas puede ser.

1.- hay que checar bien la configuracion de #fuses.
2.- Creo que estas usado un cristal que desestabiliza a tu pic, 40 MHz es hasta donde trabaja bien.
3.- lo que haces con tu configuracion es que cuando precionas la tecla 'c' haces un reseteadero de canales de lectura Analogica y los vuelves a prender y los pones a leer, cada uno de ellos por separado cosa que te quita tiempo de procesamiento y usas demasiado el restar_wdt().

Un ejemplo que vi en el mismo programa CSS esta algo asi 


```
#include <16F877.h>
#fuses HS,WDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9200, xmit=PIN_C6, rcv=PIN_C7)


void main()   {

   switch ( restart_cause() )
   {
      case WDT_TIMEOUT:
      {
         printf("\r\nRestarted processor because of watchdog timeout!\r\n");
         break;
      }


      case NORMAL_POWER_UP:
      {
         printf("\r\nNormal power up!\r\n");
         break;
      }
   }
   setup_wdt(WDT_2304MS);

   while(TRUE)
   {
      restart_wdt();
      printf("Hit any key to avoid a watchdog timeout.\r\n");
      getc();
   }
}
```

Bueno antes que nada no se para que usas el HSPLL y el PLL5, despues nunca configuras el wdt (setup_wdt(*mode*))
Dentro de mode pueden ir estas opciones WDT_ON, WDT_OFF, WDT_TIMES_32, WDT_TIMES_64, WDT_TIMES_128, WDT_TIMES_256, WDT_TIMES_512, WDT_TIMES_1024, WDT_TIMES_2048, WDT_TIMES_4096, WDT_TIMES_8192, WDT_TIMES_16384, WDT_TIMES_32768, WDT_TIMES_65536. Si vas a trabajar solo con uno en tu caso que pusiste 512 lo deberias usar con la configuracion anterior.

y para ahorrarte todo lo que pusiste podrias poner muy bien en vez de esto 


```
restart_wdt();             //Canal 0
        set_adc_channel(0);
        delay_us(10);
        restart_wdt();
        canal0 = read_adc(); //read_adc(ADC_START_ONLY);
        delay_ms( 10 );
        restart_wdt();
        canal0 = read_adc(); //read_adc(ADC_READ_ONLY);
 
        restart_wdt();
        printf("00=%3u",canal0);
        restart_wdt() ;
```

Esto:


```
restar_wdt();
set_adc_channel(ALL);
delay_us(10);
canal0=read_adc();
printf("00=%3u",canal0);
delay_ms(lo que quieras);
canal1=read_adc();
prinf("00=%3u",canal0);
delay_ms(loquequiera);
```
etc......

y dentro del programa usar algo asi para que vuelva a iniciar automaticamente:


```
while(true){

     restart_wdt();

     perform_activity();

   }
```
espero sea de ayuda y dale una revisada al datasheet para ver lo del oscilador y a la ayuda del CSS para que veas la configuracion del WDT, yo la eh usado muy poco pero si me funciona con esta configuracion.

Suerte:
[/i]


----------



## Chico3001 (Jul 29, 2009)

Por favor coloquen sus programas entre las etiquetas code y /code para que la lectura en el foro se mas facil para todos....

Gracias... .


----------



## piojoadrian (Jul 30, 2009)

Vamos por parte.

Antes que nada estoy muy agradecido por la dedicación a este problema que me está sacando el sueño.

Es mi proyecto de grado, me recibo de Ing. Electrónico. Como bien se sabe, la carrera generalmente, poco tiene que ver con la realidad que se afronta día a día, es por ello que hay que investigar e indagar todos los caminos para solucionarlo.

Nuevamente muchas gracias por responder.

El tema es el siguiente.
Es un sistema de monitoreo de temperatura wireless a distancia. Utilizo los modulos Xbee PRO.
Encuesto los PIC´s y estos me devuelven los valores de los conversores. Hasta ahí todo mas que bien. Todas las placas estan alimentadas con la misma señal de 220v. Luego de varias horas (ultimamente 1 dia ) una de las placas que contiene al pic, no responde a la encuesta. Es decir, como que se colgara, reseteando la termica y volviendo a conectar, todo vuelve a la normalidad.

Posibles fallas que no logro descifrar:

--cerca de la placa pasa un manojo de cables de alta tension (estimo trifasica) que es posible que me induzca algun campo que me haga tildar todo.

--Ya que todas las placas estan con la misma alimentacion, y solo se cuelga esta (la c) puede ser que sea la placa.



Implementando un reset periodico, es probable que solucione el problema, aunque no logre determinar el origen de tal.

Estoy en etapa de calibracion, las demas estan funcionando correctamente.

Espero pueda sacarlo andando pronto.



Vamos por parte,

Gracias *frivoldeux* por ayudar



> piojoadrian escribió: Hola. Estoy utilizando el 18F2455, despues de un dia completo de uso, se tilda. Me gustaria implementarle un reset, pero no he podido, ni con el wdt, ni e probado con el MCLR.
> 
> Me podrias ayudar?
> 
> ...



1- La configuracion de fuses la chequee, estimo que esta bien ya que funciona
2- El cristal que utilizo es de 20Mhz, pero debes colocar ese valor en el programa (desconozco porque, pero funciona)
3- No entendi, estoy haciendolo bien? Al parecer, lo puse en funcionamiento y anda, hoy te confirmo si se mantiene a lo largo de los dias.


WDT_ON, WDT_OFF, WDT_TIMES_32, WDT_TIMES_64, WDT_TIMES_128, WDT_TIMES_256, WDT_TIMES_512, WDT_TIMES_1024, WDT_TIMES_2048, WDT_TIMES_4096, WDT_TIMES_8192, WDT_TIMES_16384, WDT_TIMES_32768, WDT_TIMES_65536. Si vas a trabajar solo con uno en tu caso que pusiste 512 lo deberias usar con la configuracion anterior. 

Para que son los WDT_TIMES_1024? No lo se.

Es buena tu aclaracion de donde colocar el restart_wdt(), pero el problema, es que dentro del programa no tengo nada como ya habras visto. El PIC solo permanece a la espera de ser encuestado. Si coloco un restart_wdt() dentro del while del programa, nunca actuaria.



Muchas gracias frivoldeux, eres de lo mas en este foro! (te he leido por varios temas de debate)


----------



## frivoldeux (Jul 30, 2009)

Muy bien piojoadrian espero a que lo heches a jalar este dia, a ver que pasa, si le doy mas por la circuiteria que ni el programa por lo que dices, pero otra cosa rapida. si debes de indicar los 20 MHZ, si le pones un cristal diferente si jalan pero no en el tiempo de reloj que deberian, eso lo pienso poner mas adelante, las formulas y todo eso, se pone 48MHZ por lo general cuando manejas conexion por USB, pero en ese caso para el uso que le estas dando te recomiendo usar un DSPIC, ya que manejas por lo visto todos los puertos de A/D y manejo de señales. Si no ponle un cristal de 40MHz y configura de nuevo el #DELAY para que trabaje en sus ciclos de reloj como debe.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Ok, este progrmaa es para leer una señal analogica y mandar atravez del pic a una salida Digital, si alguna vez usaron una ADC con su potenciometro a lo que les conectaban leds. y mandaba un nemero binario a su salido esto es parecido pero dentro del programa cambiamos la salida a nuestro placer. en nuestro caso para leerlo o visulizarlo en dos display de 7 segmentos, y poara que sirve esto, pues para tener una lectura mas precisa de lo que pasa en el mundo Analogico.


```
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#build (reset=0x200)
#build (interrupt=0X208)
#ORG 0X0000, 0X01FF

void BOOTLOADER() {
      #ASM
         NOP
      #ENDASM
}

#byte PORTA= 0XF80
#byte PORTB= 0XF81
#byte PORTC= 0XF82
#byte PORTD= 0XF83
#byte PORTE= 0XF84

void main(){

  int const disp [10] = {0x3f, 0x06, 0x5b, 0x4f,0x66,     //declaramos los vectores para el display
                         0x6d, 0x7d, 0x07, 0x7f, 0x6f};

  int dato, uni, dec, multi, i;   //declaracion de variables tipo entero
  float temp;                     //Declaracion de variables tipo flotatentes

  set_tris_A(0x01);               //Puerto de lectura del ADC
  set_tris_B(0x00);               //Configuracion de los puertos
  set_tris_D(0x00);
  
  setup_port_A(2);               //Iniciamos puertos ADC en el puerto A
  setup_adc(adc_clock_div_32);   //Configuramos la lectura del ADC (reloj)
  set_adc_channel(0);            //Declaramos el canal ADC que se va a usar o leer

  portB=0;
  portC=0;

   while(TRUE)
   {
     dato = read_adc();           //Leemos el ADC del canal 0 (A0) y lo almacenamos en "dato"
     temp = 0.019607843 * dato;   //lo multiplicamos por el resultante de la resolucion esto es (5V/255=0.019607843~) y lo almacenamos en temp
     multi = temp*10;             //esto lo multiplicamos por 10 y lo almacenamos en "multi"
     dec =  multi/10;            //las decenas mostradas en el display sera multi entre 10 para entregar un valor entero
     uni = multi % 10;            //y las unidades sera el el 10 porciento del valor de multi, entregando 10 numero antes de cambiar una decena

      for(i=0;i<=40;i++)
         {
         portb=disp[uni];
         delay_ms(10);
         portb=disp[dec] + 0x80;
         delay_ms(15);
         }
        }
}
```

En lo que seria en el canal 0 (A0 ira conectado un potenciometro, y lo que nos dara en la lectura de los 2 displays es un valor entre 0 y 5 V que es lo que estamos leyendo con el potenciomentro (voltaje en este caso) entonces el lado izquierdo sera las unidades y el lado derecho seran las decimales. 

La conexión es la misma de los displays como lo era para el conteo de 0 a 99 antes ya posteado, solo se agregara el potenciometro, en caso de querer hacer el sensor de temperatura con esto ya se puede hacer, quitanm el potenciometro y ponenm su Lm35 o el que les plazca ma, configuran su programa para que haga los respectivos cambios recordando que por cada Grado Celsius equivalea a 10mV en el LM35, eso ya depende de su imaginacion para hacer la formula en su programa para hacer el sensor de temperatura, o un sistema sensorial de lo que ustes quieran. Yo eh hecho ya sistemas de flujo con esto, sistemas de monitoreo de presion, temperatura y de Efecto Hall por proximidad y magnetismo, asi que si funciona y muy bien....

el del LCD pues es super facil.

Es lo mismo pero sin la configuracon del puerto para visulaizar los displays, Solo se agrega una libreria mas para la concexion del LCD, el cual yo lo conecto al puerto B para esto si hacen su programa en PCHW PIC C compiler CSS tendremos que cambiar una cosita de la libreria.

Esta libreria esta configurada por default para que al display sea conectado al puerto D, pero siendo mas facil la canexion el el puerto B el cambio que haremos es la siguiente (Esto depende a gusto del  que hace esto, lo pueden dejar asi o cambiarlo pero pues un dato curioso para que lo sepan.)

No s vamos a la carpeta donde instalamos el programa PICC que en mi caso es este C:\Archivos de programa\PICC despues nos metemos a la carpeta que dice drivers y buscamos la libreria LCD.h una vez adentro (lo pueden abrir con block de notos o con el mismo programa PICC) modifican esta linea // #define use_portb_lcd TRUE quitando las diagonales para que se quite de ser comentario y ahora ya estara listo para hacer la conexion al puerto b, si no hacen esto nunca lo hara. Pasara lo mismo para el teclado matricial que veremos despues. Guardan los cambios y cierran y listo.


```
#include <16f877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#include <LCD_flex.c>       //Libreria del LCD modificada para que mande todo al puerto B

#byte PORTB= 6            //Cambio de nombre a los puertos.
#byte PORTD= 8

void main()
{
   int dato;           //Variables declaradas
   float temp;
   
   set_tris_b(0);
   lcd_init();                      //inicializacion del LCD
   setup_adc_ports(2);
   setup_adc(adc_clock_div_32);    //Configuracion de los ADC
   set_adc_channel(0);
   
   while (TRUE)
   {
      dato=read_adc();
      temp=0.0196078 * dato;
      printf(LCD_PUTC,"Voltaje= %1.3f",temp);     //Asi debe de ir jajaja Lo que hace es mandar UN ENTERO (1) y TRES DECIMALES (3) (1.3) y la f pues es porque es flotante la variable.
      lcd_gotoxy(0,1);  le decimos que inicie en el renglon 0, en la columna 1 porque recordemos que es un LCD de 16x2.
   }
}
```

Bueno asi como leimos que se puede modificar las librerias de los programas para hacerlos mas efectivos o eficientes, tengo un amigo que modifico la libreria del LCD para leer un lcd mucho mas grande que este por cierto es para lcd de 16 x 2, bueno a todo esto el logra hacer monitos y pajaritos y figuras bien locas que se movian atravez del LCD, esto ya es mas de meterse a la programacion del LCD pero todo es posible. Claro tambien pueden bajar librerias que ya hacen esto, pero es mejro saber como se hace ¿no creen?...
*
NOTA:* Los LCD tienen una memoria integrada, si no borran lo ultimo que dejaron en el lcd al prenderlo leeran otra vez lo mismo, asi que no olviden en caso de quitarlo apargarlo desconectarlo o lo que se limpiar el LCD. mandando imprimir nada.

Seguimos despues con mas programas y mas explicaion para ustedes.


----------



## kapotik (Ago 17, 2009)

Hola por favor podrias postear como se usa el PICC?
yo estoy tratando de iniciarme en el lenguaje C ya tengo el picc pero no se como usarlo, por ejemplo quihsiera peegar uno de los programas que pones pero despues no entiendo que tocar para que me genere el exe.

Gracias


----------



## piojoadrian (Ago 17, 2009)

El CCS no genera el exe. Te genera un .hex que luego utilizas con tu programador.

Saludos


----------



## kapotik (Ago 17, 2009)

Gracias por contestar

Perdon fue un error de tipeo quise decir hex.

quisiera saber si lo que hago esta bien 
1º abro pic wizar elijo el pic a usar y seteo las distintas configuraciones y cuando lo cierro me genera un archivo . H por ejemplo main.H
2º en la cabecera del picc pone automaticamente include el archivo que genero con el pic wizar
a continuacion escribo el programa y lo guardo con un nombre distinto al que genero el pic wizar por ejemplo modulo
3º luego le doy compile y el archivo hex. que genera se llama main.hex
y por supuesto cuando lo grabo en el pic nada hace no funciona

por favor me podrias decir que hago mal

Gracias
Saludos


----------



## frivoldeux (Ago 18, 2009)

Muy buenas kapotik, el codigo .hex se genera al momento de compilar el programa que has hecho o presionando la tecla F9 (compile).

Si esta bien lo que haces pero tu cuando hagas tu programa con el pic wizar no pongas nada solo donde lo vas a guardar y ya, lo que te ponga en la pantalla borralo TODO y pon el programa tal y como lo posteo yo (leelo comprendendelo y claro has las modificaciones necesarias si usas otro pic) a continuacion presiona compili o F9 y en la direccion donde guardaste tu archivo te generara como 7 archivos mas uno de ellos el el .HEX que andas buscando.

Mucho ojo kapotik si leiste todo esto es porque sabes que muchos de mis programas traen algo que se llama bootloader y lo tienes que borrar en caso de que tu no lo estes usando si no no te va a funcionar.

casi en todos los preogramas son estas lineas


```
#build (reset=0x200)
#build (interrupt=0X208)
#ORG 0X0000, 0X01FF

void BOOTLOADER() {
      #ASM
         NOP
      #ENDASM
}
```

Eso es lo que debes de borrar si no estas usando el botlooader que ya explique antes. Ya borrado ahora si genera tu archivo .HEX y cargalo de la manera que mas te guste mi buen. 

Para cualquier otra cosa aqui ando.


----------



## frivoldeux (Oct 6, 2009)

Pues bueno colegas estoy de nuevo despues de un largo tiempo de sin estar por aqui, pues como lo prometi, pndre como hacer el programa de elevador en 2 formas, asi mismo como pondre ya control avanzado con microprocesadores para muchas funciones como control de motores por PID y Control de Estados, tambien sobre control de temperatura por PID, todo esto explicado cmo debe de ser. Haciendo calculos y observando antes de que funcione nuestro sistema que este es estable, todo esto analizandolo con matlab. y en momneot s espero poder llegar a control de procedsadores para crear un pequeño sistema operativo para controles robustos.
La meta que logren hacer su pendulo invertido. Y pues sera escencial el manejo del pic.


----------



## danrod (Dic 3, 2009)

Buen dia compañeros del foro:
Estoy utlizando una rutina que encontre PIC C ... sin emabargo este utliza TODO el puerto B.... Pero necesito saber como se puede CREAR un PUERTO_0X que utlice 4 terminales del puerto A y 4 terminales del puerto B..... que utilice laconfigracion TRIS_X y PORT_X

Agradeceria la colaboracion


----------



## mdiazzarate (Dic 9, 2009)

Hola a todos, Frivoldeux, estoy interesado en el tema de control PID, para el control de un pendulo invertido. Encontre algo de info en la pagina de microchip, acerca de como desarrollar el programa para dicho control. Tenes algo de información que me pueda ayudar en la programación y ajuste del control?
Muchas gracias.
Saludos.


----------



## RAM0N35 (Dic 10, 2009)

la verdad muchas gracias por poner el circuito de la conexion para puerto serial, me has aclarado muchas dudas.


----------



## tascker (Ene 18, 2010)

frivoldeux dijo:


> Muy buenas tengan todos ustedes lectores de Foros de electronica, eh bajado mucha información de este lugar y eh aprendido mucho aqui, soy estudiante de ing. electromecanica y estoy en mi segunda especialidad de Automatizacion y acabo de llevar microcontroladores. Todo esto pues quisiera compartirlo con ustedes. Estare posteando varios programas en Pic C por su simplicidad, tambien programo en Assambler y empiezon con matlab para hacer controles sofisticados para misiles y posionamiento de cosas muy complejas a las cuales no me metere (porque todavia no soy un erudito en esos temas)
> 
> Bueno el dia de hoy empezare con programas sencillos como prender y apagar un led por un pin del microcontrolador sere muy especifico en los comentarios y estare trabajando con el pic 18f452 i/p , claro a lo largo del tuto sabras que en pic C y sabiendo leer los datasheets (hojas de datos) cualquier pic lo hacen jalar. OJO, me perdonaran que ponga los programas ya hechos, ya que esto es antietico porque ustedes deben de pensar para hacer las cosas, pero espero que aqui se comparta mucho conociento y verlo en aplicaicones reales.
> 
> ...



Que tal amigo, necesito de tu super ayuda. En el tercer programa (el que corresponde al corrimiento de leds) y que mencionas que puede ser util para controlar motores a pasos tengo una duda. Podrias explicarme un poco mas detalladamente la parte del corrimiento de datos donde dice: 

m1=m1>>1 | m1 <<3

La verdad no entiendo muy bien como es que se mandan los pulsos al motor o a los leds dependiendo de que se conecte, si me pudieras ayudar te lo agradeceria mucho, gracias.


----------



## george.manson.69 (Ene 21, 2010)

Hay bootloader para PIC18F2550?
Y COMO SERIA?


----------



## snakewather (Feb 7, 2010)

Hola *tascker* exelente aporte al foro: sigue asi
estaria bueno un manual del PIC c compiler como sugerencia!


----------



## albermillan69 (Feb 8, 2010)

gracias por el tuto!! necesito enviar un dato de 8bit de un pic esclavo a otro pic maestro!! por i2c!!!

como lo hago??? uso dos pic 18f4550


----------



## giovamolina (Feb 9, 2010)

Buenas, estoy tratando de comunicar dos pics 16f84A por medio del protocolo de comunicacion rs232, este tipo de comunicación ya lo he hecho en assembler, pero me gustaría desarrollarlo en pic c compiler, soy nuevo manejando este compilador, así que me sería de mucha ayuda tus concejos, gracias


----------



## Frivolito (Feb 24, 2010)

tascker dijo:


> Que tal amigo, necesito de tu super ayuda. En el tercer programa (el que corresponde al corrimiento de leds) y que mencionas que puede ser util para controlar motores a pasos tengo una duda. Podrias explicarme un poco mas detalladamente la parte del corrimiento de datos donde dice:
> 
> m1=m1>>1 | m1 <<3
> 
> La verdad no entiendo muy bien como es que se mandan los pulsos al motor o a los leds dependiendo de que se conecte, si me pudieras ayudar te lo agradeceria mucho, gracias.


 
Hola, y perdon por la grna tardanza a responder pero estuve ocupado estos días.

Muy bien, pues la formulita que ves (m1=m1>>1 | m1 <<3) es para hacer efectivamente para hacer corrimientos de bits y todo esto dependea de como hagas las sumas y multiplicaciones y es lo que hara el icrocontrolador, en este caso lo que tenemos es qu la varibale m1 esta igualada a 16, ntonces a nivel de bits lo que haremos es que recorreremos un bit a la derecha (m1>>1) y despues haremos una suma booleana de -3 a la iazquierda (m1<<3), esto para cumplir un corrimiento, especifico, mucho ojo en la parte donde dice m1=m1 & 0x0f; porque aqui es donde se multiplica por el nible alto o al bajo, o los dos sea el caso.
en el caso anterior (m1=m1 & 0x0f solo esta funcionando el nible bajo. 
Realmente pense que estaba explicado muy bien n el mismo programa.

Espero y te haya ayudado cualquier duda no duden en preguntar.



albermillan69 dijo:


> gracias por el tuto!! necesito enviar un dato de 8bit de un pic esclavo a otro pic maestro!! por i2c!!!
> 
> como lo hago??? uso dos pic 18f4550


 
Em ayudaria muhco mas si me explicaras un poco mas que es lo que desea hacer exactamente porque puedes enviar sin necesidad de ua conexion i2c un dato de 8 bits pero si es asi como lo quieres hacer, porque la verdad si seria mucho mas provechoso podria ayudar si tuviera mas información, como su aplicación para asi poder darme un a idea.

Espero tu respusta para proporcionar mi ayuda.



giovamolina dijo:


> Buenas, estoy tratando de comunicar dos pics 16f84A por medio del protocolo de comunicacion rs232, este tipo de comunicación ya lo he hecho en assembler, pero me gustaría desarrollarlo en pic c compiler, soy nuevo manejando este compilador, así que me sería de mucha ayuda tus concejos, gracias


 
Que onda giovamolina, pues efectivamente si, se puede crear una comunicacion por rs232, cin pic C compiler es mucho mas facil aun, de todos los progrmas que puse "todos" en alguna parte dice por ahí, lo unico que se necesita ahcer es cambiar el #include <18f452.h> y en tu caso pondrias #include <16f84.h> para crear la comunicacion serial por rs232 en la linea #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7), aqui es hasta donde yo te puedo ayudar porque lo que es xmint y rcv, en el 16f84 no se cuales amneja, se que los hacen por otras patitas las conexiones hacia el max232 pero no estoy seguro me informare porque algunos compañeros lo han hecho con ese pic, y como yo casi no manejo la serie 16 no s emuhco sobre eso, pero con gusto me informo para ayudarte.

hola una vez mas compañeros de Forosdeelectronica he regrsado recargado y con nuevos proyectos para ustedes siguiendo con esto de los microcontroladores, por cuestiones practicas seguire usando el pic 18f452-i/p que es muy versatil y pues ya tenemos mucha informcion sobre este pic, en dias venideros me encargar de postear dos programas, l que les debo del elevador (jejejeje) y un programa que me funciono muy bien, que es un control de teperatua manejado con un lm35, lo interesante de este programa es que es programable por medio del puerto seria y la comunicacion 232 qiere decir que si ustedes estn n un rango de entre 22 y 24 grados celcius donde el sistema es estble, pero en determinado momento ustedes lo queiren cambiar a entre 25 y 28 lo podran hacer a traves del puerto serial, o incluso atravez del teclado matricial, cualqueira de las dos funciona muy bien, bueno por el momento stoyoun tanto ocupado, tmb posteare algunas aplicaciones con el PWM para control de iluminacion y velcidad del motor. Y hareos convinaciones de los primeros programasn de corrimientos con los ultimos programas de pwm, para hcer series de corrimientos modulas en intensidad de luz, en fin mejor postear que platicar os dejo un programita para empezar.

*****************************
Programa para prender algo que caliente un espacio (sistema) cuando la tempratura sea menor a la deseada, tambien prendera otra cosa que enfrie el mismo sistema cuando la temperatura supere el valor porpuesto, este progrma se diño para crear un control en una incubadora de huevos y a grnades rasgos lo que hace es prender un foco que calienta el espacio y lleva la temperatura hasta 39 grados celcius despues apaga el foco y prende el ventilador para move el aire caleinte dentro del sistema (porque asi debe de ser con lo huevos) y una ve que la temperatura se cae por dbajo delso 33 grados celcuis se prende una vez mas el foco. Todo esto mostrado en displays de 7segmentos (temperatura leida por el lm35) 


```
#include <18f452.h>
#include <STDIO.h>
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock = 4000000,RESTART_WDT)
#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7)
#build (reset=0x200)
#build (interrupt=0x208)
#org 0x0000,0x01ff
void bootloader()
{  #asm
   nop
   #endasm
}
#byte porta=0xf80
#byte portb=0xf81
#byte portc=0xf82
#byte portd=0xf83
#byte porte=0xf84

void main()
{ 
   int const disp [10] = /*{0x3f, 0x06, 0x5b, 0x4f,0x66,     //declaramos los vectores para el display (Catodo Común)
                          0x6d, 0x7d, 0x07, 0x7f, 0x6f};*/  
                         {0x40, 0x79, 0x24,0x30, 0x19,       //declaramos los vectores para el display (Anodo Común)
                          0x12, 0x02, 0x78, 0x00, 0x18};
                          
   int uni,uni2,unip,dec,dec2,decp,multi,multi2,k,prome;
   int b=0;
   float temp,temp2;
   float dato,dato2;
   
   SETUP_TIMER_2(t2_div_by_4,200,1);
   enable_interrupts(GLOBAL);
   setup_adc_ports(2);
   setup_adc(adc_clock_div_32);
   set_adc_channel(0);
  
   
   set_tris_B(0x00);
   set_tris_C(0x80);
   set_tris_D(0x00);
 
      while (TRUE)
      {     
         dato  = read_adc();
         delay_ms(10);
         set_adc_channel(1);
         dato2 = read_adc();
         delay_ms(10);
         
         temp   = (0.019607843 * dato);
         temp2  = (0.019607843 * dato2);
         
         multi  = temp * 100;
         multi2 = temp2*100;
         
         dec    = (multi/10);
         dec2   = (multi2/10);
         decp   = (dec+dec2)/2;
         
         uni    = (multi%10);
         uni2   = (multi2%10);
         unip   = (uni+uni2)/2;
         
         
         prome = (multi + multi2)/2;
         
// Control para encender o apagar un ventilador o un foco  
            
         if (prome < 38 && b==0 || prome > 38)          
          {
            b=1;
            output_high(PIN_D2);  //vent
            output_high(PIN_D1);  //foco
          }
         if (prome  > 37 && b==1)    
          { 
            output_high(PIN_D2); //vent
            output_low(PIN_D1);  //foco
          }  
         if(prome < 30)
          {
            b=0;
          }
//Para mostrar la temperatura en dos Displays de 7 segmentos
         for(k=0;k<=30;k++)
           {
             portb=disp[unip];
             delay_ms(10);
             portb=disp[decp] + 0x80;
             delay_ms(5);
           }
      }
}
```
 
NOTA: los valores que debn de modificarse en caso de desear otras temperaturas o la logica de control debera de ser dentro y solo dentro de //Control para encender y apagar un foco. Así mismo hay que notar que son 2 sensores lm35 conectados uno l pin A0 y el otro al Pin A1 la lectura es de los dos y se promedia su valor para encontrar la temperatura de la incubadora en mi caso, si ustedes solo quieren tener un solo lm35 pues le quitan todo el promedio. 

Si tienen dudas sobre este control con muhco gusto respondo.

Estare posteando mas programas y su explicacion mas adelante. Saludos a todos


----------



## manuelato (Mar 11, 2010)

hola disculpen soy estudiante de ingenieria electronica V y quisiera saber como es la programacion de un lcd. gracias


----------



## Bazookao (May 16, 2010)

Hola

como configuro el 


```
#use delay(clock=20000000)                       //Cristal de 20 Mhz leer datasheet para conexión de capacitores se puede usar difereentes cristales ver datasheet una vez mas
```

mi PIC es el 18F4520, en base a que debo modificar este valor, es que he visto que demas gente le ponen diferentes valores

gracias de antemano


----------



## tesla (May 27, 2010)

Una pregunta, para que seria exactamente los dos transistores.


----------



## Frivolito (Jul 22, 2010)

Bazookao dijo:


> Hola
> 
> como configuro el
> 
> ...



 Buenos dias tengan todos Bazookao te menciono rapidamente, el #use  dalay (clock=xxxxxxx) es para darle velocidad de respuesta al pic, si tu  compras un cristal de 4 Mz debera de ser #use delay(clock= 4 000 000)si  compras uno de 10 Mhz pondras ese valor, todo dependera del cristal que  uses, el pic que tienes acepta como maximo un cristal de 40 Mhz pero no  te recomiendo usarlo porque se atonta el pic, con uno de 20 Mhz es mas  que suficiente.  Por otro lado comento que el valor que utilices de este  Cristal servira para hacer calculos para usar por ejemplo el PWM, los  timers entre algunas otras lecturas, en algunos de los ejemplos pongo  formulas donde se utiliza la velicidad de oscilacion del cristal, espero  haber aclarado tu duda, cualquir cosa seguimos en contacto.



tesla dijo:


> Una pregunta, para que seria exactamente los dos transistores.



  Con referente a que mi buen tesla, o sea a que ejercicio?



manuelato dijo:


> hola disculpen soy estudiante de ingenieria  electronica V y quisiera saber como es la programacion de un lcd.  gracias



  Hola manuelato, te comento que es programar en "icd" por sus siglas en  ingles es In Circuit Debugger, que significa que programas directamente  el pic desde algun ordenador, todo lo que eh puesto aqui es  programacion de esa manera, que quiere decir que no quitas tu  microcontrolador de la placa o del proto. En otras palabras mandas la  información desde la computadora haci el pic, en mi caso por el puerto  serial, también se puede hacer por el puerto paralelo, o por usb que es  lo mas reciente ahortia, algunos nuevos programadores tienen la  capacidad de hacer eso, solo pones tu pic en el zocalo ZOIC (cero  esfuerzo) y asi como compilas y programas llega a tu pic y empieza a  trabajar. Mandas datos del ordenador al pic y del pic al ordenador.   Espero haber aclarado tu duda...

Aqui un programa para tener un control de temperatura y al mismo tiempo  poder cambiar los valores de las temperaturas maxima y minima.  Si tiene  alguna duda con el codigo haganmelo saber.  Nota: se utilizo el CCS  para programar y compilar y tambien para ver por el puerto serial el  funcionamiento de las temperaturas, es un icd.  
	
	



```
#include   #include                                  //libreria para el atoi #fuses  hs,nowdt,noprotect,nolvp #use delay(clock = 4 000 000,RESTART_WDT) #use  rs232(baud = 9600,xmit = pin_c6,rcv = pin_c7) #build (reset=0x200)  #build (interrupt=0x208) #org 0x0000,0x01ff  void bootloader() {  #asm     nop    #endasm }  #byte porta=0xf80 #byte portb=0xf81 #byte  portc=0xf82 #byte portd=0xf83 #byte porte=0xf84   void main() {   int  const disp [10] = {0x3f, 0x06, 0x5b, 0x4f,0x66,     //declaramos los  vectores para el display                           0x6d, 0x7d, 0x07,  0x7f, 0x6f};  int dato,uni,dec,multi,k;  float temp,temperatura;  int  tmax = 0;  int tmin = 0;  int string1 [1];     //Matrix de 2 x 1 donde  se captura el valor de la temperatura maxima.  int string2 [1];      //Matrix de 2 x 1 donde se captura el valor de la temperatura maxima.   int i = 0;           //Captura de datos para string1  int j = 0;  int  go1;             //Temperatura Maxima  int go2;              //Temperatura Minima  int flag = 0;    setup_adc_ports(2);   setup_adc(adc_clock_div_32);  set_adc_channel(0);  set_tris_B(0x00);   set_tris_D(0x00);      while (TRUE)   {    dato  = read_adc();               //Se lee el adc    temp  = (0.0196078431373*dato);  //5 volts de  referencia entre 255 da el valor de 0.0196078431373    multi = temp *  100;    dec   = multi / 10;    uni   = multi % 10;    temperatura  =  temp * 100;       if(!input(PIN_A4))  //Para entrar al modo de  programación se activa el boton A4    {     while(!input(PIN_A4))    //Solo mientras A4 esta pulsado o activado, si no no funciona.     {       printf("Introdusca la temperatura maxima deseada %i\r",flag);       if(kbhit())      {       if(flag == 0)                       //Se  pregunta por la bandera para solo meter los valores a string1        {            {          tmax = getchar(); //captura del primer valor para la  matrix string1         }          if(tmax != 0x0D)           {             string1 [i] = tmax; //se mete el primer valor en [0] de string1             delay_ms(50);       //se esperan 50 milis            i++;                 //y se incrementa i para meter el segundo valor [1] de string1            }          if(tmax == 0x0D)           //introduce los valores de  la temperatura maxima ("segundo dato")           {            go1 =  atoi(string1);     //Le doy el valor de la matrix String1 a go1   Ejemplo: String = [2 8] // go1 = 28               printf("Temperatura  Max = %i\n\r",go1);                                 if( 0 < go1  go2 )    //para meter solo valores entre 0 a 99              {                   i = 0;     //mandamos i a 0 para k se acomode en [0] de string1               }             else              {               printf("Numero  fuera de rango Hommie %i\n\r",go1);               delay_ms(50);                i = 0;              }            flag = 1;   //Se cambia la  bandera a 1 para poder meter ahora los valores a String2            }                }       if(flag == 1 && tmax == 0x0D)       //Como  ahora la bandera esta en 1 se capturan los datos para string2        {          printf("Introdusca la temperatura minima deseada %iu\r",flag);          {          tmin = getchar();                //cachamos temp minima          }          if(tmin != 0x0D)           {            string2 [j] =  tmin; //se mete el primer valor en [0] de string2             delay_ms(50);       //se esperan 50 milis            j++;                 //y se incrementa j para meter el segundo valor en [1] de string2            }           if(tmin == 0x0D)      //introduce los valores de la  temperatura minma           {            go2 = atoi(string2);           //Le doy el valor de la matrix String2 a go2  Ejemplo: String =[2 0] //  go = 20               printf("Temperatura Min = %i\n\r",go2);                               if( 0 < go2  go1)         //Si la temperatura es  mas grande k go1        {        output_high(PIN_D2);         output_low(PIN_D1);       }      else                           //El  sistema se para       {        output_low(PIN_D2);         output_low(PIN_D1);       }          if (temperatura < go2)          //Prende la bomba       {        output_low(PIN_D2);         output_high(PIN_D1);       }    } //Para mostrar la temperatura en dos  Displays de 7 segmentos   for (k =0;k
```


----------



## frivoldeux (Jul 23, 2010)

```
#include <18f452.h>
#include <stdlib.h>                                 //libreria para el atoi
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock = 4 000 000,RESTART_WDT)
#use rs232(baud = 9600,xmit = pin_c6,rcv = pin_c7)
#build (reset=0x200)
#build (interrupt=0x208)
#org 0x0000,0x01ff

void bootloader()
{  #asm
   nop
   #endasm
}

#byte porta=0xf80
#byte portb=0xf81
#byte portc=0xf82
#byte portd=0xf83
#byte porte=0xf84


void main()
{ 
 int const disp [10] = {0x3f, 0x06, 0x5b, 0x4f,0x66,     //declaramos los vectores para el display
                          0x6d, 0x7d, 0x07, 0x7f, 0x6f};
 int dato,uni,dec,multi,k;
 float temp,temperatura;
 int tmax = 0;
 int tmin = 0;
 int string1 [1];     //Matrix de 2 x 1 donde se captura el valor de la temperatura maxima.
 int string2 [1];     //Matrix de 2 x 1 donde se captura el valor de la temperatura maxima.
 int i = 0;           //Captura de datos para string1
 int j = 0;
 int go1;             //Temperatura Maxima
 int go2;             //Temperatura Minima
 int flag = 0;
 
 setup_adc_ports(2);
 setup_adc(adc_clock_div_32);
 set_adc_channel(0);
 set_tris_B(0x00);
 set_tris_D(0x00);
 

  while (TRUE)
  {
   dato  = read_adc();              //Se lee el adc
   temp  = (0.0196078431373*dato);  //5 volts de referencia entre 255 da el valor de 0.0196078431373
   multi = temp * 100;
   dec   = multi / 10;
   uni   = multi % 10;
   temperatura  = temp * 100;
   
  if(!input(PIN_A4))  //Para entrar al modo de programación se activa el boton A4
   {
    while(!input(PIN_A4))   //Solo mientras A4 esta pulsado o activado, si no no funciona.
    {
     printf("Introdusca la temperatura maxima deseada %i\r",flag);
     if(kbhit())
     {
      if(flag == 0)                       //Se pregunta por la bandera para solo meter los valores a string1
       {  
        {
         tmax = getchar(); //captura del primer valor para la matrix string1
        }
         if(tmax != 0x0D)
          {
           string1 [i] = tmax; //se mete el primer valor en [0] de string1
           delay_ms(50);       //se esperan 50 milis
           i++;                //y se incrementa i para meter el segundo valor [1] de string1
          }
         if(tmax == 0x0D)           //introduce los valores de la temperatura maxima ("segundo dato")
          {
           go1 = atoi(string1);     //Le doy el valor de la matrix String1 a go1  Ejemplo: String = [2 8] // go1 = 28   
           printf("Temperatura Max = %i\n\r",go1);
                   
            if( 0 < go1 <= 99 && go1 > go2 )   //para meter solo valores entre 0 a 99
             {   
              i = 0;     //mandamos i a 0 para k se acomode en [0] de string1
             }
            else
             {
              printf("Numero fuera de rango Hommie %i\n\r",go1);
              delay_ms(50);
              i = 0;
             }
           flag = 1;   //Se cambia la bandera a 1 para poder meter ahora los valores a String2 
          }       
       }
      if(flag == 1 && tmax == 0x0D)       //Como ahora la bandera esta en 1 se capturan los datos para string2
       {
        printf("Introdusca la temperatura minima deseada %iu\r",flag);
        {
         tmin = getchar();                //cachamos temp minima
        }
         if(tmin != 0x0D)
          {
           string2 [j] = tmin; //se mete el primer valor en [0] de string2
           delay_ms(50);       //se esperan 50 milis
           j++;                //y se incrementa j para meter el segundo valor en [1] de string2
          } 
         if(tmin == 0x0D)      //introduce los valores de la temperatura minma
          {
           go2 = atoi(string2);          //Le doy el valor de la matrix String2 a go2  Ejemplo: String =[2 0] // go = 20   
           printf("Temperatura Min = %i\n\r",go2);
                
            if( 0 < go2 <= 99 && go2 < go1)         //para meter solo valores entre 0 a 99
             {   
              j = 0;                                //mandamos j a 0 para k se acomode en [0] de string2
             }
            else
             {
              printf("Numero fuera de rango Hommie %i\n\r",go1);
              delay_ms(50);
              j = 0;
             }
            flag = 0;
           }
       }
     }
    }
   }
  else                //Relacion de temperatura real y deseada cuando no esta ativado a4 
   {
     if (temperatura > go1)         //Si la temperatura es mas grande k go1 
      {
       output_high(PIN_D2);
       output_low(PIN_D1);
      }
     else                           //El sistema se para
      {
       output_low(PIN_D2);
       output_low(PIN_D1);
      }    
     if (temperatura < go2)         //Prende la bomba
      {
       output_low(PIN_D2);
       output_high(PIN_D1);
      }
   }
//Para mostrar la temperatura en dos Displays de 7 segmentos
  for (k =0;k<=5;k++)
         {
          portb = disp[uni];
          delay_ms(10);
          portb = disp[dec] + 0x80;
          delay_ms(5);
         }            
   }
}
```


----------



## black543211 (Ago 3, 2010)

*el siguiente programa es un cronometro con una pantalla lcd, tal vez resuelva algunas dudas con este

*


> #include <16f84a.h>
> #use delay(clock=4000000)
> #fuses xt,nowdt,noprotect
> #use fast_io(a)
> ...



la configuracion del lcd esta para funcionar en el puerto b del pic.


----------



## snakewather (Oct 18, 2010)

george.manson.69 dijo:


> Hay bootloader para PIC18F2550?
> Y COMO SERIA?



 HOLA aca les dejo *el Bootloader 18F2550 USB cheuqen la pagina esta muy buena 
a mi me sirvio.* 

MUY BUEN TUTO: saludos 

http://infopic-suky.blogspot.com/2009/04/programadores.html


----------



## axelrose (Nov 6, 2010)

buen dia foreros, gracias por ver mi mensaje.
soy novato en pic c compiler y quisiera saber que fuses utilizo o configuro inicialmente para el pic18f4550
este es el codigo. no funciona


> #include <18F4550.h>                                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que
> #fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..
> 
> #use delay(clock=20m)                       //Cristal de 20 Mhz leer
> ...



si alguien pudiera ayudarme.. a configurar el oscilador externo a 20mhz, y sin bootloader, por el momento uso el pickit2. el problema que tengo es a la hora de montarlo en la proto, donde el pin b0 enciende, cuando coloco el pin1 del micro a vcc con una resistencia. pero no efectua el parpadeo. 
gracias por la colaboracion.


----------



## frivoldeux (Feb 25, 2011)

axelrose dijo:


> buen dia foreros, gracias por ver mi mensaje.
> soy novato en pic c compiler y quisiera saber que fuses utilizo o configuro inicialmente para el pic18f4550
> este es el codigo. no funciona
> 
> ...



#include <18FXXXX.h>                                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que        dependera la configuracion de los puertos y de los bytes

#fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..

#use delay(clock=20000000)   // usalo de esta manera y dime a ver que pasa



			
				inyelber dijo:
			
		

> me puedes hehar una mano con un ascensor que estoy haciendo?



Tu dime en que puedo ayudar, perdón por contestar mucho después he estado muy ocupado con la chamba...


----------



## principiante1 (Mar 16, 2011)

hola necesito ayuda, ya estoy desesperado. veran pues necesito enviar una señal por el TX del pic 16f877a a un transmisor y para que reconosca el transmisor estas diferentes señales deebn ser en codigo ASCII, y yo le estoy metiendo al pic señales hexadecimales.

pueden ayudarme con la programacion para esta actividad. estare a la espera de su ayuda.
gracias


----------



## albermillan69 (Mar 17, 2011)

principiante1 dijo:


> hola necesito ayuda, ya estoy desesperado. veran pues necesito enviar una señal por el TX del pic 16f877a a un transmisor y para que reconosca el transmisor estas diferentes señales deebn ser en codigo ASCII, y yo le estoy metiendo al pic señales hexadecimales.
> 
> pueden ayudarme con la programacion para esta actividad. estare a la espera de su ayuda.
> gracias



un transmisor RF?? usas CCS?? coloca tu codigo!!!


----------



## principiante1 (Mar 18, 2011)

Efectivamente es un transmisor RF, MaxStream 9XStream, 900 MHz 9600 baud.
Y pues si estoy utilizando el CCS C con ayuda del ISIS 7 (o PROTEUS) y en la terminal virtual del TX supuestamente me debe mostras el caracter del codigo ASCII correspondiente.

En cuanto al codigo; como veras soy principiante en esto y solo estoy realizando pequeñas pruebas. Una de ellas es la siguiente.


#include<16f877a.h>
#include <stdio.h>
#fuses xt,nowdt,noprotect,noput,nowrt,nolvp,nobrownout,nocpd
#use delay(clock=4000000)
#use rs232 (baud=9600,XMIT=PIN_C6,RCV=PIN_C7,BITS=8,PARITY=N)
#use fast_io(b)
#use fast_io(d)
#byte portb=0x06
#byte portd=0x08


void main(void)
{
   set_tris_d(0b00000000);
   set_tris_b(0b11111111);

   while (true)
   {
      if (portb==0x01)
      {
         putchar(0x03);
      }
      else
      {
         putchar(0x00);
      }
   }

}




pues veras la idea es que si yo le introdusco al pic una señal correspondiente del 1 al 130, este me muestre en la terminal TX el valor correpondiente en codigo ASCII, es decir que el programa funcione algo asi como un selector para enviar el codigo ASCII. Estuve investigando y una forma de poder hacer este selector me parece que es con la funcion "case" pero aun no se como implementarla, o tal vez no eh intentado porque en mi codigo no me muestra el valor correspondiente en codigo ASCII.

Ojala me puedas ayudar saludos.


----------



## albermillan69 (Mar 20, 2011)

principiante1 dijo:


> Efectivamente es un transmisor RF, MaxStream 9XStream, 900 MHz 9600 baud.
> Y pues si estoy utilizando el CCS C con ayuda del ISIS 7 (o PROTEUS) y en la terminal virtual del TX supuestamente me debe mostras el caracter del codigo ASCII correspondiente.
> 
> En cuanto al codigo; como veras soy principiante en esto y solo estoy realizando pequeñas pruebas. Una de ellas es la siguiente.
> ...



Utiliza el printf a ver q tal!!


----------



## gabriel_sand (Mar 31, 2011)

El funcion printf es lo que mejor se ajusta en tu caso


----------



## albermillan69 (Abr 9, 2011)

*AYUDA: TENGO UNA DUDA*

Estoy usando un cristal de 20MHz, resulta q para usar el USB tengo q  hacer unos ajustes y cambiar el PLL  resulta q al modificar el PLL queda  trabajando a 48MHz internamente!! 

Mi pregunta es: a la hora de configurar los timer uso 20MHz o 48MHz??

Este es el encabezado de mi programa:

#include <18F4550.h>
#fuses HSPLL,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,  PLL5,CPUDIV1,VREGEN,NOPBADEN
#use delay(clock=48000000)


----------



## LEDZEPP (Abr 11, 2011)

Que tal, saludos. 
Estoy iniciando en el asunto de los pics, al darle en pic wizard para iniciar 
un nuevo proyecto despuÉs de elegir donde guardar el trabajo, me despkliega una ventana
donde tengo que habilitar ciertas caracterÍsticas, decidÍ trabajar con el pic 18f452,
perono se quÉ habilitar, podrÍa alguien ayudarme con esto??


----------



## electro0x7c1 (Abr 13, 2011)

albermillan69 dijo:


> *AYUDA: TENGO UNA DUDA*
> 
> Estoy usando un cristal de 20MHz, resulta q para usar el USB tengo q  hacer unos ajustes y cambiar el PLL  resulta q al modificar el PLL queda  trabajando a 48MHz internamente!!
> 
> ...



Saludos, este pic tiene un pll interno que eleva la frecuencia hasta 48MHz, son estos 48MHz los que "entran" al CPU, es decir es la velocidad del micro, los timer trabajan con la velocidad del micro asi que se usa 48000000. De hecho la directiva:
 #use delay(clock=48000000)
indica la velocidad del CPU del PIC, no la del crystal, y es el valor que el compilador usa para las funciones de delay y rs232.

Saludos.


----------



## albermillan69 (Abr 13, 2011)

electro0x7c1 dijo:


> Saludos, este pic tiene un pll interno que eleva la frecuencia hasta 48MHz, son estos 48MHz los que "entran" al CPU, es decir es la velocidad del micro, los timer trabajan con la velocidad del micro asi que se usa 48000000. De hecho la directiva:
> #use delay(clock=48000000)
> indica la velocidad del CPU del PIC, no la del crystal, y es el valor que el compilador usa para las funciones de delay y rs232.
> 
> Saludos.



Gracias por tu ayuda y respuesta precisa!!!


----------



## electro0x7c1 (Abr 13, 2011)

LEDZEPP dijo:


> Que tal, saludos.
> Estoy iniciando en el asunto de los pics, al darle en pic wizard para iniciar
> un nuevo proyecto despuÉs de elegir donde guardar el trabajo, me despkliega una ventana
> donde tengo que habilitar ciertas caracterÍsticas, decidÍ trabajar con el pic 18f452,
> perono se quÉ habilitar, podrÍa alguien ayudarme con esto??



saludos, yo te recomendaria que no uses el wizard si estas empezando porque talvez te pierdas, asi que mejor usar la configuracion que el autor de este foro usa:


```
#include <18F452.h>                                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que        dependera la configuracion de los puertos y de los bytes

#fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..

#use delay(clock=20000000)                       //Cristal de 20 Mhz leer datasheet para conexión de capacitores se puede usar difereentes cristales ver datasheet una vez mas
```

Para esto simplemente cuando abras PIC C le das en el boton inicio (el boton circular arriba a a la izquierda) y CLOSE ALL (cerrar todo) para cerrar algun archivo que que hayas compilado antes y que te pueda causar problemas, esto solo por seguridad.

Luego le das en NEW Y SOURCE FILE, sale la ventana en blanco ahi escribes tu codigo como lo describe el autor del foro omitiendo las lines del bootloader si no lo usas (que supongo que no) y ya.

saludos


----------



## LEDZEPP (Abr 14, 2011)

muchas gracias, fue de mucha ayuda, ahora ya estoy con los programas
podrian ayudarme con el código para monitorear la temperatura de dos distintas incubadoras
que deben estar entre 2 y 8 °C pero alpasar los 8°C y despues de pasar 15 min. que suene una alarma, ya logré que se muestre la temperatura de las 2 inc. en un lcd, pero me quedé atorado ahí, otra cosa, el pic 18f452 puede trabajar mucho tempo corrido,como por ejemplo, 72 horas seguidas?


----------



## electro0x7c1 (Abr 14, 2011)

LEDZEPP dijo:


> muchas gracias, fue de mucha ayuda, ahora ya estoy con los programas
> podrian ayudarme con el código para monitorear la temperatura de dos distintas incubadoras
> que deben estar entre 2 y 8 °C pero alpasar los 8°C y despues de pasar 15 min. que suene una alarma, ya logré que se muestre la temperatura de las 2 inc. en un lcd, pero me quedé atorado ahí, otra cosa, el pic 18f452 puede trabajar mucho tempo corrido,como por ejemplo, 72 horas seguidas?



Si puede trabajar 72 hrs seguidas y mucho mas, me parece que un tiempo indefinido. respecto a tu programa estaria bien que lo subas para que la comunidad te pueda ayudar mejor.

por lo pronto yo puedo sugerir utilizar un timer, por ejemplo el timer1 para contar tiempos de 1 segundo y habilitar las interrupciones por desborde del timer, asi en cada desborde preguntas por el estado de las temperaturas, si alguna a superado 8°C de permiso a incrementar un contador (que se incrementara cada desborde) y preguntar si el contador ha llegado a 60*15=900seg en cuyo caso activas la alarma. 

imagino que si la temperatura baja de 8°C se resetearia el contador para iniciar desde cero la proxima vez que suba de 8°C.

saludos


----------



## LEDZEPP (Abr 14, 2011)

Este es el código de los termómetros que llevo hasta el momento, como mencione estoy empezando,
no sé como usar timers,bueno estoy en eso, investigando, a lo mejor hasta el código que muestro
tiene cosas que no deberían ir, pero sí me funcionó la simulación en proteus, ojalá me puedan ayudar con el código, por que es un trabajo que me pidieron con urgencia, yo estoy investigando por mi cuenta, pero como ven es poco lo que llevo, si sigo así me tardaré mucho, espero me puedan ayudar, yo sigo investigando


```
#include "C:\Users\G\Documents\Docs GFT\TRABAJOS\term.h"


#define LCD_TYPE 2
#include <lcd.c>
double   val,SEN,val2,SEN2;
void main()
{
   lcd_init();



   setup_adc_ports(AN0_AN1_AN3);
   setup_adc(ADC_CLOCK_DIV_64);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!
   
   
   
   lcd_gotoxy(2,1);
   printf(lcd_putc,"REFRI1:");
   lcd_gotoxy(2,2);
   printf(lcd_putc,"REFRI2:");
 while(true)
 {
   set_adc_channel(0);
   delay_us(10);
   
   
   val=read_adc();                              //LEE EL VALOR DEL SENSOR1
   SEN=val*0.003925*100;                        // LO CONVIERTE A DECIMAL
   lcd_gotoxy(9,1);                                   // Y LO MUESTRA EN EL LCD
   printf(lcd_putc,"  %2.1f'C",SEN);
   
   set_adc_channel(1);
   delay_us(10);
   
  
   val2=read_adc();                              //LEE EL VALOR DEL SENSOR2
   SEN2=val2*0.003925*100;                    // LO CONVIERTE A DECIMAL
   lcd_gotoxy(9,2);                                  // Y LO MUESTRA EN LCD
   printf(lcd_putc,"  %2.1f'C",SEN2);
   
 }
}
```


----------



## electro0x7c1 (Abr 14, 2011)

LEDZEPP dijo:


> Este es el código de los termómetros que llevo hasta el momento, como mencione estoy empezando,
> no sé como usar timers,bueno estoy en eso, investigando, a lo mejor hasta el código que muestro
> tiene cosas que no deberían ir, pero sí me funcionó la simulación en proteus, ojalá me puedan ayudar con el código, por que es un trabajo que me pidieron con urgencia, yo estoy investigando por mi cuenta, pero como ven es poco lo que llevo, si sigo así me tardaré mucho, espero me puedan ayudar, yo sigo investigando
> 
> ...



Que tal, pues entonces te sugeriria que si no sabes usar timers e interrupciones entonces lo hagas mediante un simple delay de 1 segundo, es decir cada segundo se actualizan las lecturas de los sensores y se pregunta por si alguna a superado 8 grados en cuyo caso da permiso a incrementar un contador de segundos, si este contador llega a 900 (15min) pues se activa la alarma.

Te dejo un codigo basado en el tuyo, activa la alarma y eso pero solo exploro un sensor el otro no, ya te daras una idea (espero).



```
//#include "C:\Users\G\Documents\Docs GFT\TRABAJOS\term.h"
#include <18F452.h>                                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que        dependera la configuracion de los puertos y de los bytes

#fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..

#use delay(clock=20000000)

//#define LCD_TYPE 2
#include <flex_lcd.c>
double val,SEN,val2,SEN2;

int16 segundos=0;
int1  permiso=0;
#define alarma PIN_B0

void main()
{
lcd_init();



setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_DIV_64);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

// TODO: USER CODE!!



lcd_gotoxy(2,1);
printf(lcd_putc,"ReFRI1:");
lcd_gotoxy(2,2);
printf(lcd_putc,"REFRI2:");

while(true)
{
set_adc_channel(0);
delay_us(10);


val=read_adc(); //LEE EL VALOR DEL SENSOR1
SEN=val*0.3925; // LO CONVIERTE A DECIMAL
lcd_gotoxy(9,1); // Y LO MUESTRA EN EL LCD
printf(lcd_putc," %2.1fC",SEN);

set_adc_channel(1);
delay_us(10);


val2=read_adc(); //LEE EL VALOR DEL SENSOR2
SEN2=val2*0.3925; // LO CONVIERTE A DECIMAL
lcd_gotoxy(9,2); // Y LO MUESTRA EN LCD
printf(lcd_putc," %2.1fC",SEN2);

delay_ms(1000);  // simple retardo de 1 segundo sin usar timer ni interrupciones

if(SEN>8){        // si SEN supera 8 grados da permiso para incrementar
   permiso=1;        // el contador de segundos
   }
else{
   permiso=0;           // si es menor o igual que 8grados quita permiso y resetea
   segundos=0;          // la cuenta de segundos
   output_low(alarma);  // y apaga la alarma si es que ya hubiera sido activada
   }

if(permiso==1){         // si hay permiso 
   segundos++;          // se incrementa el contador de segundos y 
   if(segundos==5){     // se pregunta si ha llegado a X segundos (en este caso 5 para no esperarme tanto, en tu caso seria 900)
   output_high(alarma); // si segundos ha llegado a 5 encender alarma
   }
}

} //cierra loop infinito
} //cierra main
```

saludos


----------



## LEDZEPP (Abr 15, 2011)

Gracias en verdad me fue de mucha ayuda, ahora tengo otro problema, necesito que se active la misma alarma para un nivel inferior que en este caso sería de -1°C , igualmente pasado después de un tiempo, ya tengo una idea de como hacerle, lo que no sé es como sería para que me de temperaturas negativas el adc, ya sé que la configuración del lm35 lleva dos diodos para que me de un nivel negativo pero no sé como hacerle con eso, esa línea negativa del lm35 va a otro canal del adc?, y como lo pongo en el código?, o simplemente pongo el rango de -°1<temp<8   y ya ? o que onda?


----------



## electro0x7c1 (Abr 15, 2011)

LEDZEPP dijo:


> Gracias en verdad me fue de mucha ayuda, ahora tengo otro problema, necesito que se active la misma alarma para un nivel inferior que en este caso sería de -1°C , igualmente pasado después de un tiempo, ya tengo una idea de como hacerle, lo que no sé es como sería para que me de temperaturas negativas el adc, ya sé que la configuración del lm35 lleva dos diodos para que me de un nivel negativo pero no sé como hacerle con eso, esa línea negativa del lm35 va a otro canal del adc?, y como lo pongo en el código?, o simplemente pongo el rango de -°1<temp<8   y ya ? o que onda?



Saludos, bueno, primero que nada hay que ver que onda con varios puntos importantes cuando trabajamos con el ADC, primero, veo que hiciste una conversion del ADC a 100, osea que cuando lees 255 corresponde el 100, eso esta bien pero en este caso talvez no, yo lo recomendaria de esta forma:

El sensor lm35 te da 10mV por grado, asi que podemos ajustar el voltaje de referencia alto (del PIC) a 2.56V, asi la resolucion del ADC sera de 

2.56V/256=10mV por bit

Si te fijas de esta forma la resolucion del ADC es la misma que la del sensor, asi la lectura es directa, si la lectura del ADC da 25 entonces son 25° sin mas problema.

Para mover el voltaje de referencia hay que indicarlo con la funcion setup_adc_ports(modo); el modo lo puedes checar en el archivo de cabecera .h buscas las constantes que acepta esta funcion, quedaria algo asi:
setup_adc_ports(AN0_AN1_AN2_AN4_VSS_VREF);
Vref es la pata A3 y ahi colocamos un pot que ajuste el voltaje a 2.56V

Luego, para medir temperaturas negativas con el LM35 como dices, hay que leer ambas salidas la que dice + y la que dice -, por ninguna sale voltaje negativo sino que la diferencia entre estas es la temperatura, por ejemplo si el sensor saca por la salida "positiva" 0.02V y por la salida "negativa"  0.52V la diferencia es de -0.50 osea -50°.

saludos

pd talvez al rato suba algun codigo de ejemplo

Bueno, este es el codigo de las dos incubadoras, le quite lo que sobraba y lo deje un poco mas ordenado, enciende la alarma cuando esta fuera del rango (-1° a 8°) y nuevamente solo con uno de los sensores, espero te sirva de ejemplo:



```
#include <18F452.h>                     //Libreria del pic a usar aqui se pondra el pic que se usara de aqui que        dependera la configuracion de los puertos y de los bytes
#fuses HS,NOWDT,NOPROTECT,NOLVP         //tipo de cristal externo high speed, perro guardian off, sin proteccion etc..
#use delay(clock=20000000)

#include <flex_lcd.c>

double SEN,SEN2;
int16 segundos=0;

#define alarma PIN_B0
//Canales analogicos donde se conectan los sensores
#define sensor1_pos 0   //pin A0
#define sensor1_neg 1   //pin A1
#define sensor2_pos 2   //pin A2
#define sensor2_neg 4   //pin A5


void leer_sen1(void){
set_adc_channel(sensor1_pos); //selecciona el terminal positivo
delay_us(10);                 //del sensor 1
SEN=read_adc();               //y lo lee y guarda en SEN
set_adc_channel(sensor1_neg); //selecciona terminal negativo
delay_us(10);                 //
SEN=SEN-(read_adc());         //lo lee y lo resta de la lectura
                              //del terminal positivo
}                   

void leer_sen2(void){         //lo mesmo pero con el sensor2...
set_adc_channel(sensor2_pos);
delay_us(10);
SEN2=read_adc();
set_adc_channel(sensor2_neg);
delay_us(10);
SEN2=SEN2-(read_adc());
}


void main()
{
lcd_init();
setup_adc_ports(AN0_AN1_AN2_AN4_VSS_VREF);
setup_adc(ADC_CLOCK_DIV_64);

lcd_gotoxy(2,1);
printf(lcd_putc,"REFRI1:");
lcd_gotoxy(2,2);
printf(lcd_putc,"REFRI2:");

while(true)
{
leer_sen1();               // toma la lectura del sensor1 ya sea positiva o negativa
lcd_gotoxy(9,1);           // Y LO MUESTRA EN EL LCD
printf(lcd_putc," %2.1fC",SEN);

leer_sen2();               //toma la lectura del sensor2 ya sea positiva o negativa
lcd_gotoxy(9,2);           // Y LO MUESTRA EN LCD
printf(lcd_putc," %2.1fC",SEN2);

if( (SEN>8) | (SEN<-1) ){  // si SEN supera 8 grados o baja de -1 entonces
   segundos++;             // se incrementa el contador de segundos y 
   if(segundos==5){        // se pregunta si ha llegado a X segundos (en este caso 5 para no esperarme tanto, en tu caso seria 900)
      output_high(alarma); // si segundos ha llegado a 5 encender alarma
      }
   }
else{
   segundos=0;             // resetea la cuenta de segundos
   output_low(alarma);     // y apaga la alarma si es que ya hubiera sido activada
   }

delay_ms(1000);            // simple retardo de 1 segundo sin usar timer ni interrupciones

} //cierra loop infinito
} //cierra main
```

este es de ejemplo y funciona, seguramente se puede hacer mejor.

Saludos

De una vez dejo la imagen en proteus de como conectar los lm35 y todo, haber si a alguien mas le puede servir:







saludos


----------



## LEDZEPP (Abr 25, 2011)

Saludos, y que tal nuevamente

he tenido problemas a la hora de querer simular el programa en proteus
tengo la versiÓn seis y a la hora de darle play me sale una ventana donde dice que tiene errores, dice que los lm35 (u2,u3) no es un modelo especificado o algo asÍ,   antes por el mismo problema lo simulaba con resistencias variables, pero ahora que requiero la temperatura negativa necesito forsozamente simularlo con los sensores, pero ahora se me presenta este pequeÑo problema, acontinuaciÓn mando el mensaje que aparece, y  la simulacion en proteus, ojalÁ me puedan ayudar.:


----------



## electro0x7c1 (Abr 26, 2011)

LEDZEPP dijo:


> Saludos, y que tal nuevamente
> 
> he tenido problemas a la hora de querer simular el programa en proteus
> tengo la versiÓn seis y a la hora de darle play me sale una ventana donde dice que tiene errores, dice que los lm35 (u2,u3) no es un modelo especificado o algo asÍ...:



Pues yo creo que tendras que usar una version mas actual de proteus, en mi caso tengo la version 7.6 sp4. Saludos.


----------



## tazma (Abr 28, 2011)

hola de entrada dar las gracias por todo lo que aqui se expone decir que soy muy novato en estos temas 
y tengo algunas dudas que si bien estan aqui expuestas no las e visto 
1 como puedo pasar los codigos del hilo a hex con el pic  c  
2 por que el proteus no me abre los codigos para ver la simulacion  esto pone en proteus 
is corrupt or not an isis schematic file 
salu2


----------



## Delko (Jun 11, 2011)

bueno ya a las constantes avances que se tiene aaui y para seguir  aprendiendo bueno me gustaria mucho que tb me ayuden con el protocolo  I2c del ccs pic
Bueno estoy tratando de hacer funcionar un Pll que tiene le protocolo de  comunicacion i2c y ueno pero no consigo hacerle funcionar....
 bueno estoy tratando de hacerlo funcionar con un pic 16f84A  si bien  este pic no tiene i2c por hardware pero por software mediante el ccs   esque se puede pero no me sale jeje  Bueno sin mas el pequeño bicho es  este *MC44BS374CA* si bien la comunicacion es sencilla  pero no me funciona
 bueno resumire  la forma que estoy tratando de realizarlo
...... bueno el dato del pic a utilizar....
*#use i2c(MASTER,SDA=PIN_B1,SCL=PIN_B0,FAST,FORCE_HW)

y dentro del bucle while(true)
    i2c_start();
    delay_ms(10);
    i2c_write(0xCA);           //direccion del chip (0xCA) hoja de datos
   //envio de  4 bytes segun hoja de datos   
   i2c_write(0x80);     //  C0    (VALORES SEGUN HOJA DE DATOS)
   i2c_write(0x08);     //  C1
   i2c_write(0x1E);     //  FM    (N11...N0) SEGUN FORMULA DE HOJA DE DATOS
   i2c_write(0x94);     //  FL     
   /////////////////////////
   i2c_stop();
*bueno  esta la direccion de hoja de datos 
http://www.freescale.com/files/app_specific_stand_prod/doc/data_sheet/MC44BS374CA.pdf
 es una pasada ese chip bueno si se le hace funcionar ...  y hacer buenas ideas...... con ello
espero me ayuden con eso de los protocolo de comunicacion i2c


----------



## LEDZEPP (Jun 13, 2011)

Que tal, queria saber si alguien me puede dar una idea de cÓmo hacer lo siguiente:
Necesito hacer con el pic18f452 un dispositivo que va a tener 4 sensores de presencia (a,b,c y d) necesito que al ser accionados en el orden descrito me muestre en una lcd la velocidad entre a y b, entre b y c, y entre c y d, pero que me las vaya mostrando cuando presiono un boton, si alguien tiene alguna idea de como hacer esto por favor haganmelo saber, muchas gracias


----------



## LEDZEPP (Jun 28, 2011)

Que tal de nuevo,
tengo el mismo problema de medir el tiempo real que pasa entre dos pulsos,
ya tengo un avance con algo de investigación que he realizado, cuando presiono un botón en la simulación en proteus (simulando el primer pulso o sensor) empieza a contar el tiempo, cuando lo presiono por segunda ocas Ión (simulando el sensor dos o pulso 2) me muestra en la lcd el tiempo pero la mera verdad no sé si es la correcta, me lo muestra en micro segundos, pero cuando dejo que pase mas tiempo entre los pulsos parece ser que mide el mismo tiempo,
*lo que necesito es mostrar el tiempo real y en segundos, como comentario puse una lÍnea donde me lo podría mostrar en segundos pero sigue siendo lo mismo,, les agradecería muchísimo su ayuda, plis hheeeelp!En la realidad los sensores son de presencia los cuales son activados por un objeto que pasa muy rápido por ellos y lo que intento es medir el tiempo real en segundos que tarda en pasar del 1° al 2° sensor la distancia entre sensores es aproximadamente de 20cm.

a continuación les dejo el código y la simulación para que se observe lo que me muestra

```
#include "C:\Users\G\Documents\.Docs GFT\TRABAJOS(pic)\tiempo entre pulsos\MedTEP.h"
#use delay(clock=4000000)
float const uSxTick = 1;
#define LCD_TYPE 2
#include <lcd.c>                                   
int8  numFlancoQueLlega=0;                   // Número de Flanco que llega
int1  flagToggleFlanco=0;                    // Flag para cambiar de flanco
int16 t1=0x00,t2=0x00,t3=0x00;               // Variables para guardar estados de timers y pulsos
int16 tth=0x00,ttl=0x00,tt=0x00;            
float sth=0.0,stl=0.0,st=0.0,T=0.0;          // Para hacer las restas oportunas en uS
int1  flagHayDatos=0;                        // Flag para indicar que ya hay datos                                         // dos flancos (de subida y bajada)60.
#int_ext
void handle_ext_int()
{
++numFlancoQueLlega;                         // Cuento flanco que llega
   if(flagToggleFlanco==0)
   {                                         // He recibido Flanco de Subida
      if(numFlancoQueLlega==1)
      {
      set_timer1(0);                         // Reinicio TMR1
      t1=get_timer1();                       // Guardo en t1 el valor de TMR1 al primer Flanco de Subida      
      }
      if(numFlancoQueLlega==3)
      {
      t3=get_timer1();                       // Guardo en t1 el valor de TMR1 al primer Flanco de Subida101.
         if(flagHayDatos==0)
         {               
         flagHayDatos=1;                     // Indico que ya hay nuevos datos de flancos para calcular       
         }      
      } 
      ext_int_edge(0,H_TO_L);                // Configuro para capturar siguiente flanco de Bajada    
      flagToggleFlanco=1;                    // Indico que el siguiente flanco será de Bajada
   } 
   else 
   {                                         // He recibido Flanco de Bajada
   t2=get_timer1();                          // Guardo en t2 el valor de TMR1 al Flanco de Bajada    
   ext_int_edge(0,L_TO_H);                   // Configuro para capturar siguiente flanco de subida    
   flagToggleFlanco=0;                       // Indico que el siguiente flanco será de Subida  
   }
}
void main()
{
   lcd_init();
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!

   delay_ms(333);
   disable_interrupts(global);
   disable_interrupts(int_timer1); 
   disable_interrupts(int_rda);
   disable_interrupts(int_ext);   
   disable_interrupts(int_ext1);   
   disable_interrupts(int_ext2);   
   setup_adc_ports(NO_ANALOGS); 
   setup_adc(ADC_OFF);   
   setup_spi(FALSE);  
   setup_psp(PSP_DISABLED);   
   setup_counters(RTCC_INTERNAL,RTCC_DIV_2);  
   setup_timer_0(RTCC_OFF);   
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);   
   setup_timer_2(T2_DISABLED,0,1);  
   setup_timer_3(T3_DISABLED);   
   port_b_pullups(FALSE);  
   
   delay_ms(333);
   ext_int_edge(0,L_TO_H);
   flagToggleFlanco = 0;
   enable_interrupts(int_rda);
   enable_interrupts(int_ext);   
   enable_interrupts(global);
   lcd_gotoxy(1,1);
   lcd_putc("FISICA");
   do 
   {
      if(flagHayDatos==1)
      {
         if((t3>t2)&&(t2>t1))
         {
         tth = t2 - t1;
         ttl = t3 - t2;
         tt  = tth + ttl;
         sth = uSxTick * tth;
         stl = uSxTick * ttl;
         st  = uSxTick * tt;
         //T = st*.000001;
         lcd_gotoxy(1,2);
         printf(lcd_putc," T=%1.1fuSeg",st);
         }
      }
   }
   while(true);
}
```


----------



## elfen (Jul 7, 2011)

grasia por los aporte me sirvi mucho el del motor a pasos disculpa como soy nuevo en eto no me podrias explicar como aser un  pwm para un servo con 18f452 es que no les entiendo muy bien


----------



## Palvulito (Jul 8, 2011)

Hola estoy programando en ccs c y estoy aprendiendo a utilizar los Timer para generar un retardo de 8.33ms, pero no entiendo como "entra" la interrupción del Timer0, hice un calculo para cargar el Timer0 cada 2.78ms y también puse un contador que cuando llega a 3 pone en alto el RB0 y si el contador es mayor a 4 pone en bajo a RB0, ¿como puedo hacer que en RB0 este en alto 8.33ms y después RB0 este em bajo otros 8.33ms, por lo que entiendo es que si el contador llega a 3 el Timer entra 3 veces por lo que se tendría 3 x 2.78ms = 8.33ms, no se si esto esta bien, espero que me puedan ayudar corrigiendo mi error ya que este retardo lo necesito para un proyecto escolar, anexo el código que hice, GRACIAS.


```
#include <16F873A.H>         //Libreria del Pic Implementado.
#fuses HS, NOWDT, PUT, NOLVP   //Deshbilita el Doggy, Oscilador Externo.
#use delay( clock = 20M )      //Frecuencia de Reloj.
#byte port_B = 0x06            //Direccion del Puerto B.

 int Cont = 0;               //Variable que Cuenta.

#int_Timer0                  //Interrupcion del Timer0.               
void TIMER0_isr( void )
   {
      Cont++;               //Incrementa el Contador.
      set_timer0( 39 );     //Carga el Timer0.
   }
   
void main( void )
   {  
      set_tris_B( 0x00 );   //Puerto B como Salida.
      setup_timer_0( RTCC_INTERNAL | RTCC_DIV_64 );   //Preescaler de 64.
      enable_interrupts( INT_TIMER0 );      //Habilita la Interrupcion del Timer0.
      enable_interrupts( GLOBAL );         //Habilita la Interrupcion Global.
      set_timer0( 39 );               //Carga el Timer0.
      
      while( 1 )
      {
         if( Cont == 3 )            //Si Llega 3 RB0 = 1.
            {
               output_high( PIN_B0 );
            }
         else if( Cont > 4 )        //Si llega 4 RB0 = 0.
            {
               output_low( PIN_B0 );
               Cont = 0;
            }
      }
}
```


----------



## Palvulito (Jul 13, 2011)

Hola de Nuevo Tengo un problema con un programa que hice, quiero que con un botón mover un motor a pasos con 3 diferentes casos uno en que esta detenido, izquierda y derecha,el programa que hice solo hace la secuencia de la derecha la de izquierda y detenido no lo hace. 

Lo que hice es detectar los flancos de bajada y subida e ir cambiándolos en la interrupción pero no lo hace, si primero detecta un flanco de bajada seguiría la secuencia derecha y con esto cambiaría la detección del flaco a uno de subida, si logra detectar un cambio en el flanco tendría que seguir haciendo la secuencia de derecha y de nuevo cambia para que detecte un flanco de bajada para que ahora siga la secuencia correspondiente pero creo que la interrupción no lo hace o tal vez las condiciones que puse no están bien. Espero que puedan corregirme y ayudar a solucionar mi problema, Anexo mi código. Gracias.


```
#include <16F648A.H>   //Libreria del PIC Implementado.
#fuses HS, NOWDT, NOLVP, PUT, MCLR   //Oscilador Externo, Deshabilita el Doggy.
#use delay( clock = 20M )   //Crystal de 20MHz.
#byte port_A = 0x05         //Direccion del Puerto A.
#byte port_B = 0x06         //direccion del Puerto B.

int Pasa = 0, Cont = 0;

#INT_EXT
void ext_isr( void )
   {
      int PC;
                   
      if( Cont == 0 & Pasa == 0 | Cont == 0 & Pasa == 1 )
         {
           if( Pasa == 0 )
              {
                 ext_int_edge( 0, L_TO_H );
                 Pasa = 1;
                 Cont = 0;
              }
           else if( Pasa == 1 )
              {
                 ext_int_edge( 0, H_TO_L );
                 Cont = 1;
                 Pasa = 0;
              }
           do{
               PC = 0xC0;
               port_B = PC;
               delay_ms( 500 );
           
               PC = PC - 0X60;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC - 0X30;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC + 0X60;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC - 0X90;
               port_B = PC;
               delay_ms( 10 );
           }while( 1 );     
           
           if( Pasa == 0 )
              {
                 ext_int_edge( 0, L_TO_H );
                 Pasa = 1;
                 Cont = 0;
              }
           else if( Pasa == 1 )
              {
                 ext_int_edge( 0, H_TO_L );
                 Cont = 1;
                 Pasa = 0;
              }
         }
         
      if( Cont == 1 & Pasa == 0 | Cont == 1 & Pasa == 1 )
         {
            if( Pasa == 0 )
               {
                  ext_int_edge( 0, L_TO_H );
                  Cont = 1;
                  Pasa = 1;
               }
            else if( Pasa == 1 )
               {
                  ext_int_edge( 0, H_TO_L );
                  Cont = 2;
                  Pasa = 0;
               }
            do{
               PC = 0x90;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC - 0x60;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC + 0x30;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC + 0x60;
               port_B = PC;
               delay_ms( 500 );
            
               PC = PC - 0xC0;
               port_B = PC;
               delay_ms( 10 );
            }while( 1 );
         }
            
      if( Cont == 2 & Pasa == 0 | Cont == 2 & Pasa == 1 )
         {
            if( Pasa == 0 )
               {
                  ext_int_edge( 0, L_TO_H );
                  Cont = 2;
                  Pasa = 1;
               }
            else if( Pasa == 1 )
               {
                  ext_int_edge( 0, H_TO_L );
                  Cont = 0;
                  Pasa = 0;
               }
            do{
               port_B = 0x00;
               delay_ms( 10 );
            }while( 1 );
         }
   }

void main( void )
   { 
      set_tris_B( 0x01);
      port_B = 0x00;
      
      Pasa = 0;
      Cont = 0;
      
      ext_int_edge( 0, H_TO_L );
      enable_interrupts( INT_EXT );
      enable_interrupts( GLOBAL );
      
      while( 1 )
      {  
      }
   }
```


----------



## Palvulito (Jul 13, 2011)

Después de pensar un poco lo corregí, creo que sobraba mucho código, se que esta muy básico pero es que apenas estoy empezando lo único que falta es que cada secuencia dure hasta el próximo flanco eso no se como hacerlo dejo de nuevo el código para que lo puedan corregir si esta mal, ojala puedan ayudarme con lo del tiempo de cada secuencia, pienso que puede ser con un timer, pero mejor ayúdenme. Gracias.


```
#include <16F886.H>   //Libreria del PIC Implementado.
#fuses HS, NOWDT, NOLVP, PUT, MCLR   //Oscilador Externo, Deshabilita el Doggy.
#use delay( clock = 20M )   //Crystal de 20MHz.
#include <LCD_PORTC.C>      //Libreria del LCD.
#byte port_A = 0x05         //Direccion del Puerto A.
#byte port_B = 0x06         //direccion del Puerto B.

int PC, Cont = 0;         //Variable que Cuenta y Paso Completo.

void Derecha( void )
   {
      printf( lcd_putc, "\fMotor Derecha");   //Muestra Motor Derecha.
      
      PC = 0xC0;
      port_B = PC;
      delay_ms( 500 );
           
      PC = PC - 0X60;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC - 0X30;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC + 0X60;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC - 0X90;
      port_B = PC;
      delay_ms( 5 );            
      
      printf( lcd_putc, "\fMotor Detenido");   //Muestra Motor Detenido.
   }

void Izquierda( void )
   {
      printf( lcd_putc, "\fMotor Izquierda" );   //Muestra Motor Izquierda.
      
      PC = 0x90;         //Secuencia Motor Izquierda.
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC - 0x60;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC + 0x30;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC + 0x60;
      port_B = PC;
      delay_ms( 500 );
            
      PC = PC - 0xC0;
      port_B = PC;
      delay_ms( 5 );
      
      printf( lcd_putc, "\fMotor Detenido");   //Muestra Motor Detenido.
   }
   
void Detenido( void )
   {
      printf( lcd_putc, "\fMotor Detenido");   //Muestra Motor Detenido.
      
      port_B = 0x00;   //Secuencia Motor Detenido.
      delay_ms( 500 );
      
      printf( lcd_putc, "\fMotor Detenido");   //Muestra Motor Detenido.
   }
   
#INT_EXT
void ext_isr( void )
   {               
      if( Cont == 0 )      //Compara el Contador.
         {
           Detenido();   //Llama a Detenido.
           
           ext_int_edge( 0, L_TO_H );   //Cambia a Flanco de Subida.
           Cont = 1;      //Incrementa al Contador.
         }
         
      else if( Cont == 1 )    //Compara el Contador.
         {
            Derecha();    //Llama a Derecha.

            ext_int_edge( 0, H_TO_L );   //Cambia a Flanco de Bajada.
            Cont = 2;   //Incrementa al Contador.
         }
         
      else if( Cont == 2 )   //Compara el Contador.
         {
            Izquierda();    //Llama a Izquierda.
            
            ext_int_edge( 0, H_TO_L );   //Cambia a Flanco de Bajada.
            Cont = 0;   //Reinicia el Contador.
         }
   }

void main( void )
   { 
      set_tris_B( 0x01);   //RB7 - RB2 como Salidas, RB0 como Entrada. 
      port_B = 0x01;      //Iniciliza el Puerto B.
      
      lcd_init();   //Iniciliza el LCD.
      Cont = 0;         //Iniciliza el Contador.
      printf( lcd_putc, "\fMotor A Pasos");   //Muestra Motor A Pasos.
      
      ext_int_edge( 0, H_TO_L );      //Inicia con un Flanco de Bajada.
      enable_interrupts( INT_EXT );   //Habilita la Interrupcion Externa.
      enable_interrupts( GLOBAL );   //Habilita la Interrupcion Global.
      
      while( 1 )
      {  
      }
   }
```


----------



## agart1 (Jul 13, 2011)

Hola quiero hacer un sistema de censado de potencia, ya tengo los sensores de corriente por efecto Hall, que son no invasivos y para censar el voltaje no tengo mayor problema, estoy usando PIC18f2550 y ya tengo la parte de conversión analógica a digital y la exhibición en una LCD 16x2 sin embargo no se como hacer para almacenar los datos en algún dispositivo como una memoria por ejemplo, ni como programar la interfaz con un puerto USB, para poder obtener a través de una memoria o una PC los datos resguardados para su posterior análisis, alguien tendra algún tutorial avanzado para poder hacer lo que les comento... De antemano le agradezco su atención...


----------



## Palvulito (Jul 15, 2011)

Hola que tal, ojala me puedan ayudar con este programa, estoy intentando generar un pulso de 100useg a partir de un pwm sincronizado con la linea, lo que hago es detectar flacos de subida y bajada de un cruce por cero para lograr la sincronía, puse una interrupción externa y entra un flanco de bajada empieza a leer el adc ( resolución de 10 ) y a generar el pwm, el pwm si modula pero solo a la mitad del pulso del cruce por cero y la verdad no se por que hace esto. Pienso que que los 1024  valores del adc no son suficientes para abarcar el estado alto de la onda cuadrada del cruce por cero, lo que pienso es asignar a un valor del tiempo a cada valor del adc con una regla de tres:

8.33mseg------->1023
ADCT----------->ADC = valor que lee el adc

pero esto no se si este bien, y si hago esto no tendria forma de generar el pulso por que es un numero float, dejo mi codigo para que ME PUEDAN AYUDAR la verdad no se me ocurre una solucion. GRACIAS.

```
#include <16F886.H>   //Libreria del PIC Implementado.
#device ADC = 10   //Resolucion del ADC.
#fuses HS, NOWDT, NOLVP, PUT, MCLR   //Oscilador Externo, Deshabilita el Doggy.
#use delay( clock = 20M )   //Crystal de 20MHz.

int16 ADC, PWML;   //Varoable del ADC.
int Cambiar;

#INT_EXT
void ext_isr( void )
   {
      if( Cambiar == 0 )
         {
            ADC = read_adc();   //Lee el ADC.
            delay_us( 10 );
            PWML = 1023 - ADC;   //PWM en Bajo.
            
            for( ADC; ADC > 0; ADC-- )   //Crea el PWM en Alto.
               {
                  output_high( PIN_B2 );
               }
            for( PWML; PWML > 0; PWML-- )   //Crea el PWM en Bajo.
               {
                  output_low( PIN_B2 );
               }
            
            ext_int_edge( 0, L_TO_H );
            Cambiar = 1;
         }
         
      else if( Cambiar == 1 )
         {           
            output_low( PIN_B2 );
            
            ext_int_edge( 0, H_TO_L );
            Cambiar = 0;
         }
   }
   
void main( void )
   {
      setup_adc_ports( SAN0 );   //AN0 como Cana Analogico.
      setup_adc( ADC_CLOCK_INTERNAL );   //Oscilador Interno.
      set_adc_channel( 0 );   //Habilita el Canal 0.
      
      Cambiar = 0;   //Inicializa el Cambio.
      
      ext_int_edge( 0, H_TO_L );   //Inicia con Flanco de Subida.
      enable_interrupts( INT_EXT );   //Habilita la Interrupcion Externa.
      enable_interrupts( GLOBAL );   //Habilita la Interrupcion Global.
      
      while( 1 )
         {
         }
   }
```


----------



## qliphot (Nov 9, 2011)

Hola, tal vez ustedes me pueden colaborar, resulta que estoy metido en mi proyecto de tesis de grado y estoy haciendo una tarjeta de adquicion de datos con pic para realizar control predictivo, empece a programar en asm pero se me dificultaba realizar la gran cantidad de operaciones matematicas por lo que decidi aprender a programas con c, lo primero que encontré el la web fue pic c ccs, y me parece muy amable al momento de programar, pero ahorita que estoy tratando de realizar simulacines en proteus no me muestra lo q deberia, he tratado de simular progrmas que ya he probado en hardware y se que funcionan pero no me corren en proteus, alguien q sepa a se debe??? He llegado a pensar que sea problema del software xq tomo ejemplos bajados de la internet y los corro y funcionan hasta que lo modifico y lo compilo en mi pc el codigo fuente, necesito ayuda!!! Gracias...


----------



## babasonikomon (Nov 22, 2011)

Me da gusto saber que hay personas que postean programas funcionales y que ademas los explican. lo que si no tolero son aquellos que postean programas preguntando por el error. Yo les recomendaria que si tienen programas funcionales y su respectivo circuito en proteus los postearan para asi poder analizarlos y aprender de ellos o en caso de necesitarlos usarlos de base para la realizacion de aplicaciones similares.


----------



## frivoldeux (Nov 23, 2011)

Buenas noches, en pregunta de algunos sobre sensores, posteare un control de temperatura muy sencillo, esta basado en la lectura de un sensor de temperatura el famoso LM35 y la salida la entrega en dos displays de 7 segmentos. 

Explico:


```
#include <18f452.h>  //Mc a utilizar
#include <STDIO.h>  //librería para hacer operaciones matemáticas
#fuses hs,nowdt,noprotect,nolvp    //High speed, sin perro guardian, no pretegido, no bajo voltaje.
#use delay(clock=4000000,RESTART_WDT)     //reloj a 4 MHz

#byte porta=0xf80
#byte portb=0xf81
#byte portc=0xf82     // Cambiando nombres a los puertos
#byte portd=0xf83
#byte porte=0xf84

void main()   // Deja de leer todo lo primero y vamonos a:
{ 
   
   int const disp [10] = /*{0x3f, 0x06, 0x5b, 0x4f,0x66,     //declaramos los vectores para el display (Catodo Común)
                          0x6d, 0x7d, 0x07, 0x7f, 0x6f};*/  
                         {0x40, 0x79, 0x24,0x30, 0x19,       //declaramos los vectores para el display (Anodo Común)
                          0x12, 0x02, 0x78, 0x00, 0x18};
   int uni,dec,multi,k;      //Variables para los displays y k como retardo
   int b=1;                    // Bandera lógica
   int a=1;                    //Bandera lógica
   float temp,temperatura;    //Variables para las operaciones y así obtener la temperatura dentro del PIC
   float dato;                      

   SETUP_TIMER_2(t2_div_by_16,200,10);     //definimos el Timer 2 
   enable_interrupts(GLOBAL);                     //Activamos las interrupciones globales
   setup_adc_ports(2);                              //número de puertos ADC, puse 2 porque aveces conecto otro sensor y sacar promedios.
   setup_adc(adc_clock_div_32);                 //Configuración de los ADC
   set_adc_channel(0);                              //Activamos el ADC 0
   delay_us(10);                                       //Esperamos 10 microsegundos

   set_tris_B(0x00);
   set_tris_C(0x80);                             //Configuración de puertos.
   set_tris_D(0x00);
   portb=0;                        //Limpiamos el puerto b, que es donde estan conectados los displays de 7 segmentos.
                        

      while (TRUE)                      //Programa
      {
         dato  = read_adc();                      //Leemos el ADC y metemos el valor a la variable dato
         read_adc(ADC_START_ONLY);         //decirle al pic que solo y únicamente lea el ADC para una buena lectura
         dato = read_adc(ADC_READ_ONLY); //meter de nuevo el valor a dato para corroborar
         temp  = (0.0196078*dato);            //¿porqué 0.0196078? 5 volts entre 255 (recordemos que estamos trabajando con 8 bytes del ADC) nos da ese numero, o sea conversion de Analógico a digital. 
         multi = temp*100;                               //multiplicamos por 100 para tener la temperatura real entre 10.
         dec   = multi/10;                                 //Con esta operación solo tengo el dato de las decenas
         uni   = multi%10;                                //Con esta solo tengo el dato de las unidades en una variable
         temperatura  = temp * 100;                 //Temperatura con el valor verdadero.
         
// Control para encender o apgar un ventilador o una bomba  

         if(temperatura > 29 && a==0)      //Se activa D2 (Ventilador)
          {
            b=1;
            output_high(PIN_D2);
            output_low(PIN_D1);
          }
         if(temperatura <= 29 && temperatura >= 27)                               //Todo esta inactivo
          {
            b=1;
            output_low(PIN_D2);
            output_low(PIN_D1);
          }  
         if(temperatura < 27 && b==0)      //Se activa D1 (Calentador)
          {
            a=1;
            output_low(PIN_D2);
            output_high(PIN_D1);
          }
         if(temperatura < 25)
          {
           b=0;
          }
         if(temperatura > 31)
          {
           a=0;
          }
```

Para mostrar la temperatura en dos Displays de 7 segmentos, recordemos que los displays son multiplexados, primero prende uno y después el otro tan rapido que no alcanzamos a percibirlo, esto se logra con un transistor, si hay duda en esto, me daría a la tarea de subir el diagrama, pero el multiplexeo se hace con la patita B7, las demás son las que van conectadas con su respectiva resistencia a los displays de 7 segmentos.

Explico:


```
for (k=0;k<=50;k++)   //Variable k me permite crear ciclos con la orden "for" para el multiplexeo y aparte tiempo al PIC para que piense.
         {
          portb=disp[uni];   Le digo al pic que me arroje el dato de "uni" al vector "disp" para mostrar las unidades en los displays. 
          delay_ms(10);         //Retardo de 10 ms y se apaga.
          portb=disp[dec] + 0x80;   // le digo al pic que me arroje el dato de "dec" al vector "disp" y que mande un 1 (5 volts) a la patita B7 para que se encienda todo el display de las decenas.
          delay_ms(5);          //Dura 5 ms prendido y se apaga
         }                          //Volvemos a empezar el ciclo for infinitamente, ya que la variable al alcanzar las 51 cuentas, vuelve a leer el pic y se vuelve a hacer 0.
      }
   }
```

Bueno espero que haya quedado claro como leer un sensor y mostrarlo en displays de 7 segmentos en este caso solo 2, si se necesitan 4 displays, se ocupa un poco mas de electrónica para lograrlo sin desperdiciar patitas del PIC, muy sencillo.

Estamos para ayudar y enseñar...


----------



## gcgiron (Dic 9, 2011)

Oye, gracias por el aporte, por favor puedes subir el diagrama.

Ya lo compile y esta bien sin errores, ahora me puedes decir como arranco el segundo display con el transistor? ¿Va en que pin?

Gracias.


----------



## frivoldeux (Dic 21, 2011)

gcgiron dijo:


> Oye, gracias por el aporte, por favor puedes subir el diagrama.
> 
> Ya lo compile y esta bien sin errores, ahora me puedes decir como arranco el segundo display con el transistor? ¿Va en que pin?
> 
> Gracias.



Muy bien, el transistor va en el PIN B7, que hace las veces de interruptor multiplexor. el diagrama deja lo hago pero por el momento espero que te sirva esta información. 

En la explicación del programa especifica mejor cómo hace esto. Será un transistor conectado a la para B7 y este ira conectado al común de las decenas haciendo este las veces de interruptor a tierra. con eso consigues lo que necesitas. Haré el diagrama y lo subo en estos días espero ayudarte.


----------



## marxiano12 (Ene 24, 2012)

hice un programa para prender y apagar led de hyperterminal y funciono , ahora quiero hacer el proyecto de leer temperaturas con el lm35 en hyperterminal ahora he finalizado un programa que haga las lecturas de temperatura en hyperterminal, también simule el programa con proteus y me cree unos puertos com virtuales para así simular con proteus y hyperterminal juntos y todo anda bien en la simulacion ahora cuando lo llevo al circuito real y hago la conexión modulo y hyperteminal lo único que me muestra es xxxxxx xxxxx xxxxx como que el modulo esta transmitiendo los datos pero no los correctos mostrándome puras xxxxx en el hyperterminal 
estoy usando el pic 18f2550 y uso el ccs para la compilación.

este es el programa 


```
#include <18f2550.h>
#device adc=10
#fuses XT,NOWDT,NOLVP,MCLR,NOPROTECT
#use delay(clock=4000000)
#use rs232(uart1,baud=9600)

float TEMPERATURA;

void config(void){

set_tris_c(0xB0);
set_tris_a(0x01);
setup_adc(ADC_CLOCK_INTERNAL|VSS_VDD);
setup_adc_ports(AN0);

}

void main(void){
config();
puts("temperatura actual");
do{

delay_us(50);
TEMPERATURA=read_adc();//leo el ADC y lo guardo en variable temperatura
TEMPERATURA=(TEMPERATURA*300)/614;//combierto la lectura adc en dato real

printf("temperatura: %.1f\r\n",TEMPERATURA);//muestro temperatura en hyperterminal
delay_ms(500);



}while(true);

}
```


----------



## anrz (Ene 26, 2012)

lo intente pero no hace la multiplexion podrias apoyarme en esto 
saludos


----------



## Juliocc (Ene 26, 2012)

hola a todos en la cuestión de los retardos si deseas un retardo mayor de 1000 ms como se hace ??


----------



## frivoldeux (Ene 27, 2012)

anrz dijo:


> lo intente pero no hace la multiplexion podrias apoyarme en esto
> saludos



Trato de ser muy explicito incluso en la conexión:

1.- Esta conexión es para 2 displays de 7 segmentos, los cuales serán multiplexados por medio de transistores uno tipo npn y otro tipo npn
2.- Las conexiones se hacen de la siguiente manera:
     2.1.- Del puerto B0 al puerto B6 se conectan con sus respectivas resistencias de 330 a 
             cada una de las patititas del primer display. B0 = a, B1 = b, B2 = c, etc...
     2.2.- Del primer display al segundo se hacen las mismas conexiones a-a, b-b, c-c etc...
     2.3.- La patita B7 es la patita que hace la multiplexión y esta va coenctada a la base del    
             transistor NPN en mi caso un 3904 y de ahí mismo a la base del transistor PNP en mi 
             caso 3906.
     2.4.- El colector del NPN va conectado al comun del display 1 (las decenas), la orta patita                  
             del transistor a tierra.
     2.5.- El emisor del PNP va al comun del display 2 (unidades). La otra patita del transistor a 
             tierra.
3.- Copias el código de uno de los programas que puse y deberá de funcionar.

Lo que hace la siguiente parte del programa es prender el display 2 y apagar el 1 y despues lo contrario, esto tan rápido que no se nota, eso es un tipo de multiplexeo. Esta parte del programa portb=disp[dec] + 0x80; es lo que hace, manda un dato al la patita B7 (0x80) y es lo que hace...

```
for (k=0;k<=50;k++) //Variable k me permite crear ciclos con la orden "for" para el multiplexeo 
                               y aparte tiempo al PIC para que piense.
{
portb=disp[uni];// Le digo al pic que me arroje el dato de "uni" al vector "disp" para mostrar las  
                         unidades en los displays. 
delay_ms(10);   //Retardo de 10 ms y se apaga.
portb=disp[dec] + 0x80; // le digo al pic que me arroje el dato de "dec" al vector "disp" y que 
                                     mande un 1 (5 volts) a la patita B7 para que se encienda todo el 
                                     display de las decenas.
delay_ms(5); //Dura 5 ms prendido y se apaga
}                 //Volvemos a empezar el ciclo for infinitamente, ya que la variable al alcanzar las 
                     51 cuentas, vuelve a leer el pic y se vuelve a hacer 0.
}
}
```

Espero haber ayudado. 



Juliocc dijo:


> hola a todos en la cuestión de los retardos si deseas un retardo mayor de 1000 ms como se hace ??



Para mi lo mas fácil seria crear un contador cada 1000 ms y ya con los números de tu contador ya haces lo que quieras. 

Pero mas interesante seria saber para que quieres hacer el retardo, ya que si quieres meterte con tiempos grandes, es mejor usar los Timers...


----------



## Juliocc (Ene 29, 2012)

hola pues mira mi proyecto es de lo siguiente:
1.-monitoreo de la corriente que consume una lampara durante la noche atraves de sensor de corriente TC , la lampara es de esas de encendido automatico
2.- a travez de una fotorresistencia monitorear si es de dia o de noche.
estas dos variables a travez de un circuito obtengo de cada una de ellas una salida logica que el pic 16f84a compara de la siguiente manera:
fotorresistencia < TC = despues de 5 minutos (enciende un led);
fotorresistencia > TC =despues de 5 minutos (enciende un led);
fotorresistencia == TC =despues de 5 minutos ( apaga el led):
el puerto que estoy utilizando es el B;
es solo que el  retardo que se requiero  es para eliminar durante un tiempo las comparaciones que pueden estar surgiendo durante se enciende la lampara y durante que la fotorresistencia no logra resivir luz del sol. entonces solo requiero esa seccion en la cual aun no e logrado tener un retardo largo para evitar esos disparos falsos


----------



## rayita (Feb 4, 2012)

hola amigo una pregunta en uno de tus primeros ejemplos pones porta=0x879 por así decirlos explicas que nombras al puerto  pero donde encuentras esas direcciones en la hoja de datos por que no logro encontrarlas ni el pic18f452 y pic18f4550 me podrías ayudar de antemano muchas gracias te dejo mi correo *políticas@delforo.com *GRACIAS


*Como no cumplo las Políticas del Foro. Me editaron el mensaje.*​


----------



## arrivaellobo (Feb 4, 2012)

Rayita, en éste datasheet para el 18f452, en la página 47 tienes una tabla con todos los registros y sus direcciones.

Un abrazo


----------



## arthas1888 (Feb 21, 2012)

buenas!!
como es la instruccion para enviar varios datos por medio de un bufer para rs 232 si me pueden colaborar please....


----------



## rayita (Abr 23, 2012)

hola otra vez yo gracias por tu blog y tus respuestas he aprendido bastante. 
pero las dudas me surgen a diario, la duda con la que me encontré ahora es que quiero realizar la placa que publicas en la pagina principal para el pic18f452 para cargarle el bootloader lo que me pregunto es Puedo alimentar el pic del mismo DB9 para que todo se alimente de la computadora para evitar el uso de una fuente  

de Antemano muchísimas gracias un saludo desde Aguascalientes Mex.


----------



## Silizium (Abr 23, 2012)

Buenas gente del foro....
Tengo una pregunta, estoy programando en CCS C compiler con un PIC16F887 y por medio de un botón doy el número de vueltas (aumenta de 1 en 1) al contador que se visualiza en un display alfanumérico 16x2 y es que si lo mantengo presionado lo hace cada 300 ms, pero como le hago para que cuando mantenga presionado el botón por 1 segundo aumente o disminuya mucho más rápida porque puede llegar a 2000 vueltas y de a uno a uno tarda 10 min. en llegar a ese número. 
Agradezco su ayuda...


----------



## Palvulito (Abr 26, 2012)

Hola estoy tratando de "controlar" el timer1, si RB1 esta en 0 y RB2 esta en 1 se activa la interrupción del timer1, si RB1 esta en 1 y RB2 esta 0 se desactiva el timer1, el código que hise no funciona cuando lo compilo me marcan unos warning que dice condition always false, espero que me puedan ayudar.


```
#include <16F886.H>        //Libreria del PIC Implementado.
#fuses HS, NOWDT, NOLVP, PUT, MCLR
#use delay( clock = 4M )
#byte port_B = 0x06

int Cont = 0;

#int_TIMER1
void templs( void )
   {
      Cont++;
      
      if( Cont == 100 )
         {
            output_high( PIN_B3 );
         }
      else if( Cont == 200 )
         {
            output_low( PIN_B3 );
            Cont = 0;
         }
      set_timer1( 15536 );
   }

void main( void )
    {
      set_tris_B( 0x06 );
      
      setup_timer_1( T1_INTERNAL | T1_DIV_BY_2 );
      set_timer1( 15536 );
      
      disable_interrupts( INT_TIMER1 );
      enable_interrupts( GLOBAL );
      
      while( 1 )
         {
            if( PIN_B1 == 0 && PIN_B2 == 1 )
               {
                  set_timer1( 15536 );
                  enable_interrupts( INT_TIMER1 );
               }
            if( PIN_B1 == 1 && PIN_B2 == 0 )
               {
                  disable_interrupts( INT_TIMER1 );
               }
         }
    }
```


----------



## Silizium (Abr 27, 2012)

Hola prueba tu programa así: 
si no, me avisas


```
#include <16F886.H> //Librería del PIC Implementado.
#fuses HS, NOWDT, NOLVP, PUT, MCLR
#use delay( clock = 4M )
#byte port_B = 0x06

int Cont = 0;
#int_TIMER1
void templs( void ){
Cont++;
if( Cont == 100 ){
output_high( PIN_B3 );
}
else if( Cont == 200 ){
output_low( PIN_B3 );
Cont = 0;
}
set_timer1( 15536 );
}

void main( void ){
set_tris_B( 0x06 );

setup_timer_1( T1_INTERNAL | T1_DIV_BY_2 );
set_timer1( 15536 );

disable_interrupts( INT_TIMER1 );
enable_interrupts( GLOBAL );

while (true) { 
if(input (PIN_B1 == 0 && PIN_B2 == 1 )){
set_timer1( 15536 );
enable_interrupts( INT_TIMER1 );
}
if( input (PIN_B1 == 1 && PIN_B2 == 0 )){
disable_interrupts( INT_TIMER1 );
}
}
}
```


----------



## Palvulito (Abr 30, 2012)

Gracias por contestar a mi problema, los warnig desaparecieron pero sigue sin habilitarse la interrupcion del timer1, creo que estoy haciendo algo mal al momento de activar la interrupcion.


----------



## richon (May 4, 2012)

necesito un codigo en c para programar un pic 18f4550 necesito realizar un contador de 0a 9 qque asienda coun un boton y desienda con otro y mostrar salida en un display


----------



## gerardo tovar (May 24, 2012)

tengo una duda con este programa, no se cuales pines son los de la entrada de señal, solo se que el 0x05 es el puerto a pero no se cual seria el 0x05.3?

gracias


```
#include <16f628A.h>
#fuses   INTRC,NOWDT,NOPROTECT
#use delay (clock=4000000)
#bit s1= 0x05.3    //    en esta parte no se cual seria el pin de entrada?
#bit s2 =0x05.4    //    en esta parte no se cual seria el pin de entrada? 
void main ()
{
while (true)
  {  
  set_tris_a(0x3f);
  
  if(s1==1 && s2==1)
   { 
  output_b(0x00);
   }
     if(s1==1 && s2==0)
   { 
  output_b(0x01);
  delay_ms(50);
   }
  }
  }
```


----------



## oscarintintin (Jun 27, 2012)

disculpen, tal vez sea em lugar equivocado de para preguntar esto, pero cm estan familiarizados con el compilador pic c, podran darme respuesta......
E intalado el pic c en win 7 de 64 bits. para crear un proyecto con pic wizard, el progarma deja de funcionar y ce cierra. si utilizo 24pic wizard, este no posee el variors pics uno como el conocido pic 16f84a. Que puedo hacer para solucionar este inconveniente, faltaria librerias ?..gracias de antemano por su respuesta...


----------



## IMASDPIC (Jun 27, 2012)

en principio si tienes una version full (no limitada ) y que realmente sea compatible para windows 7 
la version mas completa de ccs c si es al que te refieres es PCWHD esta dispone de la gama
pic32 ademas de las que dices


----------



## Palvulito (Dic 11, 2012)

Hola a todos, estoy tratando de hacer un pulso que tenga una duración de 100useg que se mueva en un intervalo de 0 a 8.33mseg lo que hice es detectar flancos de subida y bajada con una interrupción externa por RB0, para moverlo lo quiero hacer con el ADC este toma valores de 0 a 1023 por lo que dividí el tiempo, los 8.33mseg en 1024 partes que serian 8.13useg y con esto calcule el valor para cargar el timer y que ocurra una interrupción en 8.13useg para poner en alto un pin. El problema es que no se por que el timer no funciona no se si sea por que el tiempo es muy pequeño. Dejo mi código para que me puedan ayudar a corregir el error es que no se que sea o no se si la interrupción este funcionando de la manera correcta.


```
#include <16F886.H>
#device ADC = 10        //Resolucion del ADC.
#fuses XT, NOWDT, PUT, MCLR, NOLVP
#use delay( clock = 4000000 )
#byte port_B = 0x06

int B_fla, B_adc;
int16 V_adc_h, V_adc_l, Cont = 0;

void Con_tie( void )             //Conversion a Tiempo.
   {
      V_adc_h = read_adc();        //Toma el Valor del Adc.
      V_adc_l = 1023 - V_adc_h;    //Calcula el Valor en Bajo. 
   }

#INT_EXT                                    //Interrupcion Externa.
void intext( void )
   {
      if( B_fla == 0 )                        //Bandera de Cambio de Flanco.
         {
            B_fla = 1;                        //Cambia la Bandera de Flanco.
            ext_int_edge( 0, H_TO_L );       //Cambia a Flanco de Bajada.
            B_adc = 1;                       //Cambia la Bandera del ADC.
         }
      
      else if( B_fla == 1 )                   //Bandera de Cambio de Falnco
         {
            B_fla = 0;                        //Cambia la Bandera de Flanco.
            ext_int_edge( 0, L_TO_H );       //Cambia a Flanco de Subida.
            B_adc = 0;                       //Cambia la Bandera del ADC.
         }
   }

#int_TIMER1                                  //Interrupcion de Timer1.
void timer1( void )
   {
      Cont++;                             //Contador se Incrementa.
      
      if( Cont == V_adc_h )                     //Condicion para el Tiempo.
         {
            output_high( PIN_B1 );
         }
      else if( Cont == V_adc_l )
         {
            output_low( PIN_B1 );
            Cont = 0;                     //Reinicia el Contador.
         }
      set_timer1( 65632 );
   }

void main( void )
   {      
       B_fla = 0, B_adc = 0;       //Inicializa la Bandera de Flanco y la Bandera de Adc y Contador de Timer1.
       
       set_tris_B( 0x01);        //Configura el Puerto B.
       port_B = 0x01;            //Inicializa el Puerto B
      
       setup_adc_ports( SAN0 );              //Configura el Canal AN0.
       setup_adc( ADC_CLOCK_INTERNAL );
       set_adc_channel( 0 );
       
       setup_timer_1( T1_INTERNAL | T1_DIV_BY_2 );    //Configura el Timer1.
       set_timer1( 65632 );
       disable_interrupts( INT_TIMER1 );
       
       ext_int_edge( 0, L_TO_H );            //Configura la Interrupcion Externa.
       enable_interrupts( INT_EXT );
       enable_interrupts( GLOBAL );          //Habilita las Interruciones.
       
       while( 1 )
         {
            if( B_adc == 1 )              //Condicion de la Bandera de Adc.
               {
                  Con_tie();              
                  set_timer1( 65632 );      //Carga el Timer1
                  enable_interrupts( INT_TIMER1 );    //Habilita la Interrupcion del Timer1.
               }
            else if( B_adc == 0 )
               {
                  disable_interrupts( INT_TIMER1 );   //Deshabilita la Interrupcion del Timer1.
               }
         }
   }
```


----------



## mendek (Sep 10, 2013)

Que tal compañeros, buenas noches, bueno pues a la hora de instalar pic c compiler, no tuve problemas, pero a la hora de querer compilar me sale un error 
"not found:
c:\users\victor\desktop\main.c"
Ya investigué acerca de este error pero no logro encontrar como solucionarlo , espero me puedan ayudar, desde ya mucas gracias.


----------



## D@rkbytes (Sep 10, 2013)

mendek dijo:


> Que tal compañeros, buenas noches, bueno pues a la hora de instalar pic c compiler, no tuve problemas, pero a la hora de querer compilar me sale un error
> "not found:
> c:\users\victor\desktop\main.c"
> Ya investigué acerca de este error pero no logro encontrar como solucionarlo , espero me puedan ayudar, desde ya mucas gracias.


Eso puede ocurrir cuando abres un proyecto realizado con versiones anteriores al que usas actualmente.
Lo que hay que hacer, es borrar los archivos que se generan durante la compilación y dejar solo los del programa.
Si se trata de un único archivo, deja solamente el archivo *.C, ábrelo y compilalo nuevamente.


----------



## mendek (Sep 11, 2013)

Como siempre D@rkbytes gracias por solucionar mis problemas con los compiladores, me mudé a C, espero encontrar mayor disponibilidad que con proton IDE


----------



## mendek (Sep 21, 2013)

Que tal! de nuevo yo jaja, bueno, tengo el siguiente programa, pero no logro mostrar el valor del TMR0 en el PORTC, dado que también quiero utilizar la bandera T0IF para activar el PORTD.0 cuando esta se active

```
/*
      PROGRAMA PARA ENCENDER UNA CARGA MEDIANTE EL DESBORDAMIENTO DEL
      TMR0 JUNTO CON LA ACTIVACIÓN DE LA BANDERA T0IF, EL DESBORDAMENTO
      SE PRODUCIRÁ CON EL CONTEO DE FLANCOS DE SUBIDA EN EL PIN T0CKI.
*/ 

   #include <16F887.h>  // PIC a utilizar.
   #use delay (clock = 8000000)  // Frecuencia de trabajo.
   #fuses XT, NOWDT
   
/* Se define el modo de gestión de los puertos B, C y D con #use fast_io(X)
   donde X = A, B, C. D, E.
   El usuario debe configurar las terminales de los puertos mediante
   set_tris_X (valor), donde X es A, B, C, D, E y valor es un entero
   de 8 bits.
 */
 
   #use fast_io(a)
   #use fast_io(d)
   #use fast_io(c)
   #bit bendera=0x0B.2
   
   int1 bandera=0;   // Se agrega a "bandera" el bit T0IF
   int8 valor=0;

VOID main() {
   set_tris_a(0b11111111);
   set_tris_d(0b00000000);
   set_tris_c(0b00000000);
   output_c(0);
   output_d(0);
   SET_TIMER0(0);
   SETUP_TIMER_0(RTCC_EXT_L_TO_H|RTCC_DIV_1);
   set_timer0(0);
   if (bandera == 1) output_high(pin_d0);
   else (bandera == 0) output_low(pin_d0);
   valor = get_timer0();
   output_c(valor);   // La variable led es llevada al portc
   delay_ms(200); 
}
```


----------



## D@rkbytes (Sep 21, 2013)

mendek dijo:


> Que tal! de nuevo yo jaja, bueno, tengo el siguiente programa, pero no logro mostrar el valor del TMR0 en el PORTC, dado que también quiero utilizar la bandera T0IF para activar el PORTD.0 cuando esta se active


En tu programa no utilizas ningún bucle para comprobar si se han ingresado pulsos por el pin T0CKI.
De esa forma el programa se ejecutará hasta la instrucción delay_ms(200); y ahí se detendrá.
También date cuenta que declaras *bendera* y otra llamada *bandera*. (Te debiste haber equivocado)

Mira si con las varias modificaciones que le hice al código, es como querías que funcionara.

Saludos.


----------



## mendek (Abr 15, 2014)

Que tal compañeros, pues yo tengo el problema de que mando una simple línea al Hyperterminal y nada, salen puros símbolos sin sentido.


```
#include <16f887.h>
   #use delay(clock=16M)
   #fuses HS, NOWDT
   #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) // RS232

     
   #use fast_io(c)         // Modo de gestión del puerto C
   #use fast_io(d)

//-----------------------------------------------------------------------------   
   
   void main(){
   
   while(1){            
   
   
   set_tris_d(0b00000000);
   output_d(0b00000001);
   printf("\rVoltaje de linea");
   delay_ms(1000);
   output_d(0);
   delay_ms(1000);
   
   }                       // Fin del while
   }                       // Fin de la función main
```


y esto es lo que e sale, lo simulé en proteus y todo bien pero montado en el pic no sale nada bien. Si alguien le ha pasado y sabe por que le agradecería mucho.


----------



## NubiaCor (Abr 24, 2014)

mendek dijo:


> Que tal compañeros, pues yo tengo el problema de que mando una simple línea al Hyperterminal y nada, salen puros símbolos sin sentido.



¿Qué te parece este código a mi me ha funcionado? Tiene adicional un display LCD


```
//Envia un dato desde la Pc al pic por el puerto serie y envía "recibido"

#include<16F887.h>
#fuses INTRC_IO,NOWDT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include<LCD.c>

char ch;

#int_rda
void serial_isr(){
 ch=getchar();
 printf(lcd_putc,"\n Recibido: %ch"ch);    //Muestra en LCD
}

void main()
{

lcd_init();  
 enable_interrupts(global);
 enable_interrupts(int_rda);

for(;;){
 delay_ms(1000);
 printf(lcd_putc,"\n Enviando... ");   //Muestra en LCD
 printf("\n Cadena de caracteres");    //Envia por puerto serie
 delay_ms(1000);
 }
}
```


----------



## mendek (Jul 6, 2014)

Que tal compañeros, he estado experimentando con la recepción de caracteres en un pic16F887, lo que pasa es que envío la posición de un slider que va de 0 a 255 al puerto serial en forma de caracteres, en fin si el slider está en la posición 0 me manda el carácter '0', si esta en la posición 142 me manda el carácter '142', lo que necesito es que estos caracteres aparezcan en una LCD y tengo lo siguiente código, pero sólo funciona para caracteres de 3 dígitos:


```
while(1==1){            // Ciclo infinito  
      
      x = getc();
                    
      if(x >= '0' && x <= '9'){

      printf(lcd_putc,"%c",x);
      val[k]=x;                      
      k=k+1;                      
      
      }
      if(k==4){
         lcd_putc('\f');      // Se borra la pantalla
         k=0;
      }
    
   }
```

No sé como puedo hacer para que cuando entre un caracter '1', aparezca en la pantalla un 1 y que cuando mande un caracter 2 aparezca un '2' y NO un 12, debido a que ya había un 1. Desde ya muchas gracias por la ayuda.


----------



## D@rkbytes (Jul 6, 2014)

Prueba usando;
*lcd_gotoxy(1,1);
printf(lcd_putc,"%03u",x);*

Suerte.


----------



## mendek (Jul 6, 2014)

Gracias, D@rkbytes, estuve modificando el programa desde la mañana de hoy y ya tengo algo mejor. 
Lo que estoy haciendo es tratar de visualizar en la LCD el valor de un slider de mi teléfono android (aplicación hecha en app inventor) y estuve viendo la función gets(); que se espera hasta tener el \r (retorno de carro) y ya logré que se visualicen los números , es decir:
1.- Cuando envío p.e. 120 a través del bluetooth terminal (lo mismo que la hyperterminal de windows) y le doy enter y se visualiza el 120 en la LCD.
2.- Ya estando el 120 en pantalla pongo 1 y se borra todo y sale el 1, justo lo que quiero.

Ahora lo que no sé es cómo enviar el retorno de carro a través de la aplicación en app inventor. Lo que tengo es esto de la aplicación en app inventor:


y mi código ya funcionando en el pic16f887 en:


```
while(1==1){// Ciclo infinito
 
    gets(string);
    x = atoi(string); // x is now 123
    lcd_gotoxy(1,1);
    printf(lcd_putc,"%u   ",x);

   }
```

En la parte del programa de bloques "join" he intentado enviar primeramente la ubicación el slider y después el texto equivalente al \r de las siguientes formas:
1.- \r
2.- '\r'
3.- "\r"

Pero con ninguna de esas formas logro obtener lo que quiero, YO sé que mi problema está en enviar el retorno de carro después de la posición del slider para que gets(); haga su trabajo después del retorno de carro.

Por la ayuda que me puedan dar muchas gracias.


----------



## D@rkbytes (Jul 7, 2014)

mendek dijo:


> En la parte del programa de bloques "join" he intentado enviar primeramente la ubicación del slider y después el texto equivalente al \r de las siguientes formas:
> 1.- \r
> 2.- '\r'
> 3.- "\r"
> ...


El ASCII de Retorno de Carro (Carriage Return) es el 13.
Prueba enviando ese valor, debe funcionar.


----------



## marcelo2112 (Sep 4, 2014)

Hola a todos, tengo que representar el valor de una variable en un display led de dos o aun mejor tres digitos, pero no logro hacerlo. 
Uso ccs, mi pregunta es, no hay una libreria como el del LDC para usar display led??Gracias.


----------



## Gantunes (Sep 4, 2014)

marcelo2112 dijo:
			
		

> Hola a todos, tengo que representar el valor de una variable en un display led de dos o aun mejor tres digitos, pero no logro hacerlo.
> Uso ccs, mi pregunta es, no hay una libreria como el del LDC para usar display led??Gracias.


Hola Tengo un ejemplo que se puede utilizar, es fácil de modificar para otro pic o más pantallas.


----------



## mendek (Nov 15, 2014)

Que tal compañeros del foro, solo una duda, que por mas que leo el manual de ccs no logro entender el funcionamiento de las siguientes lineas de código:


```
do{                              // Espera por el comando1
   gets(comando);
   if(!strcmp(comando,comando1))break;
   }while(1);
```

Lo que quiero es esperar en un pic receptor, hasta obtener toda la cadena de caracteres.

Sin más de momento reciban saludos.


----------



## D@rkbytes (Nov 16, 2014)

mendek dijo:


> ¿Qué tal compañeros del foro? Sólo una duda, que por mas que leo el manual de ccs no logro entender el funcionamiento de las siguientes lineas de código:
> 
> 
> ```
> ...


Mira el ejemplo adjunto.
Se trata de dos programas. "Transmisor y Receptor"
Se envían dos cadenas diferentes, una para encender un LED y otra para apagarlo.

Ambos códigos están comentados para que puedas comprender el funcionamiento de las instrucciones.

Suerte.


----------



## mendek (Nov 17, 2014)

Muchas gracias D@rkbytes, lo que pasa es que ese código lo vi en un programa y como no sabía cual era su función pensé que era un bucle en el que se esperaba hasta recibir el string completo, lejos de compararlo, y una vez recibiendolo procesaba la info. Eso es lo que quiero hacer con algo como una bandera o algo por el estilo, nada más que hasta ahora no he tenido mucha suerte.


----------



## washington14 (Ene 18, 2015)

Mendek. solucionaste el problema de el envió del retorno de carro  con app inventor. si lo hiciste como lo
concatenaste el retorno de carro con el slideer. yo puse en su lugar en numero 13, sin embargo a la hora de correr el app me da un error.


----------



## miglo (Sep 17, 2015)

```
set_adc_channel(0);                  
   delay_ms(10);    
   temperatura= (float)read_adc()/2;
```

Bueno pues esta es mi prgunta:
Mirando por san google me encuentro en un programa la instruccion para la temperatura, cuando yo hize unas pruebas con LM35 lo que hacia  era crear una variable int y otra float y con eso controlaba la temperatura pero en esta instruccion aparece un float delante de read_adc() y luego se divide por 2 y no se interpretar esta instruccion.

Alguien me la puede explicar para comprenderla?.

Se me olvida decir que la variable temperatura esta declarada como float.


----------



## george.manson.69 (Sep 17, 2015)

miglo dijo:
			
		

> ```
> set_adc_channel(0);
> delay_ms(10);
> temperatura= (float)read_adc()/2;
> ...



el convertidor analogo a digital almacena el valor en una variable de tipo unsigned int es decir 0 a 65535, pero claro que no llega a 65535 solo guarda un valor dependiendo de los bits de conversion, ejemplo

Si tu microcontrolador tiene una resolucion del ADC de 10 bit entonces tienes un rango de 0 - 1023,
y como no puedes guardar el valor en una variable de tipo Char ya que este es de un rango de 0 - 255, entonces usa una variable de tipo unsigned int (0-65535),

entonces con la intruccion -> (float) variable

temperatura = (float)read_adc()/2;

estas convirtiendo o transformando esa variable de tipo unsigned int a un float pero sin cambiar el resultado de la conversión que obtuviste al leer el adc para asi , realizar operaciones con decimales.

Ejemplo:

unsigned int var;
float temperatura;

var = read_adc(); //

//var = 1024

temperatura = (float)var / 2; 

//(float)var = 1024.00 / 2 = 512.00

//temperatura = 512.00


¡Saludos!


----------



## chclau (Sep 17, 2015)

Si queres mas datos sobre que significa poner ese prefijo (float), busca sobre typecasting


----------



## Nuyel (Sep 17, 2015)

usar algo como "(tipo)variable" es una conversión explicita de tipos, supongo que tu variable Temperatura es tipo float, si realizas read_adc()/2 el valor devuelto por read_adc() se divide en 2, pero si es un numero impar perderás ese 0,5 ya que es un entero y el programa interpreta la operación con enteros. al declarar (float)read_adc() indicas que se convierte explícitamente el valor devuelto en un tipo float, así al realizar la división, el programa sabe que deseas tratarlo como un tipo float en lugar de un entero y el resultado puede entregar decimales.


----------



## miglo (Sep 18, 2015)

george.manson.69 dijo:


> el convertidor analogo a digital almacena el valor en una variable de tipo unsigned int es decir 0 a 65535, pero claro que no llega a 65535 solo guarda un valor dependiendo de los bits de conversion, ejemplo
> 
> Si tu microcontrolador tiene una resolucion del ADC de 10 bit entonces tienes un rango de 0 - 1023,
> y como no puedes guardar el valor en una variable de tipo Char ya que este es de un rango de 0 - 255, entonces usa una variable de tipo unsigned int (0-65535),
> ...



Te agradezco tu explicacion pero no lo acabo de entender, yo he comentado que en el programa que vi la variable de temperatura estaba declarada como tipo (float) y solamente esta declarada esa variable, no hay declarada ninguna otra que sea de tipo int.

En el ejemplo pones una de tipo unsigned int y otra de tipo float, que es como yo lo hecho alguna vez con el protoboard para hacer pruebas, pero en este programa solo esta declarada esta variable y es de tipo float, supongo que asi se ahorra memoria y eso es lo que quiero comprender pero no entiendo el (float) delante de la funcion read_adc()/2; como lo explicas.


----------



## Nuyel (Sep 18, 2015)

¿Leíste lo que escribí?

Hay dos tipos de conversiones, las implícitas que no se declaran y se realizan automáticamente, por ejemplo convertir un tipo char a int cuando se realiza una multiplicación con un tipo int y luego se realiza la operación.

La explicitas se declaran usando (tipo)variable y son necesarias para evitar confusiones al compilador y que traten una como otra.

read_adc() devuelve un tipo, según la librería será un tipo especifico, en este caso sería un unsigned int.
float temperatura está declarada, pero si a un unsigned int le haces división a 2 como lo indicas, no se hace con números flotantes, se hace con enteros y el resultado pasa al float por conversión implícita pero sin decimales ya que los valores eran enteros y el resultado de la operación fue un entero.

Al hacer (float)read_adc()/2 se convierte explícitamente el valor de read_adc() a un float, luego se realiza la división (2 se convierte a float implícitamente, pero deberías escribir lo como 2f, el sufijo f es para declarar que es constante tipo float), el resultado de esta operación es un tipo float, así que conserva los decimales.


----------



## miglo (Sep 18, 2015)

Nuyel dijo:


> ¿Leíste lo que escribí?
> 
> Hay dos tipos de conversiones, las implícitas que no se declaran y se realizan automáticamente, por ejemplo convertir un tipo char a int cuando se realiza una multiplicación con un tipo int y luego se realiza la operación.
> 
> ...



Ahora si lo he comprendido mejor, sobretodo por el ultimo parrafo. Gracias


----------

